This commit is contained in:
Daniil Gentili 2020-11-04 10:49:05 +01:00
parent d22df4bd9c
commit e3409513c3
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
9 changed files with 362 additions and 45 deletions

View File

@ -1,27 +0,0 @@
<?php
namespace Phabel\Composer;
use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\ComposerRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\ArrayRepository as ComposerArrayRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT
*
* @property ComposerArrayRepository $repository
*/
trait ArrayRepository
{
public function addPackage(PackageInterface $package)
{
$this->repository->addPackage($package);
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace Phabel\Composer\Constraint;
use Composer\Semver\Constraint\Constraint as ComposerConstraint;
/**
* Constraint.
*
* @property ComposerConstraint $previous
*/
class Constraint extends ComposerConstraint
{
use ConstraintTrait;
public function getVersion()
{
return $this->previous->getVersion();
}
public function getOperator()
{
return $this->previous->getOperator();
}
/**
* Get all supported comparison operators.
*
* @return array
*/
public static function getSupportedOperators()
{
return ComposerConstraint::getSupportedOperators();
}
/**
* @param string $operator
* @return int
*
* @phpstan-return self::OP_*
*/
public static function getOperatorConstant($operator)
{
return ComposerConstraint::getOperatorConstant($operator);
}
/**
* @param string $a
* @param string $b
* @param string $operator
* @param bool $compareBranches
*
* @throws \InvalidArgumentException if invalid operator is given.
*
* @return bool
*/
public function versionCompare($a, $b, $operator, $compareBranches = false)
{
return $this->previous->versionCompare($a, $b, $operator, $compareBranches);
}
/**
* @param ComposerConstraint $provider
* @param bool $compareBranches
*
* @return bool
*/
public function matchSpecific(ComposerConstraint $provider, $compareBranches = false)
{
return $this->previous->matchSpecific($provider, $compareBranches);
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace Phabel\Composer\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
trait ConstraintTrait
{
/**
* Constraint.
*/
private ConstraintInterface $previous;
/**
* Config.
*/
private array $config;
/**
* Constructs new constraint with phabel config.
*
* @param ConstraintInterface $previous
* @param array $config
*/
public function __construct(ConstraintInterface $previous, array $config)
{
$this->previous = $previous;
$this->config = $config;
}
/**
* Checks whether the given constraint intersects in any way with this constraint.
*
* @param ConstraintInterface $provider
*
* @return bool
*/
public function matches(ConstraintInterface $provider)
{
return $this->previous->matches($provider);
}
/**
* Provides a compiled version of the constraint for the given operator
* The compiled version must be a PHP expression.
* Executor of compile version must provide 2 variables:
* - $v = the string version to compare with
* - $b = whether or not the version is a non-comparable branch (starts with "dev-").
*
* @see Constraint::OP_* for the list of available operators.
* @example return '!$b && version_compare($v, '1.0', '>')';
*
* @param int $operator one Constraint::OP_*
*
* @return string
*/
public function compile($operator)
{
return $this->previous->compile($operator);
}
/**
* @return Bound
*/
public function getUpperBound()
{
return $this->previous->getUpperBound();
}
/**
* @return Bound
*/
public function getLowerBound()
{
return $this->previous->getLowerBound();
}
/**
* @return string
*/
public function getPrettyString()
{
return $this->previous->getPrettyString();
}
/**
* @param string|null $prettyString
*/
public function setPrettyString($prettyString)
{
return $this->previous->setPrettyString($prettyString);
}
/**
* @return string
*/
public function __toString()
{
return $this->previous->__toString();
}
/**
* Get config.
*
* @return array
*/
public function getConfig(): array
{
return $this->config;
}
/**
* Get constraint.
*
* @return ConstraintInterface
*/
public function getPrevious(): ConstraintInterface
{
return $this->previous;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Phabel\Composer\Constraint;
use Composer\Semver\Constraint\MultiConstraint as ComposerMultiConstraint;
/**
* Constraint.
*
* @property ComposerMultiConstraint $previous
*/
class MultiConstraint extends ComposerMultiConstraint
{
use ConstraintTrait;
/**
* @return ConstraintInterface[]
*/
public function getConstraints()
{
return $this->previous->getConstraints();
}
/**
* @return bool
*/
public function isConjunctive()
{
return $this->previous->isConjunctive();
}
/**
* @return bool
*/
public function isDisjunctive()
{
return !$this->previous->isDisjunctive();
}
/**
* Tries to optimize the constraints as much as possible, meaning
* reducing/collapsing congruent constraints etc.
* Does not necessarily return a MultiConstraint instance if
* things can be reduced to a simple constraint
*
* @param ConstraintInterface[] $constraints A set of constraints
* @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive
*
* @return ConstraintInterface
*/
public static function create(array $constraints, $conjunctive = true)
{
return ComposerMultiConstraint::create($conjunctive, $conjunctive);
}
}

View File

@ -5,15 +5,17 @@ namespace Phabel\Composer;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallerEvent;
use Composer\Installer\InstallerEvents;
use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Repository\ArrayRepository as ComposerArrayRepository;
use Composer\Repository\ConfigurableRepository as ComposerConfigurableRepository;
use Composer\Repository\ComposerRepository as ComposerComposerRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\ConfigurableRepository as ComposerConfigurableRepository;
use Phabel\Composer\Repository\ArrayRepository;
use Phabel\Composer\Repository\ComposerRepository;
use Phabel\Composer\Repository\ConfigurableRepository;
use Phabel\Composer\Repository\Repository;
use ReflectionObject;
/**
@ -54,13 +56,13 @@ class Plugin implements PluginInterface, EventSubscriberInterface
$traits []= $trait;
}
}
sort($traits);
\sort($traits);
if ($traits === [ArrayRepository::class]) {
$repo = new class($repo) extends ComposerArrayRepository {
use Repository;
use ArrayRepository;
};
} else if ($traits === [ConfigurableRepository::class]) {
} elseif ($traits === [ConfigurableRepository::class]) {
$repo = new class($repo) extends ComposerRepository {
use Repository;
use ConfigurableRepository;
@ -75,7 +77,7 @@ class Plugin implements PluginInterface, EventSubscriberInterface
}
$repoManager->prependRepository($repo);
}
var_dump(array_map('get_class', $repoManager->getRepositories()));
\var_dump(\array_map('get_class', $repoManager->getRepositories()));
$this->io = $io;
}

View File

@ -0,0 +1,43 @@
<?php
namespace Phabel\Composer\Repository;
use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\ComposerRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\ArrayRepository as ComposerArrayRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT
*
* @property ComposerArrayRepository $repository
*/
trait ArrayRepository
{
public function addPackage(PackageInterface $package)
{
$this->repository->addPackage($package);
}
public function getProviders($packageName)
{
return $this->repository->getProviders($packageName);
}
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array())
{
$packages = $this->repository->loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
foreach ($packages['packages'] as &$package) {
self::preparePackage($package, []);
}
return $packages;
}
public function getPackageNames($packageFilter = null)
{
return $this->getPackageNames($packageFilter);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Phabel\Composer;
namespace Phabel\Composer\Repository;
use Composer\DependencyResolver\Pool;
use Composer\Package\PackageInterface;
@ -30,6 +30,7 @@ class ComposerRepository extends ComposerComposerRepository
* @param bool $bypassFilters If set to true, this bypasses the stability filtering, and forces a recompute without cache
* @return array|mixed
*/
/*
public function whatProvides(Pool $pool, $name, $bypassFilters = false)
{
$whatProvides = $this->reflect->getMethod('whatProvides')->invokeArgs($this->repository, [$pool, $name, $bypassFilters]);
@ -48,7 +49,7 @@ class ComposerRepository extends ComposerComposerRepository
}
}
return $whatProvides;
}
}*/
public function getProviderNames()
@ -64,4 +65,21 @@ class ComposerRepository extends ComposerComposerRepository
{
return $this->repository->resetPackageIds();
}
public function createPackages(array $packages, $class = 'Composer\Package\CompletePackage')
{
return $this->repository->createPackages($packages, $class);
}
/**
* TODO v3 should make this private once we can drop PHP 5.3 support
*
* @param string $name package name (must be lowercased already)
* @private
*/
public function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
{
self::prepareConstraint($constraint);
return $this->isVersionAcceptable($constraint, $name, $versionData, $acceptableStabilities, $stabilityFlags);
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Phabel\Composer;
namespace Phabel\Composer\Repository;
use Composer\Package\Link;
use Composer\Package\Package;

View File

@ -1,13 +1,18 @@
<?php
namespace Phabel\Composer;
namespace Phabel\Composer\Repository;
use Composer\Package\AliasPackage;
use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\Constraint as ConstraintConstraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MultiConstraint as ConstraintMultiConstraint;
use Phabel\Composer\Constraint\Constraint;
use Phabel\Composer\Constraint\MultiConstraint;
use ReflectionObject;
/**
@ -21,7 +26,7 @@ trait Repository
*/
protected RepositoryInterface $repository;
/**
* Reflection object
* Reflection object.
*/
protected ReflectionObject $reflect;
/**
@ -56,6 +61,12 @@ trait Repository
*/
private static function prepareConstraint(&$constraint): array
{
if ($constraint instanceof Constraint || $constraint instanceof MultiConstraint) {
$config = $constraint->getConfig();
$constraint = $constraint->getPrevious();
return $config;
}
/*
if (!$constraint instanceof ConstraintInterface && !\is_string($constraint)) {
return [];
}
@ -63,8 +74,8 @@ trait Repository
if (!str_starts_with($constraint, ComposerRepository::CONFIG_PREFIX)) {
return [];
}
[$config, $constraint] = \explode("\n", $constraint, 2);
return \json_decode(\substr($config, 0, \strlen(ComposerRepository::CONFIG_PREFIX)), true) ?: [];
[$config, $constraint] = \explode("\0", $constraint, 2);
return \json_decode(\substr($config, 0, \strlen(ComposerRepository::CONFIG_PREFIX)), true) ?: [];*/
}
/**
* Prepare package.
@ -94,15 +105,30 @@ trait Repository
}
}
if (!$havePhabel) {
return;
//return;
}
// Config merging logic here...
$links = [];
foreach ($package->getRequires() as $link) {
$version = ComposerRepository::CONFIG_PREFIX.\json_encode($config)."\n".($link->getConstraint() ?? '');
$links []= new Link($link->getSource(), $link->getTarget(), new Constraint('>=', $version), $link->getDescription());
if (PlatformRepository::isPlatformPackage($link->getTarget())) {
continue;
}
//var_dumP($link->getTarget(), (string) $link->getConstraint());
//$version = ComposerRepository::CONFIG_PREFIX.\json_encode($config)."\0".($link->getConstraint() ?? '');
$constraint = $link->getConstraint();
if ($constraint instanceof ConstraintMultiConstraint) {
$constraint = new MultiConstraint($constraint, $config);
} else {
$constraint = new Constraint($constraint, $config);
}
$links []= new Link($link->getSource(), $link->getTarget(), $constraint, $link->getDescription());
}
if ($package instanceof Package) {
$package->setRequires($links);
} elseif ($package instanceof AliasPackage) {
while (($p = $package->getAliasOf()) instanceof AliasPackage);
$p->setRequires($links);
}
$package->setRequires($links);
}
/**
@ -160,4 +186,9 @@ trait Repository
{
return $this->repository->search($query, $mode, $type);
}
public function getRepoName()
{
return $this->repository->getRepoName();
}
}