Merge remote-tracking branch 'sroze/feature/path-repository'
commit
3a79313b63
|
@ -29,6 +29,7 @@
|
|||
"symfony/console": "~2.5",
|
||||
"symfony/finder": "~2.2",
|
||||
"symfony/process": "~2.1",
|
||||
"symfony/filesystem": "~2.5",
|
||||
"seld/phar-utils": "~1.0",
|
||||
"seld/cli-prompt": "~1.0"
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "6fbac2ddcd4e9064c84090f6d5514412",
|
||||
"hash": "3024e89a7e808b8dece156112459a7ea",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/spdx-licenses",
|
||||
|
@ -328,6 +328,56 @@
|
|||
"homepage": "https://symfony.com",
|
||||
"time": "2015-07-26 09:08:40"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v2.6.11",
|
||||
"target-dir": "Symfony/Component/Filesystem",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/Filesystem.git",
|
||||
"reference": "823c035b1a5c13a4924e324d016eb07e70f94735"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/823c035b1a5c13a4924e324d016eb07e70f94735",
|
||||
"reference": "823c035b1a5c13a4924e324d016eb07e70f94735",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.6-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Symfony\\Component\\Filesystem\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2015-07-08 05:59:48"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v2.6.11",
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Downloader;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
/**
|
||||
* Download a package from a local path.
|
||||
*
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
* @author Johann Reinke <johann.reinke@gmail.com>
|
||||
*/
|
||||
class PathDownloader extends FileDownloader
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function download(PackageInterface $package, $path)
|
||||
{
|
||||
$fileSystem = new Filesystem();
|
||||
if ($fileSystem->exists($path)) {
|
||||
$fileSystem->remove($path);
|
||||
}
|
||||
|
||||
try {
|
||||
$fileSystem->symlink($package->getDistUrl(), $path);
|
||||
} catch (IOException $e) {
|
||||
$fileSystem->mirror($package->getDistUrl(), $path);
|
||||
}
|
||||
|
||||
$this->io->writeError(sprintf(
|
||||
' Downloaded <info>%s</info> (<comment>%s</comment>) from %s',
|
||||
$package->getName(),
|
||||
$package->getFullPrettyVersion(),
|
||||
$package->getDistUrl()
|
||||
));
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ use Composer\Config\JsonConfigSource;
|
|||
use Composer\Json\JsonFile;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\Archiver;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Repository\RepositoryManager;
|
||||
use Composer\Repository\WritableRepositoryInterface;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
|
@ -264,7 +265,8 @@ class Factory
|
|||
|
||||
// load package
|
||||
$parser = new VersionParser;
|
||||
$loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, new ProcessExecutor($io));
|
||||
$guesser = new VersionGuesser(new ProcessExecutor($io), $parser);
|
||||
$loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
|
||||
$package = $loader->load($localConfig);
|
||||
$composer->setPackage($package);
|
||||
|
||||
|
@ -331,6 +333,7 @@ class Factory
|
|||
$rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
|
||||
$rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
|
||||
$rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
|
||||
$rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
|
||||
|
||||
return $rm;
|
||||
}
|
||||
|
@ -403,6 +406,7 @@ class Factory
|
|||
$dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache));
|
||||
$dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache));
|
||||
$dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache));
|
||||
$dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache));
|
||||
|
||||
return $dm;
|
||||
}
|
||||
|
|
|
@ -16,13 +16,10 @@ use Composer\Package\BasePackage;
|
|||
use Composer\Package\AliasPackage;
|
||||
use Composer\Config;
|
||||
use Composer\Factory;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Repository\RepositoryManager;
|
||||
use Composer\Repository\Vcs\HgDriver;
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Composer\Util\Git as GitUtil;
|
||||
use Composer\Util\Svn as SvnUtil;
|
||||
|
||||
/**
|
||||
* ArrayLoader built for the sole purpose of loading the root package
|
||||
|
@ -33,16 +30,28 @@ use Composer\Util\Svn as SvnUtil;
|
|||
*/
|
||||
class RootPackageLoader extends ArrayLoader
|
||||
{
|
||||
/**
|
||||
* @var RepositoryManager
|
||||
*/
|
||||
private $manager;
|
||||
private $config;
|
||||
private $process;
|
||||
|
||||
public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, ProcessExecutor $process = null)
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var VersionGuesser
|
||||
*/
|
||||
private $versionGuesser;
|
||||
|
||||
public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
|
||||
{
|
||||
parent::__construct($parser);
|
||||
|
||||
$this->manager = $manager;
|
||||
$this->config = $config;
|
||||
$this->process = $process ?: new ProcessExecutor();
|
||||
parent::__construct($parser);
|
||||
$this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor(), $this->versionParser);
|
||||
}
|
||||
|
||||
public function load(array $config, $class = 'Composer\Package\RootPackage')
|
||||
|
@ -56,7 +65,7 @@ class RootPackageLoader extends ArrayLoader
|
|||
if (getenv('COMPOSER_ROOT_VERSION')) {
|
||||
$version = getenv('COMPOSER_ROOT_VERSION');
|
||||
} else {
|
||||
$version = $this->guessVersion($config);
|
||||
$version = $this->versionGuesser->guessVersion($this->config, $config);
|
||||
}
|
||||
|
||||
if (!$version) {
|
||||
|
@ -176,172 +185,4 @@ class RootPackageLoader extends ArrayLoader
|
|||
|
||||
return $references;
|
||||
}
|
||||
|
||||
private function guessVersion(array $config)
|
||||
{
|
||||
if (function_exists('proc_open')) {
|
||||
$version = $this->guessGitVersion($config);
|
||||
if (null !== $version) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$version = $this->guessHgVersion($config);
|
||||
if (null !== $version) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
return $this->guessSvnVersion($config);
|
||||
}
|
||||
}
|
||||
|
||||
private function guessGitVersion(array $config)
|
||||
{
|
||||
GitUtil::cleanEnv();
|
||||
|
||||
// try to fetch current version from git tags
|
||||
if (0 === $this->process->execute('git describe --exact-match --tags', $output)) {
|
||||
try {
|
||||
return $this->versionParser->normalize(trim($output));
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// try to fetch current version from git branch
|
||||
if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output)) {
|
||||
$branches = array();
|
||||
$isFeatureBranch = false;
|
||||
$version = null;
|
||||
|
||||
// find current branch and collect all branch names
|
||||
foreach ($this->process->splitLines($output) as $branch) {
|
||||
if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
|
||||
if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') {
|
||||
$version = 'dev-'.$match[2];
|
||||
$isFeatureBranch = true;
|
||||
} else {
|
||||
$version = $this->versionParser->normalizeBranch($match[1]);
|
||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
|
||||
if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
|
||||
$branches[] = $match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isFeatureBranch) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// try to find the best (nearest) version branch to assume this feature's version
|
||||
$version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%');
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
private function guessHgVersion(array $config)
|
||||
{
|
||||
// try to fetch current version from hg branch
|
||||
if (0 === $this->process->execute('hg branch', $output)) {
|
||||
$branch = trim($output);
|
||||
$version = $this->versionParser->normalizeBranch($branch);
|
||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$branch;
|
||||
}
|
||||
|
||||
if (!$isFeatureBranch) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// re-use the HgDriver to fetch branches (this properly includes bookmarks)
|
||||
$config = array('url' => getcwd());
|
||||
$driver = new HgDriver($config, new NullIO(), $this->config, $this->process);
|
||||
$branches = array_keys($driver->getBranches());
|
||||
|
||||
// try to find the best (nearest) version branch to assume this feature's version
|
||||
$version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"');
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline)
|
||||
{
|
||||
// ignore feature branches if they have no branch-alias or self.version is used
|
||||
// and find the branch they came from to use as a version instead
|
||||
if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version]))
|
||||
|| strpos(json_encode($config), '"self.version"')
|
||||
) {
|
||||
$branch = preg_replace('{^dev-}', '', $version);
|
||||
$length = PHP_INT_MAX;
|
||||
|
||||
$nonFeatureBranches = '';
|
||||
if (!empty($config['non-feature-branches'])) {
|
||||
$nonFeatureBranches = implode('|', $config['non-feature-branches']);
|
||||
}
|
||||
|
||||
foreach ($branches as $candidate) {
|
||||
// return directly, if branch is configured to be non-feature branch
|
||||
if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// do not compare against other feature branches
|
||||
if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
|
||||
if (0 !== $this->process->execute($cmdLine, $output)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen($output) < $length) {
|
||||
$length = strlen($output);
|
||||
$version = $this->versionParser->normalizeBranch($candidate);
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
private function guessSvnVersion(array $config)
|
||||
{
|
||||
SvnUtil::cleanEnv();
|
||||
|
||||
// try to fetch current version from svn
|
||||
if (0 === $this->process->execute('svn info --xml', $output)) {
|
||||
$trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk';
|
||||
$branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches';
|
||||
$tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags';
|
||||
|
||||
$urlPattern = '#<url>.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))</url>#';
|
||||
|
||||
if (preg_match($urlPattern, $output, $matches)) {
|
||||
if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
|
||||
// we are in a branches path
|
||||
$version = $this->versionParser->normalizeBranch($matches[3]);
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$matches[3];
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
return $this->versionParser->normalize(trim($matches[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Package\Version;
|
||||
|
||||
use Composer\Config;
|
||||
use Composer\Repository\Vcs\HgDriver;
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Util\Git as GitUtil;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Composer\Util\Svn as SvnUtil;
|
||||
|
||||
/**
|
||||
* Try to guess the current version number based on different VCS configuration.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
*/
|
||||
class VersionGuesser
|
||||
{
|
||||
/**
|
||||
* @var ProcessExecutor
|
||||
*/
|
||||
private $process;
|
||||
|
||||
/**
|
||||
* @var VersionParser
|
||||
*/
|
||||
private $versionParser;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $cwd;
|
||||
|
||||
/**
|
||||
* @param ProcessExecutor $process
|
||||
* @param VersionParser $versionParser
|
||||
* @param string $cwd
|
||||
*/
|
||||
public function __construct(ProcessExecutor $process, VersionParser $versionParser, $cwd = null)
|
||||
{
|
||||
$this->process = $process;
|
||||
$this->versionParser = $versionParser;
|
||||
$this->cwd = $cwd ?: getcwd();
|
||||
}
|
||||
|
||||
public function guessVersion(Config $config, array $packageConfig)
|
||||
{
|
||||
if (function_exists('proc_open')) {
|
||||
$version = $this->guessGitVersion($packageConfig);
|
||||
if (null !== $version) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$version = $this->guessHgVersion($config, $packageConfig);
|
||||
if (null !== $version) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
return $this->guessSvnVersion($packageConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private function guessGitVersion(array $config)
|
||||
{
|
||||
GitUtil::cleanEnv();
|
||||
|
||||
// try to fetch current version from git tags
|
||||
if (0 === $this->process->execute('git describe --exact-match --tags', $output, $this->cwd)) {
|
||||
try {
|
||||
return $this->versionParser->normalize(trim($output));
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// try to fetch current version from git branch
|
||||
if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->cwd)) {
|
||||
$branches = array();
|
||||
$isFeatureBranch = false;
|
||||
$version = null;
|
||||
|
||||
// find current branch and collect all branch names
|
||||
foreach ($this->process->splitLines($output) as $branch) {
|
||||
if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
|
||||
if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ') {
|
||||
$version = 'dev-'.$match[2];
|
||||
$isFeatureBranch = true;
|
||||
} else {
|
||||
$version = $this->versionParser->normalizeBranch($match[1]);
|
||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
|
||||
if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
|
||||
$branches[] = $match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isFeatureBranch) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// try to find the best (nearest) version branch to assume this feature's version
|
||||
$version = $this->guessFeatureVersion($config, $version, $branches, 'git rev-list %candidate%..%branch%');
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
private function guessHgVersion(Config $config, array $packageConfig)
|
||||
{
|
||||
// try to fetch current version from hg branch
|
||||
if (0 === $this->process->execute('hg branch', $output, $this->cwd)) {
|
||||
$branch = trim($output);
|
||||
$version = $this->versionParser->normalizeBranch($branch);
|
||||
$isFeatureBranch = 0 === strpos($version, 'dev-');
|
||||
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$branch;
|
||||
}
|
||||
|
||||
if (!$isFeatureBranch) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// re-use the HgDriver to fetch branches (this properly includes bookmarks)
|
||||
$packageConfig = array('url' => $this->cwd);
|
||||
$driver = new HgDriver($packageConfig, new NullIO(), $config, $this->process);
|
||||
$branches = array_keys($driver->getBranches());
|
||||
|
||||
// try to find the best (nearest) version branch to assume this feature's version
|
||||
$version = $this->guessFeatureVersion($config, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"');
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
private function guessFeatureVersion(array $config, $version, array $branches, $scmCmdline)
|
||||
{
|
||||
// ignore feature branches if they have no branch-alias or self.version is used
|
||||
// and find the branch they came from to use as a version instead
|
||||
if ((isset($config['extra']['branch-alias']) && !isset($config['extra']['branch-alias'][$version]))
|
||||
|| strpos(json_encode($config), '"self.version"')
|
||||
) {
|
||||
$branch = preg_replace('{^dev-}', '', $version);
|
||||
$length = PHP_INT_MAX;
|
||||
|
||||
$nonFeatureBranches = '';
|
||||
if (!empty($config['non-feature-branches'])) {
|
||||
$nonFeatureBranches = implode('|', $config['non-feature-branches']);
|
||||
}
|
||||
|
||||
foreach ($branches as $candidate) {
|
||||
// return directly, if branch is configured to be non-feature branch
|
||||
if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
// do not compare against other feature branches
|
||||
if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
|
||||
if (0 !== $this->process->execute($cmdLine, $output, $this->cwd)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen($output) < $length) {
|
||||
$length = strlen($output);
|
||||
$version = $this->versionParser->normalizeBranch($candidate);
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
private function guessSvnVersion(array $config)
|
||||
{
|
||||
SvnUtil::cleanEnv();
|
||||
|
||||
// try to fetch current version from svn
|
||||
if (0 === $this->process->execute('svn info --xml', $output, $this->cwd)) {
|
||||
$trunkPath = isset($config['trunk-path']) ? preg_quote($config['trunk-path'], '#') : 'trunk';
|
||||
$branchesPath = isset($config['branches-path']) ? preg_quote($config['branches-path'], '#') : 'branches';
|
||||
$tagsPath = isset($config['tags-path']) ? preg_quote($config['tags-path'], '#') : 'tags';
|
||||
|
||||
$urlPattern = '#<url>.*/('.$trunkPath.'|('.$branchesPath.'|'. $tagsPath .')/(.*))</url>#';
|
||||
|
||||
if (preg_match($urlPattern, $output, $matches)) {
|
||||
if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
|
||||
// we are in a branches path
|
||||
$version = $this->versionParser->normalizeBranch($matches[3]);
|
||||
if ('9999999-dev' === $version) {
|
||||
$version = 'dev-'.$matches[3];
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
return $this->versionParser->normalize(trim($matches[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository;
|
||||
|
||||
use Composer\Config;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
use Composer\Package\Loader\LoaderInterface;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
/**
|
||||
* This repository allows installing local packages that are not necessarily under their own VCS.
|
||||
*
|
||||
* The local packages will be symlinked when possible, else they will be copied.
|
||||
*
|
||||
* @code
|
||||
* "require": {
|
||||
* "<vendor>/<local-package>": "*"
|
||||
* },
|
||||
* "repositories": [
|
||||
* {
|
||||
* "type": "path",
|
||||
* "url": "../../relative/path/to/package/"
|
||||
* },
|
||||
* {
|
||||
* "type": "path",
|
||||
* "url": "/absolute/path/to/package/"
|
||||
* }
|
||||
* ]
|
||||
* @endcode
|
||||
*
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
* @author Johann Reinke <johann.reinke@gmail.com>
|
||||
*/
|
||||
class PathRepository extends ArrayRepository
|
||||
{
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
private $fileSystem;
|
||||
|
||||
/**
|
||||
* @var ArrayLoader
|
||||
*/
|
||||
private $loader;
|
||||
|
||||
/**
|
||||
* @var VersionGuesser
|
||||
*/
|
||||
private $versionGuesser;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $packageConfig;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* Initializes path repository.
|
||||
*
|
||||
* @param array $packageConfig
|
||||
* @param IOInterface $io
|
||||
* @param Config $config
|
||||
* @param LoaderInterface $loader
|
||||
* @param Filesystem $filesystem
|
||||
* @param VersionGuesser $versionGuesser
|
||||
*/
|
||||
public function __construct(array $packageConfig, IOInterface $io, Config $config, LoaderInterface $loader = null, Filesystem $filesystem = null, VersionGuesser $versionGuesser = null)
|
||||
{
|
||||
if (!isset($packageConfig['url'])) {
|
||||
throw new \RuntimeException('You must specify the `url` configuration for the path repository');
|
||||
}
|
||||
|
||||
$this->fileSystem = $filesystem ?: new Filesystem();
|
||||
$this->loader = $loader ?: new ArrayLoader();
|
||||
$this->config = $config;
|
||||
$this->packageConfig = $packageConfig;
|
||||
$this->path = realpath(rtrim($packageConfig['url'], '/')) . '/';
|
||||
$this->versionGuesser = $versionGuesser ?: new VersionGuesser(new ProcessExecutor($io), new VersionParser(), $this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes path repository.
|
||||
*
|
||||
* This method will basically read the folder and add the found package.
|
||||
*
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$composerFilePath = $this->path.'composer.json';
|
||||
if (!$this->fileSystem->exists($composerFilePath)) {
|
||||
throw new \RuntimeException(sprintf('No `composer.json` file found in path repository "%s"', $this->path));
|
||||
}
|
||||
|
||||
$json = file_get_contents($composerFilePath);
|
||||
$package = JsonFile::parseJson($json, $composerFilePath);
|
||||
$package['dist'] = array(
|
||||
'type' => 'path',
|
||||
'url' => $this->path,
|
||||
);
|
||||
|
||||
if (!isset($package['version'])) {
|
||||
$package['version'] = $this->versionGuesser->guessVersion($this->config, $this->packageConfig) ?: 'dev-master';
|
||||
}
|
||||
|
||||
$package = $this->loader->load($package);
|
||||
$this->addPackage($package);
|
||||
}
|
||||
}
|
|
@ -508,7 +508,14 @@ class Filesystem
|
|||
return unlink($path);
|
||||
}
|
||||
|
||||
private function isSymlinkedDirectory($directory)
|
||||
/**
|
||||
* return true if that directory is a symlink.
|
||||
*
|
||||
* @param string $directory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSymlinkedDirectory($directory)
|
||||
{
|
||||
if (!is_dir($directory)) {
|
||||
return false;
|
||||
|
|
|
@ -15,175 +15,11 @@ namespace Composer\Test\Package\Loader;
|
|||
use Composer\Config;
|
||||
use Composer\Package\Loader\RootPackageLoader;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
|
||||
class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testDetachedHeadBecomesDevHash()
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
$this->markTestSkipped('proc_open() is not available');
|
||||
}
|
||||
|
||||
$commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
|
||||
|
||||
$manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor
|
||||
->expects($this->at(0))
|
||||
->method('execute')
|
||||
->with('git describe --exact-match --tags')
|
||||
->willReturn(1)
|
||||
;
|
||||
|
||||
$self = $this;
|
||||
|
||||
$executor
|
||||
->expects($this->at(1))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self, $commitHash) {
|
||||
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
||||
$output = "* (no branch) $commitHash Commit message\n";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, $executor);
|
||||
$package = $loader->load(array());
|
||||
|
||||
$this->assertEquals("dev-$commitHash", $package->getVersion());
|
||||
}
|
||||
|
||||
public function testTagBecomesVersion()
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
$this->markTestSkipped('proc_open() is not available');
|
||||
}
|
||||
|
||||
$manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$self = $this;
|
||||
|
||||
$executor
|
||||
->expects($this->at(0))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||
$self->assertEquals('git describe --exact-match --tags', $command);
|
||||
$output = "v2.0.5-alpha2";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, $executor);
|
||||
$package = $loader->load(array());
|
||||
|
||||
$this->assertEquals("2.0.5.0-alpha2", $package->getVersion());
|
||||
}
|
||||
|
||||
public function testInvalidTagBecomesVersion()
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
$this->markTestSkipped('proc_open() is not available');
|
||||
}
|
||||
|
||||
$manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$self = $this;
|
||||
|
||||
$executor
|
||||
->expects($this->at(0))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||
$self->assertEquals('git describe --exact-match --tags', $command);
|
||||
$output = "foo-bar";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$executor
|
||||
->expects($this->at(1))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
||||
$output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, $executor);
|
||||
$package = $loader->load(array());
|
||||
|
||||
$this->assertEquals("dev-foo", $package->getVersion());
|
||||
}
|
||||
|
||||
public function testNoVersionIsVisibleInPrettyVersion()
|
||||
{
|
||||
$manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor
|
||||
->expects($this->any())
|
||||
->method('execute')
|
||||
->willReturn(null)
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, $executor);
|
||||
$package = $loader->load(array());
|
||||
|
||||
$this->assertEquals("1.0.0.0", $package->getVersion());
|
||||
$this->assertEquals("No version set (parsed as 1.0.0)", $package->getPrettyVersion());
|
||||
}
|
||||
|
||||
protected function loadPackage($data)
|
||||
{
|
||||
$manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager')
|
||||
|
@ -218,6 +54,37 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
), $package->getStabilityFlags());
|
||||
}
|
||||
|
||||
public function testNoVersionIsVisibleInPrettyVersion()
|
||||
{
|
||||
$manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor
|
||||
->expects($this->any())
|
||||
->method('execute')
|
||||
->willReturn(null)
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser()));
|
||||
$package = $loader->load(array());
|
||||
|
||||
$this->assertEquals("1.0.0.0", $package->getVersion());
|
||||
$this->assertEquals("No version set (parsed as 1.0.0)", $package->getPrettyVersion());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testFeatureBranchPrettyVersion()
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
|
@ -272,7 +139,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, $executor);
|
||||
$loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser()));
|
||||
$package = $loader->load(array('require' => array('foo/bar' => 'self.version')));
|
||||
|
||||
$this->assertEquals("dev-master", $package->getPrettyVersion());
|
||||
|
@ -321,7 +188,7 @@ class RootPackageLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$loader = new RootPackageLoader($manager, $config, null, $executor);
|
||||
$loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($executor, new VersionParser()));
|
||||
$package = $loader->load(array('require' => array('foo/bar' => 'self.version'), "non-feature-branches" => array("latest-.*")));
|
||||
|
||||
$this->assertEquals("dev-latest-production", $package->getPrettyVersion());
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Test\Package\Version;
|
||||
|
||||
use Composer\Config;
|
||||
use Composer\Package\Version\VersionGuesser;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
|
||||
class VersionGuesserTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
$this->markTestSkipped('proc_open() is not available');
|
||||
}
|
||||
}
|
||||
|
||||
public function testDetachedHeadBecomesDevHash()
|
||||
{
|
||||
$commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
|
||||
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$executor
|
||||
->expects($this->at(0))
|
||||
->method('execute')
|
||||
->with('git describe --exact-match --tags')
|
||||
->willReturn(1)
|
||||
;
|
||||
|
||||
$self = $this;
|
||||
|
||||
$executor
|
||||
->expects($this->at(1))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self, $commitHash) {
|
||||
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
||||
$output = "* (no branch) $commitHash Commit message\n";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$guesser = new VersionGuesser($executor, new VersionParser());
|
||||
$version = $guesser->guessVersion($config, array());
|
||||
|
||||
$this->assertEquals("dev-$commitHash", $version);
|
||||
}
|
||||
|
||||
public function testTagBecomesVersion()
|
||||
{
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$self = $this;
|
||||
|
||||
$executor
|
||||
->expects($this->at(0))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||
$self->assertEquals('git describe --exact-match --tags', $command);
|
||||
$output = "v2.0.5-alpha2";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$guesser = new VersionGuesser($executor, new VersionParser());
|
||||
$version = $guesser->guessVersion($config, array());
|
||||
|
||||
$this->assertEquals("2.0.5.0-alpha2", $version);
|
||||
}
|
||||
|
||||
public function testInvalidTagBecomesVersion()
|
||||
{
|
||||
$executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
|
||||
->setMethods(array('execute'))
|
||||
->disableArgumentCloning()
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$self = $this;
|
||||
|
||||
$executor
|
||||
->expects($this->at(0))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||
$self->assertEquals('git describe --exact-match --tags', $command);
|
||||
$output = "foo-bar";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$executor
|
||||
->expects($this->at(1))
|
||||
->method('execute')
|
||||
->willReturnCallback(function ($command, &$output) use ($self) {
|
||||
$self->assertEquals('git branch --no-color --no-abbrev -v', $command);
|
||||
$output = "* foo 03a15d220da53c52eddd5f32ffca64a7b3801bea Commit message\n";
|
||||
|
||||
return 0;
|
||||
})
|
||||
;
|
||||
|
||||
$config = new Config;
|
||||
$config->merge(array('repositories' => array('packagist' => false)));
|
||||
$guesser = new VersionGuesser($executor, new VersionParser());
|
||||
$version = $guesser->guessVersion($config, array());
|
||||
|
||||
$this->assertEquals("dev-foo", $version);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "test/path",
|
||||
"version": "0.0.2"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"name": "test/path"
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository;
|
||||
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\TestCase;
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Config;
|
||||
use Composer\Package\BasePackage;
|
||||
|
||||
class PathRepositoryTest extends TestCase
|
||||
{
|
||||
public function testLoadPackageFromFileSystemWithVersion()
|
||||
{
|
||||
$ioInterface = $this->getMockBuilder('Composer\IO\IOInterface')
|
||||
->getMock();
|
||||
|
||||
$config = new \Composer\Config();
|
||||
$loader = new ArrayLoader(new VersionParser());
|
||||
$versionGuesser = null;
|
||||
|
||||
$repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', 'with-version'));
|
||||
$repository = new PathRepository(array('url' => $repositoryUrl), $ioInterface, $config, $loader);
|
||||
$repository->getPackages();
|
||||
|
||||
$this->assertEquals(1, $repository->count());
|
||||
$this->assertTrue($repository->hasPackage($this->getPackage('test/path', '0.0.2')));
|
||||
}
|
||||
|
||||
public function testLoadPackageFromFileSystemWithoutVersion()
|
||||
{
|
||||
$ioInterface = $this->getMockBuilder('Composer\IO\IOInterface')
|
||||
->getMock();
|
||||
|
||||
$config = new \Composer\Config();
|
||||
$loader = new ArrayLoader(new VersionParser());
|
||||
$versionGuesser = null;
|
||||
|
||||
$repositoryUrl = implode(DIRECTORY_SEPARATOR, array(__DIR__, 'Fixtures', 'path', 'without-version'));
|
||||
$repository = new PathRepository(array('url' => $repositoryUrl), $ioInterface, $config, $loader);
|
||||
$packages = $repository->getPackages();
|
||||
|
||||
$this->assertEquals(1, $repository->count());
|
||||
|
||||
$package = $packages[0];
|
||||
$this->assertEquals('test/path', $package->getName());
|
||||
|
||||
$packageVersion = $package->getVersion();
|
||||
$this->assertTrue(!empty($packageVersion));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue