Skip to content

Commit

Permalink
Optimize import of package definitions with dependencies of root package
Browse files Browse the repository at this point in the history
  • Loading branch information
francoispluchino committed Oct 1, 2014
1 parent b0a36cb commit c1d81f0
Show file tree
Hide file tree
Showing 7 changed files with 620 additions and 27 deletions.
9 changes: 9 additions & 0 deletions FxpAssetPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Fxp\Composer\AssetPlugin\Event\VcsRepositoryEvent;
use Fxp\Composer\AssetPlugin\Installer\AssetInstaller;
use Fxp\Composer\AssetPlugin\Installer\BowerInstaller;
use Fxp\Composer\AssetPlugin\Repository\VcsPackageFilter;
use Fxp\Composer\AssetPlugin\Repository\Util;

/**
Expand All @@ -47,6 +48,11 @@ class FxpAssetPlugin implements PluginInterface, EventSubscriberInterface
*/
protected $pool;

/**
* @var VcsPackageFilter
*/
protected $packageFilter;

/**
* {@inheritdoc}
*/
Expand All @@ -68,6 +74,7 @@ public static function getSubscribedEvents()
public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->packageFilter = new VcsPackageFilter($composer->getPackage());
$extra = $composer->getPackage()->getExtra();
$rm = $composer->getRepositoryManager();

