Continue work on composer injector

This commit is contained in:
Daniil Gentili 2020-11-04 16:54:36 +01:00
parent 5418c27788
commit 7cea5c8b26
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
7 changed files with 88 additions and 77 deletions

View File

@ -2,7 +2,6 @@
$config = new Amp\CodeStyle\Config(); $config = new Amp\CodeStyle\Config();
$config->getFinder() $config->getFinder()
->in(__DIR__ . '/examples')
->in(__DIR__ . '/src') ->in(__DIR__ . '/src')
->in(__DIR__ . '/test'); ->in(__DIR__ . '/test');

View File

@ -4,7 +4,7 @@
"type": "composer-plugin", "type": "composer-plugin",
"require": { "require": {
"nikic/php-parser": "^4.7", "nikic/php-parser": "^4.7",
"composer-plugin-api": "^1|^2" "composer-plugin-api": "^2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^7 | ^8 | ^9", "phpunit/phpunit": "^7 | ^8 | ^9",
@ -35,4 +35,4 @@
"cs-fix": "php-cs-fixer fix -v --diff", "cs-fix": "php-cs-fixer fix -v --diff",
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text" "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
} }
} }

View File

@ -5,12 +5,12 @@ namespace Phabel\Composer\Traits;
trait Constraint trait Constraint
{ {
/** /**
* Config. * Phabel config.
*/ */
private array $config; private array $config;
/** /**
* Get config. * Get phabel config.
* *
* @return array * @return array
*/ */
@ -20,15 +20,15 @@ trait Constraint
} }
/** /**
* Set config. * Set phabel config.
* *
* @param array $config Config. * @param array $config Phabel config
* *
* @return self * @return self
*/ */
public function setConfig(array $config): self public function setConfig($config): self
{ {
$this->config = $config; $this->config = is_string($config) ? json_decode($config, true) : $config;
return $this; return $this;
} }

View File

