From 503ff8d70f2e8c2b85a8cfa9a11bc71fd45c9af9 Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Tue, 16 Feb 2016 15:24:33 +0100 Subject: [PATCH] First step towards versions in dependencies Add InstallCommand::calculateMergedDependenciesOfPackages and InstallCommand::calculateVersionNumberFromDependencyVersion and corresponding unit tests --- .../src/Grav/Console/Gpm/InstallCommand.php | 96 ++++++++++++- .../Grav/Console/Gpm/InstallCommandTest.php | 130 ++++++++++++++++++ 2 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 tests/unit/Grav/Console/Gpm/InstallCommandTest.php diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index 0d919c4ac..fed169b21 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -14,6 +14,7 @@ use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Yaml\Yaml; define('GIT_REGEX', '/http[s]?:\/\/(?:.*@)?(github|bitbucket)(?:.org|.com)\/.*\/(.*)/'); +define('SECOND_IS_HIGHER', -1); /** * Class InstallCommand @@ -25,18 +26,22 @@ class InstallCommand extends ConsoleCommand * @var */ protected $data; + /** * @var */ protected $gpm; + /** * @var */ protected $destination; + /** * @var */ protected $file; + /** * @var */ @@ -44,7 +49,6 @@ class InstallCommand extends ConsoleCommand protected $local_config; - /** * */ @@ -153,6 +157,96 @@ class InstallCommand extends ConsoleCommand $this->clearCache(); } + /** + * Calculates and merges the dependencies of the passed packages + * + * @param array $packages + * + * @return mixed + * @throws \Exception + */ + public function calculateMergedDependenciesOfPackages($packages) + { + foreach ($packages as $data) { + foreach ($data as $package) { + + //Check for dependencies + if (isset($package->dependencies_versions)) { + foreach ($package->dependencies_versions as $dependency) { + + $current_package_name = $dependency->name; + if (isset($dependency->version)) { + $current_package_version_information = $dependency->version; + } + + if (!isset($dependencies[$current_package_name])) { // Dependency added for the first time + + if (!isset($current_package_version_information)) { + $dependencies[$current_package_name] = '*'; + } else { + $dependencies[$current_package_name] = $current_package_version_information; + } + + } else { // Dependency already added by another package + + //if this package requires a version higher than the currently stored one, store this requirement instead + if (isset($current_package_version_information) && $current_package_version_information !== '*') { + + $currently_stored_version_information = $dependencies[$current_package_name]; + + $currently_stored_version_number = $this->calculateVersionNumberFromDependencyVersion($currently_stored_version_information); + if (!$currently_stored_version_number) { + $currently_stored_version_number = '*'; + } + + $current_package_version_number = $this->calculateVersionNumberFromDependencyVersion($current_package_version_information); + if (!$current_package_version_number) { + throw new \Exception('Bad format for package ' . $current_package_name); + } + + //If I had stored '*', change right away with the more specific version required + if ($currently_stored_version_number === '*') { + $dependencies[$current_package_name] = $current_package_version_information; + } else { + + if (version_compare($currently_stored_version_number, $current_package_version_number) == SECOND_IS_HIGHER) { + $dependencies[$current_package_name] = $current_package_version_information; + } + + } + } + } + } + } + } + } + + return $dependencies; + } + + /** + * Returns the actual version from a dependency version string. + * Examples: + * $versionInformation == '~2.0' => returns '2.0' + * $versionInformation == '>=2.0.2' => returns '2.0.2' + * $versionInformation == '*' => returns null + * $versionInformation == '' => returns null + * + * @param $versionInformation + * + * @return null|string + */ + public function calculateVersionNumberFromDependencyVersion($versionInformation) + { + if (substr($versionInformation, 0, 1) == '~') { + return substr($versionInformation, 1); + } elseif (substr($versionInformation, 0, 2) == '>=') { + return substr($versionInformation, 2); + } + + return null; + } + /** * @param $package */ diff --git a/tests/unit/Grav/Console/Gpm/InstallCommandTest.php b/tests/unit/Grav/Console/Gpm/InstallCommandTest.php new file mode 100644 index 000000000..59e9c24dd --- /dev/null +++ b/tests/unit/Grav/Console/Gpm/InstallCommandTest.php @@ -0,0 +1,130 @@ +grav = Fixtures::get('grav'); + $this->installCommand = new InstallCommand(); + } + + protected function _after() + { + } + + public function testTest() + { + ////////////////////////////////////////////////////////////////////////////////////////// + //First example + ////////////////////////////////////////////////////////////////////////////////////////// + $this->data = [ + [ + 'admin' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "grav", "version" => ">=1.0.10"], + (object)["name" => "form", "version" => "~2.0"], + (object)["name" => "login", "version" => ">=2.0"], + (object)["name" => "errors", "version" => "*"], + (object)["name" => "problems"], + ] + ], + 'test' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => ">=1.0"] + ] + ] + ] + ]; + + $dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($this->data); + + $this->assertTrue(is_array($dependencies)); + $this->assertTrue(count($dependencies) == 5); + + $this->assertTrue($dependencies['grav'] == '>=1.0.10'); + $this->assertTrue($dependencies['errors'] == '>=1.0'); + $this->assertFalse($dependencies['errors'] == '*'); + $this->assertTrue($dependencies['problems'] == '*'); + + ////////////////////////////////////////////////////////////////////////////////////////// + //Second example + ////////////////////////////////////////////////////////////////////////////////////////// + $this->data = [ + [ + 'admin' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => "*"], + ] + ], + 'test' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => ">=1.0"] + ] + ], + 'another' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => ">=3.2"] + ] + ] + ] + ]; + + $dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($this->data); + + $this->assertTrue(is_array($dependencies)); + $this->assertTrue(count($dependencies) == 1); + $this->assertTrue($dependencies['errors'] == '>=3.2'); + + ////////////////////////////////////////////////////////////////////////////////////////// + //Second example + ////////////////////////////////////////////////////////////////////////////////////////// + $this->data = [ + [ + 'admin' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => ">=4.0"], + ] + ], + 'test' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => ">=1.0"] + ] + ], + 'another' => (object)[ + 'dependencies_versions' => [ + (object)["name" => "errors", "version" => ">=3.2"] + ] + ] + ] + ]; + + $dependencies = $this->installCommand->calculateMergedDependenciesOfPackages($this->data); + + $this->assertTrue(is_array($dependencies)); + $this->assertTrue(count($dependencies) == 1); + $this->assertTrue($dependencies['errors'] == '>=4.0'); + + } + + + public function testCalculateVersionNumberFromDependencyVersion() + { + $this->assertSame('2.0', $this->installCommand->calculateVersionNumberFromDependencyVersion('>=2.0')); + $this->assertSame('2.0.2', $this->installCommand->calculateVersionNumberFromDependencyVersion('>=2.0.2')); + $this->assertSame('2.0.2', $this->installCommand->calculateVersionNumberFromDependencyVersion('~2.0.2')); + $this->assertSame('1', $this->installCommand->calculateVersionNumberFromDependencyVersion('~1')); + $this->assertSame(null, $this->installCommand->calculateVersionNumberFromDependencyVersion('')); + $this->assertSame(null, $this->installCommand->calculateVersionNumberFromDependencyVersion('*')); + $this->assertSame(null, $this->installCommand->calculateVersionNumberFromDependencyVersion('2.0.2')); + } +} \ No newline at end of file