From 8cc8d27fd0ed78f06ed46cb7303ae6ba16742a3b Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 11 Aug 2023 16:56:22 +0100 Subject: [PATCH] [WIP] Proof of concept forwarding specified Composer commands --- e2e/scenario13/.gitignore | 5 ++ e2e/scenario13/README.md | 1 + e2e/scenario13/composer.json | 23 ++++++++ e2e/scenario13/expected.txt | 62 +++++++++++++++++++++ e2e/scenario13/script.sh | 36 ++++++++++++ e2e/scenario13/vendor-bin/ns1/composer.json | 1 + e2e/scenario13/vendor-bin/ns2/composer.json | 1 + src/BamarniBinPlugin.php | 6 +- src/Config/Config.php | 32 +++++++++-- tests/Config/ConfigTest.php | 40 ++++++++++++- 10 files changed, 195 insertions(+), 12 deletions(-) create mode 100644 e2e/scenario13/.gitignore create mode 100644 e2e/scenario13/README.md create mode 100644 e2e/scenario13/composer.json create mode 100644 e2e/scenario13/expected.txt create mode 100755 e2e/scenario13/script.sh create mode 100644 e2e/scenario13/vendor-bin/ns1/composer.json create mode 100644 e2e/scenario13/vendor-bin/ns2/composer.json diff --git a/e2e/scenario13/.gitignore b/e2e/scenario13/.gitignore new file mode 100644 index 0000000..cac9c03 --- /dev/null +++ b/e2e/scenario13/.gitignore @@ -0,0 +1,5 @@ +/actual.txt +/composer.lock +/vendor/ +/vendor-bin/*/composer.lock +/vendor-bin/*/vendor/ diff --git a/e2e/scenario13/README.md b/e2e/scenario13/README.md new file mode 100644 index 0000000..7341f7f --- /dev/null +++ b/e2e/scenario13/README.md @@ -0,0 +1 @@ +Test explicitly configured forwarded commands are forwarded. \ No newline at end of file diff --git a/e2e/scenario13/composer.json b/e2e/scenario13/composer.json new file mode 100644 index 0000000..3038738 --- /dev/null +++ b/e2e/scenario13/composer.json @@ -0,0 +1,23 @@ +{ + "repositories": [ + { + "type": "path", + "url": "../../" + } + ], + "require-dev": { + "bamarni/composer-bin-plugin": "dev-master" + }, + "config": { + "allow-plugins": { + "bamarni/composer-bin-plugin": true + } + }, + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": true, + "forwarded-commands": ["update", "validate"] + } + } +} diff --git a/e2e/scenario13/expected.txt b/e2e/scenario13/expected.txt new file mode 100644 index 0000000..eb8d15b --- /dev/null +++ b/e2e/scenario13/expected.txt @@ -0,0 +1,62 @@ +composer update: +Loading composer repositories with package information +Updating dependencies +Lock file operations: 1 install, 0 updates, 0 removals + - Locking bamarni/composer-bin-plugin (dev-hash) +Writing lock file +Installing dependencies from lock file (including require-dev) +Package operations: 1 install, 0 updates, 0 removals + - Installing bamarni/composer-bin-plugin (dev-hash): Symlinking from ../.. +Generating autoload files +[bamarni-bin] The command is being forwarded. +[bamarni-bin] Checking namespace vendor-bin/ns1 +Loading composer repositories with package information +Updating dependencies +Nothing to modify in lock file +Writing lock file +Installing dependencies from lock file (including require-dev) +Nothing to install, update or remove +Generating autoload files +[bamarni-bin] Checking namespace vendor-bin/ns2 +Loading composer repositories with package information +Updating dependencies +Nothing to modify in lock file +Writing lock file +Installing dependencies from lock file (including require-dev) +Nothing to install, update or remove +Generating autoload files + +composer install: +Installing dependencies from lock file (including require-dev) +Verifying lock file contents can be installed on current platform. +Nothing to install, update or remove +Generating autoload files + +composer validate: +./composer.json is valid for simple usage with Composer but has +strict errors that make it unable to be published as a package +See https://getcomposer.org/doc/04-schema.md for details on the schema +# General warnings +- No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license. +# Publish warnings +- name : The property name is required +- description : The property description is required +[bamarni-bin] The command is being forwarded. +[bamarni-bin] Checking namespace vendor-bin/ns1 +./composer.json is valid for simple usage with Composer but has +strict errors that make it unable to be published as a package +See https://getcomposer.org/doc/04-schema.md for details on the schema +# General warnings +- No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license. +# Publish warnings +- name : The property name is required +- description : The property description is required +[bamarni-bin] Checking namespace vendor-bin/ns2 +./composer.json is valid for simple usage with Composer but has +strict errors that make it unable to be published as a package +See https://getcomposer.org/doc/04-schema.md for details on the schema +# General warnings +- No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license. +# Publish warnings +- name : The property name is required +- description : The property description is required diff --git a/e2e/scenario13/script.sh b/e2e/scenario13/script.sh new file mode 100755 index 0000000..2b0f4ef --- /dev/null +++ b/e2e/scenario13/script.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +# Set env variables in order to experience a behaviour closer to what happens +# in the CI locally. It should not hurt to set those in the CI as the CI should +# contain those values. +export CI=1 +export COMPOSER_NO_INTERACTION=1 + +readonly ORIGINAL_WORKING_DIR=$(pwd) + +trap "cd ${ORIGINAL_WORKING_DIR}" err exit + +# Change to script directory +cd "$(dirname "$0")" + +# Ensure we have a clean state +rm -rf actual.txt || true +rm -rf composer.lock || true +rm -rf vendor || true +rm -rf vendor-bin/*/composer.lock || true +rm -rf vendor-bin/*/vendor || true + +( + echo "composer update:" + composer update || true + echo + + echo "composer install:" + composer install || true + echo + + echo "composer validate:" + composer validate --no-check-publish || true +) 2>&1 | tee >> actual.txt diff --git a/e2e/scenario13/vendor-bin/ns1/composer.json b/e2e/scenario13/vendor-bin/ns1/composer.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/e2e/scenario13/vendor-bin/ns1/composer.json @@ -0,0 +1 @@ +{} diff --git a/e2e/scenario13/vendor-bin/ns2/composer.json b/e2e/scenario13/vendor-bin/ns2/composer.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/e2e/scenario13/vendor-bin/ns2/composer.json @@ -0,0 +1 @@ +{} diff --git a/src/BamarniBinPlugin.php b/src/BamarniBinPlugin.php index 1d21c93..5f50902 100644 --- a/src/BamarniBinPlugin.php +++ b/src/BamarniBinPlugin.php @@ -33,8 +33,6 @@ */ class BamarniBinPlugin implements PluginInterface, Capable, EventSubscriberInterface { - private const FORWARDED_COMMANDS = ['install', 'update']; - /** * @var Composer */ @@ -130,9 +128,7 @@ private function onEvent( } } - if ($config->isCommandForwarded() - && in_array($commandName, self::FORWARDED_COMMANDS, true) - ) { + if ($config->isCommandForwarded($commandName)) { return $this->onForwardedCommand($input, $output); } diff --git a/src/Config/Config.php b/src/Config/Config.php index fa62b3a..5ae64c3 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -19,11 +19,13 @@ final class Config public const BIN_LINKS_ENABLED = 'bin-links'; public const TARGET_DIRECTORY = 'target-directory'; public const FORWARD_COMMAND = 'forward-command'; + public const FORWARDED_COMMANDS = 'forwarded-commands'; private const DEFAULT_CONFIG = [ self::BIN_LINKS_ENABLED => true, self::TARGET_DIRECTORY => 'vendor-bin', self::FORWARD_COMMAND => false, + self::FORWARDED_COMMANDS => ['install', 'update'], ]; /** @@ -37,9 +39,9 @@ final class Config private $targetDirectory; /** - * @var bool + * @var list */ - private $forwardCommand; + private $forwardedCommands; /** * @var list @@ -126,9 +128,24 @@ public function __construct(array $extra) ); } + $forwardedCommands = $config[self::FORWARDED_COMMANDS]; + + if (!is_array($forwardedCommands)) { + throw new InvalidBamarniComposerExtraConfig( + sprintf( + 'Expected setting "extra.%s.%s" to be an array value. Got "%s".', + self::EXTRA_CONFIG_KEY, + self::FORWARDED_COMMANDS, + gettype($forwardCommand) + ) + ); + } + + $forwardedCommandsSetExplicitly = array_key_exists(self::FORWARDED_COMMANDS, $userExtra); + $this->binLinks = $binLinks; $this->targetDirectory = $targetDirectory; - $this->forwardCommand = $forwardCommand; + $this->forwardedCommands = $forwardCommand ? $forwardedCommands : []; } public function binLinksAreEnabled(): bool @@ -141,9 +158,14 @@ public function getTargetDirectory(): string return $this->targetDirectory; } - public function isCommandForwarded(): bool + public function isCommandForwarded(?string $name = null): bool { - return $this->forwardCommand; + // Trigger deprecation. + if ($name === null) { + return false; + } + + return in_array($name, $this->forwardedCommands, true); } /** diff --git a/tests/Config/ConfigTest.php b/tests/Config/ConfigTest.php index cf941cb..27cb147 100644 --- a/tests/Config/ConfigTest.php +++ b/tests/Config/ConfigTest.php @@ -23,14 +23,16 @@ public function test_it_can_be_instantiated( array $extra, bool $expectedBinLinksEnabled, string $expectedTargetDirectory, - bool $expectedForwardCommand, + bool $expectedForwardInstallCommand, + bool $expectedForwardUpdateCommand, array $expectedDeprecations ): void { $config = new Config($extra); self::assertSame($expectedBinLinksEnabled, $config->binLinksAreEnabled()); self::assertSame($expectedTargetDirectory, $config->getTargetDirectory()); - self::assertSame($expectedForwardCommand, $config->isCommandForwarded()); + self::assertSame($expectedForwardInstallCommand, $config->isCommandForwarded('install')); + self::assertSame($expectedForwardUpdateCommand, $config->isCommandForwarded('update')); self::assertSame($expectedDeprecations, $config->getDeprecations()); } @@ -44,6 +46,7 @@ public static function provideExtraConfig(): iterable true, 'vendor-bin', false, + false, [ $binLinksEnabledDeprecationMessage, $forwardCommandDeprecationMessage, @@ -55,6 +58,7 @@ public static function provideExtraConfig(): iterable true, 'vendor-bin', false, + false, [ $binLinksEnabledDeprecationMessage, $forwardCommandDeprecationMessage, @@ -71,6 +75,7 @@ public static function provideExtraConfig(): iterable true, 'vendor-bin', false, + false, [], ]; @@ -85,6 +90,37 @@ public static function provideExtraConfig(): iterable false, 'tools', true, + true, + [], + ]; + + yield 'only forward install command' => [ + [ + Config::EXTRA_CONFIG_KEY => [ + Config::BIN_LINKS_ENABLED => false, + Config::FORWARD_COMMAND => true, + Config::FORWARDED_COMMANDS => ['install'], + ], + ], + false, + 'vendor-bin', + true, + false, + [], + ]; + + yield 'do not forward install command' => [ + [ + Config::EXTRA_CONFIG_KEY => [ + Config::BIN_LINKS_ENABLED => false, + Config::FORWARD_COMMAND => true, + Config::FORWARDED_COMMANDS => ['about', 'update'], + ], + ], + false, + 'vendor-bin', + false, + true, [], ]; }