Deduplicate link instances between versions of a given package
parent
e753bf08b1
commit
e8c6948770
|
@ -38,6 +38,70 @@ class ArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
public function load(array $config, $class = 'Composer\Package\CompletePackage')
|
public function load(array $config, $class = 'Composer\Package\CompletePackage')
|
||||||
|
{
|
||||||
|
$package = $this->createObject($config, $class);
|
||||||
|
|
||||||
|
foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
|
||||||
|
if (isset($config[$type])) {
|
||||||
|
$method = 'set'.ucfirst($opts['method']);
|
||||||
|
$package->{$method}(
|
||||||
|
$this->parseLinks(
|
||||||
|
$package->getName(),
|
||||||
|
$package->getPrettyVersion(),
|
||||||
|
$opts['description'],
|
||||||
|
$config[$type]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$package = $this->configureObject($package, $config);
|
||||||
|
|
||||||
|
return $package;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadPackages(array $versions, $class)
|
||||||
|
{
|
||||||
|
static $uniqKeys = array('version', 'version_normalized', 'source', 'dist', 'time');
|
||||||
|
|
||||||
|
$packages = array();
|
||||||
|
$linkCache = array();
|
||||||
|
|
||||||
|
foreach ($versions as $version) {
|
||||||
|
if (isset($version['versions'])) {
|
||||||
|
$baseVersion = $version;
|
||||||
|
foreach ($uniqKeys as $key) {
|
||||||
|
unset($baseVersion[$key.'s']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($version['versions'] as $index => $dummy) {
|
||||||
|
$unpackedVersion = $baseVersion;
|
||||||
|
foreach ($uniqKeys as $key) {
|
||||||
|
$unpackedVersion[$key] = $version[$key.'s'][$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
$package = $this->createObject($unpackedVersion, $class);
|
||||||
|
|
||||||
|
$this->configureCachedLinks($linkCache, $package, $unpackedVersion);
|
||||||
|
$package = $this->configureObject($package, $unpackedVersion);
|
||||||
|
|
||||||
|
$packages[] = $package;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$package = $this->createObject($version, $class);
|
||||||
|
|
||||||
|
$this->configureCachedLinks($linkCache, $package, $version);
|
||||||
|
$package = $this->configureObject($package, $version);
|
||||||
|
|
||||||
|
$packages[] = $package;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createObject(array $config, $class)
|
||||||
{
|
{
|
||||||
if (!isset($config['name'])) {
|
if (!isset($config['name'])) {
|
||||||
throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
|
throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
|
||||||
|
@ -52,7 +116,12 @@ class ArrayLoader implements LoaderInterface
|
||||||
} else {
|
} else {
|
||||||
$version = $this->versionParser->normalize($config['version']);
|
$version = $this->versionParser->normalize($config['version']);
|
||||||
}
|
}
|
||||||
$package = new $class($config['name'], $version, $config['version']);
|
|
||||||
|
return new $class($config['name'], $version, $config['version']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function configureObject($package, array $config)
|
||||||
|
{
|
||||||
$package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
|
$package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
|
||||||
|
|
||||||
if (isset($config['target-dir'])) {
|
if (isset($config['target-dir'])) {
|
||||||
|
@ -109,20 +178,6 @@ class ArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
|
|
||||||
if (isset($config[$type])) {
|
|
||||||
$method = 'set'.ucfirst($opts['method']);
|
|
||||||
$package->{$method}(
|
|
||||||
$this->parseLinks(
|
|
||||||
$package->getName(),
|
|
||||||
$package->getPrettyVersion(),
|
|
||||||
$opts['description'],
|
|
||||||
$config[$type]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['suggest']) && is_array($config['suggest'])) {
|
if (isset($config['suggest']) && is_array($config['suggest'])) {
|
||||||
foreach ($config['suggest'] as $target => $reason) {
|
foreach ($config['suggest'] as $target => $reason) {
|
||||||
if ('self.version' === trim($reason)) {
|
if ('self.version' === trim($reason)) {
|
||||||
|
@ -202,21 +257,50 @@ class ArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aliasNormalized = $this->getBranchAlias($config)) {
|
|
||||||
if ($package instanceof RootPackageInterface) {
|
|
||||||
$package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
|
|
||||||
} else {
|
|
||||||
$package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->loadOptions && isset($config['transport-options'])) {
|
if ($this->loadOptions && isset($config['transport-options'])) {
|
||||||
$package->setTransportOptions($config['transport-options']);
|
$package->setTransportOptions($config['transport-options']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($aliasNormalized = $this->getBranchAlias($config)) {
|
||||||
|
if ($package instanceof RootPackageInterface) {
|
||||||
|
return new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
|
||||||
|
}
|
||||||
|
|
||||||
return $package;
|
return $package;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function configureCachedLinks(&$linkCache, $package, array $config)
|
||||||
|
{
|
||||||
|
$name = $package->getName();
|
||||||
|
$prettyVersion = $package->getPrettyVersion();
|
||||||
|
|
||||||
|
foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
|
||||||
|
if (isset($config[$type])) {
|
||||||
|
$method = 'set'.ucfirst($opts['method']);
|
||||||
|
|
||||||
|
$links = array();
|
||||||
|
foreach ($config[$type] as $prettyTarget => $constraint) {
|
||||||
|
$target = strtolower($prettyTarget);
|
||||||
|
if ($constraint === 'self.version') {
|
||||||
|
$links[$target] = $this->createLink($name, $prettyVersion, $opts['description'], $target, $constraint);
|
||||||
|
} else {
|
||||||
|
if (!isset($linkCache[$name][$type][$target][$constraint])) {
|
||||||
|
$linkCache[$name][$type][$target][$constraint] = array($target, $this->createLink($name, $prettyVersion, $opts['description'], $target, $constraint));
|
||||||
|
}
|
||||||
|
|
||||||
|
list($target, $link) = $linkCache[$name][$type][$target][$constraint];
|
||||||
|
$links[$target] = $link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$package->{$method}($links);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $source source package name
|
* @param string $source source package name
|
||||||
* @param string $sourceVersion source package version (pretty version ideally)
|
* @param string $sourceVersion source package version (pretty version ideally)
|
||||||
|
@ -228,21 +312,26 @@ class ArrayLoader implements LoaderInterface
|
||||||
{
|
{
|
||||||
$res = array();
|
$res = array();
|
||||||
foreach ($links as $target => $constraint) {
|
foreach ($links as $target => $constraint) {
|
||||||
if (!is_string($constraint)) {
|
$res[strtolower($target)] = $this->createLink($source, $sourceVersion, $description, $target, $constraint);
|
||||||
throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
|
|
||||||
}
|
|
||||||
if ('self.version' === $constraint) {
|
|
||||||
$parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
|
|
||||||
} else {
|
|
||||||
$parsedConstraint = $this->versionParser->parseConstraints($constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
$res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function createLink($source, $sourceVersion, $description, $target, $prettyConstraint)
|
||||||
|
{
|
||||||
|
if (!is_string($prettyConstraint)) {
|
||||||
|
throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($prettyConstraint) . ' (' . var_export($prettyConstraint, true) . ')');
|
||||||
|
}
|
||||||
|
if ('self.version' === $prettyConstraint) {
|
||||||
|
$parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
|
||||||
|
} else {
|
||||||
|
$parsedConstraint = $this->versionParser->parseConstraints($prettyConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Link($source, $target, $parsedConstraint, $description, $prettyConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists
|
* Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists
|
||||||
*
|
*
|
||||||
|
|
|
@ -61,7 +61,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
private $rootData;
|
private $rootData;
|
||||||
private $hasPartialPackages;
|
private $hasPartialPackages;
|
||||||
private $partialPackagesByName;
|
private $partialPackagesByName;
|
||||||
private $versionParser;
|
/**
|
||||||
|
* TODO v3 should make this private once we can drop PHP 5.3 support
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
public $versionParser;
|
||||||
|
|
||||||
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null)
|
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null)
|
||||||
{
|
{
|
||||||
|
@ -414,6 +418,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
|
|
||||||
$this->providers[$name] = array();
|
$this->providers[$name] = array();
|
||||||
foreach ($packages['packages'] as $versions) {
|
foreach ($packages['packages'] as $versions) {
|
||||||
|
$versionsToLoad = array();
|
||||||
foreach ($versions as $version) {
|
foreach ($versions as $version) {
|
||||||
if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
|
if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -440,8 +445,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$versionsToLoad[] = $version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// load acceptable packages in the providers
|
// load acceptable packages in the providers
|
||||||
$package = $this->createPackage($version, 'Composer\Package\CompletePackage');
|
$loadedPackages = $this->createPackages($versionsToLoad, 'Composer\Package\CompletePackage');
|
||||||
|
foreach ($loadedPackages as $package) {
|
||||||
$package->setRepository($this);
|
$package->setRepository($this);
|
||||||
|
|
||||||
if ($package instanceof AliasPackage) {
|
if ($package instanceof AliasPackage) {
|
||||||
|
@ -476,7 +486,6 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$result = $this->providers[$name];
|
$result = $this->providers[$name];
|
||||||
|
|
||||||
|
@ -501,8 +510,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
|
|
||||||
$repoData = $this->loadDataFromServer();
|
$repoData = $this->loadDataFromServer();
|
||||||
|
|
||||||
foreach ($repoData as $package) {
|
foreach ($this->createPackages($repoData, 'Composer\Package\CompletePackage') as $package) {
|
||||||
$this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
|
$this->addPackage($package);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,6 +554,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
|
|
||||||
$this->asyncFetchFile($url, $cacheKey, $lastModified)
|
$this->asyncFetchFile($url, $cacheKey, $lastModified)
|
||||||
->then(function ($response) use (&$packages, $contents, $name, $constraint, $repo, $isPackageAcceptableCallable) {
|
->then(function ($response) use (&$packages, $contents, $name, $constraint, $repo, $isPackageAcceptableCallable) {
|
||||||
|
static $uniqKeys = array('version', 'version_normalized', 'source', 'dist', 'time');
|
||||||
|
|
||||||
if (true === $response) {
|
if (true === $response) {
|
||||||
$response = $contents;
|
$response = $contents;
|
||||||
}
|
}
|
||||||
|
@ -553,24 +564,37 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$uniqKeys = array('version', 'version_normalized', 'source', 'dist', 'time');
|
$versionsToLoad = array();
|
||||||
foreach ($response['packages'][$name] as $version) {
|
foreach ($response['packages'][$name] as $version) {
|
||||||
if (isset($version['versions'])) {
|
if (isset($version['version_normalizeds'])) {
|
||||||
$baseVersion = $version;
|
foreach ($version['version_normalizeds'] as $index => $normalizedVersion) {
|
||||||
|
if (!$repo->isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $normalizedVersion)) {
|
||||||
foreach ($uniqKeys as $key) {
|
foreach ($uniqKeys as $key) {
|
||||||
unset($baseVersion[$key.'s']);
|
unset($version[$key.'s'][$index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($version['versions'] as $index => $dummy) {
|
|
||||||
$unpackedVersion = $baseVersion;
|
|
||||||
foreach ($uniqKeys as $key) {
|
|
||||||
$unpackedVersion[$key] = $version[$key.'s'][$index];
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$repo->createPackageIfAcceptable($packages, $isPackageAcceptableCallable, $unpackedVersion, $constraint);
|
if (count($version['version_normalizeds'])) {
|
||||||
|
$versionsToLoad[] = $version;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$repo->createPackageIfAcceptable($packages, $isPackageAcceptableCallable, $version, $constraint);
|
if (!isset($version['version_normalized'])) {
|
||||||
|
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($repo->isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $version['version_normalized'])) {
|
||||||
|
$versionsToLoad[] = $version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$loadedPackages = $this->createPackages($versionsToLoad, 'Composer\Package\CompletePackage');
|
||||||
|
foreach ($loadedPackages as $package) {
|
||||||
|
$package->setRepository($this);
|
||||||
|
|
||||||
|
$packages[spl_object_hash($package)] = $package;
|
||||||
|
if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
|
||||||
|
$packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, function ($e) {
|
}, function ($e) {
|
||||||
|
@ -592,27 +616,17 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
public function createPackageIfAcceptable(&$packages, $isPackageAcceptableCallable, $version, $constraint)
|
public function isVersionAcceptable($isPackageAcceptableCallable, $constraint, $name, $versionNormalized)
|
||||||
{
|
{
|
||||||
if (!call_user_func($isPackageAcceptableCallable, strtolower($version['name']), VersionParser::parseStability($version['version']))) {
|
if (!call_user_func($isPackageAcceptableCallable, strtolower($name), VersionParser::parseStability($versionNormalized))) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($version['version_normalized']) && $constraint && !$constraint->matches(new Constraint('==', $version['version_normalized']))) {
|
if ($constraint && !$constraint->matches(new Constraint('==', $versionNormalized))) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load acceptable packages in the providers
|
return true;
|
||||||
$package = $this->createPackage($version, 'Composer\Package\CompletePackage');
|
|
||||||
$package->setRepository($this);
|
|
||||||
|
|
||||||
// if there was no version_normalized, then we need to check now for the constraint
|
|
||||||
if (!$constraint || isset($version['version_normalized']) || $constraint->matches(new Constraint('==', $package->getVersion()))) {
|
|
||||||
$packages[spl_object_hash($package)] = $package;
|
|
||||||
if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
|
|
||||||
$packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadRootServerFile()
|
protected function loadRootServerFile()
|
||||||
|
@ -775,23 +789,37 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
return $packages;
|
return $packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
|
/**
|
||||||
|
* TODO v3 should make this private once we can drop PHP 5.3 support
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
public function createPackages(array $packages, $class = 'Composer\Package\CompletePackage')
|
||||||
{
|
{
|
||||||
|
if (!$packages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
foreach ($packages as &$data) {
|
||||||
if (!isset($data['notification-url'])) {
|
if (!isset($data['notification-url'])) {
|
||||||
$data['notification-url'] = $this->notifyUrl;
|
$data['notification-url'] = $this->notifyUrl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$package = $this->loader->load($data, $class);
|
$packages = $this->loader->loadPackages($packages, $class);
|
||||||
|
|
||||||
|
foreach ($packages as $package) {
|
||||||
if (isset($this->sourceMirrors[$package->getSourceType()])) {
|
if (isset($this->sourceMirrors[$package->getSourceType()])) {
|
||||||
$package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
|
$package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
|
||||||
}
|
}
|
||||||
$package->setDistMirrors($this->distMirrors);
|
$package->setDistMirrors($this->distMirrors);
|
||||||
$this->configurePackageTransportOptions($package);
|
$this->configurePackageTransportOptions($package);
|
||||||
|
}
|
||||||
|
|
||||||
return $package;
|
return $packages;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
throw new \RuntimeException('Could not load package '.(isset($data['name']) ? $data['name'] : json_encode($data)).' in '.$this->url.': ['.get_class($e).'] '.$e->getMessage(), 0, $e);
|
throw new \RuntimeException('Could not load packages '.(isset($packages[0]['name']) ? $packages[0]['name'] : json_encode($packages)).' in '.$this->url.': ['.get_class($e).'] '.$e->getMessage(), 0, $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class ComposerRepositoryTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
$repository = $this->getMockBuilder('Composer\Repository\ComposerRepository')
|
$repository = $this->getMockBuilder('Composer\Repository\ComposerRepository')
|
||||||
->setMethods(array('loadRootServerFile', 'createPackage'))
|
->setMethods(array('loadRootServerFile', 'createPackages'))
|
||||||
->setConstructorArgs(array(
|
->setConstructorArgs(array(
|
||||||
$repoConfig,
|
$repoConfig,
|
||||||
new NullIO,
|
new NullIO,
|
||||||
|
@ -47,15 +47,16 @@ class ComposerRepositoryTest extends TestCase
|
||||||
->method('loadRootServerFile')
|
->method('loadRootServerFile')
|
||||||
->will($this->returnValue($repoPackages));
|
->will($this->returnValue($repoPackages));
|
||||||
|
|
||||||
|
$stubs = array();
|
||||||
foreach ($expected as $at => $arg) {
|
foreach ($expected as $at => $arg) {
|
||||||
$stubPackage = $this->getPackage('stub/stub', '1.0.0');
|
$stubs[] = $this->getPackage('stub/stub', '1.0.0');
|
||||||
|
}
|
||||||
|
|
||||||
$repository
|
$repository
|
||||||
->expects($this->at($at + 2))
|
->expects($this->at(2))
|
||||||
->method('createPackage')
|
->method('createPackages')
|
||||||
->with($this->identicalTo($arg), $this->equalTo('Composer\Package\CompletePackage'))
|
->with($this->identicalTo($expected), $this->equalTo('Composer\Package\CompletePackage'))
|
||||||
->will($this->returnValue($stubPackage));
|
->will($this->returnValue($stubs));
|
||||||
}
|
|
||||||
|
|
||||||
// Triggers initialization
|
// Triggers initialization
|
||||||
$packages = $repository->getPackages();
|
$packages = $repository->getPackages();
|
||||||
|
|
Loading…
Reference in New Issue