commit
046c54fdb8
|
@ -27,6 +27,7 @@ use Composer\Semver\Constraint\Constraint;
|
|||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Semver\Constraint\MultiConstraint;
|
||||
use Composer\Semver\Intervals;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -57,16 +58,22 @@ class PoolBuilder
|
|||
* @var IOInterface
|
||||
*/
|
||||
private $io;
|
||||
|
||||
/**
|
||||
* @psalm-var array<string, AliasPackage>
|
||||
*/
|
||||
private $aliasMap = array();
|
||||
/**
|
||||
* @psalm-var array<string, ConstraintInterface[]|null>
|
||||
* @psalm-var array<string, ConstraintInterface>
|
||||
*/
|
||||
private $nameConstraints = array();
|
||||
private $loadedNames = array();
|
||||
private $packagesToLoad = array();
|
||||
/**
|
||||
* @psalm-var array<string, ConstraintInterface>
|
||||
*/
|
||||
private $loadedPackages = array();
|
||||
/**
|
||||
* @psalm-var array<int, array<string, array<string, PackageInterface>>>
|
||||
*/
|
||||
private $loadedPerRepo = array();
|
||||
/**
|
||||
* @psalm-var Package[]
|
||||
*/
|
||||
|
@ -77,11 +84,23 @@ class PoolBuilder
|
|||
private $unacceptableFixedPackages = array();
|
||||
private $updateAllowList = array();
|
||||
private $skippedLoad = array();
|
||||
|
||||
/**
|
||||
* Keeps a list of dependencies which are root requirements, and as such
|
||||
* have already their maximum required range loaded and can not be
|
||||
* extended by markPackageNameForLoading
|
||||
*
|
||||
* Packages get cleared from this list if they get unfixed as in that case
|
||||
* we need to actually load them
|
||||
*/
|
||||
private $maxExtendedReqs = array();
|
||||
/**
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $updateAllowWarned = array();
|
||||
|
||||
private $indexCounter = 0;
|
||||
|
||||
/**
|
||||
* @param int[] $acceptableStabilities array of stability => BasePackage::STABILITY_* value
|
||||
* @psalm-param array<string, BasePackage::STABILITY_*> $acceptableStabilities
|
||||
|
@ -121,15 +140,14 @@ class PoolBuilder
|
|||
}
|
||||
}
|
||||
|
||||
$loadNames = array();
|
||||
foreach ($request->getFixedPackages() as $package) {
|
||||
$this->nameConstraints[$package->getName()] = null;
|
||||
$this->loadedNames[$package->getName()] = true;
|
||||
// using MatchAllConstraint here because fixed packages do not need to retrigger
|
||||
// loading any packages
|
||||
$this->loadedPackages[$package->getName()] = new MatchAllConstraint();
|
||||
|
||||
// replace means conflict, so if a fixed package replaces a name, no need to load that one, packages would conflict anyways
|
||||
foreach ($package->getReplaces() as $link) {
|
||||
$this->nameConstraints[$package->getName()] = null;
|
||||
$this->loadedNames[$link->getTarget()] = true;
|
||||
$this->loadedPackages[$link->getTarget()] = new MatchAllConstraint();
|
||||
}
|
||||
|
||||
// TODO in how far can we do the above for conflicts? It's more tricky cause conflicts can be limited to
|
||||
|
@ -140,7 +158,7 @@ class PoolBuilder
|
|||
|| $package->getRepository() instanceof PlatformRepository
|
||||
|| StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $package->getNames(), $package->getStability())
|
||||
) {
|
||||
$loadNames += $this->loadPackage($request, $package, false);
|
||||
$this->loadPackage($request, $package, false);
|
||||
} else {
|
||||
$this->unacceptableFixedPackages[] = $package;
|
||||
}
|
||||
|
@ -148,60 +166,30 @@ class PoolBuilder
|
|||
|
||||
foreach ($request->getRequires() as $packageName => $constraint) {
|
||||
// fixed packages have already been added, so if a root require needs one of them, no need to do anything
|
||||
if (isset($this->loadedNames[$packageName])) {
|
||||
if (isset($this->loadedPackages[$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$loadNames[$packageName] = $constraint;
|
||||
$this->nameConstraints[$packageName] = $constraint && !($constraint instanceof MatchAllConstraint) ? array($constraint) : null;
|
||||
$this->packagesToLoad[$packageName] = $constraint;
|
||||
$this->maxExtendedReqs[$packageName] = true;
|
||||
}
|
||||
|
||||
// clean up loadNames for anything we manually marked loaded above
|
||||
foreach ($loadNames as $name => $void) {
|
||||
if (isset($this->loadedNames[$name])) {
|
||||
unset($loadNames[$name]);
|
||||
// clean up packagesToLoad for anything we manually marked loaded above
|
||||
foreach ($this->packagesToLoad as $name => $constraint) {
|
||||
if (isset($this->loadedPackages[$name])) {
|
||||
unset($this->packagesToLoad[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
while (!empty($loadNames)) {
|
||||
foreach ($loadNames as $name => $void) {
|
||||
$this->loadedNames[$name] = true;
|
||||
}
|
||||
|
||||
$newLoadNames = array();
|
||||
foreach ($repositories as $repository) {
|
||||
// these repos have their packages fixed if they need to be loaded so we
|
||||
// never need to load anything else from them
|
||||
if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) {
|
||||
continue;
|
||||
}
|
||||
$result = $repository->loadPackages($loadNames, $this->acceptableStabilities, $this->stabilityFlags);
|
||||
|
||||
foreach ($result['namesFound'] as $name) {
|
||||
// avoid loading the same package again from other repositories once it has been found
|
||||
unset($loadNames[$name]);
|
||||
}
|
||||
foreach ($result['packages'] as $package) {
|
||||
$newLoadNames += $this->loadPackage($request, $package);
|
||||
}
|
||||
}
|
||||
|
||||
$loadNames = $newLoadNames;
|
||||
while (!empty($this->packagesToLoad)) {
|
||||
$this->loadPackagesMarkedForLoading($request, $repositories);
|
||||
}
|
||||
|
||||
// filter packages according to all the require statements collected for each package
|
||||
$nameConstraints = array();
|
||||
foreach ($this->nameConstraints as $name => $constraints) {
|
||||
if (\is_array($constraints)) {
|
||||
$nameConstraints[$name] = MultiConstraint::create(array_values(array_unique($constraints)), false);
|
||||
}
|
||||
}
|
||||
foreach ($this->packages as $i => $package) {
|
||||
// we check all alias related packages at once, so no need to check individual aliases
|
||||
// isset also checks non-null value
|
||||
if (!$package instanceof AliasPackage && isset($nameConstraints[$package->getName()])) {
|
||||
$constraint = $nameConstraints[$package->getName()];
|
||||
|
||||
if (!$package instanceof AliasPackage) {
|
||||
$constraint = new Constraint('==', $package->getVersion());
|
||||
$aliasedPackages = array($i => $package);
|
||||
if (isset($this->aliasMap[spl_object_hash($package)])) {
|
||||
$aliasedPackages += $this->aliasMap[spl_object_hash($package)];
|
||||
|
@ -241,19 +229,111 @@ class PoolBuilder
|
|||
$pool = new Pool($this->packages, $this->unacceptableFixedPackages);
|
||||
|
||||
$this->aliasMap = array();
|
||||
$this->nameConstraints = array();
|
||||
$this->loadedNames = array();
|
||||
$this->packagesToLoad = array();
|
||||
$this->loadedPackages = array();
|
||||
$this->loadedPerRepo = array();
|
||||
$this->packages = array();
|
||||
$this->unacceptableFixedPackages = array();
|
||||
$this->maxExtendedReqs = array();
|
||||
$this->skippedLoad = array();
|
||||
$this->indexCounter = 0;
|
||||
|
||||
Intervals::clear();
|
||||
|
||||
return $pool;
|
||||
}
|
||||
|
||||
private function markPackageNameForLoading(Request $request, $name, ConstraintInterface $constraint)
|
||||
{
|
||||
// Skip platform requires at this stage
|
||||
if (PlatformRepository::isPlatformPackage($name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Root require (which was not unfixed) already loaded the maximum range so no
|
||||
// need to check anything here
|
||||
if (isset($this->maxExtendedReqs[$name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Root requires can not be overruled by dependencies so there is no point in
|
||||
// extending the loaded constraint for those.
|
||||
// This is triggered when loading a root require which was fixed but got unfixed, then
|
||||
// we make sure that we load at most the intervals covered by the root constraint.
|
||||
$rootRequires = $request->getRequires();
|
||||
if (isset($rootRequires[$name]) && !Intervals::isSubsetOf($constraint, $rootRequires[$name])) {
|
||||
$constraint = $rootRequires[$name];
|
||||
}
|
||||
|
||||
// Not yet loaded or already marked for a reload, override the existing constraint
|
||||
// (either it's a new one to load, or it has already been extended above)
|
||||
if (!isset($this->loadedPackages[$name])) {
|
||||
// Maybe it was already marked before but not loaded yet. In that case
|
||||
// we have to extend the constraint (we don't check if they are identical because
|
||||
// MultiConstraint::create() will optimize anyway)
|
||||
if (isset($this->packagesToLoad[$name])) {
|
||||
// Already marked for loading and this does not expand the constraint to be loaded, nothing to do
|
||||
if (Intervals::isSubsetOf($constraint, $this->packagesToLoad[$name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// extend the constraint to be loaded
|
||||
$constraint = Intervals::compactConstraint(MultiConstraint::create(array($this->packagesToLoad[$name], $constraint), false));
|
||||
}
|
||||
|
||||
$this->packagesToLoad[$name] = $constraint;
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to load this package with this constraint because it is
|
||||
// a subset of the constraint with which we have already loaded packages
|
||||
if (Intervals::isSubsetOf($constraint, $this->loadedPackages[$name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We have already loaded that package but not in the constraint that's
|
||||
// required. We extend the constraint and mark that package as not being loaded
|
||||
// yet so we get the required package versions
|
||||
$this->packagesToLoad[$name] = Intervals::compactConstraint(MultiConstraint::create(array($this->loadedPackages[$name], $constraint), false));
|
||||
unset($this->loadedPackages[$name]);
|
||||
}
|
||||
|
||||
private function loadPackagesMarkedForLoading(Request $request, $repositories)
|
||||
{
|
||||
foreach ($this->packagesToLoad as $name => $constraint) {
|
||||
$this->loadedPackages[$name] = $constraint;
|
||||
}
|
||||
|
||||
$packageBatch = $this->packagesToLoad;
|
||||
$this->packagesToLoad = array();
|
||||
|
||||
foreach ($repositories as $repoIndex => $repository) {
|
||||
if (empty($packageBatch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// these repos have their packages fixed if they need to be loaded so we
|
||||
// never need to load anything else from them
|
||||
if ($repository instanceof PlatformRepository || $repository === $request->getLockedRepository()) {
|
||||
continue;
|
||||
}
|
||||
$result = $repository->loadPackages($packageBatch, $this->acceptableStabilities, $this->stabilityFlags, isset($this->loadedPerRepo[$repoIndex]) ? $this->loadedPerRepo[$repoIndex] : array());
|
||||
|
||||
foreach ($result['namesFound'] as $name) {
|
||||
// avoid loading the same package again from other repositories once it has been found
|
||||
unset($packageBatch[$name]);
|
||||
}
|
||||
foreach ($result['packages'] as $package) {
|
||||
$this->loadedPerRepo[$repoIndex][$package->getName()][$package->getVersion()] = $package;
|
||||
$this->loadPackage($request, $package);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function loadPackage(Request $request, PackageInterface $package, $propagateUpdate = true)
|
||||
{
|
||||
end($this->packages);
|
||||
$index = key($this->packages) + 1;
|
||||
$this->packages[] = $package;
|
||||
$index = $this->indexCounter++;
|
||||
$this->packages[$index] = $package;
|
||||
|
||||
if ($package instanceof AliasPackage) {
|
||||
$this->aliasMap[spl_object_hash($package->getAliasOf())][$index] = $package;
|
||||
|
@ -283,37 +363,35 @@ class PoolBuilder
|
|||
$aliasPackage = new AliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);
|
||||
$aliasPackage->setRootPackageAlias(true);
|
||||
|
||||
$this->packages[] = $aliasPackage;
|
||||
$this->aliasMap[spl_object_hash($aliasPackage->getAliasOf())][$index+1] = $aliasPackage;
|
||||
$newIndex = $this->indexCounter++;
|
||||
$this->packages[$newIndex] = $aliasPackage;
|
||||
$this->aliasMap[spl_object_hash($aliasPackage->getAliasOf())][$newIndex] = $aliasPackage;
|
||||
}
|
||||
|
||||
$loadNames = array();
|
||||
foreach ($package->getRequires() as $link) {
|
||||
$require = $link->getTarget();
|
||||
if (!isset($this->loadedNames[$require])) {
|
||||
$loadNames[$require] = null;
|
||||
// if this is a partial update with transitive dependencies we need to unfix the package we now know is a
|
||||
// dependency of another package which we are trying to update, and then attempt to load it again
|
||||
} elseif ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies() && isset($this->skippedLoad[$require])) {
|
||||
if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$require])) {
|
||||
$this->unfixPackage($request, $require);
|
||||
$loadNames[$require] = null;
|
||||
} elseif (!$request->getUpdateAllowTransitiveRootDependencies() && $this->isRootRequire($request, $require) && !isset($this->updateAllowWarned[$require])) {
|
||||
$this->updateAllowWarned[$require] = true;
|
||||
$this->io->writeError('<warning>Dependency "'.$require.'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies to include root dependencies.</warning>');
|
||||
}
|
||||
}
|
||||
|
||||
$linkConstraint = $link->getConstraint();
|
||||
if ($linkConstraint && !($linkConstraint instanceof MatchAllConstraint)) {
|
||||
if (!\array_key_exists($require, $this->nameConstraints)) {
|
||||
$this->nameConstraints[$require] = array($linkConstraint);
|
||||
} elseif (\is_array($this->nameConstraints[$require])) {
|
||||
$this->nameConstraints[$require][] = $linkConstraint;
|
||||
|
||||
if ($propagateUpdate) {
|
||||
// if this is a partial update with transitive dependencies we need to unfix the package we now know is a
|
||||
// dependency of another package which we are trying to update, and then attempt to load it again
|
||||
if ($request->getUpdateAllowTransitiveDependencies() && isset($this->skippedLoad[$require])) {
|
||||
if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$require])) {
|
||||
$this->unfixPackage($request, $require);
|
||||
$this->markPackageNameForLoading($request, $require, $linkConstraint);
|
||||
} elseif (!$request->getUpdateAllowTransitiveRootDependencies() && $this->isRootRequire($request, $require) && !isset($this->updateAllowWarned[$require])) {
|
||||
$this->updateAllowWarned[$require] = true;
|
||||
$this->io->writeError('<warning>Dependency "'.$require.'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies to include root dependencies.</warning>');
|
||||
}
|
||||
} else {
|
||||
$this->markPackageNameForLoading($request, $require, $linkConstraint);
|
||||
}
|
||||
// else it is null and should stay null
|
||||
} else {
|
||||
$this->nameConstraints[$require] = null;
|
||||
// We also need to load the requirements of a fixed package
|
||||
// unless it was skipped
|
||||
if (!isset($this->skippedLoad[$require])) {
|
||||
$this->markPackageNameForLoading($request, $require, $linkConstraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,12 +400,10 @@ class PoolBuilder
|
|||
if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
|
||||
foreach ($package->getReplaces() as $link) {
|
||||
$replace = $link->getTarget();
|
||||
if (isset($this->loadedNames[$replace]) && isset($this->skippedLoad[$replace])) {
|
||||
if (isset($this->loadedPackages[$replace]) && isset($this->skippedLoad[$replace])) {
|
||||
if ($request->getUpdateAllowTransitiveRootDependencies() || !$this->isRootRequire($request, $this->skippedLoad[$replace])) {
|
||||
$this->unfixPackage($request, $replace);
|
||||
$loadNames[$replace] = null;
|
||||
// TODO should we try to merge constraints here?
|
||||
$this->nameConstraints[$replace] = null;
|
||||
$this->markPackageNameForLoading($request, $replace, $link->getConstraint());
|
||||
} elseif (!$request->getUpdateAllowTransitiveRootDependencies() && $this->isRootRequire($request, $replace) && !isset($this->updateAllowWarned[$replace])) {
|
||||
$this->updateAllowWarned[$replace] = true;
|
||||
$this->io->writeError('<warning>Dependency "'.$replace.'" is also a root requirement. Package has not been listed as an update argument, so keeping locked at old version. Use --with-all-dependencies to include root dependencies.</warning>');
|
||||
|
@ -335,8 +411,6 @@ class PoolBuilder
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $loadNames;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,14 +475,7 @@ class PoolBuilder
|
|||
if (!($lockedPackage instanceof AliasPackage) && $lockedPackage->getName() === $name) {
|
||||
if (false !== $index = array_search($lockedPackage, $this->packages, true)) {
|
||||
$request->unfixPackage($lockedPackage);
|
||||
unset($this->packages[$index]);
|
||||
if (isset($this->aliasMap[spl_object_hash($lockedPackage)])) {
|
||||
foreach ($this->aliasMap[spl_object_hash($lockedPackage)] as $aliasIndex => $aliasPackage) {
|
||||
$request->unfixPackage($aliasPackage);
|
||||
unset($this->packages[$aliasIndex]);
|
||||
}
|
||||
unset($this->aliasMap[spl_object_hash($lockedPackage)]);
|
||||
}
|
||||
$this->removeLoadedPackage($request, $lockedPackage, $index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -423,7 +490,20 @@ class PoolBuilder
|
|||
}
|
||||
|
||||
unset($this->skippedLoad[$name]);
|
||||
unset($this->loadedNames[$name]);
|
||||
unset($this->loadedPackages[$name]);
|
||||
unset($this->maxExtendedReqs[$name]);
|
||||
}
|
||||
|
||||
private function removeLoadedPackage(Request $request, PackageInterface $package, $index)
|
||||
{
|
||||
unset($this->packages[$index]);
|
||||
if (isset($this->aliasMap[spl_object_hash($package)])) {
|
||||
foreach ($this->aliasMap[spl_object_hash($package)] as $aliasIndex => $aliasPackage) {
|
||||
$request->unfixPackage($aliasPackage);
|
||||
unset($this->packages[$aliasIndex]);
|
||||
}
|
||||
unset($this->aliasMap[spl_object_hash($package)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ use Composer\Package\PackageInterface;
|
|||
use Composer\Package\RootAliasPackage;
|
||||
use Composer\Repository\LockArrayRepository;
|
||||
use Composer\Semver\Constraint\ConstraintInterface;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -55,6 +56,13 @@ class Request
|
|||
public function requireName($packageName, ConstraintInterface $constraint = null)
|
||||
{
|
||||
$packageName = strtolower($packageName);
|
||||
|
||||
if ($constraint === null) {
|
||||
$constraint = new MatchAllConstraint();
|
||||
}
|
||||
if (isset($this->requires[$packageName])) {
|
||||
throw new \LogicException('Overwriting requires seems like a bug ('.$packageName.' '.$this->requires[$packageName]->getPrettyConstraint().' => '.$constraint->getPrettyConstraint().', check why it is happening, might be a root alias');
|
||||
}
|
||||
$this->requires[$packageName] = $constraint;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class Link
|
|||
protected $target;
|
||||
|
||||
/**
|
||||
* @var ConstraintInterface|null
|
||||
* @var ConstraintInterface
|
||||
*/
|
||||
protected $constraint;
|
||||
|
||||
|
@ -49,13 +49,13 @@ class Link
|
|||
/**
|
||||
* Creates a new package link.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $target
|
||||
* @param ConstraintInterface|null $constraint Constraint applying to the target of this link
|
||||
* @param string $description Used to create a descriptive string representation
|
||||
* @param string|null $prettyConstraint
|
||||
* @param string $source
|
||||
* @param string $target
|
||||
* @param ConstraintInterface $constraint Constraint applying to the target of this link
|
||||
* @param string $description Used to create a descriptive string representation
|
||||
* @param string|null $prettyConstraint
|
||||
*/
|
||||
public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
|
||||
public function __construct($source, $target, ConstraintInterface $constraint, $description = 'relates to', $prettyConstraint = null)
|
||||
{
|
||||
$this->source = strtolower($source);
|
||||
$this->target = strtolower($target);
|
||||
|
@ -89,7 +89,7 @@ class Link
|
|||
}
|
||||
|
||||
/**
|
||||
* @return ConstraintInterface|null
|
||||
* @return ConstraintInterface
|
||||
*/
|
||||
public function getConstraint()
|
||||
{
|
||||
|
|
|
@ -50,7 +50,7 @@ class ArrayRepository implements RepositoryInterface
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadPackages(array $packageMap, array $acceptableStabilities, array $stabilityFlags)
|
||||
public function loadPackages(array $packageMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array())
|
||||
{
|
||||
$packages = $this->getPackages();
|
||||
|
||||
|
@ -61,6 +61,7 @@ class ArrayRepository implements RepositoryInterface
|
|||
if (
|
||||
(!$packageMap[$package->getName()] || $packageMap[$package->getName()]->matches(new Constraint('==', $package->getVersion())))
|
||||
&& StabilityFilter::isPackageAcceptable($acceptableStabilities, $stabilityFlags, $package->getNames(), $package->getStability())
|
||||
&& !isset($alreadyLoaded[$package->getName()][$package->getVersion()])
|
||||
) {
|
||||
// add selected packages which match stability requirements
|
||||
$result[spl_object_hash($package)] = $package;
|
||||
|
|
|
@ -341,13 +341,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
return $names;
|
||||
}
|
||||
|
||||
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags)
|
||||
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array())
|
||||
{
|
||||
// this call initializes loadRootServerFile which is needed for the rest below to work
|
||||
$hasProviders = $this->hasProviders();
|
||||
|
||||
if (!$hasProviders && !$this->hasPartialPackages() && !$this->lazyProvidersUrl) {
|
||||
return parent::loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags);
|
||||
return parent::loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
|
||||
}
|
||||
|
||||
$packages = array();
|
||||
|
@ -363,12 +363,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
continue;
|
||||
}
|
||||
|
||||
$candidates = $this->whatProvides($name, $acceptableStabilities, $stabilityFlags);
|
||||
$candidates = $this->whatProvides($name, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
|
||||
foreach ($candidates as $candidate) {
|
||||
if ($candidate->getName() !== $name) {
|
||||
throw new \LogicException('whatProvides should never return a package with a different name than the requested one');
|
||||
}
|
||||
$namesFound[$name] = true;
|
||||
|
||||
if (!$constraint || $constraint->matches(new Constraint('==', $candidate->getVersion()))) {
|
||||
$matches[spl_object_hash($candidate)] = $candidate;
|
||||
if ($candidate instanceof AliasPackage && !isset($matches[spl_object_hash($candidate->getAliasOf())])) {
|
||||
|
@ -401,7 +402,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
}
|
||||
}
|
||||
|
||||
$result = $this->loadAsyncPackages($packageNameMap, $acceptableStabilities, $stabilityFlags);
|
||||
$result = $this->loadAsyncPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
|
||||
$packages = array_merge($packages, $result['packages']);
|
||||
$namesFound = array_merge($namesFound, $result['namesFound']);
|
||||
}
|
||||
|
@ -531,7 +532,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
* @param string $name package name
|
||||
* @return array|mixed
|
||||
*/
|
||||
private function whatProvides($name, array $acceptableStabilities = null, array $stabilityFlags = null)
|
||||
private function whatProvides($name, array $acceptableStabilities = null, array $stabilityFlags = null, array $alreadyLoaded = array())
|
||||
{
|
||||
if (!$this->hasPartialPackages() || !isset($this->partialPackagesByName[$name])) {
|
||||
// skip platform packages, root package and composer-plugin-api
|
||||
|
@ -623,6 +624,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
||||
}
|
||||
|
||||
// avoid loading packages which have already been loaded
|
||||
if (isset($alreadyLoaded[$name][$version['version_normalized']])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isVersionAcceptable(null, $normalizedName, $version, $acceptableStabilities, $stabilityFlags)) {
|
||||
$versionsToLoad[$version['uid']] = $version;
|
||||
}
|
||||
|
@ -680,7 +686,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
/**
|
||||
* @param array $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only packages matching it will be loaded
|
||||
*/
|
||||
private function loadAsyncPackages(array $packageNames, array $acceptableStabilities = null, array $stabilityFlags = null)
|
||||
private function loadAsyncPackages(array $packageNames, array $acceptableStabilities = null, array $stabilityFlags = null, array $alreadyLoaded = array())
|
||||
{
|
||||
$this->loadRootServerFile();
|
||||
|
||||
|
@ -723,7 +729,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
}
|
||||
|
||||
$promises[] = $this->asyncFetchFile($url, $cacheKey, $lastModified)
|
||||
->then(function ($response) use (&$packages, &$namesFound, $contents, $realName, $constraint, $repo, $acceptableStabilities, $stabilityFlags) {
|
||||
->then(function ($response) use (&$packages, &$namesFound, $contents, $realName, $constraint, $repo, $acceptableStabilities, $stabilityFlags, $alreadyLoaded) {
|
||||
if (true === $response) {
|
||||
$response = $contents;
|
||||
}
|
||||
|
@ -748,6 +754,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
||||
}
|
||||
|
||||
// avoid loading packages which have already been loaded
|
||||
if (isset($alreadyLoaded[$realName][$version['version_normalized']])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($repo->isVersionAcceptable($constraint, $realName, $version, $acceptableStabilities, $stabilityFlags)) {
|
||||
$versionsToLoad[] = $version;
|
||||
}
|
||||
|
|
|
@ -102,13 +102,13 @@ class CompositeRepository implements RepositoryInterface
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadPackages(array $packageMap, array $acceptableStabilities, array $stabilityFlags)
|
||||
public function loadPackages(array $packageMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array())
|
||||
{
|
||||
$packages = array();
|
||||
$namesFound = array();
|
||||
foreach ($this->repositories as $repository) {
|
||||
/* @var $repository RepositoryInterface */
|
||||
$result = $repository->loadPackages($packageMap, $acceptableStabilities, $stabilityFlags);
|
||||
$result = $repository->loadPackages($packageMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
|
||||
$packages[] = $result['packages'];
|
||||
$namesFound[] = $result['namesFound'];
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class FilterRepository implements RepositoryInterface
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadPackages(array $packageMap, array $acceptableStabilities, array $stabilityFlags)
|
||||
public function loadPackages(array $packageMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array())
|
||||
{
|
||||
foreach ($packageMap as $name => $constraint) {
|
||||
if (!$this->isAllowed($name)) {
|
||||
|
@ -120,7 +120,7 @@ class FilterRepository implements RepositoryInterface
|
|||
return array('namesFound' => array(), 'packages' => array());
|
||||
}
|
||||
|
||||
$result = $this->repo->loadPackages($packageMap, $acceptableStabilities, $stabilityFlags);
|
||||
$result = $this->repo->loadPackages($packageMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
|
||||
if (!$this->canonical) {
|
||||
$result['namesFound'] = array();
|
||||
}
|
||||
|
|
|
@ -593,4 +593,21 @@ class PlatformRepository extends ArrayRepository
|
|||
|
||||
$this->addPackage($lib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a package name is a platform package.
|
||||
*
|
||||
* @param $name
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPlatformPackage($name)
|
||||
{
|
||||
static $cache = array();
|
||||
|
||||
if (isset($cache[$name])) {
|
||||
return $cache[$name];
|
||||
}
|
||||
|
||||
return $cache[$name] = (bool) preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,11 +75,13 @@ interface RepositoryInterface extends \Countable
|
|||
* @psalm-param array<string, BasePackage::STABILITY_*> $acceptableStabilities
|
||||
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
|
||||
* @psalm-param array<string, BasePackage::STABILITY_*> $stabilityFlags
|
||||
* @param array[] $alreadyLoaded an array of package name => package version => package
|
||||
* @psalm-param array<string, array<string, PackageInterface>> $alreadyLoaded
|
||||
*
|
||||
* @return array [namesFound => string[], packages => PackageInterface[]]
|
||||
* @psalm-return array{namesFound: string[], packages: PackageInterface[]}
|
||||
*/
|
||||
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags);
|
||||
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array());
|
||||
|
||||
/**
|
||||
* Searches the repository for packages containing the query
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Autoload\AutoloadGenerator;
|
|||
use Composer\Package\Link;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\Package;
|
||||
|
@ -366,8 +367,8 @@ class AutoloadGeneratorTest extends TestCase
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -395,7 +396,7 @@ class AutoloadGeneratorTest extends TestCase
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -403,11 +404,11 @@ class AutoloadGeneratorTest extends TestCase
|
|||
$packages[] = $b = new Package('b/b', '1.0', '1.0');
|
||||
$a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/')));
|
||||
$a->setRequires(array(
|
||||
new Link('a/a', 'b/b'),
|
||||
new Link('a/a', 'b/b', new MatchAllConstraint()),
|
||||
));
|
||||
$b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/')));
|
||||
$b->setRequires(array(
|
||||
new Link('b/b', 'a/a'),
|
||||
new Link('b/b', 'a/a', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$this->repository->expects($this->once())
|
||||
|
@ -427,13 +428,13 @@ class AutoloadGeneratorTest extends TestCase
|
|||
public function testNonDevAutoloadShouldIncludeReplacedPackages()
|
||||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(new Link('a', 'a/a')));
|
||||
$package->setRequires(array(new Link('a', 'a/a', new MatchAllConstraint())));
|
||||
|
||||
$packages = array();
|
||||
$packages[] = $a = new Package('a/a', '1.0', '1.0');
|
||||
$packages[] = $b = new Package('b/b', '1.0', '1.0');
|
||||
|
||||
$a->setRequires(array(new Link('a/a', 'b/c')));
|
||||
$a->setRequires(array(new Link('a/a', 'b/c', new MatchAllConstraint())));
|
||||
|
||||
$b->setAutoload(array('psr-4' => array('B\\' => 'src/')));
|
||||
$b->setReplaces(
|
||||
|
@ -462,7 +463,7 @@ class AutoloadGeneratorTest extends TestCase
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -470,11 +471,11 @@ class AutoloadGeneratorTest extends TestCase
|
|||
$packages[] = $b = new Package('b/b', '1.0', '1.0');
|
||||
$a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/')));
|
||||
$a->setRequires(array(
|
||||
new Link('a/a', 'c/c'),
|
||||
new Link('a/a', 'c/c', new MatchAllConstraint()),
|
||||
));
|
||||
$b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/')));
|
||||
$b->setReplaces(array(
|
||||
new Link('b/b', 'c/c'),
|
||||
new Link('b/b', 'c/c', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$this->repository->expects($this->once())
|
||||
|
@ -495,7 +496,7 @@ class AutoloadGeneratorTest extends TestCase
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a')
|
||||
new Link('a', 'a/a', new MatchAllConstraint())
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -506,18 +507,18 @@ class AutoloadGeneratorTest extends TestCase
|
|||
$packages[] = $e = new Package('e/e', '1.0', '1.0');
|
||||
$a->setAutoload(array('classmap' => array('src/A.php')));
|
||||
$a->setRequires(array(
|
||||
new Link('a/a', 'b/b')
|
||||
new Link('a/a', 'b/b', new MatchAllConstraint())
|
||||
));
|
||||
$b->setAutoload(array('classmap' => array('src/B.php')));
|
||||
$b->setRequires(array(
|
||||
new Link('b/b', 'e/e')
|
||||
new Link('b/b', 'e/e', new MatchAllConstraint())
|
||||
));
|
||||
$c->setAutoload(array('classmap' => array('src/C.php')));
|
||||
$c->setReplaces(array(
|
||||
new Link('c/c', 'b/b')
|
||||
new Link('c/c', 'b/b', new MatchAllConstraint())
|
||||
));
|
||||
$c->setRequires(array(
|
||||
new Link('c/c', 'd/d')
|
||||
new Link('c/c', 'd/d', new MatchAllConstraint())
|
||||
));
|
||||
$d->setAutoload(array('classmap' => array('src/D.php')));
|
||||
$e->setAutoload(array('classmap' => array('src/E.php')));
|
||||
|
@ -547,7 +548,7 @@ class AutoloadGeneratorTest extends TestCase
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$package->setAutoload(array(
|
||||
|
@ -652,8 +653,8 @@ EOF;
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -692,8 +693,8 @@ EOF;
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -732,9 +733,9 @@ EOF;
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'c/c'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
new Link('a', 'c/c', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -777,9 +778,9 @@ EOF;
|
|||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'c/c'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
new Link('a', 'c/c', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -827,9 +828,9 @@ EOF;
|
|||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setAutoload(array('files' => array('root.php')));
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'c/c'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
new Link('a', 'c/c', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -878,9 +879,9 @@ EOF;
|
|||
$notAutoloadPackage = new Package('a', '1.0', '1.0');
|
||||
|
||||
$requires = array(
|
||||
new Link('a', 'a/a'),
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'c/c'),
|
||||
new Link('a', 'a/a', new MatchAllConstraint()),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
new Link('a', 'c/c', new MatchAllConstraint()),
|
||||
);
|
||||
$autoloadPackage->setRequires($requires);
|
||||
$notAutoloadPackage->setRequires($requires);
|
||||
|
@ -949,10 +950,10 @@ EOF;
|
|||
$package = new Package('a', '1.0', '1.0');
|
||||
$package->setAutoload(array('files' => array('root2.php')));
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'z/foo'),
|
||||
new Link('a', 'b/bar'),
|
||||
new Link('a', 'd/d'),
|
||||
new Link('a', 'e/e'),
|
||||
new Link('a', 'z/foo', new MatchAllConstraint()),
|
||||
new Link('a', 'b/bar', new MatchAllConstraint()),
|
||||
new Link('a', 'd/d', new MatchAllConstraint()),
|
||||
new Link('a', 'e/e', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -963,18 +964,18 @@ EOF;
|
|||
$packages[] = $e = new Package('e/e', '1.0', '1.0');
|
||||
|
||||
$z->setAutoload(array('files' => array('testA.php')));
|
||||
$z->setRequires(array(new Link('z/foo', 'c/lorem')));
|
||||
$z->setRequires(array(new Link('z/foo', 'c/lorem', new MatchAllConstraint())));
|
||||
|
||||
$b->setAutoload(array('files' => array('testB.php')));
|
||||
$b->setRequires(array(new Link('b/bar', 'c/lorem'), new Link('b/bar', 'd/d')));
|
||||
$b->setRequires(array(new Link('b/bar', 'c/lorem', new MatchAllConstraint()), new Link('b/bar', 'd/d', new MatchAllConstraint())));
|
||||
|
||||
$c->setAutoload(array('files' => array('testC.php')));
|
||||
|
||||
$d->setAutoload(array('files' => array('testD.php')));
|
||||
$d->setRequires(array(new Link('d/d', 'c/lorem')));
|
||||
$d->setRequires(array(new Link('d/d', 'c/lorem', new MatchAllConstraint())));
|
||||
|
||||
$e->setAutoload(array('files' => array('testE.php')));
|
||||
$e->setRequires(array(new Link('e/e', 'c/lorem')));
|
||||
$e->setRequires(array(new Link('e/e', 'c/lorem', new MatchAllConstraint())));
|
||||
|
||||
$this->repository->expects($this->once())
|
||||
->method('getCanonicalPackages')
|
||||
|
@ -1022,8 +1023,8 @@ EOF;
|
|||
'classmap' => array($this->workingDir.'/src'),
|
||||
));
|
||||
$mainPackage->setRequires(array(
|
||||
new Link('z', 'a/a'),
|
||||
new Link('z', 'b/b'),
|
||||
new Link('z', 'a/a', new MatchAllConstraint()),
|
||||
new Link('z', 'b/b', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$packages = array();
|
||||
|
@ -1285,7 +1286,7 @@ EOF;
|
|||
'files' => array('test.php'),
|
||||
));
|
||||
$package->setRequires(array(
|
||||
new Link('a', 'b/b'),
|
||||
new Link('a', 'b/b', new MatchAllConstraint()),
|
||||
));
|
||||
|
||||
$vendorPackage = new Package('b/b', '1.0', '1.0');
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
--TEST--
|
||||
Check root aliases are loaded
|
||||
|
||||
--ROOT--
|
||||
{
|
||||
"minimum-stability": "dev",
|
||||
"aliases": [
|
||||
{
|
||||
"package": "req/pkg",
|
||||
"version": "dev-feature-foo",
|
||||
"alias": "dev-master"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"package/a": "dev-master",
|
||||
"req/pkg": "dev-feature-foo"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{
|
||||
"name": "req/pkg", "version": "dev-feature-foo",
|
||||
"source": { "reference": "feat.f", "type": "git", "url": "" }
|
||||
},
|
||||
{
|
||||
"name": "req/pkg", "version": "dev-master",
|
||||
"extra": { "branch-alias": { "dev-master": "1.0.x-dev" } },
|
||||
"source": { "reference": "forked", "type": "git", "url": "" },
|
||||
"default-branch": true
|
||||
},
|
||||
{
|
||||
"name": "req/pkg", "version": "dev-master",
|
||||
"extra": { "branch-alias": { "dev-master": "1.0.x-dev" } },
|
||||
"source": { "reference": "master", "type": "git", "url": "" },
|
||||
"default-branch": true
|
||||
},
|
||||
{
|
||||
"name": "package/a", "version": "dev-master",
|
||||
"require": { "req/pkg": "dev-master" },
|
||||
"default-branch": true
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"req/pkg-dev-feature-foo#feat.f",
|
||||
"req/pkg-dev-master#feat.f (alias of dev-feature-foo)",
|
||||
"package/a-dev-master",
|
||||
"package/a-9999999-dev (alias of dev-master)"
|
||||
]
|
|
@ -0,0 +1,59 @@
|
|||
--TEST--
|
||||
Check root aliases get selected correctly
|
||||
|
||||
--ROOT--
|
||||
{
|
||||
"stability-flags": {
|
||||
"a/aliased": "dev"
|
||||
},
|
||||
"aliases": [
|
||||
{
|
||||
"package": "a/aliased",
|
||||
"version": "dev-master",
|
||||
"alias": "1.0.0"
|
||||
}
|
||||
],
|
||||
"references": {
|
||||
"a/aliased": "abcd"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"a/aliased": "dev-master",
|
||||
"b/requirer": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{
|
||||
"name": "a/aliased", "version": "dev-master",
|
||||
"source": { "reference": "orig", "type": "git", "url": "" },
|
||||
"default-branch": true
|
||||
},
|
||||
{
|
||||
"name": "a/aliased", "version": "1.0"
|
||||
},
|
||||
{
|
||||
"name": "b/requirer", "version": "1.0.0",
|
||||
"require": { "a/aliased": "1.0.0" },
|
||||
"source": { "reference": "1.0.0", "type": "git", "url": "" }
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"a/aliased-dev-master#abcd",
|
||||
"a/aliased-1.0.0.0#abcd (alias of dev-master)",
|
||||
"b/requirer-1.0.0.0#1.0.0",
|
||||
"a/aliased-9999999-dev#abcd (alias of dev-master)"
|
||||
]
|
|
@ -0,0 +1,31 @@
|
|||
--TEST--
|
||||
Tests if version constraint is expanded. If not, dep/dep 3.0.0 would not be loaded here.
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.3.4"}},
|
||||
{"name": "dep/dep", "version": "2.3.4", "require": {"dep/dep2": "2.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.5"},
|
||||
{"name": "dep/dep2", "version": "2.3.4", "require": {"dep/dep": "2.*"}}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"root/req-1.0.0.0",
|
||||
"dep/dep-2.3.4.0",
|
||||
"dep/dep2-2.3.4.0",
|
||||
"dep/dep-2.3.5.0"
|
||||
]
|
|
@ -3,21 +3,34 @@ Fixed packages do not get loaded from the repos
|
|||
|
||||
--REQUEST--
|
||||
{
|
||||
"some/pkg": "*"
|
||||
"require": {
|
||||
"some/pkg": "*",
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.3", "id": 1}
|
||||
{"name": "some/pkg", "version": "1.0.3", "id": 1},
|
||||
{"name": "dep/dep", "version": "2.1.5", "id": 2}
|
||||
]
|
||||
|
||||
--PACKAGES--
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.0"},
|
||||
{"name": "some/pkg", "version": "1.1.0"}
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.0"},
|
||||
{"name": "some/pkg", "version": "1.1.0"},
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "root/req", "version": "2.0.0", "require": {"dep/dep": "3.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4"},
|
||||
{"name": "dep/dep", "version": "3.0.1"}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
1
|
||||
1,
|
||||
2,
|
||||
"root/req-1.0.0.0",
|
||||
"root/req-2.0.0.0"
|
||||
]
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
--TEST--
|
||||
Packages replaced by fixed packages do not get loaded from the repos
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"some/pkg": "*",
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.3", "replace": {"dep/dep": "2.1.0"}, "id": 1}
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.0"},
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "root/req", "version": "2.0.0", "require": {"dep/dep": "3.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4"},
|
||||
{"name": "dep/dep", "version": "3.0.1"}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
1,
|
||||
"root/req-1.0.0.0",
|
||||
"root/req-2.0.0.0"
|
||||
]
|
|
@ -0,0 +1,107 @@
|
|||
--TEST--
|
||||
Check that replacers from additional repositories are loaded when doing a partial update
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"base/package": "^1.0",
|
||||
"indirect/replacer": "^1.0"
|
||||
},
|
||||
"locked": [
|
||||
{"name": "shared/dep", "version": "1.2.0", "id": 1},
|
||||
{"name": "indirect/replacer", "version": "1.2.0", "require": {"replacer/package": "^1.2"}, "id": 2},
|
||||
{"name": "replacer/package", "version": "1.2.0", "require": {"shared/dep": "^1.1"}, "replace": {"base/package": "1.2.0"}, "id": 3}
|
||||
],
|
||||
"allowList": [
|
||||
"indirect/replacer"
|
||||
],
|
||||
"allowTransitiveDepsNoRootRequire": true
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{
|
||||
"name": "base/package",
|
||||
"version": "1.0.0",
|
||||
"require": {
|
||||
"shared/dep": "^1.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.2.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "base/package",
|
||||
"version": "1.1.0"
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.3.0"
|
||||
}
|
||||
],
|
||||
{
|
||||
"canonical": false,
|
||||
"packages": [
|
||||
{
|
||||
"name": "indirect/replacer",
|
||||
"version": "1.2.0",
|
||||
"require": {
|
||||
"replacer/package": "^1.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "replacer/package",
|
||||
"version": "1.2.0",
|
||||
"require": {
|
||||
"shared/dep": "^1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.1.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
[
|
||||
{
|
||||
"name": "replacer/package",
|
||||
"version": "1.0.0",
|
||||
"require": {
|
||||
"shared/dep": "^1.0"
|
||||
},
|
||||
"replace": {
|
||||
"base/package": "1.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "indirect/replacer",
|
||||
"version": "1.0.0",
|
||||
"require": {
|
||||
"replacer/package": "^1.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"indirect/replacer-1.2.0.0",
|
||||
"indirect/replacer-1.0.0.0",
|
||||
"replacer/package-1.2.0.0",
|
||||
"replacer/package-1.0.0.0",
|
||||
"base/package-1.0.0.0",
|
||||
"shared/dep-1.0.0.0",
|
||||
"shared/dep-1.2.0.0"
|
||||
]
|
|
@ -0,0 +1,98 @@
|
|||
--TEST--
|
||||
Check that replacers from additional repositories are loaded
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"base/package": "^1.0",
|
||||
"indirect/replacer": "^1.0"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{
|
||||
"name": "base/package",
|
||||
"version": "1.0.0",
|
||||
"require": {
|
||||
"shared/dep": "^1.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.2.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "base/package",
|
||||
"version": "1.1.0"
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.3.0"
|
||||
}
|
||||
],
|
||||
{
|
||||
"canonical": false,
|
||||
"packages": [
|
||||
{
|
||||
"name": "indirect/replacer",
|
||||
"version": "1.2.0",
|
||||
"require": {
|
||||
"replacer/package": "^1.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "replacer/package",
|
||||
"version": "1.2.0",
|
||||
"require": {
|
||||
"shared/dep": "^1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "shared/dep",
|
||||
"version": "1.1.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
[
|
||||
{
|
||||
"name": "replacer/package",
|
||||
"version": "1.0.0",
|
||||
"require": {
|
||||
"shared/dep": "^1.0"
|
||||
},
|
||||
"replace": {
|
||||
"base/package": "1.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "indirect/replacer",
|
||||
"version": "1.0.0",
|
||||
"require": {
|
||||
"replacer/package": "^1.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"base/package-1.0.0.0",
|
||||
"indirect/replacer-1.2.0.0",
|
||||
"indirect/replacer-1.0.0.0",
|
||||
"shared/dep-1.2.0.0",
|
||||
"replacer/package-1.2.0.0",
|
||||
"replacer/package-1.0.0.0",
|
||||
"shared/dep-1.0.0.0"
|
||||
]
|
|
@ -0,0 +1,36 @@
|
|||
--TEST--
|
||||
Fixed packages do not get loaded from the repos
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"some/pkg": "*",
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.3", "id": 1},
|
||||
{"name": "dep/dep", "version": "2.1.5", "id": 2}
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.0"},
|
||||
{"name": "some/pkg", "version": "1.1.0"},
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "root/req", "version": "2.0.0", "require": {"dep/dep": "3.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4"},
|
||||
{"name": "dep/dep", "version": "3.0.1"}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
1,
|
||||
2,
|
||||
"root/req-1.0.0.0",
|
||||
"root/req-2.0.0.0"
|
||||
]
|
|
@ -0,0 +1,34 @@
|
|||
--TEST--
|
||||
Tests if version constraint is expanded. If not, dep/dep 3.0.0 would not be loaded here.
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4", "require": {"dep/dep2": "2.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.5"},
|
||||
{"name": "dep/dep", "version": "3.0.0"},
|
||||
{"name": "dep/dep", "version": "4.0.0"},
|
||||
{"name": "dep/dep2", "version": "2.3.4", "require": {"dep/dep": "3.*"}}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"root/req-1.0.0.0",
|
||||
"dep/dep-2.3.4.0",
|
||||
"dep/dep-2.3.5.0",
|
||||
"dep/dep2-2.3.4.0",
|
||||
"dep/dep-3.0.0.0"
|
||||
]
|
|
@ -0,0 +1,31 @@
|
|||
--TEST--
|
||||
Test irrelevant package versions are not loaded recursively
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4", "require": {"dep/dep2": "2.*"}},
|
||||
{"name": "dep/dep", "version": "3.0.1"},
|
||||
{"name": "dep/dep2", "version": "2.3.4"},
|
||||
{"name": "dep/dep2", "version": "3.0.1"}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"root/req-1.0.0.0",
|
||||
"dep/dep-2.3.4.0",
|
||||
"dep/dep2-2.3.4.0"
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
--TEST--
|
||||
Test package is not found
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/req": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4", "require": {"dep/dep3": "2.*"}}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"root/req-1.0.0.0",
|
||||
"dep/dep-2.3.4.0"
|
||||
]
|
|
@ -0,0 +1,49 @@
|
|||
--TEST--
|
||||
Partially updating one root requirement with transitive deps without root requirements keeps the other root requirement fixed.
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/update": "*",
|
||||
"root/fix": "*"
|
||||
},
|
||||
"locked": [
|
||||
{"name": "root/update", "version": "1.0.1", "require": {"dep/dep": "1.*", "dep2/dep2": "1.*"}, "id": 1},
|
||||
{"name": "dep/dep", "version": "1.0.2", "require": {"root/fix": "1.*"}, "id": 2},
|
||||
{"name": "dep2/dep2", "version": "1.0.2", "require": {"dep/dep": "1.*"}, "id": 3},
|
||||
{"name": "root/fix", "version": "1.0.3", "id": 4}
|
||||
],
|
||||
"allowList": [
|
||||
"root/update"
|
||||
],
|
||||
"allowTransitiveDepsNoRootRequire": true
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/update", "version": "1.0.4", "require": {"dep/dep": "1.*", "dep2/dep2": "1.*"}},
|
||||
{"name": "root/update", "version": "1.0.5", "require": {"dep/dep": "2.*", "dep2/dep2": "2.*"}},
|
||||
{"name": "root/fix", "version": "1.0.6"},
|
||||
{"name": "root/fix", "version": "2.0.7"},
|
||||
{"name": "dep/dep", "version": "1.0.8", "require": {"root/fix": "1.*"}},
|
||||
{"name": "dep/dep", "version": "2.0.9", "require": {"root/fix": "2.*"}},
|
||||
{"name": "dep2/dep2", "version": "1.0.8", "require": {"dep/dep": "1.*"}},
|
||||
{"name": "dep2/dep2", "version": "2.0.9", "require": {"dep/dep": "2.*"}}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
4,
|
||||
"root/update-1.0.4.0",
|
||||
"root/update-1.0.5.0",
|
||||
"dep/dep-1.0.8.0",
|
||||
"dep/dep-2.0.9.0",
|
||||
"dep2/dep2-1.0.8.0",
|
||||
"dep2/dep2-2.0.9.0"
|
||||
]
|
|
@ -0,0 +1,50 @@
|
|||
--TEST--
|
||||
Partially updating one root requirement with transitive deps fully updates another one too.
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/update": "*",
|
||||
"root/dep": "1.0.*",
|
||||
"root/dep2": "*"
|
||||
},
|
||||
"locked": [
|
||||
{"name": "root/update", "version": "1.0.1", "require": {"dep/dep": "1.*"}},
|
||||
{"name": "dep/dep", "version": "1.0.2", "require": {"root/dep": "1.*", "root/dep2": "1.*"}},
|
||||
{"name": "root/dep", "version": "1.0.3"},
|
||||
{"name": "root/dep2", "version": "1.0.3"}
|
||||
],
|
||||
"allowList": [
|
||||
"root/update"
|
||||
],
|
||||
"allowTransitiveDeps": true
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/update", "version": "1.0.4", "require": {"dep/dep": "1.*"}},
|
||||
{"name": "root/update", "version": "1.0.5", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "root/dep", "version": "1.0.6"},
|
||||
{"name": "root/dep", "version": "2.0.7"},
|
||||
{"name": "root/dep2", "version": "1.0.6"},
|
||||
{"name": "root/dep2", "version": "2.0.7"},
|
||||
{"name": "dep/dep", "version": "1.0.8", "require": {"root/dep": "1.*", "root/dep2": "1.*"}},
|
||||
{"name": "dep/dep", "version": "2.0.9", "require": {"root/dep": "2.*", "root/dep2": "2.*"}}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"root/update-1.0.4.0",
|
||||
"root/update-1.0.5.0",
|
||||
"dep/dep-1.0.8.0",
|
||||
"dep/dep-2.0.9.0",
|
||||
"root/dep-1.0.6.0",
|
||||
"root/dep2-1.0.6.0",
|
||||
"root/dep2-2.0.7.0"
|
||||
]
|
|
@ -0,0 +1,52 @@
|
|||
--TEST--
|
||||
Fixed packages and replacers get unfixed correctly (refs https://github.com/composer/composer/pull/8942)
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"root/req1": "*",
|
||||
"root/req3": "*"
|
||||
},
|
||||
"locked": [
|
||||
{"name": "root/req1", "version": "1.0.0", "require": {"replacer/pkg": "1.*"}},
|
||||
{"name": "root/req3", "version": "1.0.0", "require": {"replaced/pkg": "1.*", "dep/dep": "2.*"}},
|
||||
{"name": "replacer/pkg", "version": "1.0.0", "replace": {"replaced/pkg": "*"}},
|
||||
{"name": "dep/dep", "version": "2.3.5"}
|
||||
],
|
||||
"allowList": [
|
||||
"root/req1"
|
||||
],
|
||||
"allowTransitiveDeps": true
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "root/req1", "version": "1.0.0", "require": {"replacer/pkg": "1.*"}},
|
||||
{"name": "root/req1", "version": "1.1.0", "require": {"replacer/pkg": "1.*"}},
|
||||
{"name": "root/req3", "version": "1.0.0", "require": {"replaced/pkg": "1.*"}},
|
||||
{"name": "root/req3", "version": "1.1.0", "require": {"replaced/pkg": "1.*"}},
|
||||
{"name": "replacer/pkg", "version": "1.0.0", "replace": {"replaced/pkg": "*"}},
|
||||
{"name": "replacer/pkg", "version": "1.1.0", "replace": {"replaced/pkg": "*"}},
|
||||
{"name": "replaced/pkg", "version": "1.2.3"},
|
||||
{"name": "replaced/pkg", "version": "1.2.4"},
|
||||
{"name": "dep/dep", "version": "2.3.5"},
|
||||
{"name": "dep/dep", "version": "2.3.6"}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
"root/req3-1.0.0.0 (locked)",
|
||||
"dep/dep-2.3.5.0 (locked)",
|
||||
"root/req1-1.0.0.0",
|
||||
"root/req1-1.1.0.0",
|
||||
"replacer/pkg-1.0.0.0",
|
||||
"replacer/pkg-1.1.0.0",
|
||||
"replaced/pkg-1.2.3.0",
|
||||
"replaced/pkg-1.2.4.0"
|
||||
]
|
|
@ -0,0 +1,39 @@
|
|||
--TEST--
|
||||
Partially updating a root requirement without deps, still selects a new dependency if the update results in a replacement missing for another locked package.
|
||||
|
||||
--REQUEST--
|
||||
{
|
||||
"require": {
|
||||
"some/pkg": "*",
|
||||
"root/req": "*"
|
||||
},
|
||||
"locked": [
|
||||
{"name": "some/pkg", "version": "1.0.3", "replace": {"dep/dep": "2.1.0"}, "id": 1},
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}, "id": 2}
|
||||
],
|
||||
"allowList": [
|
||||
"some/pkg"
|
||||
]
|
||||
}
|
||||
|
||||
--FIXED--
|
||||
[
|
||||
]
|
||||
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
[
|
||||
{"name": "some/pkg", "version": "1.0.4"},
|
||||
{"name": "root/req", "version": "1.0.0", "require": {"dep/dep": "2.*"}},
|
||||
{"name": "root/req", "version": "2.0.0", "require": {"dep/dep": "3.*"}},
|
||||
{"name": "dep/dep", "version": "2.3.4"},
|
||||
{"name": "dep/dep", "version": "3.0.1"}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
[
|
||||
2,
|
||||
"some/pkg-1.0.4.0",
|
||||
"dep/dep-2.3.4.0"
|
||||
]
|
|
@ -18,19 +18,23 @@ Stability flags apply
|
|||
|
||||
--REQUEST--
|
||||
{
|
||||
"flagged/pkg": "*",
|
||||
"default/pkg": "*"
|
||||
"require": {
|
||||
"flagged/pkg": "*",
|
||||
"default/pkg": "*"
|
||||
}
|
||||
}
|
||||
|
||||
--PACKAGES--
|
||||
--PACKAGE-REPOS--
|
||||
[
|
||||
{"name": "flagged/pkg", "version": "1.0.0", "id": 1},
|
||||
{"name": "flagged/pkg", "version": "1.0.0-beta", "id": 2},
|
||||
{"name": "flagged/pkg", "version": "1.0.0-dev", "id": 3},
|
||||
{"name": "flagged/pkg", "version": "1.0.0-RC", "id": 4},
|
||||
{"name": "default/pkg", "version": "1.0.0", "id": 5},
|
||||
{"name": "default/pkg", "version": "1.0.0-RC", "id": 6},
|
||||
{"name": "default/pkg", "version": "1.0.0-alpha", "id": 7}
|
||||
[
|
||||
{"name": "flagged/pkg", "version": "1.0.0", "id": 1},
|
||||
{"name": "flagged/pkg", "version": "1.0.0-beta", "id": 2},
|
||||
{"name": "flagged/pkg", "version": "1.0.0-dev", "id": 3},
|
||||
{"name": "flagged/pkg", "version": "1.0.0-RC", "id": 4},
|
||||
{"name": "default/pkg", "version": "1.0.0", "id": 5},
|
||||
{"name": "default/pkg", "version": "1.0.0-RC", "id": 6},
|
||||
{"name": "default/pkg", "version": "1.0.0-alpha", "id": 7}
|
||||
]
|
||||
]
|
||||
|
||||
--EXPECT--
|
||||
|
@ -40,5 +44,5 @@ Stability flags apply
|
|||
4,
|
||||
5,
|
||||
6,
|
||||
"default/pkg-1.2.0.0 alias of 6"
|
||||
"default/pkg-1.2.0.0 (alias of 6)"
|
||||
]
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Test\DependencyResolver;
|
|||
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Repository\FilterRepository;
|
||||
use Composer\Repository\LockArrayRepository;
|
||||
use Composer\DependencyResolver\DefaultPolicy;
|
||||
use Composer\DependencyResolver\Pool;
|
||||
|
@ -36,11 +37,12 @@ class PoolBuilderTest extends TestCase
|
|||
/**
|
||||
* @dataProvider getIntegrationTests
|
||||
*/
|
||||
public function testPoolBuilder($file, $message, $expect, $root, $requestData, $packages, $fixed)
|
||||
public function testPoolBuilder($file, $message, $expect, $root, $requestData, $packageRepos, $fixed)
|
||||
{
|
||||
$rootAliases = !empty($root['aliases']) ? $root['aliases'] : array();
|
||||
$minimumStability = !empty($root['minimum-stability']) ? $root['minimum-stability'] : 'stable';
|
||||
$stabilityFlags = !empty($root['stability-flags']) ? $root['stability-flags'] : array();
|
||||
$rootReferences = !empty($root['references']) ? $root['references'] : array();
|
||||
$stabilityFlags = array_map(function ($stability) {
|
||||
return BasePackage::$stabilities[$stability];
|
||||
}, $stabilityFlags);
|
||||
|
@ -71,16 +73,42 @@ class PoolBuilderTest extends TestCase
|
|||
return $pkg;
|
||||
};
|
||||
|
||||
$repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases);
|
||||
$repositorySet->addRepository($repo = new ArrayRepository());
|
||||
foreach ($packages as $package) {
|
||||
$repo->addPackage($loadPackage($package));
|
||||
$repositorySet = new RepositorySet($minimumStability, $stabilityFlags, $rootAliases, $rootReferences);
|
||||
foreach ($packageRepos as $packages) {
|
||||
$repo = new ArrayRepository();
|
||||
if (isset($packages['canonical']) || isset($packages['only']) || isset($packages['exclude'])) {
|
||||
$options = $packages;
|
||||
$packages = $options['packages'];
|
||||
unset($options['packages']);
|
||||
$repositorySet->addRepository(new FilterRepository($repo, $options));
|
||||
} else {
|
||||
$repositorySet->addRepository($repo);
|
||||
}
|
||||
foreach ($packages as $package) {
|
||||
$repo->addPackage($loadPackage($package));
|
||||
}
|
||||
}
|
||||
$repositorySet->addRepository($lockedRepo = new LockArrayRepository());
|
||||
|
||||
$request = new Request();
|
||||
foreach ($requestData as $package => $constraint) {
|
||||
if (isset($requestData['locked'])) {
|
||||
foreach ($requestData['locked'] as $package) {
|
||||
$lockedRepo->addPackage($loadPackage($package));
|
||||
}
|
||||
}
|
||||
$request = new Request($lockedRepo);
|
||||
foreach ($requestData['require'] as $package => $constraint) {
|
||||
$request->requireName($package, $parser->parseConstraints($constraint));
|
||||
}
|
||||
if (isset($requestData['allowList'])) {
|
||||
$transitiveDeps = Request::UPDATE_ONLY_LISTED;
|
||||
if (isset($requestData['allowTransitiveDepsNoRootRequire']) && $requestData['allowTransitiveDepsNoRootRequire']) {
|
||||
$transitiveDeps = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS_NO_ROOT_REQUIRE;
|
||||
}
|
||||
if (isset($requestData['allowTransitiveDeps']) && $requestData['allowTransitiveDeps']) {
|
||||
$transitiveDeps = Request::UPDATE_LISTED_WITH_TRANSITIVE_DEPS;
|
||||
}
|
||||
$request->setUpdateAllowList(array_flip($requestData['allowList']), $transitiveDeps);
|
||||
}
|
||||
|
||||
foreach ($fixed as $fixedPackage) {
|
||||
$request->fixPackage($loadPackage($fixedPackage));
|
||||
|
@ -97,11 +125,23 @@ class PoolBuilderTest extends TestCase
|
|||
return $id;
|
||||
}
|
||||
|
||||
if ($package instanceof AliasPackage && $id = array_search($package->getAliasOf(), $packageIds, true)) {
|
||||
return (string) $package->getName().'-'.$package->getVersion() .' alias of '.$id;
|
||||
$suffix = '';
|
||||
if ($package->getSourceReference()) {
|
||||
$suffix = '#'.$package->getSourceReference();
|
||||
}
|
||||
if ($package->getRepository() instanceof LockArrayRepository) {
|
||||
$suffix .= ' (locked)';
|
||||
}
|
||||
|
||||
return (string) $package;
|
||||
if ($package instanceof AliasPackage) {
|
||||
if ($id = array_search($package->getAliasOf(), $packageIds, true)) {
|
||||
return (string) $package->getName().'-'.$package->getVersion() . $suffix . ' (alias of '.$id . ')';
|
||||
}
|
||||
|
||||
return (string) $package->getName().'-'.$package->getVersion() . $suffix . ' (alias of '.$package->getAliasOf()->getVersion().')';
|
||||
}
|
||||
|
||||
return (string) $package->getName().'-'.$package->getVersion() . $suffix;
|
||||
}, $result);
|
||||
|
||||
$this->assertSame($expect, $result);
|
||||
|
@ -124,7 +164,7 @@ class PoolBuilderTest extends TestCase
|
|||
$request = JsonFile::parseJson($testData['REQUEST']);
|
||||
$root = !empty($testData['ROOT']) ? JsonFile::parseJson($testData['ROOT']) : array();
|
||||
|
||||
$packages = JsonFile::parseJson($testData['PACKAGES']);
|
||||
$packageRepos = JsonFile::parseJson($testData['PACKAGE-REPOS']);
|
||||
$fixed = array();
|
||||
if (!empty($testData['FIXED'])) {
|
||||
$fixed = JsonFile::parseJson($testData['FIXED']);
|
||||
|
@ -134,7 +174,7 @@ class PoolBuilderTest extends TestCase
|
|||
die(sprintf('Test "%s" is not valid: '.$e->getMessage(), str_replace($fixturesDir.'/', '', $file)));
|
||||
}
|
||||
|
||||
$tests[basename($file)] = array(str_replace($fixturesDir.'/', '', $file), $message, $expect, $root, $request, $packages, $fixed);
|
||||
$tests[basename($file)] = array(str_replace($fixturesDir.'/', '', $file), $message, $expect, $root, $request, $packageRepos, $fixed);
|
||||
}
|
||||
|
||||
return $tests;
|
||||
|
@ -149,7 +189,7 @@ class PoolBuilderTest extends TestCase
|
|||
'ROOT' => false,
|
||||
'REQUEST' => true,
|
||||
'FIXED' => false,
|
||||
'PACKAGES' => true,
|
||||
'PACKAGE-REPOS' => true,
|
||||
'EXPECT' => true,
|
||||
);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Test\DependencyResolver;
|
|||
|
||||
use Composer\DependencyResolver\Request;
|
||||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Test\TestCase;
|
||||
|
||||
class RequestTest extends TestCase
|
||||
|
@ -34,7 +35,7 @@ class RequestTest extends TestCase
|
|||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'foo' => null,
|
||||
'foo' => new MatchAllConstraint(),
|
||||
),
|
||||
$request->getRequires()
|
||||
);
|
||||
|
|
|
@ -19,6 +19,7 @@ use Composer\DependencyResolver\Pool;
|
|||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Test\TestCase;
|
||||
|
||||
class RuleTest extends TestCase
|
||||
|
@ -102,8 +103,11 @@ class RuleTest extends TestCase
|
|||
$repositorySetMock = $this->getMockBuilder('Composer\Repository\RepositorySet')->disableOriginalConstructor()->getMock();
|
||||
$requestMock = $this->getMockBuilder('Composer\DependencyResolver\Request')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$rule = new GenericRule(array($p1->getId(), -$p2->getId()), Rule::RULE_PACKAGE_REQUIRES, new Link('baz', 'foo'));
|
||||
$emptyConstraint = new MatchAllConstraint();
|
||||
$emptyConstraint->setPrettyString('*');
|
||||
|
||||
$this->assertEquals('baz 1.1 relates to foo -> satisfiable by foo[2.1].', $rule->getPrettyString($repositorySetMock, $requestMock, $pool, false));
|
||||
$rule = new GenericRule(array($p1->getId(), -$p2->getId()), Rule::RULE_PACKAGE_REQUIRES, new Link('baz', 'foo', $emptyConstraint));
|
||||
|
||||
$this->assertEquals('baz 1.1 relates to foo * -> satisfiable by foo[2.1].', $rule->getPrettyString($repositorySetMock, $requestMock, $pool, false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -235,8 +235,8 @@ class SolverTest extends TestCase
|
|||
$this->repo->addPackage($newPackageA = $this->getPackage('A', '1.1'));
|
||||
$this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1'));
|
||||
|
||||
$packageA->setRequires(array('b' => new Link('A', 'B', null, 'requires')));
|
||||
$newPackageA->setRequires(array('b' => new Link('A', 'B', null, 'requires')));
|
||||
$packageA->setRequires(array('b' => new Link('A', 'B', new MatchAllConstraint(), 'requires')));
|
||||
$newPackageA->setRequires(array('b' => new Link('A', 'B', new MatchAllConstraint(), 'requires')));
|
||||
|
||||
$this->reposComplete();
|
||||
|
||||
|
@ -639,8 +639,11 @@ class SolverTest extends TestCase
|
|||
|
||||
$this->reposComplete();
|
||||
|
||||
$this->request->requireName('A');
|
||||
$this->request->requireName('B');
|
||||
$emptyConstraint = new MatchAllConstraint();
|
||||
$emptyConstraint->setPrettyString('*');
|
||||
|
||||
$this->request->requireName('A', $emptyConstraint);
|
||||
$this->request->requireName('B', $emptyConstraint);
|
||||
|
||||
$this->createSolver();
|
||||
try {
|
||||
|
@ -652,9 +655,9 @@ class SolverTest extends TestCase
|
|||
|
||||
$msg = "\n";
|
||||
$msg .= " Problem 1\n";
|
||||
$msg .= " - Root composer.json requires a -> satisfiable by A[1.0].\n";
|
||||
$msg .= " - Root composer.json requires a * -> satisfiable by A[1.0].\n";
|
||||
$msg .= " - A 1.0 conflicts with B 1.0.\n";
|
||||
$msg .= " - Root composer.json requires b -> satisfiable by B[1.0].\n";
|
||||
$msg .= " - Root composer.json requires b * -> satisfiable by B[1.0].\n";
|
||||
$this->assertEquals($msg, $e->getPrettyString($this->repoSet, $this->request, $this->pool, false));
|
||||
}
|
||||
}
|
||||
|
@ -683,7 +686,7 @@ class SolverTest extends TestCase
|
|||
|
||||
$msg = "\n";
|
||||
$msg .= " Problem 1\n";
|
||||
$msg .= " - Root composer.json requires a -> satisfiable by A[1.0].\n";
|
||||
$msg .= " - Root composer.json requires a * -> satisfiable by A[1.0].\n";
|
||||
$msg .= " - A 1.0 requires b >= 2.0 -> found B[1.0] but it does not match the constraint.\n";
|
||||
$this->assertEquals($msg, $e->getPrettyString($this->repoSet, $this->request, $this->pool, false));
|
||||
}
|
||||
|
@ -712,7 +715,10 @@ class SolverTest extends TestCase
|
|||
|
||||
$this->reposComplete();
|
||||
|
||||
$this->request->requireName('A');
|
||||
$emptyConstraint = new MatchAllConstraint();
|
||||
$emptyConstraint->setPrettyString('*');
|
||||
|
||||
$this->request->requireName('A', $emptyConstraint);
|
||||
|
||||
$this->createSolver();
|
||||
try {
|
||||
|
@ -729,7 +735,7 @@ class SolverTest extends TestCase
|
|||
$msg .= " - B 1.0 requires c >= 1.0 -> satisfiable by C[1.0].\n";
|
||||
$msg .= " - You can only install one version of a package, so only one of these can be installed: B[0.9, 1.0].\n";
|
||||
$msg .= " - A 1.0 requires b >= 1.0 -> satisfiable by B[1.0].\n";
|
||||
$msg .= " - Root composer.json requires a -> satisfiable by A[1.0].\n";
|
||||
$msg .= " - Root composer.json requires a * -> satisfiable by A[1.0].\n";
|
||||
$this->assertEquals($msg, $e->getPrettyString($this->repoSet, $this->request, $this->pool, false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Test\Package;
|
|||
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\RootAliasPackage;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Test\TestCase;
|
||||
use Prophecy\Argument;
|
||||
|
||||
|
@ -26,7 +27,7 @@ class RootAliasPackageTest extends TestCase
|
|||
|
||||
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
|
||||
$this->assertEmpty($alias->getRequires());
|
||||
$links = array(new Link('a', 'b', null, 'foo', 'self.version'));
|
||||
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
|
||||
$alias->setRequires($links);
|
||||
$this->assertNotEmpty($alias->getRequires());
|
||||
}
|
||||
|
@ -38,7 +39,7 @@ class RootAliasPackageTest extends TestCase
|
|||
|
||||
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
|
||||
$this->assertEmpty($alias->getDevRequires());
|
||||
$links = array(new Link('a', 'b', null, 'foo', 'self.version'));
|
||||
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
|
||||
$alias->setDevRequires($links);
|
||||
$this->assertNotEmpty($alias->getDevRequires());
|
||||
}
|
||||
|
@ -50,7 +51,7 @@ class RootAliasPackageTest extends TestCase
|
|||
|
||||
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
|
||||
$this->assertEmpty($alias->getConflicts());
|
||||
$links = array(new Link('a', 'b', null, 'foo', 'self.version'));
|
||||
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
|
||||
$alias->setConflicts($links);
|
||||
$this->assertNotEmpty($alias->getConflicts());
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ class RootAliasPackageTest extends TestCase
|
|||
|
||||
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
|
||||
$this->assertEmpty($alias->getProvides());
|
||||
$links = array(new Link('a', 'b', null, 'foo', 'self.version'));
|
||||
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
|
||||
$alias->setProvides($links);
|
||||
$this->assertNotEmpty($alias->getProvides());
|
||||
}
|
||||
|
@ -74,7 +75,7 @@ class RootAliasPackageTest extends TestCase
|
|||
|
||||
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
|
||||
$this->assertEmpty($alias->getReplaces());
|
||||
$links = array(new Link('a', 'b', null, 'foo', 'self.version'));
|
||||
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
|
||||
$alias->setReplaces($links);
|
||||
$this->assertNotEmpty($alias->getReplaces());
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Repository\InstalledRepository;
|
|||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Repository\InstalledArrayRepository;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
use Composer\Test\TestCase;
|
||||
|
||||
class InstalledRepositoryTest extends TestCase
|
||||
|
@ -30,8 +31,8 @@ class InstalledRepositoryTest extends TestCase
|
|||
$arrayRepoTwo->addPackage($bar = $this->getPackage('bar', '1'));
|
||||
$arrayRepoTwo->addPackage($bar2 = $this->getPackage('bar', '2'));
|
||||
|
||||
$foo->setReplaces(array(new Link('foo', 'provided')));
|
||||
$bar2->setProvides(array(new Link('bar', 'provided')));
|
||||
$foo->setReplaces(array(new Link('foo', 'provided', new MatchAllConstraint())));
|
||||
$bar2->setProvides(array(new Link('bar', 'provided', new MatchAllConstraint())));
|
||||
|
||||
$repo = new InstalledRepository(array($arrayRepoOne, $arrayRepoTwo));
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ use Composer\Package\Link;
|
|||
use Composer\Package\Package;
|
||||
use Composer\Test\TestCase;
|
||||
use Composer\Util\PackageSorter;
|
||||
use Composer\Semver\Constraint\MatchAllConstraint;
|
||||
|
||||
class PackageSorterTest extends TestCase
|
||||
{
|
||||
|
@ -120,7 +121,7 @@ class PackageSorterTest extends TestCase
|
|||
|
||||
$links = array();
|
||||
foreach ($requires as $requireName) {
|
||||
$links[] = new Link($package->getName(), $requireName);
|
||||
$links[] = new Link($package->getName(), $requireName, new MatchAllConstraint);
|
||||
}
|
||||
$package->setRequires($links);
|
||||
|
||||
|
|
Loading…
Reference in New Issue