diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2014-12-05 13:52:51 +0100 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2014-12-11 12:02:11 +0100 |
commit | 770f9876595a3cebd4b911a237ec1e681bc506be (patch) | |
tree | 7e6e3dda9ccfe843d506380d5c26f6c8f38911c4 /lib | |
parent | 08f1db445134e98188f3e1e5b6b84a6eac1f6346 (diff) | |
download | nextcloud-server-770f9876595a3cebd4b911a237ec1e681bc506be.tar.gz nextcloud-server-770f9876595a3cebd4b911a237ec1e681bc506be.zip |
adding supported libraries - including min and max version
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/app/dependencyanalyzer.php | 48 | ||||
-rw-r--r-- | lib/private/app/platform.php | 6 | ||||
-rw-r--r-- | lib/private/app/platformrepository.php | 210 |
3 files changed, 257 insertions, 7 deletions
diff --git a/lib/private/app/dependencyanalyzer.php b/lib/private/app/dependencyanalyzer.php index 172b8e88c06..af36637b675 100644 --- a/lib/private/app/dependencyanalyzer.php +++ b/lib/private/app/dependencyanalyzer.php @@ -44,13 +44,14 @@ class DependencyAnalyzer { * @returns array of missing dependencies */ public function analyze() { - $this->analysePhpVersion(); - $this->analyseSupportedDatabases(); - $this->analyseCommands(); + $this->analyzePhpVersion(); + $this->analyzeDatabases(); + $this->analyzeCommands(); + $this->analyzeLibraries(); return $this->missing; } - private function analysePhpVersion() { + private function analyzePhpVersion() { if (isset($this->dependencies['php']['@attributes']['min-version'])) { $minVersion = $this->dependencies['php']['@attributes']['min-version']; if (version_compare($this->platform->getPhpVersion(), $minVersion, '<')) { @@ -60,12 +61,12 @@ class DependencyAnalyzer { if (isset($this->dependencies['php']['@attributes']['max-version'])) { $maxVersion = $this->dependencies['php']['@attributes']['max-version']; if (version_compare($this->platform->getPhpVersion(), $maxVersion, '>')) { - $this->addMissing((string)$this->l->t('PHP with a version less then %s is required.', $maxVersion)); + $this->addMissing((string)$this->l->t('PHP with a version lower than %s is required.', $maxVersion)); } } } - private function analyseSupportedDatabases() { + private function analyzeDatabases() { if (!isset($this->dependencies['database'])) { return; } @@ -83,7 +84,7 @@ class DependencyAnalyzer { } } - private function analyseCommands() { + private function analyzeCommands() { if (!isset($this->dependencies['command'])) { return; } @@ -101,6 +102,39 @@ class DependencyAnalyzer { } } + private function analyzeLibraries() { + if (!isset($this->dependencies['lib'])) { + return; + } + + $libs = $this->dependencies['lib']; + foreach($libs as $lib) { + $libName = $this->getValue($lib); + $libVersion = $this->platform->getLibraryVersion($libName); + if (is_null($libVersion)) { + $this->addMissing((string)$this->l->t('The library %s is not available.', $libName)); + continue; + } + + if (is_array($lib)) { + if (isset($lib['@attributes']['min-version'])) { + $minVersion = $lib['@attributes']['min-version']; + if (version_compare($libVersion, $minVersion, '<')) { + $this->addMissing((string)$this->l->t('Library %s with a version higher than %s is required - available version %s.', + array($libName, $minVersion, $libVersion))); + } + } + if (isset($lib['@attributes']['max-version'])) { + $maxVersion = $lib['@attributes']['max-version']; + if (version_compare($libVersion, $maxVersion, '>')) { + $this->addMissing((string)$this->l->t('Library %s with a version lower than %s is required - available version %s.', + array($libName, $maxVersion, $libVersion))); + } + } + } + } + } + /** * @param $element * @return mixed diff --git a/lib/private/app/platform.php b/lib/private/app/platform.php index da515a235a2..6279bb5f20c 100644 --- a/lib/private/app/platform.php +++ b/lib/private/app/platform.php @@ -62,4 +62,10 @@ class Platform { $path = \OC_Helper::findBinaryPath($command); return ($path !== null); } + + public function getLibraryVersion($name) { + $repo = new PlatformRepository(); + $lib = $repo->findLibrary($name); + return $lib; + } } diff --git a/lib/private/app/platformrepository.php b/lib/private/app/platformrepository.php new file mode 100644 index 00000000000..96d04ec2e42 --- /dev/null +++ b/lib/private/app/platformrepository.php @@ -0,0 +1,210 @@ +<?php + +namespace OC\App; + +/** + * Class PlatformRepository + * + * Inspired by the composer project - licensed under MIT + * https://github.com/composer/composer/blob/master/src/Composer/Repository/PlatformRepository.php#L82 + * + * @package OC\App + */ +class PlatformRepository { + public function __construct() { + $this->packages = $this->initialize(); + } + + protected function initialize() { + $loadedExtensions = get_loaded_extensions(); + $packages = array(); + + // Extensions scanning + foreach ($loadedExtensions as $name) { + if (in_array($name, array('standard', 'Core'))) { + continue; + } + + $ext = new \ReflectionExtension($name); + try { + $prettyVersion = $ext->getVersion(); + } catch (\UnexpectedValueException $e) { + $prettyVersion = '0'; + } + try { + $prettyVersion = $this->normalizeVersion($prettyVersion); + } catch (\UnexpectedValueException $e) { + continue; + } + + $packages[$this->buildPackageName($name)] = $prettyVersion; + } + + foreach ($loadedExtensions as $name) { + $prettyVersion = null; + switch ($name) { + case 'curl': + $curlVersion = curl_version(); + $prettyVersion = $curlVersion['version']; + break; + + case 'iconv': + $prettyVersion = ICONV_VERSION; + break; + + case 'intl': + $name = 'ICU'; + if (defined('INTL_ICU_VERSION')) { + $prettyVersion = INTL_ICU_VERSION; + } else { + $reflector = new \ReflectionExtension('intl'); + + ob_start(); + $reflector->info(); + $output = ob_get_clean(); + + preg_match('/^ICU version => (.*)$/m', $output, $matches); + $prettyVersion = $matches[1]; + } + + break; + + case 'libxml': + $prettyVersion = LIBXML_DOTTED_VERSION; + break; + + case 'openssl': + $prettyVersion = preg_replace_callback('{^(?:OpenSSL\s*)?([0-9.]+)([a-z]?).*}', function ($match) { + return $match[1] . (empty($match[2]) ? '' : '.' . (ord($match[2]) - 96)); + }, OPENSSL_VERSION_TEXT); + break; + + case 'pcre': + $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION); + break; + + case 'uuid': + $prettyVersion = phpversion('uuid'); + break; + + case 'xsl': + $prettyVersion = LIBXSLT_DOTTED_VERSION; + break; + + default: + // None handled extensions have no special cases, skip + continue 2; + } + + try { + $prettyVersion = $this->normalizeVersion($prettyVersion); + } catch (\UnexpectedValueException $e) { + continue; + } + + $packages[$this->buildPackageName($name)] = $prettyVersion; + } + + return $packages; + } + + private function buildPackageName($name) { + return str_replace(' ', '-', $name); + } + + /** + * @param $name + * @return string + */ + public function findLibrary($name) { + $extName = $this->buildPackageName($name); + if (isset($this->packages[$extName])) { + return $this->packages[$extName]; + } + return null; + } + + private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?'; + + /** + * Normalizes a version string to be able to perform comparisons on it + * + * https://github.com/composer/composer/blob/master/src/Composer/Package/Version/VersionParser.php#L94 + * + * @param string $version + * @param string $fullVersion optional complete version string to give more context + * @throws \UnexpectedValueException + * @return string + */ + public function normalizeVersion($version, $fullVersion = null) { + $version = trim($version); + if (null === $fullVersion) { + $fullVersion = $version; + } + // ignore aliases and just assume the alias is required instead of the source + if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $version, $match)) { + $version = $match[1]; + } + // match master-like branches + if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) { + return '9999999-dev'; + } + if ('dev-' === strtolower(substr($version, 0, 4))) { + return 'dev-' . substr($version, 4); + } + // match classical versioning + if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?' . self::$modifierRegex . '$}i', $version, $matches)) { + $version = $matches[1] + . (!empty($matches[2]) ? $matches[2] : '.0') + . (!empty($matches[3]) ? $matches[3] : '.0') + . (!empty($matches[4]) ? $matches[4] : '.0'); + $index = 5; + } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) { // match date-based versioning + $version = preg_replace('{\D}', '-', $matches[1]); + $index = 2; + } elseif (preg_match('{^v?(\d{4,})(\.\d+)?(\.\d+)?(\.\d+)?' . self::$modifierRegex . '$}i', $version, $matches)) { + $version = $matches[1] + . (!empty($matches[2]) ? $matches[2] : '.0') + . (!empty($matches[3]) ? $matches[3] : '.0') + . (!empty($matches[4]) ? $matches[4] : '.0'); + $index = 5; + } + // add version modifiers if a version was matched + if (isset($index)) { + if (!empty($matches[$index])) { + if ('stable' === $matches[$index]) { + return $version; + } + $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? $matches[$index + 1] : ''); + } + if (!empty($matches[$index + 2])) { + $version .= '-dev'; + } + return $version; + } + $extraMessage = ''; + if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) { + $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; + } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) { + $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; + } + throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage); + } + + private function expandStability($stability) { + $stability = strtolower($stability); + switch ($stability) { + case 'a': + return 'alpha'; + case 'b': + return 'beta'; + case 'p': + case 'pl': + return 'patch'; + case 'rc': + return 'RC'; + default: + return $stability; + } + } +} |