@ -11,6 +11,7 @@ use Composer\Semver\Constraint\Constraint as ComposerConstraint;
use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MultiConstraint; use Composer\Semver\Constraint\MultiConstraint;
use Phabel\Composer\PhabelConstraintInterface; use Phabel\Composer\PhabelConstraintInterface;
use Phabel\Target\Php;
use Phabel\Tools; use Phabel\Tools;
/** /**
@ -44,47 +45,12 @@ trait Repository
return $packages; return $packages;
} }
/**
* Look for phabel configuration parameters in constraint.
*
* @param \Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against
*
* @return ?array
*/
public static function extractConfig(&$constraint): ?array
{
$config = null;
if ($constraint instanceof PhabelConstraintInterface) {
$config = $constraint->getConfig();
} elseif ($constraint instanceof ComposerConstraint) {
$version = $constraint->getVersion();
if (str_starts_with($version, 'phabel')) {
[$version, $config] = \explode("\0", \substr($version, 6));
$config = \json_decode($config, true);
$constraint = new ComposerConstraint($constraint->getOperator(), $version);
}
} elseif ($constraint instanceof MultiConstraint) {
$constraints = $constraint->getConstraints() ;
foreach ($constraints as &$cur) {
$config = self::trickleMergeConfig($config, self::extractConfig($cur));
}
$constraint = new MultiConstraint($constraints, $constraint->isConjunctive());
}
return $config;
/*
if (!$constraint instanceof ConstraintInterface && !\is_string($constraint)) {
return [];
}
$constraint = (string) $constraint;
if (!str_starts_with($constraint, ComposerRepository::CONFIG_PREFIX)) {
return [];
}
[$config, $constraint] = \explode("\0", $constraint, 2);
return \json_decode(\substr($config, 0, \strlen(ComposerRepository::CONFIG_PREFIX)), true) ?: [];*/
}
private static function trickleMergeConfig(?array $prev, ?array $new): ?array private static function trickleMergeConfig(?array $prev, ?array $new): ?array
{ {
return $new; if ($prev === null || empty($prev)) {
return $new;
}
return $prev;
} }
/** /**
* Prepare package. * Prepare package.
@ -107,7 +73,7 @@ trait Repository
$havePhabel = true; $havePhabel = true;
} }
if ($link->getTarget() === 'php') { if ($link->getTarget() === 'php') {
$myConfig['target'] = $link->getConstraint(); $myConfig['target'] = Php::normalizeVersion($link->getConstraint()->getLowerBound()->getVersion());
if ($havePhabel) { if ($havePhabel) {
break; break;
} }
@ -118,14 +84,11 @@ trait Repository
return; return;
} }
\var_dump("Applying ".$package->getName()); \var_dump("Applying ".$package->getName());
// Config merging logic here... $config = self::trickleMergeConfig($config, $myConfig);
if ($config === null || empty($config)) { self::processRequires($package, \json_encode($config));
$config = $myConfig;
}
self::processRequires($package, $config);
} }
private static function processRequires(PackageInterface $package, array $config) private static function processRequires(PackageInterface $package, string $config)
{ {
$links = []; $links = [];
foreach ($package->getRequires() as $link) { foreach ($package->getRequires() as $link) {
@ -133,20 +96,10 @@ trait Repository
continue; continue;
} }
//var_dumP($link->getTarget(), (string) $link->getConstraint()); //var_dumP($link->getTarget(), (string) $link->getConstraint());
$constraint = $link->getConstraint();
if ($constraint instanceof ComposerConstraint) {
$version = $constraint-
}
if ($constraint instanceof PhabelConstraintInterface) {
$constraint = clone $constraint;
} else {
$constraint = Tools::cloneWithTrait($constraint, Constraint::class, PhabelConstraintInterface::class);
}
$constraint->setConfig($config);
$links []= new Link( $links []= new Link(
$link->getSource(), $link->getSource(),
$link->getTarget(), $link->getTarget(),
$constraint, self::injectConfig($link->getConstraint(), $config),
$link->getDescription(), $link->getDescription(),
$link->getPrettyConstraint() $link->getPrettyConstraint()
); );
@ -159,8 +112,59 @@ trait Repository
} }
} }
private static function injectConstraint /**
* Inject config into constraint.
*
* @param ConstraintInterface $constraint
* @param string $config
* @return ConstraintInterface
*/
private static function injectConfig(ConstraintInterface $constraint, string $config): ConstraintInterface
{
if ($constraint instanceof ComposerConstraint) {
$version = $constraint->getVersion();
$version = "phabel$version\0$config";
return new ComposerConstraint($constraint->getOperator(), $version);
} elseif ($constraint instanceof MultiConstraint) {
$constraints = $constraint->getConstraints();
foreach ($constraints as &$cur) {
$cur = self::injectConfig($cur, $config);
}
return new MultiConstraint($constraints, $constraint->isConjunctive());
}
return $constraint;
}
/**
* Look for phabel configuration parameters in constraint.
*
* @param \Composer\Semver\Constraint\ConstraintInterface $constraint package version or version constraint to match against
*
* @return ?array
*/
public static function extractConfig(ConstraintInterface &$constraint): ?array
{
$config = null;
if ($constraint instanceof ComposerConstraint) {
$version = $constraint->getVersion();
if (str_starts_with($version, 'phabel')) {
[$version, $config] = \explode("\0", \substr($version, 6));
$config = \json_decode($config, true);
if ($config === false) {
$config = null;
}
$constraint = new ComposerConstraint($constraint->getOperator(), $version);
}
} elseif ($constraint instanceof MultiConstraint) {
$constraints = $constraint->getConstraints() ;
foreach ($constraints as &$cur) {
$config = self::trickleMergeConfig($config, self::extractConfig($cur));
}
$constraint = new MultiConstraint($constraints, $constraint->isConjunctive());
}
return $config;
}
/** /**
* Searches for the first match of a package by name and version. * Searches for the first match of a package by name and version.
* *

View File

@ -119,35 +119,35 @@ abstract class Plugin extends Tools implements PluginInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public static function composerRequires(): array public static function composerRequires(array $config): array
{ {
return []; return [];
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public static function runAfter(): array public static function runAfter(array $config): array
{ {
return []; return [];
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public static function runBefore(): array public static function runBefore(array $config): array
{ {
return []; return [];
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public static function runWithBefore(): array public static function runWithBefore(array $config): array
{ {
return []; return [];
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public static function runWithAfter(): array public static function runWithAfter(array $config): array
{ {
return []; return [];
} }

View File

@ -24,7 +24,7 @@ interface PluginInterface
* *
* @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array> * @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array>
*/ */
public static function runAfter(): array; public static function runAfter(array $config): array;
/** /**
* Specify which plugins should run before this plugin. * Specify which plugins should run before this plugin.
* *
@ -32,7 +32,7 @@ interface PluginInterface
* *
* @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array> * @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array>
*/ */
public static function runBefore(): array; public static function runBefore(array $config): array;
/** /**
* Specify which plugins does this plugin extend. * Specify which plugins does this plugin extend.
* *
@ -44,21 +44,21 @@ interface PluginInterface
* *
* @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array> * @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array>
*/ */
public static function runWithBefore(): array; public static function runWithBefore(array $config): array;
/** /**
* *
* @return array Plugin name(s) * @return array Plugin name(s)
* *
* @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array> * @psalm-return class-string<PluginInterface>[]|array<class-string<PluginInterface>, array>
*/ */
public static function runWithAfter(): array; public static function runWithAfter(array $config): array;
/** /**
* Specify a list of composer dependencies. * Specify a list of composer dependencies.
* *
* @return array * @return array
*/ */
public static function composerRequires(): array; public static function composerRequires(array $config): array;
/** /**
* Set configuration array. * Set configuration array.
* *

View File

@ -29,6 +29,14 @@ class Php extends Plugin
* Default target. * Default target.
*/ */
private const DEFAULT_TARGET = '70'; private const DEFAULT_TARGET = '70';
public static function normalizeVersion(string $target): string
{
if (\preg_match(":^\D*(\d+\.\d+)\..*:", $target, $matches)) {
$target = $matches[1];
}
$target = \str_replace('.', '', $target);
return in_array($target, self::VERSIONS) ? $target : self::DEFAULT_TARGET;
}
/** /**
* Get PHP version range to target. * Get PHP version range to target.
* *