function testValidRange() { $compare = array(array("1.0.0 - 2.0.0", ">=1.0.0 <=2.0.0"), array("1.0.0", "1.0.0"), array(">=*", ">=0.0.0-"), array("*", ">=0"), array(">=1.0.0", ">=1.0.0"), array(">1.0.0", ">1.0.0"), array("<=2.0.0", "<=2.0.0"), array("1", ">=1 <2.0.0-"), array("<=2.0.0", "<=2.0.0"), array("<2.0.0", "<2.0.0"), array(">= 1.0.0", ">=1.0.0"), array(">= 1.0.0", ">=1.0.0"), array(">= 1.0.0", ">=1.0.0"), array("> 1.0.0", ">1.0.0"), array("> 1.0.0", ">1.0.0"), array("<= 2.0.0", "<=2.0.0"), array("<= 2.0.0", "<=2.0.0"), array("<= 2.0.0", "<=2.0.0"), array("< 2.0.0", "<2.0.0"), array("<\t2.0.0", "<2.0.0"), array(">=0.1.97", ">=0.1.97"), array(">=0.1.97", ">=0.1.97"), array("0.1.20 || 1.2.4", "0.1.20||1.2.4"), array(">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"), array(">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"), array(">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"), array("2.x.x", ">=2 <3.0.0-"), array("1.2.x", ">=1.2 <1.3.0-"), array("1.2.x || 2.x", ">=1.2 <1.3.0-||>=2 <3.0.0-"), array("x", ">=0"), array("2.*.*", '>=2 <3.0.0-'), array("1.2.*", '>=1.2 <1.3.0-'), array("1.2.* || 2.*", '>=1.2 <1.3.0-||>=2 <3.0.0-'), array("*", ">=0"), array("2", ">=2 <3.0.0-"), array("2.3", ">=2.3 <2.4.0-"), array("~2.4", ">=2.4 <2.5.0-"), array("~>3.2.1", ">=3.2.1 <3.3.0-"), array("~1", ">=1 <2.0.0-"), array("~>1", ">=1 <2.0.0-"), array("~> 1", ">=1 <2.0.0-"), array("~1.0", ">=1.0 <1.1.0-"), array("~ 1.0", ">=1.0 <1.1.0-"), array("<1", "<1"), array("< 1", "<1"), array(">=1", ">=1"), array(">= 1", ">=1"), array("<1.2", "<1.2"), array("< 1.2", "<1.2")); foreach ($compare as $set) { $v = new SemVer\expression($set[0]); $this->assertEqual($v->getString(), $set[1], "%s > validRange({$set['0']}) === {$set['1']}"); } }
/** * {@inheritdoc} */ public function findPackage($rawCriteria = '*') { list($repoUser, $repoName) = explode('/', $this->clearGitURL($this->url)); $paginator = new ResultPager($this->githubClient); $tags = $paginator->fetchAll($this->githubClient->api('repo'), 'tags', array($repoUser, $repoName)); // edge case: package has no tags if (count($tags) === 0) { return 'master'; } // edge case: user asked for latest package if ($rawCriteria == 'latest' || $rawCriteria == '*' || empty($rawCriteria)) { $sortedTags = $this->sortTags($tags); $this->tag = end($sortedTags); return $this->tag['name']; } // edge case for versions vith slash (like ckeditor). See also issue #120 if (strpos($rawCriteria, '/') > 0) { $tagNames = ArrayColumn::array_column($tags, 'name'); if (false !== ($tag = array_search($rawCriteria, $tagNames))) { $this->tag = $tag; return $rawCriteria; } } try { $criteria = new expression($rawCriteria); } catch (SemVerException $sve) { throw new RuntimeException(sprintf('Criteria %s is not valid.', $rawCriteria), self::INVALID_CRITERIA, $sve); } $sortedTags = $this->sortTags($tags); // Yes, the php-semver lib does offer a maxSatisfying() method similar the code below. // We're not using it because it will throw an exception on what it considers to be an // "invalid" candidate version, and not continue checking the rest of the candidates. // So, even if it's faster than this code, it's not a complete solution. $matches = array_filter($sortedTags, function ($tag) use($criteria) { $candidate = $tag['parsed_version']; return $criteria->satisfiedBy($candidate) ? $tag : false; }); // If the array has elements, the LAST element is the best (highest numbered) version. if (count($matches) > 0) { // @todo Get rid of this side effect? $this->tag = array_pop($matches); return $this->tag['name']; } throw new RuntimeException(sprintf('%s: No suitable version for %s was found.', $repoName, $rawCriteria), self::VERSION_NOT_FOUND); }
public function testNotSatisfiedBy() { $t = array('1.0.0' => '1.0.1', '1.2.3' => '2.0.0', '<1.0.1' => array('1.0.1', '1.0.2', '1.2.0', '2.0.0'), '<=2' => array('2.0.1', '2.1.5', '3.0.0'), '>=2.4' => array('1.2.0', '2.0.0'), '3.x' => array('1.0.0', '1.9.9', '2.999.9999', '4.0.0'), '<1.5.6 || >=2.3.4 <3.0.0' => array('1.5.6', '1.5.7', '1.6.0', '2.1.0', '2.3.0', '2.3.3', '3.0.0', '3.2.1'), '1.2.0 - 2.1.2' => array('1.1.2', '2.2.0'), '>4.0.0 <=4.2.3' => array('4.0.0', '4.2.4', '4.5.0', '3.2.2')); foreach ($t as $range => $satisfies) { $e = new SemVer\expression($range, true); if (!is_array($satisfies)) { $satisfies = array($satisfies); } foreach ($satisfies as $version) { $v = new SemVer\version($version, true); $this->assertFalse($e->satisfiedBy($v), '[' . $range . ' :: ' . $version . '] %s'); $this->assertFalse($v->satisfies($e), '[' . $range . ' :: ' . $version . '] %s'); } } }
/** * compute if bundle requirements are met * * @param array $dependency * @return bool */ private function bundleDependencySatisfied(array &$dependency) { if ($dependency['modname'] == "php") { $phpVersion = new version(PHP_VERSION); $requiredVersionExpression = new expression($dependency['minversion']); return $requiredVersionExpression->satisfiedBy($phpVersion); } if (strpos($dependency['modname'], 'composer/') !== false) { // @todo this specifically is for `composer/installers` but will catch all with `composer/` return true; } if ($dependency['minversion'] == "-1") { // dependency is "suggested" list($dependency['modname'], $dependency['minversion']) = explode(':', $dependency['modname']); return false; } if (strpos($dependency['modname'], '/') !== false) { if ($this->get('kernel')->isBundle($dependency['modname'])) { if (empty($this->installedPackages)) { // create and cache installed packages from composer.lock file $appPath = $this->get('kernel')->getRootDir(); $composerLockPath = realpath($appPath . '/../') . 'composer.lock'; $packages = json_decode(file_get_contents($composerLockPath), true); foreach ($packages as $package) { $this->installedPackages[$package['name']] = $package; } } $bundleVersion = new version($this->installedPackages[$dependency['modname']]['version']); $requiredVersionExpression = new expression($dependency['minversion']); return $requiredVersionExpression->satisfiedBy($bundleVersion); } $dependency['reason'] = $this->__('This dependency can only be resolved via `composer update`'); return false; } return false; }
/** * Checks if the plugin can be enabled. * * @return boolean */ public function canBeEnabled() { if ($this->isEnabled()) { // The plugin cannot be enabled twice return false; } if ($this->hasUnsatisfiedSystemRequirements()) { return false; } // Make sure all plugin's dependencies exist, are enabled and have // appropriate versions foreach ($this->getDependencies() as $plugin_name => $required_version) { if (!Utils::pluginExists($plugin_name)) { return false; } $plugin = new PluginInfo($plugin_name); if (!$plugin->isInstalled() || !$plugin->isEnabled()) { return false; } $version_constrain = new VersionExpression($required_version); if (!$version_constrain->satisfiedBy(new Version($plugin->getInstalledVersion()))) { return false; } } return true; }
/** * Checks whether this version satisfies an expression * @param expression $versions The expression to check against * @return bool */ public function satisfies(expression $versions) { return $versions->satisfiedBy($this); }
/** * Determine if $min and $max values are compatible with Current Core version * * @param string $compatibilityString Semver * @return bool */ private function isCoreCompatible($compatibilityString) { $coreVersion = new version(Zikula_Core::VERSION_NUM); $requiredVersionExpression = new expression($compatibilityString); return $requiredVersionExpression->satisfiedBy($coreVersion); }
/** * Performs a step of plugin's verification algorithm. * * Actually this method represents a step of depth-first search algorithm * with additions related with plugin's verification. * * @param PluginInfo $plugin A plugin that should be verified. * @throws \LogicException If cyclic dependencies are found. */ protected function doVerificationStep(PluginInfo $plugin) { if ($this->getDfsState($plugin) == self::DFS_IN_PROGRESS) { throw new \LogicException(sprintf('Cyclic dependencies found for plugin "%s"', $plugin->getName())); } $this->setDfsState($plugin, self::DFS_IN_PROGRESS); $can_be_loaded = true; foreach ($plugin->getDependencies() as $dependency_name => $required_version) { // Make sure the dependency exist if (!$this->hasPlugin($dependency_name)) { trigger_error(sprintf('Plugin "%s" does not exist but is listed in "%s" dependencies!', $dependency_name, $plugin->getName()), E_USER_WARNING); $can_be_loaded = false; break; } // Check that version of the dependency satisfied requirements $version_constrain = new VersionExpression($required_version); $dependency = $this->getPlugin($dependency_name); if (!$version_constrain->satisfiedBy(new Version($dependency->getInstalledVersion()))) { trigger_error(sprintf('Plugin "%s" has version incompatible with "%s" requirements!', $dependency_name, $plugin->getName()), E_USER_WARNING); $can_be_loaded = false; break; } // Check that dependencies of the current dependency are satisfied if ($this->getDfsState($dependency) != self::DFS_VISITED) { $this->doVerificationStep($dependency); } if (!isset($this->loadablePlugins[$dependency_name])) { trigger_error(sprintf('Not all dependencies of "%s" plugin are satisfied!', $plugin->getName()), E_USER_WARNING); $can_be_loaded = false; break; } } $this->setDfsState($plugin, self::DFS_VISITED); if ($can_be_loaded) { $this->loadablePlugins[$plugin->getName()] = $plugin; } }
/** * @param version $currentVersion * @param $releases * * @return bool|array */ private function getHighestPatchReleaseOfNextMinorVersion(version $currentVersion, $releases) { $nextMinorStep = new expression($currentVersion->getMajor() . "." . ($currentVersion->getMinor() + 1) . ".*"); foreach ($releases as $release) { if ($nextMinorStep->satisfiedBy($this->getVersionFromRelease($release))) { return $release; } } return false; }
protected function findTag(Repository $repository, $tag) { $tags = (array) $repository->getTags(); $tagExpression = new SemanticExpression($tag); return $this->getMappedVersionTag($tags, $tagExpression->maxSatisfying($tags)); }