From 51c356ea516f084d16aba3996151f986ac0d0855 Mon Sep 17 00:00:00 2001 From: Steven Rombauts Date: Tue, 12 Dec 2017 11:34:23 +0000 Subject: [PATCH 1/3] #36: Split _clone() method into _clone() and _archive() --- bin/.files/cache/.gitkeep | 0 .../Console/Command/Site/Create.php | 11 +- .../Console/Command/Site/Download.php | 162 ++++++++++++------ 3 files changed, 120 insertions(+), 53 deletions(-) delete mode 100644 bin/.files/cache/.gitkeep diff --git a/bin/.files/cache/.gitkeep b/bin/.files/cache/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Joomlatools/Console/Command/Site/Create.php b/src/Joomlatools/Console/Command/Site/Create.php index 24be6f74..310b7290 100644 --- a/src/Joomlatools/Console/Command/Site/Create.php +++ b/src/Joomlatools/Console/Command/Site/Create.php @@ -139,6 +139,12 @@ protected function configure() null, InputOption::VALUE_REQUIRED, "A YAML file consisting of serialized parameters to override JConfig." + ) + ->addOption( + 'clone', + null, + InputOption::VALUE_NONE, + 'Clone the Git repository instead of creating a copy in the target directory.' ); } @@ -192,9 +198,10 @@ public function download(InputInterface $input, OutputInterface $output) $arguments = array( 'site:download', 'site' => $this->site, - '--release' => $input->getOption('release'), + '--release' => $input->getOption('release'), '--clear-cache' => $input->getOption('clear-cache'), - '--www' => $this->www + '--www' => $this->www, + '--clone' => $input->getOption('clone') ); $repo = $input->getOption('repo'); diff --git a/src/Joomlatools/Console/Command/Site/Download.php b/src/Joomlatools/Console/Command/Site/Download.php index 922707f7..415c5830 100644 --- a/src/Joomlatools/Console/Command/Site/Download.php +++ b/src/Joomlatools/Console/Command/Site/Download.php @@ -35,6 +35,11 @@ class Download extends AbstractSite */ protected $output = null; + /** + * @var InputInterface + */ + protected $input = null; + protected function configure() { parent::configure(); @@ -67,12 +72,19 @@ protected function configure() InputOption::VALUE_REQUIRED, 'Alternative Git repository to clone. Also accepts a gzipped tar archive instead of a Git repository. To use joomlatools/platform, use --repo=platform. For Kodekit Platform, use --repo=kodekit-platform.' ) + ->addOption( + 'clone', + null, + InputOption::VALUE_NONE, + 'Clone the Git repository instead of creating a copy in the target directory.' + ) ; } protected function execute(InputInterface $input, OutputInterface $output) { $this->output = $output; + $this->input = $input; parent::execute($input, $output); @@ -98,39 +110,24 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->setVersion($input->getOption('release')); - if ($this->version != 'none') - { - $tarball = $this->_getTarball($output); - - if (!$this->_isValidTarball($tarball)) - { - if (file_exists($tarball)) { - unlink($tarball); - } - - throw new \RuntimeException(sprintf('Downloaded tar archive "%s" could not be verified. A common cause is an interrupted download: check your internet connection and try again.', basename($tarball))); - } - - if (!file_exists($this->target_dir)) { - `mkdir -p $this->target_dir`; - } - - `cd $this->target_dir; tar xzf $tarball --strip 1`; + if (strtolower($this->version) == 'none') { + return; + } - if ($this->versions->isBranch($this->version)) { - unlink($tarball); - } + if ($input->getOption('clone')) { + $this->_setupClone(); + } + else $this->_setupCopy(); - $isPlatform = Util::isPlatform($this->target_dir); + $isPlatform = Util::isPlatform($this->target_dir); - $directory = $this->target_dir. ($isPlatform ? '/web' : ''); - if (file_exists($directory.'/htaccess.txt')) { - `cp $directory/htaccess.txt $directory/.htaccess`; - } + $directory = $this->target_dir. ($isPlatform ? '/web' : ''); + if (file_exists($directory.'/htaccess.txt')) { + `cp $directory/htaccess.txt $directory/.htaccess`; + } - if ($isPlatform || Util::isKodekitPlatform($this->target_dir)) { - `cd $this->target_dir; composer --no-interaction install -q`; - } + if ($isPlatform || Util::isKodekitPlatform($this->target_dir)) { + `cd $this->target_dir; composer --no-interaction install -q`; } } @@ -200,7 +197,42 @@ public function setVersion($version) $this->version = $result; } - protected function _getTarball(OutputInterface $output) + protected function _setupCopy() + { + $tarball = $this->_getTarball(); + + if (!$this->_isValidTarball($tarball)) + { + if (file_exists($tarball)) { + unlink($tarball); + } + + throw new \RuntimeException(sprintf('Downloaded tar archive "%s" could not be verified. A common cause is an interrupted download: check your internet connection and try again.', basename($tarball))); + } + + if (!file_exists($this->target_dir)) { + `mkdir -p $this->target_dir`; + } + + `cd $this->target_dir; tar xzf $tarball --strip 1`; + + if ($this->versions->isBranch($this->version)) { + unlink($tarball); + } + } + + protected function _setupClone() + { + if (!$this->versions->isGitRepository()) { + throw new \RuntimeException(sprintf('The --clone flag requires a valid Git repository')); + } + + $repository = $this->versions->getRepository(); + + $this->_clone(); + } + + protected function _getTarball() { $tar = $this->version.'.tar.gz'; // Replace forward slashes with a dash, otherwise the path looks like it contains more subdirectories @@ -223,7 +255,14 @@ protected function _getTarball(OutputInterface $output) if (in_array($scheme, array('http', 'https')) && $isGitHub && $extension != '.git') { $result = $this->_downloadFromGitHub($cache); } - else $result = $this->_clone($cache); + else + { + $directory = $this->versions->getCacheDirectory() . '/source'; + + if ($this->_clone($directory)) { + $result = $this->_archive($directory, $cache); + } + } } else $result = $this->_download($cache); @@ -274,51 +313,72 @@ protected function _download($target) } /** - * Clone Git repository and create tarball + * Clone Git repository to $target directory * * @param $target * @return bool */ - protected function _clone($target) + protected function _clone($directory) { - if (substr($target, -3) == '.gz') { - $target = substr($target, 0, -3); - } - - $clone = $this->versions->getCacheDirectory() . '/source'; $repository = $this->versions->getRepository(); - if (!file_exists($clone)) + if (!file_exists($directory)) { $this->output->writeln("Cloning $repository - this could take a few minutes .."); - `git clone --recursive "$repository" "$clone"`; + exec(sprintf("git clone --recursive %s %s", escapeshellarg($repository), escapeshellarg($directory)), $result, $exit_code); + + if ($exit_code > 0) { + return false; + } } if ($this->versions->isBranch($this->version)) { $this->output->writeln("Fetching latest changes from $repository - this could take a few minutes .."); - `git --git-dir "$clone/.git" fetch`; + exec(sprintf("git --git-dir %s fetch", escapeshellarg("$directory/.git")), $result, $exit_code); + + if ($exit_code > 0) { + return false; + } } + + return true; + } + + /** + * Create tarball from cloned Git repository. + * + * @param $source Git repository + * @param $filename Output filename + * @return bool + */ + protected function _archive($source, $filename) + { + $repository = $this->versions->getRepository(); $this->output->writeln("Creating $this->version archive for $repository .."); - `git --git-dir "$clone/.git" archive --prefix=base/ $this->version >"$target"`; + if (substr($filename, -3) == '.gz') { + $filename = substr($filename, 0, -3); + } + + `git --git-dir "$source/.git" archive --prefix=base/ $this->version >"$filename"`; // Make sure to include submodules - if (file_exists("$clone/.gitmodules")) + if (file_exists("$source/.gitmodules")) { - exec("cd $clone && (git submodule foreach) | while read entering path; do echo \$path; done", $output, $return_var); + exec("cd $source && (git submodule foreach) | while read entering path; do echo \$path; done", $result, $return_var); - if (is_array($output)) + if (is_array($result)) { - foreach ($output as $module) + foreach ($result as $module) { $module = trim($module, "'"); - $path = "$clone/$module"; + $path = "$source/$module"; - $cmd = "cd $path && git archive --prefix=base/$module/ HEAD > /tmp/$module.tar && tar --concatenate --file=\"$target\" /tmp/$module.tar"; + $cmd = "cd $path && git archive --prefix=base/$module/ HEAD > /tmp/$module.tar && tar --concatenate --file=\"$filename\" /tmp/$module.tar"; exec($cmd); @unlink("/tmp/$module.tar"); @@ -326,9 +386,9 @@ protected function _clone($target) } } - `gzip $target`; + `gzip $filename`; - return (bool) @filesize("$target.gz"); + return (bool) @filesize("$filename.gz"); } /** @@ -350,7 +410,7 @@ protected function _isValidTarball($file) foreach ($commands as $command) { - exec($command, $output, $returnVal); + exec($command, $result, $returnVal); if ($returnVal != 0) { return false; From ad41c45b0b839847cdc0c38ba6ff4d71ba9d19f8 Mon Sep 17 00:00:00 2001 From: Steven Rombauts Date: Tue, 12 Dec 2017 12:06:14 +0000 Subject: [PATCH 2/3] #36: Implement direct clone functionality --- .../Console/Command/Site/Create.php | 5 ++-- .../Console/Command/Site/Download.php | 24 ++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Joomlatools/Console/Command/Site/Create.php b/src/Joomlatools/Console/Command/Site/Create.php index 310b7290..08853cee 100644 --- a/src/Joomlatools/Console/Command/Site/Create.php +++ b/src/Joomlatools/Console/Command/Site/Create.php @@ -143,8 +143,9 @@ protected function configure() ->addOption( 'clone', null, - InputOption::VALUE_NONE, - 'Clone the Git repository instead of creating a copy in the target directory.' + InputOption::VALUE_OPTIONAL, + 'Clone the Git repository instead of creating a copy in the target directory. Use --clone=shallow for a shallow clone or leave empty.', + true ); } diff --git a/src/Joomlatools/Console/Command/Site/Download.php b/src/Joomlatools/Console/Command/Site/Download.php index 415c5830..f4d535eb 100644 --- a/src/Joomlatools/Console/Command/Site/Download.php +++ b/src/Joomlatools/Console/Command/Site/Download.php @@ -75,8 +75,8 @@ protected function configure() ->addOption( 'clone', null, - InputOption::VALUE_NONE, - 'Clone the Git repository instead of creating a copy in the target directory.' + InputOption::VALUE_OPTIONAL, + 'Clone the Git repository instead of creating a copy in the target directory. Use --clone=shallow for a shallow clone or leave empty.' ) ; } @@ -227,9 +227,7 @@ protected function _setupClone() throw new \RuntimeException(sprintf('The --clone flag requires a valid Git repository')); } - $repository = $this->versions->getRepository(); - - $this->_clone(); + $this->_clone($this->target_dir, $this->version); } protected function _getTarball() @@ -315,10 +313,11 @@ protected function _download($target) /** * Clone Git repository to $target directory * - * @param $target + * @param $target Target directory + * @param $tag Tag or branch to check out * @return bool */ - protected function _clone($directory) + protected function _clone($directory, $tag = false) { $repository = $this->versions->getRepository(); @@ -326,7 +325,16 @@ protected function _clone($directory) { $this->output->writeln("Cloning $repository - this could take a few minutes .."); - exec(sprintf("git clone --recursive %s %s", escapeshellarg($repository), escapeshellarg($directory)), $result, $exit_code); + $option = strtolower($this->input->getOption('clone')); + $args = $option == 'shallow' ? '--depth 1' : ''; + + if (is_string($tag)) { + $args .= sprintf(' --branch %s', escapeshellarg($tag)); + } + + $command = sprintf("git clone %s --recursive %s %s", $args, escapeshellarg($repository), escapeshellarg($directory)); + + exec($command, $result, $exit_code); if ($exit_code > 0) { return false; From acbf9fab42274ab9b2dd49925689544c1c4be0e4 Mon Sep 17 00:00:00 2001 From: Steven Rombauts Date: Tue, 12 Dec 2017 12:14:08 +0000 Subject: [PATCH 3/3] #36: Fix --clone option default value The InputOption::VALUE_OPTIONAL option mode will always return null if you don't set a default value, but returning any other value makes it impossible to correctly determine whether the flag was set or not. Solution is to rely on $input->hasParameterOption() instead. See: https://github.com/symfony/symfony/issues/11572\#issuecomment-197929086 --- src/Joomlatools/Console/Command/Site/Create.php | 7 +++++-- src/Joomlatools/Console/Command/Site/Download.php | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Joomlatools/Console/Command/Site/Create.php b/src/Joomlatools/Console/Command/Site/Create.php index 08853cee..13222249 100644 --- a/src/Joomlatools/Console/Command/Site/Create.php +++ b/src/Joomlatools/Console/Command/Site/Create.php @@ -201,10 +201,13 @@ public function download(InputInterface $input, OutputInterface $output) 'site' => $this->site, '--release' => $input->getOption('release'), '--clear-cache' => $input->getOption('clear-cache'), - '--www' => $this->www, - '--clone' => $input->getOption('clone') + '--www' => $this->www ); + if ($input->hasParameterOption('--clone')) { + $arguments['--clone'] = $input->getOption('clone'); + } + $repo = $input->getOption('repo'); if (!empty($repo)) { $arguments['--repo'] = $repo; diff --git a/src/Joomlatools/Console/Command/Site/Download.php b/src/Joomlatools/Console/Command/Site/Download.php index f4d535eb..b902f3a0 100644 --- a/src/Joomlatools/Console/Command/Site/Download.php +++ b/src/Joomlatools/Console/Command/Site/Download.php @@ -76,8 +76,9 @@ protected function configure() 'clone', null, InputOption::VALUE_OPTIONAL, - 'Clone the Git repository instead of creating a copy in the target directory. Use --clone=shallow for a shallow clone or leave empty.' - ) + 'Clone the Git repository instead of creating a copy in the target directory. Use --clone=shallow for a shallow clone or leave empty.', + true + ); ; } @@ -114,7 +115,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return; } - if ($input->getOption('clone')) { + if ($input->hasParameterOption('--clone')) { $this->_setupClone(); } else $this->_setupCopy(); @@ -333,7 +334,7 @@ protected function _clone($directory, $tag = false) } $command = sprintf("git clone %s --recursive %s %s", $args, escapeshellarg($repository), escapeshellarg($directory)); - + exec($command, $result, $exit_code); if ($exit_code > 0) {