First draft of deleted file check (#25559)

This commit is contained in:
George Wilson 2021-07-13 19:22:25 +01:00 committed by GitHub
parent a5183489f0
commit c8e4f93248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 168 additions and 76 deletions

2
build/.gitignore vendored
View File

@ -11,3 +11,5 @@
# Ignore the deleted file script output
/deleted_files.txt
/deleted_folders.txt
/renamed_files.txt

View File

@ -18,59 +18,11 @@
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// Detect the native operating system type.
$os = strtoupper(substr(PHP_OS, 0, 3));
if ($os === 'WIN')
{
echo 'Sorry, this script is not supported on Windows.' . PHP_EOL;
exit(1);
}
/*
* Constants
*/
const PHP_TAB = "\t";
/*
* Globals
*/
global $currentDir;
$currentDir = getcwd();
global $changedFiles;
$changedFiles = array();
global $deletedFiles;
$deletedFiles = array();
global $gitBinary;
ob_start();
passthru('which git', $gitBinary);
$gitBinary = trim(ob_get_clean());
/*
* Functions
*/
function run_git_command($command)
{
global $currentDir;
chdir(dirname(__DIR__));
ob_start();
passthru($command);
$return = trim(ob_get_clean());
chdir($currentDir);
return $return;
}
function usage($command)
{
echo PHP_EOL;
@ -90,7 +42,7 @@ $options = getopt('', array('from:', 'to::'));
if (empty($options['from']))
{
echo PHP_EOL;
echo 'Missing starting commit reference' . PHP_EOL;
echo 'Missing starting directory' . PHP_EOL;
usage($argv[0]);
@ -100,46 +52,184 @@ if (empty($options['from']))
// Missing the to reference? No problem, grab the current HEAD
if (empty($options['to']))
{
$options['to'] = run_git_command("$gitBinary rev-parse HEAD");
echo PHP_EOL;
echo 'Missing ending directory' . PHP_EOL;
usage($argv[0]);
exit(1);
}
// Parse the git diff to know what files have been added, removed, or renamed
$fileDiff = explode("\n", run_git_command("$gitBinary diff --name-status {$options['from']} {$options['to']}"));
// Directories to skip for the check (needs to include anything from J3 we want to keep)
$previousReleaseExclude = [
$options['from'] . '/administrator/components/com_search',
$options['from'] . '/components/com_search',
$options['from'] . '/images/sampledata',
$options['from'] . '/installation',
$options['from'] . '/modules/mod_search',
$options['from'] . '/plugins/fields/repeatable',
$options['from'] . '/plugins/search',
];
$deletedFiles = array();
foreach ($fileDiff as $file)
{
$fileName = substr($file, 2);
// Act on the file based on the action
switch (substr($file, 0, 1))
/**
* @param SplFileInfo $file The file being checked
* @param mixed $key ?
* @param RecursiveCallbackFilterIterator $iterator The iterator being processed
*
* @return bool True if you need to recurse or if the item is acceptable
*/
$previousReleaseFilter = function ($file, $key, $iterator) use ($previousReleaseExclude) {
if ($iterator->hasChildren() && !in_array($file->getPathname(), $previousReleaseExclude))
{
// This is a new case with git 2.9 to handle renamed files
case 'R':
// Explode the file on the tab character; key 0 is the action (rename), key 1 is the old filename, and key 2 is the new filename
$renamedFileData = explode("\t", $file);
return true;
}
// And flag the old file as deleted
$deletedFiles[] = "'/{$renamedFileData[1]}',";
return $file->isFile();
};
break;
// Directories to skip for the check
$newReleaseExclude = [
$options['to'] . '/installation'
];
case 'D':
$deletedFiles[] = "'/$fileName',";
/**
* @param SplFileInfo $file The file being checked
* @param mixed $key ?
* @param RecursiveCallbackFilterIterator $iterator The iterator being processed
*
* @return bool True if you need to recurse or if the item is acceptable
*/
$newReleaseFilter = function ($file, $key, $iterator) use ($newReleaseExclude) {
if ($iterator->hasChildren() && !in_array($file->getPathname(), $newReleaseExclude))
{
return true;
}
break;
return $file->isFile();
};
default:
// Ignore file additions and modifications
break;
$previousReleaseDirIterator = new RecursiveDirectoryIterator($options['from'], RecursiveDirectoryIterator::SKIP_DOTS);
$previousReleaseIterator = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator($previousReleaseDirIterator, $previousReleaseFilter),
RecursiveIteratorIterator::SELF_FIRST
);
$previousReleaseFiles = [];
$previousReleaseFolders = [];
foreach ($previousReleaseIterator as $info)
{
if ($info->isDir())
{
$previousReleaseFolders[] = "'" . str_replace($options['from'], '', $info->getPathname()) . "',";
continue;
}
$previousReleaseFiles[] = "'" . str_replace($options['from'], '', $info->getPathname()) . "',";
}
$newReleaseDirIterator = new RecursiveDirectoryIterator($options['to'], RecursiveDirectoryIterator::SKIP_DOTS);
$newReleaseIterator = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator($newReleaseDirIterator, $newReleaseFilter),
RecursiveIteratorIterator::SELF_FIRST
);
$newReleaseFiles = [];
$newReleaseFolders = [];
foreach ($newReleaseIterator as $info)
{
if ($info->isDir())
{
$newReleaseFolders[] = "'" . str_replace($options['to'], '', $info->getPathname()) . "',";
continue;
}
$newReleaseFiles[] = "'" . str_replace($options['to'], '', $info->getPathname()) . "',";
}
$filesDifference = array_diff($previousReleaseFiles, $newReleaseFiles);
$foldersDifference = array_diff($previousReleaseFolders, $newReleaseFolders);
// Specific files (e.g. language files) that we want to keep on upgrade
$filesToKeep = [
"'/administrator/language/en-GB/en-GB.com_search.ini',",
"'/administrator/language/en-GB/en-GB.com_search.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_editors-xtd_weblink.ini',",
"'/administrator/language/en-GB/en-GB.plg_editors-xtd_weblink.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_fields_repeatable.ini',",
"'/administrator/language/en-GB/en-GB.plg_fields_repeatable.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_categories.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_categories.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_contacts.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_contacts.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_content.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_content.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_newsfeeds.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_newsfeeds.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_tags.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_tags.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_weblinks.ini',",
"'/administrator/language/en-GB/en-GB.plg_search_weblinks.sys.ini',",
"'/administrator/language/en-GB/en-GB.plg_system_weblinks.ini',",
"'/administrator/language/en-GB/en-GB.plg_system_weblinks.sys.ini',",
"'/language/en-GB/en-GB.com_search.ini',",
"'/language/en-GB/en-GB.mod_search.ini',",
"'/language/en-GB/en-GB.mod_search.sys.ini',",
];
// Specific folders that we want to keep on upgrade
$foldersToKeep = [
"'/bin',",
];
// Remove folders from the results which we want to keep on upgrade
foreach ($foldersToKeep as $folder)
{
if (($key = array_search($folder, $foldersDifference)) !== false) {
unset($foldersDifference[$key]);
}
}
asort($deletedFiles);
asort($filesDifference);
rsort($foldersDifference);
// Write the deleted files list to a file for later reference
$deletedFiles = [];
$renamedFiles = [];
foreach ($filesDifference as $file)
{
// Don't remove any specific files (e.g. language files) that we want to keep on upgrade
if (array_search($file, $filesToKeep) !== false)
{
continue;
}
// Check for files which might have been renamed only
$matches = preg_grep('/^' . preg_quote($file, '/') . '$/i', $newReleaseFiles);
if ($matches !== false)
{
foreach ($matches as $match)
{
if (dirname($match) === dirname($file) && strtolower(basename($match)) === strtolower(basename($file)))
{
// File has been renamed only: Add to renamed files list
$renamedFiles[] = substr($file, 0, -1) . ' => ' . $match;
// Go on with the next file in $filesDifference
continue 2;
}
}
}
// File has been really deleted and not just renamed
$deletedFiles[] = $file;
}
// Write the lists to files for later reference
file_put_contents(__DIR__ . '/deleted_files.txt', implode("\n", $deletedFiles));
file_put_contents(__DIR__ . '/deleted_folders.txt', implode("\n", $foldersDifference));
file_put_contents(__DIR__ . '/renamed_files.txt', implode("\n", $renamedFiles));
echo PHP_EOL;
echo 'There are ' . count($deletedFiles) . ' deleted files in comparison to "' . $options['from'] . '"' . PHP_EOL;
echo 'There are ' . count($deletedFiles) . ' deleted files, ' . count($foldersDifference) . ' deleted folders and ' . count($renamedFiles) . ' renamed files in comparison to "' . $options['from'] . '"' . PHP_EOL;