Hello community, here is the log from the commit of package platformsh-cli for openSUSE:Factory checked in at 2019-07-28 10:22:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/platformsh-cli (Old) and /work/SRC/openSUSE:Factory/.platformsh-cli.new.4126 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "platformsh-cli" Sun Jul 28 10:22:32 2019 rev:77 rq:719006 version:3.45.0 Changes: -------- --- /work/SRC/openSUSE:Factory/platformsh-cli/platformsh-cli.changes 2019-07-15 22:44:04.179901522 +0200 +++ /work/SRC/openSUSE:Factory/.platformsh-cli.new.4126/platformsh-cli.changes 2019-07-28 10:22:34.784568003 +0200 @@ -1,0 +2,13 @@ +Fri Jul 26 20:44:09 UTC 2019 - jimmy@boombatower.com + +- Update to version 3.45.0: + * Release v3.45.0 + * Update client to only enable gzip if the zlib extension is loaded + * Update client to enable gzipped API responses + * In mount:upload, convert OS X filename characters using --iconv + * Add --all option to mount:download + * Refactor MountCommandBase + * Do not fetch an empty commit hash (after parents notation) + * Installer: fix check for git on Windows (#824) + +------------------------------------------------------------------- Old: ---- platformsh-cli-3.44.0.tar.xz New: ---- platformsh-cli-3.45.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ platformsh-cli.spec ++++++ --- /var/tmp/diff_new_pack.Ln284m/_old 2019-07-28 10:22:35.516567987 +0200 +++ /var/tmp/diff_new_pack.Ln284m/_new 2019-07-28 10:22:35.520567987 +0200 @@ -17,7 +17,7 @@ Name: platformsh-cli -Version: 3.44.0 +Version: 3.45.0 Release: 0 Summary: Tool for managing Platform.sh services from the command line # See licenses.txt for dependency licenses. ++++++ _service ++++++ --- /var/tmp/diff_new_pack.Ln284m/_old 2019-07-28 10:22:35.552567986 +0200 +++ /var/tmp/diff_new_pack.Ln284m/_new 2019-07-28 10:22:35.556567986 +0200 @@ -2,7 +2,7 @@ <service name="tar_scm" mode="disabled"> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> - <param name="revision">refs/tags/v3.44.0</param> + <param name="revision">refs/tags/v3.45.0</param> <param name="url">git://github.com/platformsh/platformsh-cli.git</param> <param name="scm">git</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.Ln284m/_old 2019-07-28 10:22:35.572567985 +0200 +++ /var/tmp/diff_new_pack.Ln284m/_new 2019-07-28 10:22:35.572567985 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">git://github.com/platformsh/platformsh-cli.git</param> - <param name="changesrevision">49c17dee8c54c4b64794b787d6d2a09e0372413d</param> + <param name="changesrevision">13bfd296b0a6d6fed21b5ca285cd387d149e6df5</param> </service> </servicedata> ++++++ licenses.txt ++++++ --- /var/tmp/diff_new_pack.Ln284m/_old 2019-07-28 10:22:35.604567985 +0200 +++ /var/tmp/diff_new_pack.Ln284m/_new 2019-07-28 10:22:35.604567985 +0200 @@ -16,7 +16,7 @@ padraic/phar-updater v1.0.6 BSD-3-Clause paragonie/random_compat v2.0.18 MIT pjcdawkins/guzzle-oauth2-plugin v2.2.0 MIT -platformsh/client v0.27.0 MIT +platformsh/client v0.28.1 MIT platformsh/console-form v0.0.23 MIT psr/container 1.0.0 MIT psr/log 1.1.0 MIT ++++++ platformsh-cli-3.44.0.tar.xz -> platformsh-cli-3.45.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/composer.json new/platformsh-cli-3.45.0/composer.json --- old/platformsh-cli-3.44.0/composer.json 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/composer.json 2019-07-25 14:45:39.000000000 +0200 @@ -8,7 +8,7 @@ "guzzlehttp/guzzle": "^5.3", "guzzlehttp/ringphp": "^1.1", "platformsh/console-form": ">=0.0.22 <2.0", - "platformsh/client": ">=0.27.0 <2.0", + "platformsh/client": ">=0.28.1 <2.0", "symfony/console": "^3.0 >=3.2", "symfony/yaml": "^3.0 || ^2.6", "symfony/finder": "^3.0", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/composer.lock new/platformsh-cli-3.45.0/composer.lock --- old/platformsh-cli-3.44.0/composer.lock 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/composer.lock 2019-07-25 14:45:39.000000000 +0200 @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c1ff0b9b2fc1425569ea1ea6f811defa", + "content-hash": "3b15e017599176f45d3e1b9094dc9a81", "packages": [ { "name": "cocur/slugify", @@ -663,16 +663,16 @@ }, { "name": "platformsh/client", - "version": "v0.27.0", + "version": "v0.28.1", "source": { "type": "git", "url": "https://github.com/platformsh/platformsh-client-php.git", - "reference": "317b4db1bddc86dfa63376fc92bd9c98cab78c38" + "reference": "01bbf0289adad03102179412f710fdc7527fab60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/317b4d...", - "reference": "317b4db1bddc86dfa63376fc92bd9c98cab78c38", + "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/01bbf0...", + "reference": "01bbf0289adad03102179412f710fdc7527fab60", "shasum": "" }, "require": { @@ -702,7 +702,7 @@ } ], "description": "Platform.sh API client", - "time": "2019-06-12T08:13:33+00:00" + "time": "2019-07-25T12:06:41+00:00" }, { "name": "platformsh/console-form", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/dist/installer.php new/platformsh-cli-3.45.0/dist/installer.php --- old/platformsh-cli-3.44.0/dist/installer.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/dist/installer.php 2019-07-25 14:45:39.000000000 +0200 @@ -93,7 +93,12 @@ 'Git is installed.', 'Warning: Git will be needed.', function () { - exec('command -v git', $output, $return_var); + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $command = 'where git'; + } else { + $command = 'command -v git'; + } + exec($command, $output, $return_var); return $return_var === 0; }, false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/dist/manifest.json new/platformsh-cli-3.45.0/dist/manifest.json --- old/platformsh-cli-3.44.0/dist/manifest.json 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/dist/manifest.json 2019-07-25 14:45:39.000000000 +0200 @@ -17,10 +17,10 @@ }, { "name": "platform.phar", - "sha1": "46d60cc2b9a106e6cc95d88a9051997979af6acb", - "sha256": "f1620dfd149fd17071c7bb538eb0b8ccb847d29dd13169ace67ceab8c2a63585", - "url": "https://github.com/platformsh/platformsh-cli/releases/download/v3.44.0/platf...", - "version": "3.44.0", + "sha1": "d325f44a66e8187bf27fcb5d60f6565d0d9aee5c", + "sha256": "5056bf2b35968c157d9f93b667fe621b3339e0531c0fb54be63b3ef53d6e0756", + "url": "https://github.com/platformsh/platformsh-cli/releases/download/v3.45.0/platf...", + "version": "3.45.0", "php": { "min": "5.5.9" }, @@ -208,6 +208,11 @@ "notes": "New features:\n\n* Allow the `app:config` command to read from PLATFORM_APPLICATION in the\n local environment.\n* Improvements to the `environment:url` (`url`) command:\n * Read URLs from PLATFORM_ROUTES in the local environment.\n * Always prefer the primary route URL when sorting URLs.\n * Add a --primary option, to print or open only the primary route URL.\n * Just print URLs (without interaction) when there is no display/browser\n available.\n\nOther changes:\n\n* Prefer the primary route as the site URL (for Drush aliases, etc.).\n* Use embedded user account information if available in the access API (small\n performance improvement).\n* Fix \"Failed to decode\" in the `relationships` command when there are no\n relationships.\n* Adapt `welcome` command for offline-on-container uses. If you install the CLI\n into your own Platform.sh project, running `platform` on its own now gives\n you a list of useful commands that work \"offline\" without needing to\n configure an API token.\n* Do not require login for the `self:stats` command.\n* Improve app/worker choice message.\n* Clearer error for no config (`.platform.app.yaml`) file.\n* Match user email addresses case-insensitively. This fixes all user commands\n that need an email address (user:add, user:get, user:update and user:delete).", "show from": "3.43.0", "hide from": "3.44.0" + }, + { + "notes": "New features:\n\n* Add --all (-a) option to mount:download command. This lets you download files\n from all of an application's mounts.\n* Enable gzip encoding in all API requests, if the zlib PHP extension is\n available. This should result in a performance improvement, particularly for\n slow connections or API responses containing a lot of data (e.g. the\n activity:list or environment:list commands).\n\nOther changes:\n\n* In mount:upload, convert OS X filename characters using rsync's `--iconv`.\n* Small bug fix for commit and repo commands: do not fetch an empty commit\n hash (after stripping commit parents notation).\n* Installer: fix check for git on Windows.", + "show from": "3.44.0", + "hide from": "3.45.0" } ] } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/services.yaml new/platformsh-cli-3.45.0/services.yaml --- old/platformsh-cli-3.44.0/services.yaml 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/services.yaml 2019-07-25 14:45:39.000000000 +0200 @@ -97,6 +97,10 @@ class: '\Platformsh\Cli\Service\Relationships' arguments: ['@remote_env_vars'] + rsync: + class: '\Platformsh\Cli\Service\Rsync' + arguments: ['@shell'] + self_updater: class: '\Platformsh\Cli\Service\SelfUpdater' arguments: ['@input', '@output', '@config', '@question_helper'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Command/Mount/MountCommandBase.php new/platformsh-cli-3.45.0/src/Command/Mount/MountCommandBase.php --- old/platformsh-cli-3.44.0/src/Command/Mount/MountCommandBase.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Command/Mount/MountCommandBase.php 1970-01-01 01:00:00.000000000 +0100 @@ -1,100 +0,0 @@ - $definition) { - if ($definition['source'] === 'local' && isset($definition['source_path'])) { - $options[$path] = sprintf('<question>%s</question> (shared:files/%s)', $path, $definition['source_path']); - } else { - $options[$path] = sprintf('<question>%s</question>: %s', $path, $definition['source']); - } - } - - return $options; - } - - /** - * Validate a directory argument. - * - * @param string $directory - * @param bool $writable - */ - protected function validateDirectory($directory, $writable = false) - { - if (!is_dir($directory)) { - throw new \InvalidArgumentException(sprintf('Directory not found: %s', $directory)); - } elseif (!is_readable($directory)) { - throw new \InvalidArgumentException(sprintf('Directory not readable: %s', $directory)); - } elseif ($writable && !is_writable($directory)) { - throw new \InvalidArgumentException(sprintf('Directory not writable: %s', $directory)); - } - } - - /** - * Push the local contents to the chosen mount. - * - * @param string $sshUrl - * @param string $mountPath - * @param string $localPath - * @param bool $up - * @param array $options - */ - protected function runSync($sshUrl, $mountPath, $localPath, $up, array $options = []) - { - /** @var \Platformsh\Cli\Service\Shell $shell */ - $shell = $this->getService('shell'); - - $params = ['rsync', '--archive', '--compress', '--human-readable']; - - if ($this->stdErr->isVeryVerbose()) { - $params[] = '-vv'; - } elseif (!$this->stdErr->isQuiet()) { - $params[] = '-v'; - } - - if ($up) { - $params[] = rtrim($localPath, '/') . '/'; - $params[] = sprintf('%s:%s', $sshUrl, $mountPath); - } else { - $params[] = sprintf('%s:%s/', $sshUrl, $mountPath); - $params[] = $localPath; - } - - if (!empty($options['delete'])) { - $params[] = '--delete'; - } - foreach (['exclude', 'include'] as $option) { - if (!empty($options[$option])) { - foreach ($options[$option] as $value) { - $params[] = '--' . $option . '=' . $value; - } - } - } - - $start = microtime(true); - $shell->execute($params, null, true, false, [], null); - - $this->stdErr->writeln(sprintf(' time: %ss', number_format(microtime(true) - $start, 2)), OutputInterface::VERBOSITY_NORMAL); - - if ($up) { - $this->stdErr->writeln('The upload completed successfully.'); - } else { - $this->stdErr->writeln('The download completed successfully.'); - } - } -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Command/Mount/MountDownloadCommand.php new/platformsh-cli-3.45.0/src/Command/Mount/MountDownloadCommand.php --- old/platformsh-cli-3.44.0/src/Command/Mount/MountDownloadCommand.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Command/Mount/MountDownloadCommand.php 2019-07-25 14:45:39.000000000 +0200 @@ -2,14 +2,17 @@ namespace Platformsh\Cli\Command\Mount; +use Platformsh\Cli\Command\CommandBase; use Platformsh\Cli\Local\LocalApplication; +use Platformsh\Cli\Model\RemoteContainer\App; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; -class MountDownloadCommand extends MountCommandBase +class MountDownloadCommand extends CommandBase { + private $localApps; /** * {@inheritdoc} @@ -19,8 +22,10 @@ $this ->setName('mount:download') ->setDescription('Download files from a mount, using rsync') + ->addOption('all', 'a', InputOption::VALUE_NONE, 'Download from all mounts') ->addOption('mount', 'm', InputOption::VALUE_REQUIRED, 'The mount (as an app-relative path)') - ->addOption('target', null, InputOption::VALUE_REQUIRED, 'The directory to which files will be downloaded') + ->addOption('target', null, InputOption::VALUE_REQUIRED, 'The directory to which files will be downloaded. If --all is used, the mount path will be appended') + ->addOption('source-path', null, InputOption::VALUE_NONE, "Use the mount's source path (rather than the mount path) as a subdirectory of the target, when --all is used") ->addOption('delete', null, InputOption::VALUE_NONE, 'Whether to delete extraneous files in the target directory') ->addOption('exclude', null, InputOption::VALUE_IS_ARRAY|InputOption::VALUE_REQUIRED, 'File(s) to exclude from the download (pattern)') ->addOption('include', null, InputOption::VALUE_IS_ARRAY|InputOption::VALUE_REQUIRED, 'File(s) to include in the download (pattern)') @@ -37,6 +42,7 @@ { $this->validateInput($input); + /** @var App $container */ $container = $this->selectRemoteContainer($input); $mounts = $container->getMounts(); @@ -54,52 +60,57 @@ /** @var \Platformsh\Cli\Service\Filesystem $fs */ $fs = $this->getService('fs'); + $all = $input->getOption('all'); + if ($input->getOption('mount')) { + if ($all) { + $this->stdErr->writeln('You cannot combine the <error>--mount</error> option with <error>--all</error>.'); + + return 1; + } + $mountPath = $mountService->matchMountPath($input->getOption('mount'), $mounts); - } elseif ($input->isInteractive()) { - $mountPath = $questionHelper->choose( - $this->getMountsAsOptions($mounts), + } elseif (!$all && $input->isInteractive()) { + $mountOptions = []; + foreach ($mounts as $path => $definition) { + if ($definition['source'] === 'local') { + $mountOptions[$path] = sprintf('<question>%s</question>', $path); + } else { + $mountOptions[$path] = sprintf('<question>%s</question>: %s', $path, $definition['source']); + } + } + $mountOptions['\\ALL'] = 'All mounts'; + + $choice = $questionHelper->choose( + $mountOptions, 'Enter a number to choose a mount to download from:' ); - } else { + if ($choice === '\\ALL') { + $all = true; + } else { + $mountPath = $choice; + } + } elseif (!$all) { $this->stdErr->writeln('The <error>--mount</error> option must be specified (in non-interactive mode).'); return 1; } $target = null; - $defaultTarget = null; if ($input->getOption('target')) { $target = $input->getOption('target'); - } elseif ($projectRoot = $this->getProjectRoot()) { - $sharedMounts = $mountService->getSharedFileMounts($mounts); - if (isset($sharedMounts[$mountPath])) { - if (file_exists($projectRoot . '/' . $this->config()->get('local.shared_dir') . '/' . $sharedMounts[$mountPath])) { - $defaultTarget = $projectRoot . '/' . $this->config()->get('local.shared_dir') . '/' . $sharedMounts[$mountPath]; - } - } - - $applications = LocalApplication::getApplications($projectRoot, $this->config()); - $appPath = $projectRoot; - foreach ($applications as $path => $candidateApp) { - if ($candidateApp->getName() === $container->getName()) { - $appPath = $path; - break; - } - } - if (is_dir($appPath . '/' . $mountPath)) { - $defaultTarget = $appPath . '/' . $mountPath; - } } - if (empty($target)) { + if (empty($target) && $input->isInteractive()) { $questionText = 'Target directory'; + $defaultTarget = isset($mountPath) ? $this->getDefaultTarget($container, $mountPath) : '.'; if ($defaultTarget !== null) { $formattedDefaultTarget = $fs->formatPathForDisplay($defaultTarget); $questionText .= ' <question>[' . $formattedDefaultTarget . ']</question>'; } $questionText .= ': '; $target = $questionHelper->ask($input, $this->stdErr, new Question($questionText, $defaultTarget)); + $this->stdErr->writeln(''); } if (empty($target)) { @@ -114,26 +125,151 @@ if (!$questionHelper->confirm(sprintf('Directory not found: <comment>%s</comment>. Do you want to create it?', $target))) { return 1; } + $this->stdErr->writeln(''); } else { - $this->validateDirectory($target, true); + $fs->validateDirectory($target, true); } - $confirmText = sprintf( - "\nDownloading files from the remote mount <comment>%s</comment> to <comment>%s</comment>" - . "\n\nAre you sure you want to continue?", - $mountPath, - $fs->formatPathForDisplay($target) - ); - if (!$questionHelper->confirm($confirmText)) { - return 1; - } + /** @var \Platformsh\Cli\Service\Rsync $rsync */ + $rsync = $this->getService('rsync'); - $this->runSync($container->getSshUrl(), $mountPath, $target, false, [ + $rsyncOptions = [ 'delete' => $input->getOption('delete'), 'exclude' => $input->getOption('exclude'), 'include' => $input->getOption('include'), - ]); + 'verbose' => $output->isVeryVerbose(), + 'quiet' => $output->isQuiet(), + ]; + $sshUrl = $container->getSshUrl(); + + if ($all) { + $confirmText = sprintf( + 'Downloading files from all remote mounts to <comment>%s</comment>' + . "\n\nAre you sure you want to continue?", + $fs->formatPathForDisplay($target) + ); + if (!$questionHelper->confirm($confirmText)) { + return 1; + } + + $useSourcePath = $input->getOption('source-path'); + + foreach ($mounts as $mountPath => $definition) { + $this->stdErr->writeln(''); + $mountSpecificTarget = $target . '/' . $mountPath; + if ($useSourcePath) { + if (isset($definition['source_path'])) { + $mountSpecificTarget = $target . '/' . trim($definition['source_path'], '/'); + } else { + $this->stdErr->writeln('No source path defined for mount <error>' . $mountPath . '</error>'); + } + } + $this->stdErr->writeln(sprintf( + 'Downloading files from <comment>%s</comment> to <comment>%s</comment>', + $mountPath, + $fs->formatPathForDisplay($mountSpecificTarget) + )); + $fs->mkdir($mountSpecificTarget); + $rsync->syncDown($sshUrl, $mountPath, $mountSpecificTarget, $rsyncOptions); + } + } elseif (isset($mountPath)) { + $confirmText = sprintf( + 'Downloading files from the remote mount <comment>%s</comment> to <comment>%s</comment>' + . "\n\nAre you sure you want to continue?", + $mountPath, + $fs->formatPathForDisplay($target) + ); + if (!$questionHelper->confirm($confirmText)) { + return 1; + } + + $this->stdErr->writeln(''); + $rsync->syncDown($sshUrl, $mountPath, $target, $rsyncOptions); + } else { + throw new \LogicException('Mount path not defined'); + } return 0; } + + /** + * @param \Platformsh\Cli\Model\RemoteContainer\App $app + * @param string $mountPath + * + * @return string|null + */ + private function getDefaultTarget(App $app, $mountPath) + { + /** @var \Platformsh\Cli\Service\Mount $mountService */ + $mountService = $this->getService('mount'); + + $appPath = $this->getLocalAppPath($app); + if ($appPath !== null && is_dir($appPath . '/' . $mountPath)) { + return $appPath . '/' . $mountPath; + } + + $sharedMounts = $mountService->getSharedFileMounts($app->getMounts()); + if (isset($sharedMounts[$mountPath])) { + $sharedDir = $this->getSharedDir($app); + if ($sharedDir !== null && file_exists($sharedDir . '/' . $sharedMounts[$mountPath])) { + return $sharedDir . '/' . $sharedMounts[$mountPath]; + } + } + + return null; + } + + /** + * @return LocalApplication[] + */ + private function getLocalApps() + { + if (!isset($this->localApps)) { + $this->localApps = []; + if ($projectRoot = $this->getProjectRoot()) { + $this->localApps = LocalApplication::getApplications($projectRoot, $this->config()); + } + } + + return $this->localApps; + } + + /** + * Returns the local path to an app. + * + * @param App $app + * + * @return string|null + */ + private function getLocalAppPath(App $app) + { + foreach ($this->getLocalApps() as $path => $candidateApp) { + if ($candidateApp->getName() === $app->getName()) { + return $path; + } + } + + return null; + } + + /** + * @param \Platformsh\Cli\Model\RemoteContainer\App $app + * + * @return string|null + */ + private function getSharedDir(App $app) + { + $projectRoot = $this->getProjectRoot(); + if (!$projectRoot) { + return null; + } + + $localApps = $this->getLocalApps(); + $dirname = $projectRoot . '/' . $this->config()->get('local.shared_dir'); + if (count($localApps) > 1 && is_dir($dirname)) { + $dirname .= $app->getName(); + } + + return file_exists($dirname) ? $dirname : null; + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Command/Mount/MountListCommand.php new/platformsh-cli-3.45.0/src/Command/Mount/MountListCommand.php --- old/platformsh-cli-3.44.0/src/Command/Mount/MountListCommand.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Command/Mount/MountListCommand.php 2019-07-25 14:45:39.000000000 +0200 @@ -2,12 +2,13 @@ namespace Platformsh\Cli\Command\Mount; +use Platformsh\Cli\Command\CommandBase; use Platformsh\Cli\Service\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class MountListCommand extends MountCommandBase +class MountListCommand extends CommandBase { /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Command/Mount/MountSizeCommand.php new/platformsh-cli-3.45.0/src/Command/Mount/MountSizeCommand.php --- old/platformsh-cli-3.44.0/src/Command/Mount/MountSizeCommand.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Command/Mount/MountSizeCommand.php 2019-07-25 14:45:39.000000000 +0200 @@ -2,6 +2,7 @@ namespace Platformsh\Cli\Command\Mount; +use Platformsh\Cli\Command\CommandBase; use Platformsh\Cli\Service\Ssh; use Platformsh\Cli\Service\Table; use Symfony\Component\Console\Helper\Helper; @@ -9,7 +10,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class MountSizeCommand extends MountCommandBase +class MountSizeCommand extends CommandBase { /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Command/Mount/MountUploadCommand.php new/platformsh-cli-3.45.0/src/Command/Mount/MountUploadCommand.php --- old/platformsh-cli-3.44.0/src/Command/Mount/MountUploadCommand.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Command/Mount/MountUploadCommand.php 2019-07-25 14:45:39.000000000 +0200 @@ -2,13 +2,15 @@ namespace Platformsh\Cli\Command\Mount; +use Platformsh\Cli\Command\CommandBase; use Platformsh\Cli\Local\LocalApplication; +use Platformsh\Cli\Util\OsUtil; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; -class MountUploadCommand extends MountCommandBase +class MountUploadCommand extends CommandBase { /** @@ -57,8 +59,17 @@ if ($input->getOption('mount')) { $mountPath = $mountService->matchMountPath($input->getOption('mount'), $mounts); } elseif ($input->isInteractive()) { + $options = []; + foreach ($mounts as $path => $definition) { + if ($definition['source'] === 'local') { + $options[$path] = sprintf('<question>%s</question>', $path); + } else { + $options[$path] = sprintf('<question>%s</question>: %s', $path, $definition['source']); + } + } + $mountPath = $questionHelper->choose( - $this->getMountsAsOptions($mounts), + $options, 'Enter a number to choose a mount to upload to:' ); } else { @@ -108,7 +119,10 @@ return 1; } - $this->validateDirectory($source); + $fs->validateDirectory($source); + + /** @var \Platformsh\Cli\Service\Rsync $rsync */ + $rsync = $this->getService('rsync'); $confirmText = sprintf( "\nUploading files from <comment>%s</comment> to the remote mount <comment>%s</comment>" @@ -120,11 +134,26 @@ return 1; } - $this->runSync($container->getSshUrl(), $mountPath, $source, true, [ + $rsyncOptions = [ 'delete' => $input->getOption('delete'), 'exclude' => $input->getOption('exclude'), 'include' => $input->getOption('include'), - ]); + 'verbose' => $output->isVeryVerbose(), + 'quiet' => $output->isQuiet(), + ]; + + if (OsUtil::isOsX()) { + if ($rsync->supportsConvertingFilenames() !== false) { + $this->debug('Converting filenames with special characters (utf-8-mac to utf-8)'); + $rsyncOptions['convert-mac-filenames'] = true; + } else { + $this->stdErr->writeln(''); + $this->stdErr->writeln('Warning: the installed version of <comment>rsync</comment> does not support converting filenames with special characters (the --iconv flag). You may need to upgrade rsync.'); + } + } + + $this->stdErr->writeln(''); + $rsync->syncUp($container->getSshUrl(), $source, $mountPath, $rsyncOptions); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Service/Filesystem.php new/platformsh-cli-3.45.0/src/Service/Filesystem.php --- old/platformsh-cli-3.44.0/src/Service/Filesystem.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Service/Filesystem.php 2019-07-25 14:45:39.000000000 +0200 @@ -492,4 +492,21 @@ } throw new \RuntimeException("Tar command not found"); } + + /** + * Validates a directory. + * + * @param string $directory + * @param bool $writable + */ + public function validateDirectory($directory, $writable = false) + { + if (!is_dir($directory)) { + throw new \InvalidArgumentException(sprintf('Directory not found: %s', $directory)); + } elseif (!is_readable($directory)) { + throw new \InvalidArgumentException(sprintf('Directory not readable: %s', $directory)); + } elseif ($writable && !is_writable($directory)) { + throw new \InvalidArgumentException(sprintf('Directory not writable: %s', $directory)); + } + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Service/GitDataApi.php new/platformsh-cli-3.45.0/src/Service/GitDataApi.php --- old/platformsh-cli-3.44.0/src/Service/GitDataApi.php 2019-07-10 12:59:25.000000000 +0200 +++ new/platformsh-cli-3.45.0/src/Service/GitDataApi.php 2019-07-25 14:45:39.000000000 +0200 @@ -71,6 +71,9 @@ $parents = $this->parseParents($sha); $sha = preg_replace('/[\^~].*$/', '', $sha); + if ($sha === '') { + return false; + } // Get the first commit. $commit = $this->getCommitByShaHash($environment, $sha); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.44.0/src/Service/Rsync.php new/platformsh-cli-3.45.0/src/Service/Rsync.php --- old/platformsh-cli-3.44.0/src/Service/Rsync.php 1970-01-01 01:00:00.000000000 +0100 +++ new/platformsh-cli-3.45.0/src/Service/Rsync.php 2019-07-25 14:45:39.000000000 +0200 @@ -0,0 +1,110 @@ +shell = $shellHelper ?: new Shell(); + } + + /** + * Finds whether the installed version of rsync supports the --iconv flag. + * + * @return bool|null + */ + public function supportsConvertingFilenames() + { + static $supportsIconv; + if (!isset($supportsIconv)) { + $result = $this->shell->execute(['rsync', '-h']); + if (is_string($result)) { + $supportsIconv = strpos($result, '--iconv') !== false; + } + } + + return $supportsIconv; + } + + /** + * Syncs files from a local to a remote location. + * + * @param string $sshUrl + * @param string $localPath + * @param string $remotePath + * @param array $options + */ + public function syncUp($sshUrl, $localPath, $remotePath, array $options = []) + { + $this->doSync($sshUrl, $remotePath, $localPath, true, $options); + } + + /** + * Syncs files from a remote to a local location. + * + * @param string $sshUrl + * @param string $remotePath + * @param string $localPath + * @param array $options + */ + public function syncDown($sshUrl, $remotePath, $localPath, array $options = []) + { + $this->doSync($sshUrl, $remotePath, $localPath, false, $options); + } + + /** + * Runs rsync. + * + * @param string $sshUrl + * @param string $remotePath + * @param string $localPath + * @param bool $up + * @param array $options + */ + private function doSync($sshUrl, $remotePath, $localPath, $up, array $options = []) + { + $params = ['rsync', '--archive', '--compress', '--human-readable']; + + if (!empty($options['verbose'])) { + $params[] = '-vv'; + } elseif (empty($options['quiet'])) { + $params[] = '-v'; + } + + if ($up) { + $params[] = rtrim($localPath, '/') . '/'; + $params[] = sprintf('%s:%s', $sshUrl, $remotePath); + } else { + $params[] = sprintf('%s:%s/', $sshUrl, $remotePath); + $params[] = $localPath; + } + + if (!empty($options['convert-mac-filenames'])) { + $params[] = '--iconv=utf-8-mac,utf-8'; + } + if (!empty($options['delete'])) { + $params[] = '--delete'; + } + foreach (['exclude', 'include'] as $option) { + if (!empty($options[$option])) { + foreach ($options[$option] as $value) { + $params[] = '--' . $option . '=' . $value; + } + } + } + + $this->shell->execute($params, null, true, false, [], null); + } +} ++++++ platformsh-cli-vendor.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/autoload.php new/vendor/autoload.php --- old/vendor/autoload.php 2019-07-10 21:38:44.398202600 +0200 +++ new/vendor/autoload.php 2019-07-26 22:44:12.344120655 +0200 @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInit4011949b48404cad63159961b9f979ba::getLoader(); +return ComposerAutoloaderInite7cf5b1805bce3b2279ae358e5d9e864::getLoader(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/composer/autoload_real.php new/vendor/composer/autoload_real.php --- old/vendor/composer/autoload_real.php 2019-07-10 21:38:44.398202600 +0200 +++ new/vendor/composer/autoload_real.php 2019-07-26 22:44:12.344120655 +0200 @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit4011949b48404cad63159961b9f979ba +class ComposerAutoloaderInite7cf5b1805bce3b2279ae358e5d9e864 { private static $loader; @@ -19,15 +19,15 @@ return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit4011949b48404cad63159961b9f979ba', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInite7cf5b1805bce3b2279ae358e5d9e864', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit4011949b48404cad63159961b9f979ba', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInite7cf5b1805bce3b2279ae358e5d9e864', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit4011949b48404cad63159961b9f979ba::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInite7cf5b1805bce3b2279ae358e5d9e864::getInitializer($loader)); } else { $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -48,19 +48,19 @@ $loader->register(true); if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInit4011949b48404cad63159961b9f979ba::$files; + $includeFiles = Composer\Autoload\ComposerStaticInite7cf5b1805bce3b2279ae358e5d9e864::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { - composerRequire4011949b48404cad63159961b9f979ba($fileIdentifier, $file); + composerRequiree7cf5b1805bce3b2279ae358e5d9e864($fileIdentifier, $file); } return $loader; } } -function composerRequire4011949b48404cad63159961b9f979ba($fileIdentifier, $file) +function composerRequiree7cf5b1805bce3b2279ae358e5d9e864($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/composer/autoload_static.php new/vendor/composer/autoload_static.php --- old/vendor/composer/autoload_static.php 2019-07-10 21:38:44.398202600 +0200 +++ new/vendor/composer/autoload_static.php 2019-07-26 22:44:12.344120655 +0200 @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit4011949b48404cad63159961b9f979ba +class ComposerStaticInite7cf5b1805bce3b2279ae358e5d9e864 { public static $files = array ( '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', @@ -193,9 +193,9 @@ public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit4011949b48404cad63159961b9f979ba::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit4011949b48404cad63159961b9f979ba::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit4011949b48404cad63159961b9f979ba::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInite7cf5b1805bce3b2279ae358e5d9e864::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInite7cf5b1805bce3b2279ae358e5d9e864::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInite7cf5b1805bce3b2279ae358e5d9e864::$classMap; }, null, ClassLoader::class); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/composer/installed.json new/vendor/composer/installed.json --- old/vendor/composer/installed.json 2019-07-10 21:38:43.958198678 +0200 +++ new/vendor/composer/installed.json 2019-07-26 22:44:11.940117048 +0200 @@ -680,17 +680,17 @@ }, { "name": "platformsh/client", - "version": "v0.27.0", - "version_normalized": "0.27.0.0", + "version": "v0.28.1", + "version_normalized": "0.28.1.0", "source": { "type": "git", "url": "https://github.com/platformsh/platformsh-client-php.git", - "reference": "317b4db1bddc86dfa63376fc92bd9c98cab78c38" + "reference": "01bbf0289adad03102179412f710fdc7527fab60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/317b4d...", - "reference": "317b4db1bddc86dfa63376fc92bd9c98cab78c38", + "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/01bbf0...", + "reference": "01bbf0289adad03102179412f710fdc7527fab60", "shasum": "" }, "require": { @@ -704,7 +704,7 @@ "require-dev": { "phpunit/phpunit": "~4.5" }, - "time": "2019-06-12T08:13:33+00:00", + "time": "2019-07-25T12:06:41+00:00", "type": "library", "installation-source": "dist", "autoload": { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Connection/Connector.php new/vendor/platformsh/client/src/Connection/Connector.php --- old/vendor/platformsh/client/src/Connection/Connector.php 2019-06-12 10:13:33.000000000 +0200 +++ new/vendor/platformsh/client/src/Connection/Connector.php 2019-07-25 14:06:41.000000000 +0200 @@ -65,6 +65,7 @@ 'proxy' => null, 'api_token' => null, 'api_token_type' => 'access', + 'gzip' => extension_loaded('zlib'), ]; $this->config = Collection::fromConfig($config, $defaults); @@ -385,6 +386,12 @@ 'auth' => 'oauth2', ], ]; + + if ($this->config['gzip']) { + $options['defaults']['decode_content'] = true; + $options['defaults']['headers']['Accept-Encoding'] = 'gzip'; + } + $client = $this->getGuzzleClient($options); $this->setUpCache($client);