From 1c1f2c268a10f9b55bfd921b3c91dabfccdb64aa Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sat, 14 Feb 2015 22:33:50 -0700 Subject: [PATCH 1/6] beginning of dependency work --- system/src/Grav/Common/GPM/GPM.php | 17 +++- .../src/Grav/Console/Gpm/InstallCommand.php | 91 ++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/system/src/Grav/Common/GPM/GPM.php b/system/src/Grav/Common/GPM/GPM.php index fd82f3642..26f8999e8 100644 --- a/system/src/Grav/Common/GPM/GPM.php +++ b/system/src/Grav/Common/GPM/GPM.php @@ -347,7 +347,20 @@ class GPM extends Iterator $packages = ['total' => 0, 'not_found' => []]; foreach ($searches as $search) { + $repository = ''; + // if this is an object, get the search data from the key + if (is_object($search)) { + $search = (array) $search; + $key = key($search); + $repository = $search[$key]; + $search = $key; + } + if ($found = $this->findPackage($search)) { + // set override respository if provided + if ($repository) { + $found->override_repository = $repository; + } if (!isset($packages[$found->package_type])) { $packages[$found->package_type] = []; } @@ -355,7 +368,9 @@ class GPM extends Iterator $packages[$found->package_type][$found->slug] = $found; $packages['total']++; } else { - $packages['not_found'][] = $search; + $not_found = new \stdClass(); + $not_found->override_repository = $repository; + $packages['not_found'][$search] = $not_found; } } diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index 261a73f4a..f546dd3ec 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -12,6 +12,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Yaml\Yaml; + /** * Class InstallCommand @@ -42,6 +45,8 @@ class InstallCommand extends Command */ protected $tmp; + protected $local_config; + /** * */ @@ -93,6 +98,11 @@ class InstallCommand extends Command $packages = array_map('strtolower', $this->input->getArgument('package')); $this->data = $this->gpm->findPackages($packages); + $local_config_file = exec('eval echo ~/.grav/config'); + if (file_exists($local_config_file)) { + $this->local_config = Yaml::parse($local_config_file); + } + if ( !Installer::isGravInstance($this->destination) || !Installer::isValidDestination($this->destination, [Installer::EXISTS, Installer::IS_LINK]) @@ -111,7 +121,7 @@ class InstallCommand extends Command if (count($this->data['not_found'])) { $this->output->writeln("These packages were not found on Grav: " . implode(', ', - $this->data['not_found']) . ""); + array_keys($this->data['not_found'])) . ""); } unset($this->data['not_found']); @@ -119,7 +129,48 @@ class InstallCommand extends Command foreach ($this->data as $data) { foreach ($data as $package) { + + //Check for dependencies + if (isset($package->dependencies)) { + $this->output->writeln("Package " . $package->name . " has required dependencies that must be installed first..."); + $this->output->writeln(''); + + $dependency_data = $this->gpm->findPackages($package->dependencies); + + if (!$dependency_data['total']) { + $this->output->writeln("No dependcies found..."); + $this->output->writeln(''); + } else { + unset($dependency_data['total']); + + foreach($dependency_data as $type => $dep_data) { + foreach($dep_data as $name => $dep_package) { + $this->output->writeln("Preparing to install dependency: " . $name . ""); + $this->processPackage($dep_package); + } + + } + +// foreach((array)$package->dependencies as $dependency) { +// if (is_object($dependency)) { +// foreach($dependency as $key=>$val) { +// $dep = $key; +// $install_options[] = 'git'; +// } +// } else { +// // just name for GPM retrieval +// $dep = $dependency; +// } +// +// +// +// +// } + } + } + $version = isset($package->available) ? $package->available : $package->version; + $this->output->writeln("Preparing to install " . $package->name . " [v" . $version . "]"); $this->output->write(" |- Downloading package... 0%"); @@ -133,7 +184,8 @@ class InstallCommand extends Command $this->output->writeln(''); } else { $this->output->write(" |- Installing package... "); - $installation = $this->installPackage($package); + //$installation = $this->installPackage($package); + $installation = true; if (!$installation) { $this->output->writeln(" '- Installation failed or aborted."); $this->output->writeln(''); @@ -149,6 +201,41 @@ class InstallCommand extends Command $this->clearCache(); } + private function processPackage($package) + { + $install_options = ['gpm']; + + // if no name, not found in GPM + if (!isset($package->name)) { + unset($install_options[0]); + } + // if local config found symlink is a valid option + if (isset($this->local_config)) { + $install_options[] = 'symlink'; + } + // if override set, can install via git + if (isset($package->override_repository)) { + $install_options[] = 'git'; + } + + if (count($install_options) == 0) { + // no valid install options + } elseif (count($install_options) == 1) { + // only one option, use it... + } else { + $helper = $this->getHelper('question'); + $install_list = array_values($install_options); + $default = $install_list[0]; + $question = new ChoiceQuestion( + 'Please select installation method ('.$default.' is default)', array_values($install_list), 0 + ); + $question->setErrorMessage('Method %s is invalid'); + $method = $helper->ask($this->input, $this->output, $question); + $this->output->writeln('You chose: ' . $method); + + } + } + /** * @param $package * From ace8823bd6fe5fa756031eb09c0df479e385bfe7 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 15 Feb 2015 13:37:51 -0700 Subject: [PATCH 2/6] Added symlink + git clone installation methods --- system/src/Grav/Common/GPM/GPM.php | 14 ++ .../src/Grav/Console/Gpm/InstallCommand.php | 235 +++++++++++++----- 2 files changed, 185 insertions(+), 64 deletions(-) diff --git a/system/src/Grav/Common/GPM/GPM.php b/system/src/Grav/Common/GPM/GPM.php index 26f8999e8..3a0c4a886 100644 --- a/system/src/Grav/Common/GPM/GPM.php +++ b/system/src/Grav/Common/GPM/GPM.php @@ -1,7 +1,9 @@ 'user/plugins/%name%', 'themes' => 'user/themes/%name%', 'skeletons' => 'user/']; + /** * Creates a new GPM instance with Local and Remote packages available * @param boolean $refresh Applies to Remote Packages only and forces a refetch of data @@ -368,7 +372,17 @@ class GPM extends Iterator $packages[$found->package_type][$found->slug] = $found; $packages['total']++; } else { + // make a best guess at the type based on the repo URL + if (Utils::contains($repository, '-theme')) { + $type = 'themes'; + } else { + $type = 'plugins'; + } + $not_found = new \stdClass(); + $not_found->name = Inflector::camelize($search); + $not_found->slug = $search; + $not_found->install_path = str_replace('%name%', $search, $this->install_paths[$type]); $not_found->override_repository = $repository; $packages['not_found'][$search] = $not_found; } diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index f546dd3ec..89a9d8cd6 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -5,6 +5,8 @@ use Grav\Common\Filesystem\Folder; use Grav\Common\GPM\GPM; use Grav\Common\GPM\Installer; use Grav\Common\GPM\Response; +use Grav\Common\Inflector; +use Grav\Common\Utils; use Grav\Console\ConsoleTrait; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -15,6 +17,7 @@ use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Yaml\Yaml; +define('GIT_REGEX', '/http[s]?:\/\/(?:.*@)?(github|bitbucket)(?:.org|.com)\/.*\/(.*)/'); /** * Class InstallCommand @@ -47,6 +50,7 @@ class InstallCommand extends Command protected $local_config; + /** * */ @@ -132,49 +136,126 @@ class InstallCommand extends Command //Check for dependencies if (isset($package->dependencies)) { - $this->output->writeln("Package " . $package->name . " has required dependencies that must be installed first..."); + $this->output->writeln("Package " . $package->name . " has ". count($package->dependencies) . " required dependencies that must be installed first..."); $this->output->writeln(''); $dependency_data = $this->gpm->findPackages($package->dependencies); if (!$dependency_data['total']) { - $this->output->writeln("No dependcies found..."); + $this->output->writeln("No dependencies found..."); $this->output->writeln(''); } else { unset($dependency_data['total']); foreach($dependency_data as $type => $dep_data) { foreach($dep_data as $name => $dep_package) { - $this->output->writeln("Preparing to install dependency: " . $name . ""); + $this->processPackage($dep_package); } - } - -// foreach((array)$package->dependencies as $dependency) { -// if (is_object($dependency)) { -// foreach($dependency as $key=>$val) { -// $dep = $key; -// $install_options[] = 'git'; -// } -// } else { -// // just name for GPM retrieval -// $dep = $dependency; -// } -// -// -// -// -// } } } - $version = isset($package->available) ? $package->available : $package->version; + $this->processPackage($package); + } + } - $this->output->writeln("Preparing to install " . $package->name . " [v" . $version . "]"); + // clear cache after successful upgrade + $this->clearCache(); + } - $this->output->write(" |- Downloading package... 0%"); - $this->file = $this->downloadPackage($package); + /** + * @param $package + */ + private function processPackage($package) + { + $install_options = ['GPM']; + + // if no name, not found in GPM + if (!isset($package->version)) { + unset($install_options[0]); + } + // if local config found symlink is a valid option + if (isset($this->local_config)) { + $install_options[] = 'Symlink'; + } + // if override set, can install via git + if (isset($package->override_repository)) { + $install_options[] = 'Git'; + } + + // reindex list + $install_options = array_values($install_options); + + if (count($install_options) == 0) { + // no valid install options - error and return + } elseif (count($install_options) == 1) { + // only one option, use it... + $method = $install_options[0]; + } else { + $helper = $this->getHelper('question'); + $question = new ChoiceQuestion( + 'Please select installation method for ' . $package->name . ' ('.$install_options[0].' is default)', array_values($install_options), 0 + ); + $question->setErrorMessage('Method %s is invalid'); + $method = $helper->ask($this->input, $this->output, $question); + } + + $this->output->writeln(''); + + $method_name = 'process'.$method; + + $this->$method_name($package); + } + + /** + * @param $package + * + * @return array + */ + private function getGitRegexMatches($package) + { + if (isset($package->override_repository)) { + $repository = $package->override_repository; + } elseif (isset($package->repository)) { + $repository = $package->repository; + } else { + return false; + } + + preg_match(GIT_REGEX, $repository, $matches); + + return $matches; + } + + /** + * @param $package + */ + private function processSymlink($package) + { + + exec('cd ' . $this->destination); + + $to = $this->destination . DS . $package->install_path; + + $matches = $this->getGitRegexMatches($package); + + $this->output->writeln("Preparing to Symlink " . $package->name . ""); + $this->output->write(" |- Checking source... "); + + foreach ($this->local_config as $path) { + + if (Utils::endsWith($matches[2], '.git')) { + $repo_dir = preg_replace('/\.git$/', '', $matches[2]); + } else { + $repo_dir = $matches[2]; + } + + $from = rtrim($path, '/') . '/' . $repo_dir; + + if (file_exists($from)) { + + $this->output->writeln("ok"); $this->output->write(" |- Checking destination... "); $checks = $this->checkDestination($package); @@ -183,56 +264,80 @@ class InstallCommand extends Command $this->output->writeln(" '- Installation failed or aborted."); $this->output->writeln(''); } else { - $this->output->write(" |- Installing package... "); - //$installation = $this->installPackage($package); - $installation = true; - if (!$installation) { - $this->output->writeln(" '- Installation failed or aborted."); - $this->output->writeln(''); - } else { - $this->output->writeln(" '- Success! "); - $this->output->writeln(''); - } + + symlink($from, $to); + + // extra white spaces to clear out the buffer properly + $this->output->writeln(" |- Symlinking package... ok "); + + $this->output->writeln(" '- Success! "); + $this->output->writeln(''); + } + return; + } else { + $this->output->writeln("not found!"); } } - - // clear cache after successful upgrade - $this->clearCache(); } - private function processPackage($package) + /** + * @param $package + */ + private function processGit($package) { - $install_options = ['gpm']; + $matches = $this->getGitRegexMatches($package); - // if no name, not found in GPM - if (!isset($package->name)) { - unset($install_options[0]); - } - // if local config found symlink is a valid option - if (isset($this->local_config)) { - $install_options[] = 'symlink'; - } - // if override set, can install via git - if (isset($package->override_repository)) { - $install_options[] = 'git'; - } + $to = $this->destination . DS . $package->install_path; - if (count($install_options) == 0) { - // no valid install options - } elseif (count($install_options) == 1) { - // only one option, use it... + $this->output->writeln("Preparing to Git clone " . $package->name . ""); + + $this->output->write(" |- Checking destination... "); + $checks = $this->checkDestination($package); + + if (!$checks) { + $this->output->writeln(" '- Installation failed or aborted."); + $this->output->writeln(''); } else { - $helper = $this->getHelper('question'); - $install_list = array_values($install_options); - $default = $install_list[0]; - $question = new ChoiceQuestion( - 'Please select installation method ('.$default.' is default)', array_values($install_list), 0 - ); - $question->setErrorMessage('Method %s is invalid'); - $method = $helper->ask($this->input, $this->output, $question); - $this->output->writeln('You chose: ' . $method); + $cmd = 'cd ' . $this->destination . ' && git clone ' . $matches[0] . ' ' . $package->install_path; + exec($cmd); + // extra white spaces to clear out the buffer properly + $this->output->writeln(" |- Cloning package... ok "); + + $this->output->writeln(" '- Success! "); + $this->output->writeln(''); + } + } + + /** + * @param $package + */ + private function processGPM($package) + { + $version = isset($package->available) ? $package->available : $package->version; + + $this->output->writeln("Preparing to install " . $package->name . " [v" . $version . "]"); + + $this->output->write(" |- Downloading package... 0%"); + $this->file = $this->downloadPackage($package); + + $this->output->write(" |- Checking destination... "); + $checks = $this->checkDestination($package); + + if (!$checks) { + $this->output->writeln(" '- Installation failed or aborted."); + $this->output->writeln(''); + } else { + $this->output->write(" |- Installing package... "); + $installation = $this->installPackage($package); + if (!$installation) { + $this->output->writeln(" '- Installation failed or aborted."); + $this->output->writeln(''); + } else { + $this->output->writeln(" '- Success! "); + $this->output->writeln(''); + } } } @@ -305,6 +410,8 @@ class InstallCommand extends Command $this->output->writeln(" | '- You decided to not delete the symlink automatically."); return false; + } else { + unlink($this->destination . DS . $package->install_path); } } From bd595ca9f6905f826a6bf74a451885315ebb70a7 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 15 Feb 2015 14:04:50 -0700 Subject: [PATCH 3/6] some corner case fixes --- .../src/Grav/Console/Gpm/InstallCommand.php | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index 89a9d8cd6..8ee61bbe7 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -189,6 +189,8 @@ class InstallCommand extends Command if (count($install_options) == 0) { // no valid install options - error and return + $this->output->writeln("not valid installation methods found!"); + return; } elseif (count($install_options) == 1) { // only one option, use it... $method = $install_options[0]; @@ -264,21 +266,26 @@ class InstallCommand extends Command $this->output->writeln(" '- Installation failed or aborted."); $this->output->writeln(''); } else { + if (file_exists($to)) { + $this->output->writeln(" '- Symlink cannot overwrite an existing folder"); + $this->output->writeln(''); + } else { + symlink($from, $to); - symlink($from, $to); + // extra white spaces to clear out the buffer properly + $this->output->writeln(" |- Symlinking package... ok "); - // extra white spaces to clear out the buffer properly - $this->output->writeln(" |- Symlinking package... ok "); + $this->output->writeln(" '- Success! "); + $this->output->writeln(''); + } - $this->output->writeln(" '- Success! "); - $this->output->writeln(''); } return; - } else { - $this->output->writeln("not found!"); } } + $this->output->writeln("not found!"); + $this->output->writeln(" '- Installation failed or aborted."); } /** From 85fb5bccf3679ec0c6ea534f39c73b9e628ab701 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 15 Feb 2015 14:07:40 -0700 Subject: [PATCH 4/6] text addition --- system/src/Grav/Console/Gpm/InstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index 8ee61bbe7..d0272a1c9 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -267,7 +267,7 @@ class InstallCommand extends Command $this->output->writeln(''); } else { if (file_exists($to)) { - $this->output->writeln(" '- Symlink cannot overwrite an existing folder"); + $this->output->writeln(" '- Symlink cannot overwrite an existing package, please remove first"); $this->output->writeln(''); } else { symlink($from, $to); From 9248c5b7096b5d5861d279b1370d400894f14c74 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 15 Feb 2015 14:21:17 -0700 Subject: [PATCH 5/6] added repo URL to output --- system/src/Grav/Console/Gpm/InstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index d0272a1c9..fd015a0e8 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -297,7 +297,7 @@ class InstallCommand extends Command $to = $this->destination . DS . $package->install_path; - $this->output->writeln("Preparing to Git clone " . $package->name . ""); + $this->output->writeln("Preparing to Git clone " . $package->name . " from " . $matches[0]); $this->output->write(" |- Checking destination... "); $checks = $this->checkDestination($package); From 9959868022d18dba2af2eec2a92b3bfcad0e0c87 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 15 Feb 2015 15:24:07 -0700 Subject: [PATCH 6/6] Don't critically fail, only log when plugin has config but is missing --- system/src/Grav/Common/Plugins.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index dd495963e..c33845fac 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -47,7 +47,8 @@ class Plugins extends Iterator $filePath = $this->grav['locator']('plugins://' . $plugin . DS . $plugin . PLUGIN_EXT); if (!is_file($filePath)) { - throw new \RuntimeException(sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clear-cache`", $plugin)); + $this->grav['log']->addWarning(sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clear-cache`", $plugin)); + continue; } require_once $filePath;