Merge remote-tracking branch 'github-seldaek/stability'
* github-seldaek/stability: Add stability docs Add test for Pool handling and refactor a couple things Add support for stabilities in lock file Infer stability flags for requirements that have an explicit version required of a lower stability Add InstalledArrayRepository to make sure the root package is not purged by the Pool because of a lower stability Basic handling of stability flags Add list of stabilities to base package Add minimum-stability flag on root package to filter packages by stability Add CompositeRepo::getRepositories Add package stabilitypull/682/head
commit
7c7cac61b6
|
@ -200,22 +200,10 @@ An example:
|
||||||
|
|
||||||
Optional, but highly recommended.
|
Optional, but highly recommended.
|
||||||
|
|
||||||
### Package links <span>(require, require-dev, conflict, replace, provide)</span>
|
### Package links
|
||||||
|
|
||||||
Each of these takes an object which maps package names to version constraints.
|
All of the following take an object which maps package names to
|
||||||
|
[version constraints](01-basic-usage.md#package-versions).
|
||||||
* **require:** Packages required by this package.
|
|
||||||
* **require-dev:** Packages required for developing this package, or running
|
|
||||||
tests, etc. They are installed if install or update is ran with `--dev`.
|
|
||||||
* **conflict:** Mark this version of this package as conflicting with other
|
|
||||||
packages.
|
|
||||||
* **replace:** Packages that can be replaced by this package. This is useful
|
|
||||||
for large repositories with subtree splits. It allows the main package to
|
|
||||||
replace all of it's child packages.
|
|
||||||
* **provide:** List of other packages that are provided by this package. This
|
|
||||||
is mostly useful for common interfaces. A package could depend on some virtual
|
|
||||||
`logger` package, any library that provides this logger, would simply list it
|
|
||||||
in `provide`.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -225,7 +213,59 @@ Example:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional.
|
All links are optional fields.
|
||||||
|
|
||||||
|
`require` and `require-dev` additionally support stability flags (root-only).
|
||||||
|
These allow you to further restrict or expand the stability of a package beyond
|
||||||
|
the scope of the [minimum-stability](#minimum-stability) setting. You can apply
|
||||||
|
them to a constraint, or just apply them to an empty constraint if you want to
|
||||||
|
allow unstable packages of a dependency's dependency for example.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"monolog/monolog": "1.0.*@beta"
|
||||||
|
"acme/foo": "@dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#### require
|
||||||
|
|
||||||
|
Lists packages required by this package. The package will not be installed
|
||||||
|
unless those requirements can be met.
|
||||||
|
|
||||||
|
#### require-dev
|
||||||
|
|
||||||
|
Lists packages required for developing this package, or running
|
||||||
|
tests, etc. They are installed if install or update is ran with `--dev`.
|
||||||
|
|
||||||
|
#### conflict
|
||||||
|
|
||||||
|
Lists packages that conflict with this version of this package. They
|
||||||
|
will not be allowed to be installed together with your package.
|
||||||
|
|
||||||
|
#### replace
|
||||||
|
|
||||||
|
Lists packages that are replaced by this package.
|
||||||
|
|
||||||
|
This is useful for packages that contain sub-packages, for example the main
|
||||||
|
symfony/symfony package contains all the Symfony Components which are also
|
||||||
|
available as individual packages. If you require the main package it will
|
||||||
|
automatically fulfill any requirement of one of the individual components,
|
||||||
|
since it replaces them.
|
||||||
|
|
||||||
|
Caution is advised when using replace however, for the sub-package example
|
||||||
|
above you should typically only replace using `self.version` as a version
|
||||||
|
constraint, to make sure the main package only replaces the sub-packages of
|
||||||
|
that exact version, and not any other version, which would be incorrect.
|
||||||
|
|
||||||
|
#### provide
|
||||||
|
|
||||||
|
List of other packages that are provided by this package. This is mostly
|
||||||
|
useful for common interfaces. A package could depend on some virtual
|
||||||
|
`logger` package, any library that implements this logger interface would
|
||||||
|
simply list it in `provide`.
|
||||||
|
|
||||||
### suggest
|
### suggest
|
||||||
|
|
||||||
|
@ -340,6 +380,19 @@ To do that, `autoload` and `target-dir` are defined as follows:
|
||||||
|
|
||||||
Optional.
|
Optional.
|
||||||
|
|
||||||
|
### minimum-stability <span>(root-only)</span>
|
||||||
|
|
||||||
|
This defines the default behavior for filtering packages by stability. This
|
||||||
|
defaults to `dev` but in the future will be switched to `stable`. As such if
|
||||||
|
you rely on a default of `dev` you should specify it in your file to avoid
|
||||||
|
surprises.
|
||||||
|
|
||||||
|
All versions of each package is checked for stability, and those that are less
|
||||||
|
stable than the `minimum-stability` setting will be ignored when resolving
|
||||||
|
your project dependencies. Specific changes to the stability requirements of
|
||||||
|
a given package can be done in `require` or `require-dev` (see
|
||||||
|
[package links](#package-links)).
|
||||||
|
|
||||||
### repositories <span>(root-only)</span>
|
### repositories <span>(root-only)</span>
|
||||||
|
|
||||||
Custom package repositories to use.
|
Custom package repositories to use.
|
||||||
|
|
|
@ -143,6 +143,10 @@
|
||||||
"description": "A set of additional repositories where packages can be found.",
|
"description": "A set of additional repositories where packages can be found.",
|
||||||
"additionalProperties": true
|
"additionalProperties": true
|
||||||
},
|
},
|
||||||
|
"minimum-stability": {
|
||||||
|
"type": ["string"],
|
||||||
|
"description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable."
|
||||||
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"type": ["array"],
|
"type": ["array"],
|
||||||
"description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
|
"description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
|
||||||
|
|
|
@ -12,19 +12,39 @@
|
||||||
|
|
||||||
namespace Composer\DependencyResolver;
|
namespace Composer\DependencyResolver;
|
||||||
|
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Package\LinkConstraint\LinkConstraintInterface;
|
use Composer\Package\LinkConstraint\LinkConstraintInterface;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
|
use Composer\Repository\CompositeRepository;
|
||||||
|
use Composer\Repository\InstalledRepositoryInterface;
|
||||||
|
use Composer\Repository\PlatformRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A package pool contains repositories that provide packages.
|
* A package pool contains repositories that provide packages.
|
||||||
*
|
*
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class Pool
|
class Pool
|
||||||
{
|
{
|
||||||
protected $repositories = array();
|
protected $repositories = array();
|
||||||
protected $packages = array();
|
protected $packages = array();
|
||||||
protected $packageByName = array();
|
protected $packageByName = array();
|
||||||
|
protected $acceptableStabilities;
|
||||||
|
protected $stabilityFlags;
|
||||||
|
|
||||||
|
// TODO BC change to stable end of june?
|
||||||
|
public function __construct($minimumStability = 'dev', array $stabilityFlags = array())
|
||||||
|
{
|
||||||
|
$stabilities = BasePackage::$stabilities;
|
||||||
|
$this->acceptableStabilities = array();
|
||||||
|
foreach (BasePackage::$stabilities as $stability => $value) {
|
||||||
|
if ($value <= BasePackage::$stabilities[$minimumStability]) {
|
||||||
|
$this->acceptableStabilities[$stability] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->stabilityFlags = $stabilityFlags;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a repository and its packages to this package pool
|
* Adds a repository and its packages to this package pool
|
||||||
|
@ -33,14 +53,38 @@ class Pool
|
||||||
*/
|
*/
|
||||||
public function addRepository(RepositoryInterface $repo)
|
public function addRepository(RepositoryInterface $repo)
|
||||||
{
|
{
|
||||||
$this->repositories[] = $repo;
|
if ($repo instanceof CompositeRepository) {
|
||||||
|
$repos = $repo->getRepositories();
|
||||||
|
} else {
|
||||||
|
$repos = array($repo);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($repo->getPackages() as $package) {
|
$id = count($this->packages) + 1;
|
||||||
$package->setId(count($this->packages) + 1);
|
foreach ($repos as $repo) {
|
||||||
$this->packages[] = $package;
|
$this->repositories[] = $repo;
|
||||||
|
|
||||||
foreach ($package->getNames() as $name) {
|
$exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
|
||||||
$this->packageByName[$name][] = $package;
|
foreach ($repo->getPackages() as $package) {
|
||||||
|
$name = $package->getName();
|
||||||
|
$stability = $package->getStability();
|
||||||
|
if (
|
||||||
|
// always allow exempt repos
|
||||||
|
$exempt
|
||||||
|
// allow if package matches the global stability requirement and has no exception
|
||||||
|
|| (!isset($this->stabilityFlags[$name])
|
||||||
|
&& isset($this->acceptableStabilities[$stability]))
|
||||||
|
// allow if package matches the package-specific stability flag
|
||||||
|
|| (isset($this->stabilityFlags[$name])
|
||||||
|
&& BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$name]
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
$package->setId($id++);
|
||||||
|
$this->packages[] = $package;
|
||||||
|
|
||||||
|
foreach ($package->getNames() as $name) {
|
||||||
|
$this->packageByName[$name][] = $package;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use Composer\Package\Locker;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Repository\ArrayRepository;
|
use Composer\Repository\ArrayRepository;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
|
use Composer\Repository\InstalledArrayRepository;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Repository\RepositoryManager;
|
use Composer\Repository\RepositoryManager;
|
||||||
|
@ -139,7 +140,7 @@ class Installer
|
||||||
$repos = array_merge(
|
$repos = array_merge(
|
||||||
$this->repositoryManager->getLocalRepositories(),
|
$this->repositoryManager->getLocalRepositories(),
|
||||||
array(
|
array(
|
||||||
new ArrayRepository(array($this->package)),
|
new InstalledArrayRepository(array($this->package)),
|
||||||
new PlatformRepository(),
|
new PlatformRepository(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -179,7 +180,9 @@ class Installer
|
||||||
$updatedLock = $this->locker->setLockData(
|
$updatedLock = $this->locker->setLockData(
|
||||||
$this->repositoryManager->getLocalRepository()->getPackages(),
|
$this->repositoryManager->getLocalRepository()->getPackages(),
|
||||||
$this->devMode ? $this->repositoryManager->getLocalDevRepository()->getPackages() : null,
|
$this->devMode ? $this->repositoryManager->getLocalDevRepository()->getPackages() : null,
|
||||||
$aliases
|
$aliases,
|
||||||
|
$this->package->getMinimumStability(),
|
||||||
|
$this->package->getStabilityFlags()
|
||||||
);
|
);
|
||||||
if ($updatedLock) {
|
if ($updatedLock) {
|
||||||
$this->io->write('<info>Writing lock file</info>');
|
$this->io->write('<info>Writing lock file</info>');
|
||||||
|
@ -201,13 +204,18 @@ class Installer
|
||||||
|
|
||||||
protected function doInstall($localRepo, $installedRepo, $aliases, $devMode = false)
|
protected function doInstall($localRepo, $installedRepo, $aliases, $devMode = false)
|
||||||
{
|
{
|
||||||
|
$minimumStability = $this->package->getMinimumStability();
|
||||||
|
$stabilityFlags = $this->package->getStabilityFlags();
|
||||||
|
|
||||||
// initialize locker to create aliased packages
|
// initialize locker to create aliased packages
|
||||||
if (!$this->update && $this->locker->isLocked($devMode)) {
|
if (!$this->update && $this->locker->isLocked($devMode)) {
|
||||||
$lockedPackages = $this->locker->getLockedPackages($devMode);
|
$lockedPackages = $this->locker->getLockedPackages($devMode);
|
||||||
|
$minimumStability = $this->locker->getMinimumStability();
|
||||||
|
$stabilityFlags = $this->locker->getStabilityFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
// creating repository pool
|
// creating repository pool
|
||||||
$pool = new Pool;
|
$pool = new Pool($minimumStability, $stabilityFlags);
|
||||||
$pool->addRepository($installedRepo);
|
$pool->addRepository($installedRepo);
|
||||||
foreach ($this->repositoryManager->getRepositories() as $repository) {
|
foreach ($this->repositoryManager->getRepositories() as $repository) {
|
||||||
$pool->addRepository($repository);
|
$pool->addRepository($repository);
|
||||||
|
|
|
@ -28,6 +28,7 @@ class AliasPackage extends BasePackage
|
||||||
protected $dev;
|
protected $dev;
|
||||||
protected $aliasOf;
|
protected $aliasOf;
|
||||||
protected $rootPackageAlias = false;
|
protected $rootPackageAlias = false;
|
||||||
|
protected $stability;
|
||||||
|
|
||||||
protected $requires;
|
protected $requires;
|
||||||
protected $conflicts;
|
protected $conflicts;
|
||||||
|
@ -50,7 +51,8 @@ class AliasPackage extends BasePackage
|
||||||
$this->version = $version;
|
$this->version = $version;
|
||||||
$this->prettyVersion = $prettyVersion;
|
$this->prettyVersion = $prettyVersion;
|
||||||
$this->aliasOf = $aliasOf;
|
$this->aliasOf = $aliasOf;
|
||||||
$this->dev = VersionParser::isDev($version);
|
$this->stability = VersionParser::parseStability($version);
|
||||||
|
$this->dev = $this->stability === 'dev';
|
||||||
|
|
||||||
// replace self.version dependencies
|
// replace self.version dependencies
|
||||||
foreach (array('requires', 'devRequires') as $type) {
|
foreach (array('requires', 'devRequires') as $type) {
|
||||||
|
@ -91,6 +93,14 @@ class AliasPackage extends BasePackage
|
||||||
return $this->version;
|
return $this->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getStability()
|
||||||
|
{
|
||||||
|
return $this->stability;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,6 +32,20 @@ abstract class BasePackage implements PackageInterface
|
||||||
'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
|
'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const STABILITY_STABLE = 0;
|
||||||
|
const STABILITY_RC = 5;
|
||||||
|
const STABILITY_BETA = 10;
|
||||||
|
const STABILITY_ALPHA = 15;
|
||||||
|
const STABILITY_DEV = 20;
|
||||||
|
|
||||||
|
public static $stabilities = array(
|
||||||
|
'stable' => self::STABILITY_STABLE,
|
||||||
|
'RC' => self::STABILITY_RC,
|
||||||
|
'beta' => self::STABILITY_BETA,
|
||||||
|
'alpha' => self::STABILITY_ALPHA,
|
||||||
|
'dev' => self::STABILITY_DEV,
|
||||||
|
);
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $prettyName;
|
protected $prettyName;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Composer\Package\Loader;
|
namespace Composer\Package\Loader;
|
||||||
|
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
use Composer\Repository\RepositoryManager;
|
use Composer\Repository\RepositoryManager;
|
||||||
use Composer\Util\ProcessExecutor;
|
use Composer\Util\ProcessExecutor;
|
||||||
|
@ -60,20 +61,22 @@ class RootPackageLoader extends ArrayLoader
|
||||||
|
|
||||||
$package = parent::load($config);
|
$package = parent::load($config);
|
||||||
|
|
||||||
|
$aliases = array();
|
||||||
|
$stabilityFlags = array();
|
||||||
if (isset($config['require'])) {
|
if (isset($config['require'])) {
|
||||||
$aliases = array();
|
$aliases = $this->extractAliases($config['require'], $aliases);
|
||||||
foreach ($config['require'] as $reqName => $reqVersion) {
|
$stabilityFlags = $this->extractStabilityFlags($config['require'], $stabilityFlags);
|
||||||
if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $reqVersion, $match)) {
|
}
|
||||||
$aliases[] = array(
|
if (isset($config['require-dev'])) {
|
||||||
'package' => strtolower($reqName),
|
$aliases = $this->extractAliases($config['require-dev'], $aliases);
|
||||||
'version' => $this->versionParser->normalize($match[1]),
|
$stabilityFlags = $this->extractStabilityFlags($config['require-dev'], $stabilityFlags);
|
||||||
'alias' => $match[2],
|
}
|
||||||
'alias_normalized' => $this->versionParser->normalize($match[2]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$package->setAliases($aliases);
|
$package->setAliases($aliases);
|
||||||
|
$package->setStabilityFlags($stabilityFlags);
|
||||||
|
|
||||||
|
if (isset($config['minimum-stability'])) {
|
||||||
|
$package->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($config['repositories'])) {
|
if (isset($config['repositories'])) {
|
||||||
|
@ -95,4 +98,51 @@ class RootPackageLoader extends ArrayLoader
|
||||||
|
|
||||||
return $package;
|
return $package;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function extractAliases(array $requires, array $aliases)
|
||||||
|
{
|
||||||
|
foreach ($requires as $reqName => $reqVersion) {
|
||||||
|
if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $reqVersion, $match)) {
|
||||||
|
$aliases[] = array(
|
||||||
|
'package' => strtolower($reqName),
|
||||||
|
'version' => $this->versionParser->normalize($match[1]),
|
||||||
|
'alias' => $match[2],
|
||||||
|
'alias_normalized' => $this->versionParser->normalize($match[2]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function extractStabilityFlags(array $requires, array $stabilityFlags)
|
||||||
|
{
|
||||||
|
$stabilities = BasePackage::$stabilities;
|
||||||
|
foreach ($requires as $reqName => $reqVersion) {
|
||||||
|
// parse explicit stability flags
|
||||||
|
if (preg_match('{^[^,\s]*?@('.implode('|', array_keys($stabilities)).')$}i', $reqVersion, $match)) {
|
||||||
|
$name = strtolower($reqName);
|
||||||
|
$stability = $stabilities[VersionParser::normalizeStability($match[1])];
|
||||||
|
|
||||||
|
if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$stabilityFlags[$name] = $stability;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// infer flags for requirements that have an explicit -dev or -beta version specified for example
|
||||||
|
if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
|
||||||
|
$name = strtolower($reqName);
|
||||||
|
$stability = $stabilities[$stabilityName];
|
||||||
|
if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$stabilityFlags[$name] = $stability;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stabilityFlags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,10 +82,10 @@ class Locker
|
||||||
*/
|
*/
|
||||||
public function getLockedPackages($dev = false)
|
public function getLockedPackages($dev = false)
|
||||||
{
|
{
|
||||||
$lockList = $this->getLockData();
|
$lockData = $this->getLockData();
|
||||||
$packages = array();
|
$packages = array();
|
||||||
|
|
||||||
$lockedPackages = $dev ? $lockList['packages-dev'] : $lockList['packages'];
|
$lockedPackages = $dev ? $lockData['packages-dev'] : $lockData['packages'];
|
||||||
$repo = $dev ? $this->repositoryManager->getLocalDevRepository() : $this->repositoryManager->getLocalRepository();
|
$repo = $dev ? $this->repositoryManager->getLocalDevRepository() : $this->repositoryManager->getLocalRepository();
|
||||||
|
|
||||||
foreach ($lockedPackages as $info) {
|
foreach ($lockedPackages as $info) {
|
||||||
|
@ -128,22 +128,38 @@ class Locker
|
||||||
return $packages;
|
return $packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMinimumStability()
|
||||||
|
{
|
||||||
|
$lockData = $this->getLockData();
|
||||||
|
|
||||||
|
// TODO BC change dev to stable end of june?
|
||||||
|
return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'dev';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStabilityFlags()
|
||||||
|
{
|
||||||
|
$lockData = $this->getLockData();
|
||||||
|
|
||||||
|
return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
|
||||||
|
}
|
||||||
|
|
||||||
public function getAliases()
|
public function getAliases()
|
||||||
{
|
{
|
||||||
$lockList = $this->getLockData();
|
$lockData = $this->getLockData();
|
||||||
return isset($lockList['aliases']) ? $lockList['aliases'] : array();
|
|
||||||
|
return isset($lockData['aliases']) ? $lockData['aliases'] : array();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLockData()
|
public function getLockData()
|
||||||
{
|
{
|
||||||
if (!$this->lockFile->exists()) {
|
|
||||||
throw new \LogicException('No lockfile found. Unable to read locked packages');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $this->lockDataCache) {
|
if (null !== $this->lockDataCache) {
|
||||||
return $this->lockDataCache;
|
return $this->lockDataCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->lockFile->exists()) {
|
||||||
|
throw new \LogicException('No lockfile found. Unable to read locked packages');
|
||||||
|
}
|
||||||
|
|
||||||
return $this->lockDataCache = $this->lockFile->read();
|
return $this->lockDataCache = $this->lockFile->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,13 +172,15 @@ class Locker
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
public function setLockData(array $packages, $devPackages, array $aliases)
|
public function setLockData(array $packages, $devPackages, array $aliases, $minimumStability, array $stabilityFlags)
|
||||||
{
|
{
|
||||||
$lock = array(
|
$lock = array(
|
||||||
'hash' => $this->hash,
|
'hash' => $this->hash,
|
||||||
'packages' => null,
|
'packages' => null,
|
||||||
'packages-dev' => null,
|
'packages-dev' => null,
|
||||||
'aliases' => $aliases,
|
'aliases' => $aliases,
|
||||||
|
'minimum-stability' => $minimumStability,
|
||||||
|
'stability-flags' => $stabilityFlags,
|
||||||
);
|
);
|
||||||
|
|
||||||
$lock['packages'] = $this->lockPackages($packages);
|
$lock['packages'] = $this->lockPackages($packages);
|
||||||
|
|
|
@ -48,6 +48,10 @@ class MemoryPackage extends BasePackage
|
||||||
protected $prettyAlias;
|
protected $prettyAlias;
|
||||||
protected $dev;
|
protected $dev;
|
||||||
|
|
||||||
|
// TODO BC change dev to stable end of june?
|
||||||
|
protected $minimumStability = 'dev';
|
||||||
|
protected $stabilityFlags = array();
|
||||||
|
|
||||||
protected $requires = array();
|
protected $requires = array();
|
||||||
protected $conflicts = array();
|
protected $conflicts = array();
|
||||||
protected $provides = array();
|
protected $provides = array();
|
||||||
|
@ -71,7 +75,8 @@ class MemoryPackage extends BasePackage
|
||||||
$this->version = $version;
|
$this->version = $version;
|
||||||
$this->prettyVersion = $prettyVersion;
|
$this->prettyVersion = $prettyVersion;
|
||||||
|
|
||||||
$this->dev = VersionParser::isDev($version);
|
$this->stability = VersionParser::parseStability($version);
|
||||||
|
$this->dev = $this->stability === 'dev';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,6 +103,14 @@ class MemoryPackage extends BasePackage
|
||||||
return $this->type ?: 'library';
|
return $this->type ?: 'library';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getStability()
|
||||||
|
{
|
||||||
|
return $this->stability;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $targetDir
|
* @param string $targetDir
|
||||||
*/
|
*/
|
||||||
|
@ -588,6 +601,42 @@ class MemoryPackage extends BasePackage
|
||||||
return $this->homepage;
|
return $this->homepage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimumStability
|
||||||
|
*
|
||||||
|
* @param string $minimumStability
|
||||||
|
*/
|
||||||
|
public function setMinimumStability($minimumStability)
|
||||||
|
{
|
||||||
|
$this->minimumStability = $minimumStability;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getMinimumStability()
|
||||||
|
{
|
||||||
|
return $this->minimumStability;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the stabilityFlags
|
||||||
|
*
|
||||||
|
* @param array $stabilityFlags
|
||||||
|
*/
|
||||||
|
public function setStabilityFlags(array $stabilityFlags)
|
||||||
|
{
|
||||||
|
$this->stabilityFlags = $stabilityFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getStabilityFlags()
|
||||||
|
{
|
||||||
|
return $this->stabilityFlags;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the autoload mapping
|
* Set the autoload mapping
|
||||||
*
|
*
|
||||||
|
|
|
@ -180,6 +180,13 @@ interface PackageInterface
|
||||||
*/
|
*/
|
||||||
function getPrettyVersion();
|
function getPrettyVersion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stability of this package: one of (dev, alpha, beta, RC, stable)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getStability();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the package license, e.g. MIT, BSD, GPL
|
* Returns the package license, e.g. MIT, BSD, GPL
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Composer\Package\Version;
|
namespace Composer\Package\Version;
|
||||||
|
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Package\LinkConstraint\MultiConstraint;
|
use Composer\Package\LinkConstraint\MultiConstraint;
|
||||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
|
|
||||||
|
@ -22,17 +23,37 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
*/
|
*/
|
||||||
class VersionParser
|
class VersionParser
|
||||||
{
|
{
|
||||||
private $modifierRegex = '[.-]?(?:(beta|RC|alpha|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
|
private static $modifierRegex = '[.-]?(?:(beta|RC|alpha|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a version is dev or not
|
* Returns the stability of a version
|
||||||
*
|
*
|
||||||
* @param string $version
|
* @param string $version
|
||||||
* @return Boolean
|
* @return string
|
||||||
*/
|
*/
|
||||||
static public function isDev($version)
|
static public function parseStability($version)
|
||||||
{
|
{
|
||||||
return 'dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4);
|
if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
|
||||||
|
return 'dev';
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('{'.self::$modifierRegex.'$}', $version, $match);
|
||||||
|
if (!empty($match[3])) {
|
||||||
|
return 'dev';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($match[1]) && ($match[1] === 'beta' || $match[1] === 'alpha' || $match[1] === 'RC')) {
|
||||||
|
return $match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'stable';
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function normalizeStability($stability)
|
||||||
|
{
|
||||||
|
$stability = strtolower($stability);
|
||||||
|
|
||||||
|
return $stability === 'rc' ? 'RC' : $stability;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,13 +81,13 @@ class VersionParser
|
||||||
}
|
}
|
||||||
|
|
||||||
// match classical versioning
|
// match classical versioning
|
||||||
if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?'.$this->modifierRegex.'$}i', $version, $matches)) {
|
if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?'.self::$modifierRegex.'$}i', $version, $matches)) {
|
||||||
$version = $matches[1]
|
$version = $matches[1]
|
||||||
.(!empty($matches[2]) ? $matches[2] : '.0')
|
.(!empty($matches[2]) ? $matches[2] : '.0')
|
||||||
.(!empty($matches[3]) ? $matches[3] : '.0')
|
.(!empty($matches[3]) ? $matches[3] : '.0')
|
||||||
.(!empty($matches[4]) ? $matches[4] : '.0');
|
.(!empty($matches[4]) ? $matches[4] : '.0');
|
||||||
$index = 5;
|
$index = 5;
|
||||||
} elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)'.$this->modifierRegex.'$}i', $version, $matches)) { // match date-based versioning
|
} 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]);
|
$version = preg_replace('{\D}', '-', $matches[1]);
|
||||||
$index = 2;
|
$index = 2;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +151,10 @@ class VersionParser
|
||||||
*/
|
*/
|
||||||
public function parseConstraints($constraints)
|
public function parseConstraints($constraints)
|
||||||
{
|
{
|
||||||
|
if (preg_match('{^([^,\s]*?)@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $constraints, $match)) {
|
||||||
|
$constraints = empty($match[1]) ? '*' : $match[1];
|
||||||
|
}
|
||||||
|
|
||||||
$constraints = preg_split('{\s*,\s*}', trim($constraints));
|
$constraints = preg_split('{\s*,\s*}', trim($constraints));
|
||||||
|
|
||||||
if (count($constraints) > 1) {
|
if (count($constraints) > 1) {
|
||||||
|
|
|
@ -36,6 +36,16 @@ class CompositeRepository implements RepositoryInterface
|
||||||
$this->repositories = $repositories;
|
$this->repositories = $repositories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the wrapped repositories
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRepositories()
|
||||||
|
{
|
||||||
|
return $this->repositories;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?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\Json\JsonFile;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Package\Loader\ArrayLoader;
|
||||||
|
use Composer\Package\Dumper\ArrayDumper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installed array repository.
|
||||||
|
*
|
||||||
|
* This is used for serving the RootPackage inside an in-memory InstalledRepository
|
||||||
|
*
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*/
|
||||||
|
class InstalledArrayRepository extends ArrayRepository implements InstalledRepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function write()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function reload()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ namespace Composer\Test\DependencyResolver;
|
||||||
|
|
||||||
use Composer\DependencyResolver\Pool;
|
use Composer\DependencyResolver\Pool;
|
||||||
use Composer\Repository\ArrayRepository;
|
use Composer\Repository\ArrayRepository;
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Test\TestCase;
|
use Composer\Test\TestCase;
|
||||||
|
|
||||||
class PoolTest extends TestCase
|
class PoolTest extends TestCase
|
||||||
|
@ -31,6 +32,22 @@ class PoolTest extends TestCase
|
||||||
$this->assertEquals(array($package), $pool->whatProvides('foo'));
|
$this->assertEquals(array($package), $pool->whatProvides('foo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testPoolIgnoresIrrelevantPackages()
|
||||||
|
{
|
||||||
|
$pool = new Pool('stable', array('bar' => BasePackage::STABILITY_BETA));
|
||||||
|
$repo = new ArrayRepository;
|
||||||
|
$repo->addPackage($package = $this->getPackage('bar', '1'));
|
||||||
|
$repo->addPackage($betaPackage = $this->getPackage('bar', '1-beta'));
|
||||||
|
$repo->addPackage($alphaPackage = $this->getPackage('bar', '1-alpha'));
|
||||||
|
$repo->addPackage($package2 = $this->getPackage('foo', '1'));
|
||||||
|
$repo->addPackage($rcPackage2 = $this->getPackage('foo', '1rc'));
|
||||||
|
|
||||||
|
$pool->addRepository($repo);
|
||||||
|
|
||||||
|
$this->assertEquals(array($package, $betaPackage), $pool->whatProvides('bar'));
|
||||||
|
$this->assertEquals(array($package2), $pool->whatProvides('foo'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \RuntimeException
|
* @expectedException \RuntimeException
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -157,9 +157,11 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
),
|
),
|
||||||
'packages-dev' => array(),
|
'packages-dev' => array(),
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
'minimum-stability' => 'dev',
|
||||||
|
'stability-flags' => array(),
|
||||||
));
|
));
|
||||||
|
|
||||||
$locker->setLockData(array($package1, $package2), array(), array());
|
$locker->setLockData(array($package1, $package2), array(), array(), 'dev', array());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLockBadPackages()
|
public function testLockBadPackages()
|
||||||
|
@ -177,7 +179,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
$this->setExpectedException('LogicException');
|
$this->setExpectedException('LogicException');
|
||||||
|
|
||||||
$locker->setLockData(array($package1), array(), array());
|
$locker->setLockData(array($package1), array(), array(), 'dev', array());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIsFresh()
|
public function testIsFresh()
|
||||||
|
|
|
@ -106,6 +106,12 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testParseConstraintsIgnoresStabilityFlag()
|
||||||
|
{
|
||||||
|
$parser = new VersionParser;
|
||||||
|
$this->assertSame((string) new VersionConstraint('=', '1.0.0.0'), (string) $parser->parseConstraints('1.0@dev'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider simpleConstraints
|
* @dataProvider simpleConstraints
|
||||||
*/
|
*/
|
||||||
|
@ -195,21 +201,25 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider dataIsDev
|
* @dataProvider stabilityProvider
|
||||||
*/
|
*/
|
||||||
public function testIsDev($expected, $version)
|
public function testParseStability($expected, $version)
|
||||||
{
|
{
|
||||||
$this->assertSame($expected, VersionParser::isDev($version));
|
$this->assertSame($expected, VersionParser::parseStability($version));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dataIsDev()
|
public function stabilityProvider()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array(false, '1.0'),
|
array('stable', '1.0'),
|
||||||
array(false, 'v2.0.*'),
|
array('dev', 'v2.0.x-dev'),
|
||||||
array(false, '3.0dev'),
|
array('RC', '3.0-RC2'),
|
||||||
array(true, 'dev-master'),
|
array('dev', 'dev-master'),
|
||||||
array(true, '3.1.2-dev'),
|
array('dev', '3.1.2-dev'),
|
||||||
|
array('stable', '3.1.2-pl2'),
|
||||||
|
array('stable', '3.1.2-patch'),
|
||||||
|
array('alpha', '3.1.2-alpha5'),
|
||||||
|
array('beta', '3.1.2-beta'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue