Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify calls to list directory contents #695

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 7 additions & 75 deletions classes/TaskRunner/Upgrade/UpgradeFiles.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,62 +88,18 @@ public function run()
return true;
}

/**
* list files to upgrade and return it as array
* TODO: This method needs probably to be moved in FilesystemAdapter.
*
* @param string $dir
*
* @return array|false Number of files found, or false if param is not a folder
*/
protected function listFilesToUpgrade($dir)
{
$list = [];
if (!is_dir($dir)) {
$this->logger->error($this->translator->trans('[ERROR] %s does not exist or is not a directory.', [$dir], 'Modules.Autoupgrade.Admin'));
$this->logger->info($this->translator->trans('Nothing has been extracted. It seems the unzipping step has been skipped.', [], 'Modules.Autoupgrade.Admin'));
$this->next = 'error';

return false;
}

$allFiles = scandir($dir);
foreach ($allFiles as $file) {
$fullPath = $dir . DIRECTORY_SEPARATOR . $file;

if ($this->container->getFilesystemAdapter()->isFileSkipped(
$file,
$fullPath,
'upgrade',
$this->container->getProperty(UpgradeContainer::LATEST_PATH)
)) {
if (!in_array($file, ['.', '..'])) {
$this->logger->debug($this->translator->trans('File %s is preserved', [$file], 'Modules.Autoupgrade.Admin'));
}
continue;
}
$list[] = str_replace($this->container->getProperty(UpgradeContainer::LATEST_PATH), '', $fullPath);
if (is_dir($fullPath)) {
$list = array_merge($list, $this->listFilesToUpgrade($fullPath));
}
}

return $list;
}

/**
* upgradeThisFile.
*
* @param mixed $file
* @param mixed $orig The absolute path to the file from the upgrade archive
*/
public function upgradeThisFile($file)
public function upgradeThisFile($orig)
{
// translations_custom and mails_custom list are currently not used
// later, we could handle customization with some kind of diff functions
// for now, just copy $file in str_replace($this->latestRootDir,_PS_ROOT_DIR_)

// The path to the file from the upgrade archive
$orig = $this->container->getProperty(UpgradeContainer::LATEST_PATH) . $file;
$file = str_replace($this->container->getProperty(UpgradeContainer::LATEST_PATH), '', $orig);

// The path to the file in our prestashop directory
$dest = $this->destUpgradePath . $file;
Expand Down Expand Up @@ -263,7 +219,7 @@ protected function warmUp()
if (file_exists($filepath_list_diff)) {
$list_files_diff = $this->container->getFileConfigurationStorage()->load(UpgradeFileNames::FILES_DIFF_LIST);
// $list_files_diff now contains an array with a list of changed and deleted files.
// We only keep list of files to delete. The modified files will be listed with listFilesToUpgrade below.
// We only keep list of files to delete. The modified files will be listed in list_files_to_upgrade below.
$list_files_diff = $list_files_diff['deleted'];

// Admin folder name in this deleted files list is standard /admin/.
Expand All @@ -282,37 +238,13 @@ protected function warmUp()
}

// Now, we get the list of files that are either new or must be modified
$list_files_to_upgrade = $this->listFilesToUpgrade($newReleasePath);
if (false === $list_files_to_upgrade) {
return false;
}
$list_files_to_upgrade = $this->container->getFilesystemAdapter()->listFilesInDir(
$newReleasePath, 'upgrade', true
);

// Add our previously created list of deleted files
$list_files_to_upgrade = array_reverse(array_merge($list_files_diff, $list_files_to_upgrade));

// Now, some files should be updated as an absolute last step, if they are present in the list,
// we will put them to the end of it.
$filesToMoveToTheEnd = [
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'ClassLoader.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_classmap.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_files.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_namespaces.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_psr4.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_real.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_static.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'include_paths.php',
DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer',
DIRECTORY_SEPARATOR . 'vendor',
];

foreach ($filesToMoveToTheEnd as $file) {
if ($key = array_search($file, $list_files_to_upgrade)) {
unset($list_files_to_upgrade[$key]);
$list_files_to_upgrade[] = $file;
}
}

// Save in a serialized array in UpgradeFileNames::toUpgradeFileList, to be later used by the upgrade step itself above,
// after run() is called.
$this->container->getFileConfigurationStorage()->save($list_files_to_upgrade, UpgradeFileNames::FILES_TO_UPGRADE_LIST);
Expand Down
4 changes: 2 additions & 2 deletions classes/UpgradeTools/FileFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,13 @@ public function getFilesToIgnoreOnUpgrade()
return $this->excludeAbsoluteFilesFromUpgrade;
}

// do not copy install, neither app/config/parameters.php in case it would be present
$this->excludeAbsoluteFilesFromUpgrade = [
'/app/config/parameters.php',
'/app/config/parameters.yml',
'/install',
'/install-dev',
// TODO: Uncomment when a better management of modules upgrades is implemented
// '/modules',
'/override',
'/override/classes',
'/override/controllers',
Expand Down Expand Up @@ -173,7 +174,6 @@ public function getFilesToIgnoreOnUpgrade()
}
}

// this will exclude autoupgrade dir from admin, and autoupgrade from modules
// If set to false, we need to preserve the default themes
if (!$this->configuration->shouldUpdateDefaultTheme()) {
$this->excludeAbsoluteFilesFromUpgrade[] = '/themes/classic';
Expand Down
64 changes: 31 additions & 33 deletions classes/UpgradeTools/FilesystemAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@

namespace PrestaShop\Module\AutoUpgrade\UpgradeTools;

use FilesystemIterator;
use PrestaShop\Module\AutoUpgrade\Tools14;
use RecursiveCallbackFilterIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

class FilesystemAdapter
{
Expand Down Expand Up @@ -81,37 +85,31 @@ public static function deleteDirectory($dirname, $delete_self = true)
return Tools14::deleteDirectory($dirname, $delete_self);
}

public function listFilesInDir($dir, $way = 'backup', $list_directories = false)
/**
* @param string $dir
* @param 'upgrade'|'restore'|'backup' $way
* @param bool $listDirectories
*/
public function listFilesInDir($dir, $way, $listDirectories = false)
{
$list = [];
$dir = rtrim($dir, '/') . DIRECTORY_SEPARATOR;
$allFiles = false;
if (is_dir($dir) && is_readable($dir)) {
$allFiles = scandir($dir);
}
if (!is_array($allFiles)) {
return $list;
}
foreach ($allFiles as $file) {
$fullPath = $dir . $file;
// skip broken symbolic links
if (is_link($fullPath) && !is_readable($fullPath)) {
continue;
}
if ($this->isFileSkipped($file, $fullPath, $way)) {
continue;
}
if (is_dir($fullPath)) {
$list = array_merge($list, $this->listFilesInDir($fullPath, $way, $list_directories));
if ($list_directories) {
$list[] = $fullPath;
}
} else {
$list[] = $fullPath;
}
$files = [];
$directory = new RecursiveDirectoryIterator(
$dir,
FilesystemIterator::SKIP_DOTS | FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::CURRENT_AS_PATHNAME | FilesystemIterator::UNIX_PATHS
);
$filter = new RecursiveCallbackFilterIterator($directory, function ($current, $key, $iterator) use ($way, $dir) {
return !$this->isFileSkipped($key, $current, $way, $dir);
});
$iterator = new \RecursiveIteratorIterator(
$filter,
$listDirectories ? RecursiveIteratorIterator::SELF_FIRST : RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($iterator as $info) {
$files[] = $info;
}

return $list;
return $files;
}

/**
Expand Down Expand Up @@ -195,12 +193,12 @@ public function listSampleFiles($dir, $fileext = '.jpg')
}

/**
* bool _skipFile : check whether a file is in backup or restore skip list.
*
* @param string $file : current file or directory name eg:'.svn' , 'settings.inc.php'
* @param string $fullpath : current file or directory fullpath eg:'/home/web/www/prestashop/app/config/parameters.php'
* @param string $way : 'backup' , 'upgrade'
* @param string $temporaryWorkspace : If needed, another folder than the shop root can be used (used for releases)
* @param 'upgrade'|'restore'|'backup' $way
* @param string|null $temporaryWorkspace : If needed, another folder than the shop root can be used (used for releases)
*
* @return bool
*/
public function isFileSkipped($file, $fullpath, $way = 'backup', $temporaryWorkspace = null)
{
Expand All @@ -226,7 +224,7 @@ public function isFileSkipped($file, $fullpath, $way = 'backup', $temporaryWorks

foreach ($ignoreList as $path) {
$path = str_replace(DIRECTORY_SEPARATOR . 'admin', DIRECTORY_SEPARATOR . $this->adminSubDir, $path);
if ($fullpath === $rootpath . $path) {
if (strpos($fullpath, $rootpath . $path) === 0 && /* endsWith */ substr($fullpath, -strlen($rootpath . $path)) === $rootpath . $path) {
return true;
}
}
Expand Down