Expand Down Expand Up @@ -119,6 +126,7 @@ protected function addRegistryRepositories(RepositoryManager $rm, array $extra)
foreach (Assets::getRegistries() as $assetType => $registryClass) {
$config = array(
'repository-manager' => $rm,
'vcs-package-filter' => $this->packageFilter,
'asset-options' => $this->crateAssetOptions($opts, $assetType),
);

Expand Down Expand Up @@ -158,6 +166,7 @@ protected function addRepositories(RepositoryManager $rm, array $repositories, P
$this->validateRepositories($index, $repo);
$name = is_int($index) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
$name = isset($repo['name']) ? $repo['name'] : $name;
$repo['vcs-package-filter'] = $this->packageFilter;

Util::addRepository($rm, $this->repos, $name, $repo, $pool);
}
Expand Down
8 changes: 8 additions & 0 deletions Repository/AbstractAssetVcsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ abstract class AbstractAssetVcsRepository extends VcsRepository
*/
protected $rootData;

/**
* @var VcsPackageFilter
*/
protected $filter;

/**
* Constructor.
*
Expand All @@ -82,6 +87,9 @@ public function __construct(array $repoConfig, IOInterface $io, Config $config,
$repoConfig['filename'] = $assetType->getFilename();
$this->assetType = $assetType;
$this->dispatcher = $dispatcher;
$this->filter = isset($repoConfig['vcs-package-filter'])
? $repoConfig['vcs-package-filter']
: null;

parent::__construct($repoConfig, $io, $config, $dispatcher, $drivers);
}
Expand Down
9 changes: 9 additions & 0 deletions Repository/AbstractAssetsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ abstract class AbstractAssetsRepository extends ComposerRepository
*/
protected $repositoryManager;

/**
* @var VcsPackageFilter
*/
protected $packageFilter;

/**
* Constructor.
*
Expand All @@ -82,6 +87,9 @@ public function __construct(array $repoConfig, IOInterface $io, Config $config,
$this->searchUrl = $this->getSearchUrl();
$this->hasProviders = true;
$this->rm = $repoConfig['repository-manager'];
$this->packageFilter = isset($repoConfig['vcs-package-filter'])
? $repoConfig['vcs-package-filter']
: null;
$this->repos = array();
$this->searchable = (bool) $this->getOption($repoConfig['asset-options'], 'searchable', true);
$this->fallbackProviders = false;
Expand Down Expand Up @@ -126,6 +134,7 @@ public function whatProvides(Pool $pool, $name)
$cacheName = $packageName . '-' . sha1($packageName) . '-package.json';
$data = $this->fetchFile($packageUrl, $cacheName);
$repo = $this->createVcsRepositoryConfig($data, Util::cleanPackageName($name));
$repo['vcs-package-filter'] = $this->packageFilter;

Util::addRepository($this->rm, $this->repos, $name, $repo, $pool);

Expand Down
52 changes: 34 additions & 18 deletions Repository/AssetVcsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,43 +55,59 @@ protected function initialize()
*/
protected function initTags(VcsDriverInterface $driver)
{
$verbose = $this->verbose;
$packageClass = 'Fxp\Composer\AssetPlugin\Package\LazyCompletePackage';

foreach ($driver->getTags() as $tag => $identifier) {
$packageName = $this->createPackageName();

// strip the release- prefix from tags if present
$tag = str_replace('release-', '', $tag);

if (null !== $this->filter && $this->filter->skip($this->assetType, $packageName, $tag)) {
continue;
}

if (!$parsedTag = Validator::validateTag($tag, $this->assetType, $this->versionParser)) {
if ($verbose) {
if ($this->verbose) {
$this->io->write('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
}
continue;
}

$data = $this->createMockOfPackageConfig($packageName, $tag);
$data['version'] = $this->assetType->getVersionConverter()->convertVersion($tag);
$data['version_normalized'] = $parsedTag;

// make sure tag packages have no -dev flag
$data['version'] = preg_replace('{[.-]?dev$}i', '', (string) $data['version']);
$data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', (string) $data['version_normalized']);

$packageData = $this->preProcessAsset($data);
$package = $this->loader->load($packageData, $packageClass);
$lazyLoader = $this->createLazyLoader('tag', $identifier, $packageData, $driver);
/* @var LazyCompletePackage $package */
$package->setLoader($lazyLoader);
$this->addPackage($package);
$this->initTag($driver, $packageName, $tag, $identifier, $parsedTag);
}

if (!$this->verbose) {
$this->io->overwrite('', false);
}
}

/**
* Initializes the tag.
*
* @param VcsDriverInterface $driver
* @param string $packageName
* @param string $tag
* @param string $identifier
* @param string $parsedTag
*/
protected function initTag(VcsDriverInterface $driver, $packageName, $tag, $identifier, $parsedTag)
{
$packageClass = 'Fxp\Composer\AssetPlugin\Package\LazyCompletePackage';
$data = $this->createMockOfPackageConfig($packageName, $tag);
$data['version'] = $this->assetType->getVersionConverter()->convertVersion($tag);
$data['version_normalized'] = $parsedTag;

// make sure tag packages have no -dev flag
$data['version'] = preg_replace('{[.-]?dev$}i', '', (string) $data['version']);
$data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', (string) $data['version_normalized']);

$packageData = $this->preProcessAsset($data);
$package = $this->loader->load($packageData, $packageClass);
$lazyLoader = $this->createLazyLoader('tag', $identifier, $packageData, $driver);
/* @var LazyCompletePackage $package */
$package->setLoader($lazyLoader);
$this->addPackage($package);
}

/**
* Initializes all branches.
*
Expand Down
174 changes: 174 additions & 0 deletions Repository/VcsPackageFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

/*
* This file is part of the Fxp Composer Asset Plugin package.
*
* (c) François Pluchino <francois.pluchino@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Fxp\Composer\AssetPlugin\Repository;

use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\RootPackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Package\LinkConstraint\LinkConstraintInterface;
use Fxp\Composer\AssetPlugin\Type\AssetTypeInterface;

/**
* Filters the asset packages imported into VCS repository to optimize
* performance when getting the informations of packages.
*
* @author François Pluchino <francois.pluchino@gmail.com>
*/
class VcsPackageFilter
{
/**
* @var RootPackageInterface
*/
protected $package;

/**
* @var VersionParser
*/
protected $versionParser;

/**
* @var array
*/
protected $requires;

/**
* Constructor.
*
* @param RootPackageInterface $package The root package
*/
public function __construct(RootPackageInterface $package)
{
$this->package = $package;
$this->versionParser = new VersionParser();

$this->initialize();
}

/**
* Check if the version must be skipped.
*
* @param AssetTypeInterface $assetType The asset type
* @param string $name The composer package name
* @param string $version The version
*
* @return bool
*/
public function skip(AssetTypeInterface $assetType, $name, $version)
{
if (!isset($this->requires[$name])) {
return true;
}

/* @var Link $require */
$require = $this->requires[$name];
$cVersion = $assetType->getVersionConverter()->convertVersion($version);
$normalizedVersion = $this->versionParser->normalize($cVersion);

return !$this->satisfy($require, $normalizedVersion);
}

/**
* Check if the require dependency has a satisfactory version and stability.
*
* @param Link $require The require link defined in root package.
* @param string $normalizedVersion The normalized version
*
* @return bool
*/
protected function satisfy(Link $require, $normalizedVersion)
{
return $this->satisfyVersion($require, $normalizedVersion)
&& $this->satisfyStability($require, $normalizedVersion);
}

/**
* Check if the require dependency has a satisfactory version.
*
* @param Link $require The require link defined in root package.
* @param string $normalizedVersion The normalized version
*
* @return bool
*/
protected function satisfyVersion(Link $require, $normalizedVersion)
{
$constraintSame = $this->versionParser->parseConstraints($normalizedVersion);
$sameVersion = (bool) $require->getConstraint()->matches($constraintSame);

$normalizedVersion = $this->getVersionConstraint($normalizedVersion);
$constraint = $this->getVersionConstraint($normalizedVersion);

return (bool) $require->getConstraint()->matches($constraint) || $sameVersion;
}

/**
* Check if the require dependency has a satisfactory stability.
*
* @param Link $require The require link defined in root package.
* @param string $normalizedVersion The normalized version
*
* @return bool
*/
protected function satisfyStability(Link $require, $normalizedVersion)
{
$requireStability = $this->getRequireStability($require);
$stability = $this->versionParser->parseStability($normalizedVersion);
$stability = false !== strpos($normalizedVersion, '-patch') ? 'dev' : $stability;

return Package::$stabilities[$stability] <= Package::$stabilities[$requireStability];
}

/**
* Get the minimum stability for the require dependency defined in root package.
*
* @param Link $require The require link defined in root package.
*
* @return string The minimum stability
*/
protected function getRequireStability(Link $require)
{
$prettyConstraint = $require->getPrettyConstraint();

if (false !== strpos($prettyConstraint, '@')) {
return $this->versionParser->parseStability($prettyConstraint);
}

return $this->package->getMinimumStability();
}

/**
* Get the link constraint of normalized version.
*
* @param string $normalizedVersion The normalized version
*
* @return LinkConstraintInterface The constraint
*/
protected function getVersionConstraint($normalizedVersion)
{
if (preg_match('/^\d+(\.\d+)(\.\d+)(\.\d+)\-[A-Za-z0-9]+$/', $normalizedVersion)) {
$normalizedVersion = substr($normalizedVersion, 0, strpos($normalizedVersion, '-'));
}

return $this->versionParser->parseConstraints($normalizedVersion);
}

/**
* Initialize.
*/
protected function initialize()
{
$this->requires = array_merge(
$this->package->getRequires(),
$this->package->getDevRequires()
);
}
}
Loading

0 comments on commit c1d81f0

Please sign in to comment.