@@ -1375,10 +1375,63 @@ private function cleanup_extra_files( $version_from, $version_to, $locale, $inse
13751375 // Compare the files from the old version and the new version in a case-insensitive manner,
13761376 // to prevent files being incorrectly deleted on systems with case-insensitive filesystems
13771377 // when core changes the case of filenames.
1378- $ files_to_remove = array_diff (
1379- array_map ( 'strtolower ' , array_keys ( $ old_checksums ) ),
1380- array_map ( 'strtolower ' , array_keys ( $ new_checksums ) )
1381- );
1378+ // The main logic for this was taken from the Joomla project and adapted for WP.
1379+ // See: https://github.com/joomla/joomla-cms/blob/bb5368c7ef9c20270e6e9fcc4b364cd0849082a5/administrator/components/com_admin/script.php#L8158
1380+
1381+ $ old_filepaths = array_keys ( $ old_checksums );
1382+ $ new_filepaths = array_keys ( $ new_checksums );
1383+
1384+ $ new_filepaths = array_combine ( array_map ( 'strtolower ' , $ new_filepaths ), $ new_filepaths );
1385+
1386+ $ old_filepaths_to_check = array_diff ( $ old_filepaths , $ new_filepaths );
1387+
1388+ foreach ( $ old_filepaths_to_check as $ old_filepath_to_check ) {
1389+ $ old_realpath = realpath ( ABSPATH . $ old_filepath_to_check );
1390+
1391+ // On Unix without incorrectly cased file.
1392+ if ( false === $ old_realpath ) {
1393+ continue ;
1394+ }
1395+
1396+ $ lowercase_old_filepath_to_check = strtolower ( $ old_filepath_to_check );
1397+
1398+ if ( ! array_key_exists ( $ lowercase_old_filepath_to_check , $ new_filepaths ) ) {
1399+ $ files_to_remove [] = $ old_filepath_to_check ;
1400+ continue ;
1401+ }
1402+
1403+ // We are now left with only the files that are similar from old to new except for their case.
1404+
1405+ $ old_basename = basename ( $ old_realpath );
1406+ $ expected_basename = basename ( $ new_filepaths [ $ lowercase_old_filepath_to_check ] );
1407+ $ new_realpath = realpath ( ABSPATH . $ new_filepaths [ $ lowercase_old_filepath_to_check ] );
1408+ $ new_basename = basename ( $ new_realpath );
1409+
1410+ // On Windows or Unix with only the incorrectly cased file.
1411+ if ( $ new_basename !== $ expected_basename ) {
1412+ // Rename the file.
1413+ rename ( ABSPATH . $ old_filepath_to_check , ABSPATH . $ old_filepath_to_check . '.tmp ' );
1414+ rename ( ABSPATH . $ old_filepath_to_check . '.tmp ' , ABSPATH . $ new_filepaths [ $ lowercase_old_filepath_to_check ] );
1415+
1416+ continue ;
1417+ }
1418+
1419+ // There might still be an incorrectly cased file on other OS than Windows.
1420+ if ( basename ( $ old_filepath_to_check ) === $ old_basename ) {
1421+ // Check if case-insensitive file system, eg on OSX.
1422+ if ( fileinode ( $ old_realpath ) === fileinode ( $ new_realpath ) ) {
1423+ // Check deeper because even realpath or glob might not return the actual case.
1424+ if ( ! in_array ( $ expected_basename , scandir ( dirname ( $ new_realpath ) ), true ) ) {
1425+ // Rename the file.
1426+ rename ( ABSPATH . $ old_filepath_to_check , ABSPATH . $ old_filepath_to_check . '.tmp ' );
1427+ rename ( ABSPATH . $ old_filepath_to_check . '.tmp ' , ABSPATH . $ expected );
1428+ }
1429+ } else {
1430+ // On Unix with both files: Delete the incorrectly cased file.
1431+ $ files_to_remove [] = $ old_filepath_to_check ;
1432+ }
1433+ }
1434+ }
13821435
13831436 if ( ! empty ( $ files_to_remove ) ) {
13841437 WP_CLI ::log ( 'Cleaning up files... ' );
0 commit comments