From c8bc331e26639661d05f14bf3d41fdbb34d9d20c Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 7 Jan 2024 16:36:22 +0100 Subject: [PATCH 01/11] Fixes and improvements for deleted_file_check.php - Add feature to use zip files without unpacking. - Let "to" parameter really be optional. - Create also lists of files and folders which have been added back. - Fix the help and doc blocks. --- build/deleted_file_check.php | 293 +++++++++++++++++++++++++---------- 1 file changed, 213 insertions(+), 80 deletions(-) diff --git a/build/deleted_file_check.php b/build/deleted_file_check.php index b18fd3971cb2f..e9e82d23a08a7 100644 --- a/build/deleted_file_check.php +++ b/build/deleted_file_check.php @@ -1,17 +1,21 @@ :' . PHP_TAB . 'Starting commit reference (branch/tag)' . PHP_EOL; - echo PHP_TAB . '--to :' . PHP_TAB . 'Ending commit reference (branch/tag) [optional]' . PHP_EOL; + echo PHP_TAB . '--from :' . PHP_TAB . 'Path to starting version' . PHP_EOL; + echo PHP_TAB . '--to :' . PHP_TAB . 'Path to ending version [optional]' . PHP_EOL; + echo PHP_EOL; + echo ' can be either of the following:' . PHP_EOL; + echo PHP_TAB . '- Path to a full package Zip file.' . PHP_EOL; + echo PHP_TAB . '- Path to a directory where a full package Zip file has been extracted to.' . PHP_EOL; + echo PHP_EOL; + echo 'If the "to" parameter is not specified, file "build/tmp/packages/*Full_Package.zip"' . PHP_EOL; + echo 'is used if it exists from a previous run of the build script.' . PHP_EOL; echo PHP_EOL; } @@ -39,108 +52,183 @@ function usage($command) $options = getopt('', ['from:', 'to::']); -// We need the from reference, otherwise we're doomed to fail +// We need the "from" parameter, otherwise we're doomed to fail if (empty($options['from'])) { echo PHP_EOL; - echo 'Missing starting directory' . PHP_EOL; + echo 'Missing "from" parameter' . PHP_EOL; usage($argv[0]); exit(1); } -// Missing the to reference? No problem, grab the current HEAD +// If the "to" parameter is not specified, use the default if (empty($options['to'])) { + // Import the version class to get the version information + \define('JPATH_PLATFORM', 1); + require_once \dirname(__DIR__) . '/libraries/src/Version.php'; + + $fullVersion = (new Version())->getShortVersion(); + $packageStability = str_replace(' ', '_', Version::DEV_STATUS); + $packageFile = __DIR__ . '/tmp/packages/Joomla_' . $fullVersion . '-' . $packageStability . '-Full_Package.zip'; + + if (is_file($packageFile)) { + $options['to'] = $packageFile; + } else { + echo PHP_EOL; + echo 'Missing "to" parameter and no zip file "' . $packageFile . '" found.' . PHP_EOL; + + usage($argv[0]); + + exit(1); + } +} + +// Check from and to if folder or zip file +if (!is_dir($options['from']) && !(is_file($options['from']) && substr(strtolower($options['from']), -4) === '.zip')) { echo PHP_EOL; - echo 'Missing ending directory' . PHP_EOL; + echo 'The "from" parameter is neither a directory nor a zip file' . PHP_EOL; - usage($argv[0]); + exit(1); +} + +if (!is_dir($options['to']) && !(is_file($options['to']) && substr(strtolower($options['to']), -4) === '.zip')) { + echo PHP_EOL; + echo 'The "to" parameter is neither a directory nor a zip file' . PHP_EOL; exit(1); } -// Directories to skip for the check (needs to include anything from previous versions which we want to keep) -$previousReleaseExclude = [ - $options['from'] . '/images/sampledata', - $options['from'] . '/installation', - $options['from'] . '/media/plg_captcha_recaptcha', - $options['from'] . '/media/plg_captcha_recaptcha_invisible', - $options['from'] . '/media/plg_behaviour_compat', - $options['from'] . '/plugins/behaviour/compat', +// Directories to skip for the check +$excludedFolders = [ + 'images/sampledata', + 'installation', + '/media/plg_captcha_recaptcha', + '/media/plg_captcha_recaptcha_invisible', + '/media/plg_behaviour_compat', + '/plugins/behaviour/compat', ]; /** - * @param SplFileInfo $file The file being checked - * @param mixed $key ? - * @param RecursiveCallbackFilterIterator $iterator The iterator being processed + * @param string $folderPath Path to the folder with the extracted full package + * @param array $excludeFolders Excluded folders * - * @return bool True if you need to recurse or if the item is acceptable + * @return stdClass An object with arrays "files" and "folders" */ -$previousReleaseFilter = function ($file, $key, $iterator) use ($previousReleaseExclude) { - if ($iterator->hasChildren() && !\in_array($file->getPathname(), $previousReleaseExclude)) { - return true; +function readFolder($folderPath, $excludeFolders): stdClass +{ + $return = new stdClass(); + + $return->files = []; + $return->folders = []; + + $skipFolders = []; + + foreach ($excludeFolders as $excludeFolder) { + $skipFolders[] = $folderPath . '/' . $excludeFolder; } - return $file->isFile(); -}; + /** + * @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 + */ + $releaseFilter = function ($file, $key, $iterator) use ($skipFolders) { + if ($iterator->hasChildren() && !\in_array($file->getPathname(), $skipFolders)) { + return true; + } -// Directories to skip for the check -$newReleaseExclude = [ - $options['to'] . '/installation', -]; + return $file->isFile(); + }; + + $releaseDirIterator = new RecursiveDirectoryIterator($folderPath, RecursiveDirectoryIterator::SKIP_DOTS); + $releaseIterator = new RecursiveIteratorIterator( + new RecursiveCallbackFilterIterator($releaseDirIterator, $releaseFilter), + RecursiveIteratorIterator::SELF_FIRST + ); + + foreach ($releaseIterator as $info) { + if ($info->isDir()) { + $return->folders[] = "'" . str_replace($folderPath, '', $info->getPathname()) . "',"; + continue; + } + + $return->files[] = "'" . str_replace($folderPath, '', $info->getPathname()) . "',"; + } + + return $return; +} /** - * @param SplFileInfo $file The file being checked - * @param mixed $key ? - * @param RecursiveCallbackFilterIterator $iterator The iterator being processed + * @param string $filePath Path to the full package zip file + * @param array $excludeFolders Excluded folders * - * @return bool True if you need to recurse or if the item is acceptable + * @return stdClass An object with arrays "files" and "folders" */ -$newReleaseFilter = function ($file, $key, $iterator) use ($newReleaseExclude) { - if ($iterator->hasChildren() && !\in_array($file->getPathname(), $newReleaseExclude)) { - return true; - } +function readZipFile($filePath, $excludeFolders): stdClass +{ + $return = new stdClass(); - return $file->isFile(); -}; + $return->files = []; + $return->folders = []; -$previousReleaseDirIterator = new RecursiveDirectoryIterator($options['from'], RecursiveDirectoryIterator::SKIP_DOTS); -$previousReleaseIterator = new RecursiveIteratorIterator( - new RecursiveCallbackFilterIterator($previousReleaseDirIterator, $previousReleaseFilter), - RecursiveIteratorIterator::SELF_FIRST -); -$previousReleaseFiles = []; -$previousReleaseFolders = []; + $zipArchive = new ZipArchive(); -foreach ($previousReleaseIterator as $info) { - if ($info->isDir()) { - $previousReleaseFolders[] = "'" . str_replace($options['from'], '', $info->getPathname()) . "',"; - continue; + if ($zipArchive->open($filePath) !== true) { + echo PHP_EOL; + echo 'Could not open zip archive "' . $filePath . '".' . PHP_EOL; + + exit(1); } - $previousReleaseFiles[] = "'" . str_replace($options['from'], '', $info->getPathname()) . "',"; -} + $excludeRegexp = '/^('; -$newReleaseDirIterator = new RecursiveDirectoryIterator($options['to'], RecursiveDirectoryIterator::SKIP_DOTS); -$newReleaseIterator = new RecursiveIteratorIterator( - new RecursiveCallbackFilterIterator($newReleaseDirIterator, $newReleaseFilter), - RecursiveIteratorIterator::SELF_FIRST -); -$newReleaseFiles = []; -$newReleaseFolders = []; + foreach ($excludeFolders as $excludeFolder) { + $excludeRegexp .= preg_quote($excludeFolder, '/') . '|'; + } -foreach ($newReleaseIterator as $info) { - if ($info->isDir()) { - $newReleaseFolders[] = "'" . str_replace($options['to'], '', $info->getPathname()) . "',"; - continue; + $excludeRegexp = rtrim($excludeRegexp, '|') . ')\/.*/'; + + for ($i = 0; $i < $zipArchive->numFiles; $i++) { + $stat = $zipArchive->statIndex($i); + + $name = $stat['name']; + + if (preg_match($excludeRegexp, $name) === 1) { + continue; + } + + if (substr($name, -1) === '/') { + $return->folders[] = "'/" . rtrim($name, '/') . "',"; + } else { + $return->files[] = "'/" . $name . "',"; + } } - $newReleaseFiles[] = "'" . str_replace($options['to'], '', $info->getPathname()) . "',"; + $zipArchive->close(); + + return $return; +} + +// Read files and folders lists from folders or zip files +if (is_dir($options['from'])) { + $previousReleaseFilesFolders = readFolder($options['from'], $excludedFolders); +} else { + $previousReleaseFilesFolders = readZipFile($options['from'], $excludedFolders); } -$filesDifference = array_diff($previousReleaseFiles, $newReleaseFiles); +if (is_dir($options['to'])) { + $newReleaseFilesFolders = readFolder($options['to'], $excludedFolders); +} else { + $newReleaseFilesFolders = readZipFile($options['to'], $excludedFolders); +} -$foldersDifference = array_diff($previousReleaseFolders, $newReleaseFolders); +$filesDifferenceAdd = array_diff($newReleaseFilesFolders->files, $previousReleaseFilesFolders->files); +$filesDifferenceDelete = array_diff($previousReleaseFilesFolders->files, $newReleaseFilesFolders->files); +$foldersDifferenceAdd = array_diff($newReleaseFilesFolders->folders, $previousReleaseFilesFolders->folders); +$foldersDifferenceDelete = array_diff($previousReleaseFilesFolders->folders, $newReleaseFilesFolders->folders); // Specific files (e.g. language files) that we want to keep on upgrade $filesToKeep = [ @@ -156,25 +244,25 @@ function usage($command) // 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]); + if (($key = array_search($folder, $foldersDifferenceDelete)) !== false) { + unset($foldersDifferenceDelete[$key]); } } -asort($filesDifference); -rsort($foldersDifference); +asort($filesDifferenceDelete); +rsort($foldersDifferenceDelete); $deletedFiles = []; $renamedFiles = []; -foreach ($filesDifference as $file) { +foreach ($filesDifferenceDelete 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); + $matches = preg_grep('/^' . preg_quote($file, '/') . '$/i', $newReleaseFilesFolders->files); if ($matches !== false) { foreach ($matches as $match) { @@ -182,7 +270,7 @@ function usage($command) // File has been renamed only: Add to renamed files list $renamedFiles[] = substr($file, 0, -1) . ' => ' . $match; - // Go on with the next file in $filesDifference + // Go on with the next file in $filesDifferenceDelete continue 2; } } @@ -193,9 +281,54 @@ function usage($command) } // 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)); +$addedFilesFile = __DIR__ . '/added_files.txt'; +$addedFoldersFile = __DIR__ . '/added_folders.txt'; +$deletedFilesFile = __DIR__ . '/deleted_files.txt'; +$deletedFoldersFile = __DIR__ . '/deleted_folders.txt'; +$renamedFilesFile = __DIR__ . '/renamed_files.txt'; + +@unlink($addedFilesFile); +@unlink($addedFoldersFile); +@unlink($deletedFilesFile); +@unlink($deletedFoldersFile); +@unlink($renamedFilesFile); + +if (\count($filesDifferenceAdd) > 0) { + file_put_contents($addedFilesFile, implode("\n", $filesDifferenceAdd)); +} + +if (\count($foldersDifferenceAdd) > 0) { + file_put_contents($addedFoldersFile, implode("\n", $foldersDifferenceAdd)); +} + +if (\count($deletedFiles) > 0) { + file_put_contents($deletedFilesFile, implode("\n", $deletedFiles)); +} + +if (\count($foldersDifferenceDelete) > 0) { + file_put_contents($deletedFoldersFile, implode("\n", $foldersDifferenceDelete)); +} + +if (\count($renamedFiles) > 0) { + file_put_contents($renamedFilesFile, implode("\n", $renamedFiles)); +} + +echo PHP_EOL; +echo 'There are ' . PHP_EOL; +echo ' - ' . \count($filesDifferenceAdd) . ' added files, ' . PHP_EOL; +echo ' - ' . \count($foldersDifferenceAdd) . ' added folders, ' . PHP_EOL; +echo ' - ' . \count($deletedFiles) . ' deleted files, ' . PHP_EOL; +echo ' - ' . \count($foldersDifferenceDelete) . ' deleted folders and ' . PHP_EOL; +echo ' - ' . \count($renamedFiles) . ' renamed files' . PHP_EOL; +echo PHP_EOL; +echo 'in comparison' . PHP_EOL; +echo ' from "' . $options['from'] . '"' . PHP_EOL; +echo ' to "' . $options['to'] . '"' . PHP_EOL; +echo PHP_EOL; +echo 'The following folders and their subfolders have been skipped so they were not included in the comparison:' . PHP_EOL; + +foreach ($excludedFolders as $excludedFolder) { + echo ' - ' . $excludedFolder . PHP_EOL; +} echo 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; From 3b003c6ab15d6f3336d9364c548e85bb7437614a Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 7 Jan 2024 16:36:56 +0100 Subject: [PATCH 02/11] Add new tool build/update_deleted_files.php --- build/update_deleted_files.php | 595 +++++++++++++++++++++++++++++++++ 1 file changed, 595 insertions(+) create mode 100644 build/update_deleted_files.php diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php new file mode 100644 index 0000000000000..91b1ee86adc63 --- /dev/null +++ b/build/update_deleted_files.php @@ -0,0 +1,595 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// Set flag that this is a parent file. +const _JEXEC = 1; + +// phpcs:disable PSR1.Files.SideEffects +\define('JPATH_BASE', \dirname(__DIR__)); +// phpcs:enable PSR1.Files.SideEffects + +// Configure error reporting to maximum for CLI output. +error_reporting(E_ALL); +ini_set('display_errors', 1); + +/* + * Constants + */ +const PHP_TAB = "\t"; + +// Change the following value to false when the previous major release has reached end of development. +const PREVIOUS_CHECK = true; + +const PREVIOUS_VERSION = '4.4'; + +const PREVIOUS_BRANCH = '4.4-dev'; + +const GITHUB_REPO = 'https://github.com/joomla/joomla-cms.git'; + +function usage($command) +{ + echo PHP_EOL; + echo 'Usage: php ' . $command . ' [options]' . PHP_EOL; + echo PHP_TAB . '[options]:' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--prevBranch=:' . PHP_TAB . 'The git branch to build the previous major version from' . (PREVIOUS_CHECK ? ', defaults to ' . PREVIOUS_BRANCH : '') . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--prevRemote=:' . PHP_TAB . 'The git remote reference to build the previous major version from, defaults to the most recent tag for the "prevBranch" branch' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--prevZipUrl=:' . PHP_TAB . 'Full package zip download URL for the previous major version' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--currRemote=:' . PHP_TAB . 'The git remote reference to build the current major version from, defaults to the most recent tag for the current branch' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--currZipUrl=:' . PHP_TAB . 'Full package zip download URL for the current major version' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--relZipUrl=:' . PHP_TAB . 'Full package zip download URL for the latest release of the current major version' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--init:' . PHP_TAB . PHP_TAB . PHP_TAB . 'Start with empty lists' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--reuse:' . PHP_TAB . PHP_TAB . 'Reuse full package zip files from previous builds or downloads if they are present' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--temp:' . PHP_TAB . PHP_TAB . PHP_TAB . 'Changes will not be written to the script.php file but to a copy in the "build/tmp" folder' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--test:' . PHP_TAB . PHP_TAB . PHP_TAB . 'Test mode, changes will be reported but not applied' . PHP_EOL; + echo PHP_TAB . PHP_TAB . '--help:' . PHP_TAB . PHP_TAB . PHP_TAB . 'Show this help output' . PHP_EOL; + echo PHP_EOL; +} + +$options = getopt('', ['init', 'temp', 'test', 'help', 'prevBranch::', 'prevRemote::', 'prevZipUrl::', 'currRemote::', 'currZipUrl::', 'relZipUrl::', 'reuse::']); + +if (isset($options['help'])) { + usage($argv[0]); + + exit(0); +} + +chdir(__DIR__); + +// Try to set path to git binary (e.g., /usr/local/bin/git or /usr/bin/git) +try { + ob_start(); + passthru('which git', $systemGit); + $systemGit = trim(ob_get_clean()); +} catch (Exception $e) { + $systemGit = 'git'; +} + +$packagesPath = __DIR__ . '/tmp/update_deleted_files/packages'; +@mkdir($packagesPath, 0755, true); + +// Build current major version if there is no result present from a previous build or download from URL +$currentVersionPackage = ''; +$currentMajorDownload = $options['currZipUrl'] ?? ''; + +if (empty($currentMajorDownload)) { + // No download URL: Check if there is a saved package from a previous build. + $files = isset($options['reuse']) ? glob(__DIR__ . '/tmp/packages/*Full_Package.zip') : false; + + if ($files !== false && \count($files) === 1) { + $currentVersionPackage = $files[0]; + } else { + echo PHP_EOL; + echo 'Runing build script for current version.' . PHP_EOL; + echo PHP_EOL; + + system('php ./build.php --remote=' . ($options['currRemote'] ?? 'HEAD') . ' --exclude-gzip --exclude-zstd'); + + $files = glob(__DIR__ . '/tmp/packages/*Full_Package.zip'); + + if ($files !== false && \count($files) === 1) { + $currentVersionPackage = $files[0]; + } + + // Create the packages folder again because it has been deleted by the build + @mkdir($packagesPath, 0755, true); + } +} else { + // Use download URL: Check if there is a saved package from a previous download. + $currentVersionPackage = $packagesPath . '/' . basename($currentMajorDownload); + + if (!isset($options['reuse']) || !is_file($currentVersionPackage)) { + // Donwload package. + echo PHP_EOL; + echo 'Downloading package "' . $currentMajorDownload . '".' . PHP_EOL; + + system('curl -L -o ' . $currentVersionPackage . ' ' . $currentMajorDownload); + } + + if (!is_file($currentVersionPackage)) { + $currentVersionPackage = ''; + } +} + +if (!$currentVersionPackage) { + echo PHP_EOL; + echo 'Error: Could not find current version package' . __DIR__ . '/tmp/packages/*Full_Package.zip.' . PHP_EOL; + + exit(1); +} + +// Get the version of the current major release package +$currentVersionBuild = ''; + +$zipArchive = new ZipArchive(); + +if ($zipArchive->open($currentVersionPackage) !== true) { + echo PHP_EOL; + echo 'Could not open zip archive "' . $currentVersionPackage . '".' . PHP_EOL; + + exit(1); +} + +if (($xmlFileContent = $zipArchive->getFromName('administrator/manifests/files/joomla.xml')) !== false) { + $xml = simplexml_load_string($xmlFileContent); + + if ($xml instanceof \SimpleXMLElement && isset($xml->version)) { + $currentVersionBuild = (string) $xml->version; + } +} + +if (!$currentVersionBuild) { + echo PHP_EOL; + echo 'Error: Could not get version from manifest XML file in the current version package.' . PHP_EOL; + + exit(1); +} + +if (!preg_match('/^(?P\d+)\.(?P\d+)\.(?P\d+)/i', $currentVersionBuild, $currentVersionBuildParts)) { + echo PHP_EOL; + echo 'Error: Could not get version parts from manifest XML file in the current version package.' . PHP_EOL; + + exit(1); +} + +$currentVersionBuild = str_replace('-dev', '', $currentVersionBuild); + +if ($currentVersionBuildParts['minor'] > 0) { + if (version_compare($currentVersionBuild, $currentVersionBuildParts['major'] . '.' . $currentVersionBuildParts['minor'] . '.0-alpha1', '>')) { + // There should be a previous release for that minor version. + $previousPackageVersion = $currentVersionBuildParts['major'] . '.' . $currentVersionBuildParts['minor']; + } else { + // There is no previous release for that minor version: Check for previous minor version. + $previousPackageVersion = $currentVersionBuildParts['major'] . '.' . ($currentVersionBuildParts['minor'] - 1); + } +} elseif (version_compare($currentVersionBuild, $currentVersionBuildParts['major'] . '.0.0-alpha1', '>')) { + // There should be a previous release for minor version zero. + $previousPackageVersion = $currentVersionBuildParts['major'] . '.' . $currentVersionBuildParts['minor']; +} else { + // There is no previous release package for this major version. + $previousPackageVersion = false; +} + +if (!$previousPackageVersion && isset($options['relZipUrl'])) { + echo PHP_EOL; + echo 'There cannot be a previous release package for the build version"' . $currentVersionBuild . '". The "relZipUrl" parameter will be ignored.' . PHP_EOL; + unset($options['relZipUrl']); +} + +// Clone and build previous major version or download from URL +if (PREVIOUS_CHECK) { + $previousBuildPath = __DIR__ . '/tmp/update_deleted_files/previous-build'; + $previousBuildPackagePath = __DIR__ . '/tmp/update_deleted_files/previous-package'; + $previousMajorPackage = ''; + $previousMajorDownload = $options['prevZipUrl'] ?? ''; + + if (empty($previousMajorDownload)) { + // No download URL: Check if there is a saved package from a previous build. + $files = isset($options['reuse']) ? glob($previousBuildPackagePath . '/Joomla_' . PREVIOUS_VERSION . '.*Full_Package.zip') : false; + + if ($files !== false && \count($files) > 0) { + // There is one matching saved package from a previous build. + $previousMajorPackage = $files[0]; + } + + // No package found from previous build: Clone the repository and build the previous release. + if ($previousMajorPackage === '') { + system('rm -rf ' . $previousBuildPath); + + $prevMajorBranch = $options['prevBranch'] ?? PREVIOUS_BRANCH; + + echo PHP_EOL; + echo 'Cloning branch "' . $prevMajorBranch . '" into folder "' . $previousBuildPath . '"' . PHP_EOL; + echo PHP_EOL; + + @mkdir($previousBuildPath, 0755, true); + @mkdir($previousBuildPackagePath, 0755, true); + + chdir($previousBuildPath); + + system($systemGit . ' clone -b ' . $prevMajorBranch . ' ' . GITHUB_REPO . ' .'); + + echo PHP_EOL; + echo 'Runing build script for previous major version.' . PHP_EOL; + echo PHP_EOL; + + system('php ./build/build.php --remote=' . ($options['prevRemote'] ?? 'HEAD') . ' --exclude-gzip --exclude-bzip2'); + + chdir(__DIR__); + + $files = glob($previousBuildPath . '/build/tmp/packages/Joomla_' . PREVIOUS_VERSION . '.*Full_Package.zip'); + + if ($files !== false && \count($files) === 1) { + $previousMajorPackage = $previousBuildPackagePath . '/' . basename($files[0]); + + copy($files[0], $previousMajorPackage); + } + + system('rm -rf ' . $previousBuildPath); + } + } else { + // Use download URL: Check if there is a saved package from a previous download. + $previousMajorPackage = $previousBuildPackagePath . '/' . basename($previousMajorDownload); + + if (!isset($options['reuse']) || !is_file($previousMajorPackage)) { + // Donwload package. + echo PHP_EOL; + echo 'Downloading package "' . $previousMajorDownload . '".' . PHP_EOL; + + system('curl -L -o ' . $previousMajorPackage . ' ' . $previousMajorDownload); + } + + if (!is_file($previousMajorPackage)) { + $previousMajorPackage = ''; + } + } + + // If nothing found for the previous major version we can't continue. + if (!$previousMajorPackage) { + echo PHP_EOL; + echo 'Error: Could not find previous major release package "' . $packagesPath . '/Joomla_' . PREVIOUS_VERSION . '.*Full_Package.zip".' . PHP_EOL; + + exit(1); + } +} + +$previousVersionPackageUrl = ''; + +if (isset($options['relZipUrl'])) { + $previousVersionPackageUrl = $options['relZipUrl']; +} elseif ($previousPackageVersion) { + // Fetch release information from GitHub + echo PHP_EOL; + echo 'Fetching releases information from GitHub.' . PHP_EOL; + + ob_start(); + passthru('curl -H "Accept: application/vnd.github.v3+json" -L https://api.github.com/repos/joomla/joomla-cms/releases', $gitHubReleasesString); + $gitHubReleasesString = trim(ob_get_clean()); + + if (!$gitHubReleasesString) { + echo PHP_EOL; + echo 'Error: Could not get releases information from GitHub.' . PHP_EOL; + + exit(1); + } + + $gitHubReleases = json_decode($gitHubReleasesString); + + // Get the latest release before current release build version + foreach ($gitHubReleases as $gitHubRelease) { + if ($gitHubRelease->draft) { + continue; + } + + if ( + version_compare(substr($gitHubRelease->tag_name, 0, \strlen($previousPackageVersion)), $previousPackageVersion, '=') + && version_compare($gitHubRelease->tag_name, $currentVersionBuild, '<') + ) { + foreach ($gitHubRelease->assets as $asset) { + if (preg_match('/^Joomla_.*-Full_Package\.zip$/', $asset->name) === 1) { + $previousVersionPackageUrl = $asset->browser_download_url; + + break 2; + } + } + } + } + + if (!$previousVersionPackageUrl) { + echo PHP_EOL; + echo 'Error: Could not get package download URL from GitHub.' . PHP_EOL; + + exit(1); + } +} + +if ($previousPackageVersion) { + $previousVersionPackage = $packagesPath . '/' . basename($previousVersionPackageUrl); + + // Download full zip package of latest release before current version if not done before + if (!is_file($previousVersionPackage)) { + echo PHP_EOL; + echo 'Downloading package "' . $previousVersionPackageUrl . '".' . PHP_EOL; + + system('curl -L -o ' . $previousVersionPackage . ' ' . $previousVersionPackageUrl); + } + + if (!is_file($previousVersionPackage)) { + echo PHP_EOL; + echo 'Error: Could not download package.' . PHP_EOL; + + exit(1); + } +} + +$addedFilesFile = __DIR__ . '/added_files.txt'; +$addedFoldersFile = __DIR__ . '/added_folders.txt'; +$deletedFilesFile = __DIR__ . '/deleted_files.txt'; +$deletedFoldersFile = __DIR__ . '/deleted_folders.txt'; +$renamedFilesFile = __DIR__ . '/renamed_files.txt'; + +if (PREVIOUS_CHECK) { + echo PHP_EOL; + echo 'Comparing from ".' . substr($previousMajorPackage, \strlen(__DIR__)) . '"' . PHP_EOL; + echo ' to ".' . substr($currentVersionPackage, \strlen(__DIR__)) . '".' . PHP_EOL; + + system('php ./deleted_file_check.php --from=' . $previousMajorPackage . ' --to=' . $currentVersionPackage . ' > /dev/null'); + + $addedFiles = file_exists($addedFilesFile) ? explode("\n", file_get_contents($addedFilesFile)) : []; + $addedFolders = file_exists($addedFoldersFile) ? explode("\n", file_get_contents($addedFoldersFile)) : []; + $deletedFiles = file_exists($deletedFilesFile) ? explode("\n", file_get_contents($deletedFilesFile)) : []; + $deletedFolders = file_exists($deletedFoldersFile) ? explode("\n", file_get_contents($deletedFoldersFile)) : []; + $renamedFilesRows = file_exists($renamedFilesFile) ? explode("\n", file_get_contents($renamedFilesFile)) : []; +} else { + $addedFiles = []; + $addedFolders = []; + $deletedFiles = []; + $deletedFolders = []; + $renamedFilesRows = []; +} + +if ($previousPackageVersion) { + echo PHP_EOL; + echo 'Comparing from ".' . substr($previousVersionPackage, \strlen(__DIR__)) . '"' . PHP_EOL; + echo ' to ".' . substr($currentVersionPackage, \strlen(__DIR__)) . '".' . PHP_EOL; + + system('php ./deleted_file_check.php --from=' . $previousVersionPackage . ' --to=' . $currentVersionPackage . ' > /dev/null'); + + $addedFiles = array_unique(array_merge($addedFiles, file_exists($addedFilesFile) ? explode("\n", file_get_contents($addedFilesFile)) : [])); + $addedFolders = array_unique(array_merge($addedFolders, file_exists($addedFoldersFile) ? explode("\n", file_get_contents($addedFoldersFile)) : [])); + $deletedFiles = array_unique(array_merge($deletedFiles, file_exists($deletedFilesFile) ? explode("\n", file_get_contents($deletedFilesFile)) : [])); + $deletedFolders = array_unique(array_merge($deletedFolders, file_exists($deletedFoldersFile) ? explode("\n", file_get_contents($deletedFoldersFile)) : [])); + $renamedFilesRows = array_unique(array_merge($renamedFilesRows, file_exists($renamedFilesFile) ? explode("\n", file_get_contents($renamedFilesFile)) : [])); +} + +asort($deletedFiles); +rsort($deletedFolders); +asort($renamedFilesRows); + +$deletedFilesRowsAdd = []; +$deletedFilesRowsRemove = []; +$deletedFoldersRowsAdd = []; +$deletedFoldersRowsRemove = []; +$renamedFilesRowsAdd = []; +$renamedFilesRowsRemove = []; + +$hasChanges = false; +$doInit = isset($options['init']); +$useTempFile = isset($options['temp']); + +if ($useTempFile) { + $scriptFile = __DIR__ . '/tmp/script.php'; + + if (!is_file($scriptFile)) { + copy(JPATH_BASE . '/administrator/components/com_admin/script.php', $scriptFile); + } +} else { + $scriptFile = JPATH_BASE . '/administrator/components/com_admin/script.php'; +} + +if ( + !preg_match( + '/^(?P[\s\S]*?\s+public\s+function\s+deleteUnexistingFiles[\s\S]*?\$files\s*=\s*\[\n+)' + . '(?P\s+)' + . '(?P[\s\S]*?\n+)' + . '(?P\s+\];[\s\S]*?\$folders\s*=\s*\[\n+)' + . '(?P\s+)' + . '(?P[\s\S]*?\n+)' + . '(?P\s+\];[\s\S]*?\s+protected\s+function\s+fixFilenameCasing[\s\S]*?\$files\s*=\s*\[\n+)' + . '(?P\s+)' + . '(?P[\s\S]*?\n+)' + . '(?P\s+\];[\s\S]*?)$/', + file_get_contents($scriptFile), + $matchesScriptFile + ) +) { + echo PHP_EOL; + echo 'Error: Could not find relevant section in script file "' . $scriptFile . '".' . PHP_EOL; + + exit(1); +} + +if ($doInit) { + $deletedFilesOld = []; + $deletedFoldersOld = []; + $renamedFilesOld = []; +} else { + $deletedFilesOld = array_filter(preg_replace('/^\s*/', '', explode("\n", $matchesScriptFile['deletedFiles']))); + $deletedFoldersOld = array_filter(preg_replace('/^\s*/', '', explode("\n", $matchesScriptFile['deletedFolders']))); + $renamedFilesOld = array_filter(preg_replace('/^\s*/', '', explode("\n", $matchesScriptFile['renamedFiles']))); +} + +// Remove files from the deleted or renamed files classes which are added back by the "to" version +foreach ($addedFiles as $addedFile) { + if (($key = array_search($addedFile, $deletedFilesOld)) !== false) { + $deletedFilesRowsRemove[] = $addedFile . "\n"; + unset($deletedFilesOld[$key]); + + $hasChanges = true; + + continue; + } + + // Check for files which might have been renamed only + $matches = preg_grep("/^'" . preg_quote($addedFile, '/') . "'\s+=>\s+'/", $renamedFilesOld); + + if ($matches !== false) { + foreach ($matches as $key => $value) { + $renamedFilesRowsRemove[] = $value . "\n"; + unset($renamedFilesOld[$key]); + + $hasChanges = true; + } + } +} + +// Remove folders from previous results which are added back by the "to" version +foreach ($addedFolders as $addedFolder) { + if (($key = array_search($addedFolder, $deletedFoldersOld)) !== false) { + $deletedFoldersRowsRemove[] = $addedFolder . "\n"; + unset($deletedFoldersOld[$key]); + + $hasChanges = true; + } +} + +// Append current results +foreach ($deletedFiles as $deletedFile) { + if (array_search($deletedFile, $deletedFilesOld) === false) { + $deletedFilesRowsAdd[] = $deletedFile . "\n"; + + $hasChanges = true; + } +} + +foreach ($deletedFolders as $deletedFolder) { + if (array_search($deletedFolder, $deletedFoldersOld) === false) { + $deletedFoldersRowsAdd[] = $deletedFolder . "\n"; + + $hasChanges = true; + } +} + +foreach ($renamedFilesRows as $renamedFilesRow) { + if (($pos = strpos($renamedFilesRow, ' => ')) > 1) { + $renamedFileOld = trim(substr($renamedFilesRow, 0, $pos), "'"); + $renamedFileNew = trim(rtrim(substr($renamedFilesRow, $pos + 4), ','), "'"); + + $matches = preg_grep("/^'" . preg_quote($renamedFileOld, '/') . "'\s+=>\s+'" . preg_quote($renamedFileNew, '/') . "',/", $renamedFilesOld); + + if ($matches === false) { + $renamedFilesRowsAdd[] = "'" . $renamedFileOld . "' => '" . $renamedFileNew . "',\n"; + + $hasChanges = true; + } + } +} + +if (!$hasChanges) { + echo PHP_EOL; + echo 'There have been no changes for the deleted files and folders and renamed files lists.' . PHP_EOL; + + exit(0); +} + +if (\count($deletedFilesRowsRemove) > 0) { + echo PHP_EOL; + echo 'The following rows have to be removed from the deleted files list because the files were added back later:' . PHP_EOL; + + foreach ($deletedFilesRowsRemove as $row) { + echo $row; + } +} + +if (\count($deletedFoldersRowsRemove) > 0) { + echo PHP_EOL; + echo 'The following rows have to be removed from the deleted folders list because the folders were added back later:' . PHP_EOL; + + foreach ($deletedFoldersRowsRemove as $row) { + echo $row; + } +} + +if (\count($renamedFilesRowsRemove) > 0) { + echo PHP_EOL; + echo 'The following rows have to be removed from the renamed files list because the files were added back later with the old name:' . PHP_EOL; + + foreach ($renamedFilesRowsRemove as $row) { + echo $row; + } +} + +if (\count($deletedFilesRowsAdd) > 0) { + echo PHP_EOL; + echo 'The following rows have to be added to the deleted files list:' . PHP_EOL; + + foreach ($deletedFilesRowsAdd as $row) { + echo $row; + } +} + +if (\count($deletedFoldersRowsAdd) > 0) { + echo PHP_EOL; + echo 'The following rows have to be added to the deleted folders list:' . PHP_EOL; + + foreach ($deletedFoldersRowsAdd as $row) { + echo $row; + } +} + +if (\count($renamedFilesRowsAdd) > 0) { + echo PHP_EOL; + echo 'The following rows have to be added to the renamed files list:' . PHP_EOL; + + foreach ($renamedFilesRowsAdd as $row) { + echo $row; + } +} + +if (isset($options['test'])) { + echo PHP_EOL; + echo 'Test mode: Changes are not saved.' . PHP_EOL; + + exit(0); +} + +$deletedFilesOld = preg_replace("/^('|\/\/)/", $matchesScriptFile['indentDeletedFile'] . '\1', $deletedFilesOld); +$deletedFilesRowsAdd = preg_replace("/^'/", $matchesScriptFile['indentDeletedFile'] . "'", $deletedFilesRowsAdd); +$deletedFoldersOld = preg_replace("/^('|\/\/)/", $matchesScriptFile['indentDeletedFolder'] . '\1', $deletedFoldersOld); +$deletedFoldersRowsAdd = preg_replace("/^'/", $matchesScriptFile['indentDeletedFolder'] . "'", $deletedFoldersRowsAdd); +$renamedFilesOld = preg_replace("/^('|\/\/)/", $matchesScriptFile['indentRenamedFile'] . '\1', $renamedFilesOld); +$renamedFilesRowsAdd = preg_replace("/^'/", $matchesScriptFile['indentRenamedFile'] . "'", $renamedFilesRowsAdd); + +file_put_contents($scriptFile, $matchesScriptFile['preDeletedFiles']); +file_put_contents($scriptFile, implode("\n", $deletedFilesOld) . "\n", FILE_APPEND); + +if (\count($deletedFilesRowsAdd) > 0) { + file_put_contents($scriptFile, $matchesScriptFile['indentDeletedFile'] . '// ' . $currentVersionBuild . "\n", FILE_APPEND); + file_put_contents($scriptFile, $deletedFilesRowsAdd, FILE_APPEND); +} + +file_put_contents($scriptFile, $matchesScriptFile['preDeletedFolders'], FILE_APPEND); +file_put_contents($scriptFile, implode("\n", $deletedFoldersOld) . "\n", FILE_APPEND); + +if (\count($deletedFoldersRowsAdd) > 0) { + file_put_contents($scriptFile, $matchesScriptFile['indentDeletedFolder'] . '// ' . $currentVersionBuild . "\n", FILE_APPEND); + file_put_contents($scriptFile, $deletedFoldersRowsAdd, FILE_APPEND); +} + +file_put_contents($scriptFile, $matchesScriptFile['preRenamedFiles'], FILE_APPEND); +file_put_contents($scriptFile, implode("\n", $renamedFilesOld) . "\n", FILE_APPEND); + +if (\count($renamedFilesRowsAdd) > 0) { + file_put_contents($scriptFile, $matchesScriptFile['indentRenamedFile'] . '// ' . $currentVersionBuild . "\n", FILE_APPEND); + file_put_contents($scriptFile, $renamedFilesRowsAdd, FILE_APPEND); +} + +file_put_contents($scriptFile, $matchesScriptFile['post'], FILE_APPEND); From e2a6e500f0426a079a81cfdcdfe665b55f51e80d Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 7 Jan 2024 16:38:53 +0100 Subject: [PATCH 03/11] Adapt to 6.0-dev --- build/update_deleted_files.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php index 91b1ee86adc63..36f15041d90c4 100644 --- a/build/update_deleted_files.php +++ b/build/update_deleted_files.php @@ -29,9 +29,9 @@ // Change the following value to false when the previous major release has reached end of development. const PREVIOUS_CHECK = true; -const PREVIOUS_VERSION = '4.4'; +const PREVIOUS_VERSION = '5.1'; -const PREVIOUS_BRANCH = '4.4-dev'; +const PREVIOUS_BRANCH = '5.1-dev'; const GITHUB_REPO = 'https://github.com/joomla/joomla-cms.git'; @@ -221,7 +221,7 @@ function usage($command) echo 'Runing build script for previous major version.' . PHP_EOL; echo PHP_EOL; - system('php ./build/build.php --remote=' . ($options['prevRemote'] ?? 'HEAD') . ' --exclude-gzip --exclude-bzip2'); + system('php ./build/build.php --remote=' . ($options['prevRemote'] ?? 'HEAD') . ' --exclude-gzip --exclude-zstd'); chdir(__DIR__); From 4fd078e207c3271fb0e43f0c90bbce78adc04df3 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Tue, 18 Jun 2024 12:44:45 +0200 Subject: [PATCH 04/11] Change previous version from 5.1 to 5.2 --- build/update_deleted_files.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php index 36f15041d90c4..490ea7b688495 100644 --- a/build/update_deleted_files.php +++ b/build/update_deleted_files.php @@ -29,9 +29,9 @@ // Change the following value to false when the previous major release has reached end of development. const PREVIOUS_CHECK = true; -const PREVIOUS_VERSION = '5.1'; +const PREVIOUS_VERSION = '5.2'; -const PREVIOUS_BRANCH = '5.1-dev'; +const PREVIOUS_BRANCH = '5.2-dev'; const GITHUB_REPO = 'https://github.com/joomla/joomla-cms.git'; From bd619fd4d962515a42a6287c71c0b73016b3f27b Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Thu, 3 Oct 2024 11:37:28 +0200 Subject: [PATCH 05/11] Change previous version from 5.2 to 5.3 --- build/update_deleted_files.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php index 490ea7b688495..d6066f5696f94 100644 --- a/build/update_deleted_files.php +++ b/build/update_deleted_files.php @@ -29,9 +29,9 @@ // Change the following value to false when the previous major release has reached end of development. const PREVIOUS_CHECK = true; -const PREVIOUS_VERSION = '5.2'; +const PREVIOUS_VERSION = '5.3'; -const PREVIOUS_BRANCH = '5.2-dev'; +const PREVIOUS_BRANCH = '5.3-dev'; const GITHUB_REPO = 'https://github.com/joomla/joomla-cms.git'; From 98328e46f71477f19b6d9349930ef28f0d287109 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Fri, 28 Feb 2025 15:03:21 +0100 Subject: [PATCH 06/11] Change previous version from 5.3 to 5.4 --- build/update_deleted_files.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php index d6066f5696f94..0149d9f49aa8c 100644 --- a/build/update_deleted_files.php +++ b/build/update_deleted_files.php @@ -29,9 +29,9 @@ // Change the following value to false when the previous major release has reached end of development. const PREVIOUS_CHECK = true; -const PREVIOUS_VERSION = '5.3'; +const PREVIOUS_VERSION = '5.4'; -const PREVIOUS_BRANCH = '5.3-dev'; +const PREVIOUS_BRANCH = '5.4-dev'; const GITHUB_REPO = 'https://github.com/joomla/joomla-cms.git'; From be40556ebb3ace74f8d2bafced013d852fff66b9 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Fri, 28 Feb 2025 15:29:19 +0100 Subject: [PATCH 07/11] Add excluded folders from PR #44321 --- build/deleted_file_check.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/deleted_file_check.php b/build/deleted_file_check.php index e9e82d23a08a7..1b788c3bdc758 100644 --- a/build/deleted_file_check.php +++ b/build/deleted_file_check.php @@ -103,10 +103,10 @@ function usage($command) $excludedFolders = [ 'images/sampledata', 'installation', - '/media/plg_captcha_recaptcha', - '/media/plg_captcha_recaptcha_invisible', - '/media/plg_behaviour_compat', - '/plugins/behaviour/compat', + 'media/plg_captcha_recaptcha', + 'media/plg_captcha_recaptcha_invisible', + 'media/plg_behaviour_compat', + 'plugins/behaviour/compat', ]; /** From 64ceb5b5c07c6b4364bb88bf20feadf272a4799a Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 15 Jun 2025 15:37:32 +0200 Subject: [PATCH 08/11] Add exceptions from PR #45512 . --- build/deleted_file_check.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/deleted_file_check.php b/build/deleted_file_check.php index 1b788c3bdc758..466b711f5e9c7 100644 --- a/build/deleted_file_check.php +++ b/build/deleted_file_check.php @@ -103,9 +103,10 @@ function usage($command) $excludedFolders = [ 'images/sampledata', 'installation', + 'media/com_guidedtours/images', + 'media/plg_behaviour_compat', 'media/plg_captcha_recaptcha', 'media/plg_captcha_recaptcha_invisible', - 'media/plg_behaviour_compat', 'plugins/behaviour/compat', ]; From 3b7ab4acff2fbe9021bec02a2d695f66e6fb2d29 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Tue, 16 Sep 2025 21:35:43 +0200 Subject: [PATCH 09/11] Revert "Add exceptions from PR #45512 ." This reverts commit 23bdec8031efb66b50f2de013e8b098a2a9611e1. --- build/deleted_file_check.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/deleted_file_check.php b/build/deleted_file_check.php index 466b711f5e9c7..1b788c3bdc758 100644 --- a/build/deleted_file_check.php +++ b/build/deleted_file_check.php @@ -103,10 +103,9 @@ function usage($command) $excludedFolders = [ 'images/sampledata', 'installation', - 'media/com_guidedtours/images', - 'media/plg_behaviour_compat', 'media/plg_captcha_recaptcha', 'media/plg_captcha_recaptcha_invisible', + 'media/plg_behaviour_compat', 'plugins/behaviour/compat', ]; From 0cf10fea9d157bb989d233991c211629c5682006 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Wed, 17 Sep 2025 11:08:56 +0200 Subject: [PATCH 10/11] Fix typos --- build/update_deleted_files.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php index 0149d9f49aa8c..74a5339754f35 100644 --- a/build/update_deleted_files.php +++ b/build/update_deleted_files.php @@ -88,7 +88,7 @@ function usage($command) $currentVersionPackage = $files[0]; } else { echo PHP_EOL; - echo 'Runing build script for current version.' . PHP_EOL; + echo 'Running build script for current version.' . PHP_EOL; echo PHP_EOL; system('php ./build.php --remote=' . ($options['currRemote'] ?? 'HEAD') . ' --exclude-gzip --exclude-zstd'); @@ -107,7 +107,7 @@ function usage($command) $currentVersionPackage = $packagesPath . '/' . basename($currentMajorDownload); if (!isset($options['reuse']) || !is_file($currentVersionPackage)) { - // Donwload package. + // Download package. echo PHP_EOL; echo 'Downloading package "' . $currentMajorDownload . '".' . PHP_EOL; @@ -218,7 +218,7 @@ function usage($command) system($systemGit . ' clone -b ' . $prevMajorBranch . ' ' . GITHUB_REPO . ' .'); echo PHP_EOL; - echo 'Runing build script for previous major version.' . PHP_EOL; + echo 'Running build script for previous major version.' . PHP_EOL; echo PHP_EOL; system('php ./build/build.php --remote=' . ($options['prevRemote'] ?? 'HEAD') . ' --exclude-gzip --exclude-zstd'); @@ -240,7 +240,7 @@ function usage($command) $previousMajorPackage = $previousBuildPackagePath . '/' . basename($previousMajorDownload); if (!isset($options['reuse']) || !is_file($previousMajorPackage)) { - // Donwload package. + // Download package. echo PHP_EOL; echo 'Downloading package "' . $previousMajorDownload . '".' . PHP_EOL; From 1629d38efb3c50eb1eef4384f8e9cb207d3ae123 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sat, 18 Oct 2025 17:26:24 +0200 Subject: [PATCH 11/11] Fix previous major package download --- build/update_deleted_files.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build/update_deleted_files.php b/build/update_deleted_files.php index 74a5339754f35..efe9291503904 100644 --- a/build/update_deleted_files.php +++ b/build/update_deleted_files.php @@ -237,14 +237,16 @@ function usage($command) } } else { // Use download URL: Check if there is a saved package from a previous download. - $previousMajorPackage = $previousBuildPackagePath . '/' . basename($previousMajorDownload); + $previousMajorPackage = $previousBuildPackagePath . '/' . preg_replace('/\?.*$/', '', basename($previousMajorDownload)); if (!isset($options['reuse']) || !is_file($previousMajorPackage)) { + @mkdir($previousBuildPackagePath, 0755, true); + // Download package. echo PHP_EOL; echo 'Downloading package "' . $previousMajorDownload . '".' . PHP_EOL; - system('curl -L -o ' . $previousMajorPackage . ' ' . $previousMajorDownload); + system('curl -L -o "' . $previousMajorPackage . '" ' . $previousMajorDownload); } if (!is_file($previousMajorPackage)) {