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\Composer;
use Composer\EventDispatcher\EventSubscriberInterface; use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallerEvent; use Composer\Installer\InstallerEvent;
use Composer\Installer\InstallerEvents;
use Composer\Installer\PackageEvent; use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents; use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface; use Composer\Plugin\PluginInterface;
use Composer\Repository\ArrayRepository as ComposerArrayRepository; use Composer\Repository\ArrayRepository as ComposerArrayRepository;
use Composer\Repository\ConfigurableRepository as ComposerConfigurableRepository;
use Composer\Repository\ComposerRepository as ComposerComposerRepository; 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; use ReflectionObject;
/** /**
@ -54,13 +56,13 @@ class Plugin implements PluginInterface, EventSubscriberInterface
$traits []= $trait; $traits []= $trait;
} }
} }
sort($traits); \sort($traits);
if ($traits === [ArrayRepository::class]) { if ($traits === [ArrayRepository::class]) {
$repo = new class($repo) extends ComposerArrayRepository { $repo = new class($repo) extends ComposerArrayRepository {
use Repository; use Repository;
use ArrayRepository; use ArrayRepository;
}; };
} else if ($traits === [ConfigurableRepository::class]) { } elseif ($traits === [ConfigurableRepository::class]) {
$repo = new class($repo) extends ComposerRepository { $repo = new class($repo) extends ComposerRepository {
use Repository; use Repository;
use ConfigurableRepository; use ConfigurableRepository;
@ -75,7 +77,7 @@ class Plugin implements PluginInterface, EventSubscriberInterface
} }
$repoManager->prependRepository($repo); $repoManager->prependRepository($repo);
} }
var_dump(array_map('get_class', $repoManager->getRepositories())); \var_dump(\array_map('get_class', $repoManager->getRepositories()));
$this->io = $io; $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 <?php
namespace Phabel\Composer; namespace Phabel\Composer\Repository;
use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Pool;
use Composer\Package\PackageInterface; 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 * @param bool $bypassFilters If set to true, this bypasses the stability filtering, and forces a recompute without cache
* @return array|mixed * @return array|mixed
*/ */
/*
public function whatProvides(Pool $pool, $name, $bypassFilters = false) public function whatProvides(Pool $pool, $name, $bypassFilters = false)
{ {
$whatProvides = $this->reflect->getMethod('whatProvides')->invokeArgs($this->repository, [$pool, $name, $bypassFilters]); $whatProvides = $this->reflect->getMethod('whatProvides')->invokeArgs($this->repository, [$pool, $name, $bypassFilters]);
@ -48,7 +49,7 @@ class ComposerRepository extends ComposerComposerRepository
} }
} }
return $whatProvides; return $whatProvides;
} }*/
public function getProviderNames() public function getProviderNames()
@ -64,4 +65,21 @@ class ComposerRepository extends ComposerComposerRepository
{ {
return $this->repository->resetPackageIds(); 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 <?php
namespace Phabel\Composer; namespace Phabel\Composer\Repository;
use Composer\Package\Link; use Composer\Package\Link;
use Composer\Package\Package; use Composer\Package\Package;

View File

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