diff --git a/.travis.yml b/.travis.yml index 8c052a3..b7d5ffb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ jobs: fast_finish: true allow_failures: - php: nightly + - php: 5.3 install: - test -f composer.lock && rm composer.lock || true - ./composer update --ansi --prefer-dist --no-interaction --optimize-autoloader --no-suggest --no-progress $COMPOSER_ADDITIONAL_FLAGS diff --git a/README.md b/README.md index 884c8d0..231e430 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,12 @@ Done, your colleagues should worry never again about installing composer and kee There are 3 parameters that can be set via [environment variables](https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps) or in composer.json file (`extra.wrapper` section). Environment variables take precedence over composer.json, so it's safe to keep defaults for local dev environment in composer.json and override them via environment variables on a build server if needed. -| Environment variable | composer.json `extra.wrapper` option | Meaning | -|----------------------|--------------------------------------|---------| -| `COMPOSER_UPDATE_FREQ` | `update-freq` | Time between checks for updates (defaults to 7 days). This is a [relative time specifier](http://php.net/manual/en/datetime.formats.relative.php) that is fed to [`DateTime::modify`](http://php.net/manual/en/datetime.modify.php). It's chosen because it can be perfectly readable by someone who knows no PHP and doesn't want to (e.g. ops people), and it's recommended to keep it that way, e.g. "5 days", "2 weeks", "1 month". | -| `COMPOSER_DIR` | `composer-dir` | Directory where composer.phar will be searched for and copied to. Defaults to the directory where the script is located (`__DIR__`); note: *not* the current working directory! Sometimes it's useful to keep real composer.phar a couple of levels higher up the directory where wrapper is placed, for example, on a CI server: it would help avoid downloading composer afresh for every build. | -| `COMPOSER_FORCE_MAJOR_VERSION` | `major-version` | When set to either 1 or 2, forces composer to self-update to the most recent version in the specified major branch (1.x or 2.x respectively) or install the specified version. | +| Environment variable | composer.json `extra.wrapper` option | Meaning | +|--------------------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `COMPOSER_UPDATE_FREQ` | `update-freq` | Time between checks for updates (defaults to 7 days). This is a [relative time specifier](http://php.net/manual/en/datetime.formats.relative.php) that is fed to [`DateTime::modify`](http://php.net/manual/en/datetime.modify.php). It's chosen because it can be perfectly readable by someone who knows no PHP and doesn't want to (e.g. ops people), and it's recommended to keep it that way, e.g. "5 days", "2 weeks", "1 month". | +| `COMPOSER_DIR` | `composer-dir` | Directory where composer.phar will be searched for and copied to. Defaults to the directory where the script is located (`__DIR__`); note: *not* the current working directory! Sometimes it's useful to keep real composer.phar a couple of levels higher up the directory where wrapper is placed, for example, on a CI server: it would help avoid downloading composer afresh for every build. | +| `COMPOSER_FORCE_MAJOR_VERSION` | `major-version` | **REMOVED IN v1.3.0 in favor of ** When set to either 1 or 2, forces composer to self-update to the most recent version in the specified major branch (1.x or 2.x respectively) or install the specified version. | +| `COMPOSER_CHANNEL` | `channel` | List of values may be found in https://getcomposer.org/versions When set, forces composer to self-update to the most recent version in the specified channel or install the last version in requested channel. | Here is an example of composer.json file that contains wrapper parameter that forces using of Composer 1: ```json @@ -43,7 +44,7 @@ Here is an example of composer.json file that contains wrapper parameter that fo }, "extra": { "wrapper": { - "major-version": 1 + "channel": 2.2 } } } diff --git a/composer b/composer index 51e63ec..9508812 100755 --- a/composer +++ b/composer @@ -8,14 +8,14 @@ * If it breaks, check out newer version or report an issue at * https://github.com/kamazee/composer-wrapper * - * @version 1.2.1 + * @version 1.3.0 */ if (!class_exists('ComposerWrapper')) { class ComposerWrapperParams { /** - * @var int|null + * @var string|null */ - private $forceMajorVersion; + private $channel; /** * @var string */ @@ -51,8 +51,8 @@ if (!class_exists('ComposerWrapper')) { if ( false !== $value = \getenv('COMPOSER_UPDATE_FREQ')) { $this->setUpdateFreq($value); } - if ( false !== $value = \getenv('COMPOSER_FORCE_MAJOR_VERSION')) { - $this->setForceMajorVersion($value); + if ( false !== $value = \getenv('COMPOSER_CHANNEL')) { + $this->setChannel($value); } if ( false !== $value = \getenv('COMPOSER_DIR')) { $this->setComposerDir($value); @@ -77,8 +77,8 @@ if (!class_exists('ComposerWrapper')) { if (array_key_exists('update-freq', $wrapper)) { $this->setUpdateFreq($wrapper['update-freq']); } - if (array_key_exists('major-version', $wrapper)) { - $this->setForceMajorVersion($wrapper['major-version']); + if (array_key_exists('channel', $wrapper)) { + $this->setChannel($wrapper['channel']); } if (array_key_exists('composer-dir', $wrapper)) { $this->setComposerDir($wrapper['composer-dir']); @@ -86,28 +86,19 @@ if (!class_exists('ComposerWrapper')) { } /** - * @return int|null + * @return string|null */ - public function getForceMajorVersion() + public function getChannel() { - return $this->forceMajorVersion; + return $this->channel; } /** - * @param false|int $version + * @param false|string $channel */ - public function setForceMajorVersion($version) + public function setChannel($channel) { - $allowed = array("1", 1, "2", 2); - if (false === in_array($version, $allowed, true)) { - throw new Exception( - sprintf( - 'Wrong major version is requested: "%s"; only 1 and 2 are supported in string or integer format', - $version - ) - ); - } - $this->forceMajorVersion = (int) $version; + $this->channel = (string) $channel; } /** @@ -189,7 +180,12 @@ if (!class_exists('ComposerWrapper')) { public function __construct(ComposerWrapperParams $params = null) { - $this->params = null === $params ? new ComposerWrapperParams() : $params; + if (null === $params ) { + $this->params = new ComposerWrapperParams(); + $this->params->loadReal(); + } else { + $this->params = $params; + } } protected function file_get_contents() @@ -217,15 +213,21 @@ if (!class_exists('ComposerWrapper')) { return \call_user_func_array('touch', \func_get_args()); } - protected function supportsForceVersionFlag($command, $version) + /** + * @param array $arrayCommand + * @param string $channel + * @return bool + */ + protected function supportsChannelFlag($arrayCommand, $channel) { + $command = implode(' ', $arrayCommand); try { $php = \escapeshellarg($this->getPhpBinary()); $output = $this->getCliCallOutput($php . ' ' . $command); } catch (Exception $e) { throw new \Exception( 'Error when trying to check support for forcing ' . - 'specific major version on self-update', + 'specific channel on either self-update or installer', 0, $e ); @@ -233,7 +235,7 @@ if (!class_exists('ComposerWrapper')) { foreach ($output as $line) { $line = trim($line); - if (0 === strpos($line, "--$version ")) { + if (0 === strpos($line, "--$channel ")) { return true; } } @@ -276,23 +278,23 @@ if (!class_exists('ComposerWrapper')) { $this->verifyChecksum($installerPathName); - $majorVersion = $this->params->getForceMajorVersion(); - $majorVersionFlag = null; - if (null !== $majorVersion) { - $helpCommandParts = array( + $requestedChannel = $this->params->getChannel(); + $channelFlag = null; + if (null !== $requestedChannel) { + $installerHelpCommand = array( \escapeshellarg($installerPathName), '--no-ansi', '--help', ); - $helpCommand = implode(' ', $helpCommandParts); - if ($this->supportsForceVersionFlag($helpCommand, $majorVersion)) { - $majorVersionFlag = '--' . $majorVersion; + + if ($this->supportsChannelFlag($installerHelpCommand, $requestedChannel)) { + $channelFlag = '--' . $requestedChannel; } else { $this->showError( - "Installer doesn't allow to specify major version.\n" . - "Requested major version $majorVersion flag is ignored.\n" . + "Installer doesn't allow to specify channel or channel is wrong.\n" . + "Requested channel $requestedChannel flag is ignored.\n" . "The installer's default is going to be installed.\n" . - "Please remove major version requirement from wrapper's environment variables or extra.wrapper section of composer.json file (as installer doesn't seem to support major version flags anymore), or report an issue at https://github.com/kamazee/composer-wrapper/issues is you think it does and the support is not detected properly" + "Please remove channel requirement from wrapper's environment variables or extra.wrapper section of composer.json file (as installer doesn't seem to support channel flags anymore), or report an issue at https://github.com/kamazee/composer-wrapper/issues is you think it does and the support is not detected properly" ); } } @@ -304,8 +306,8 @@ if (!class_exists('ComposerWrapper')) { '--install-dir=' . \escapeshellarg($dir), ); - if (null !== $majorVersionFlag) { - $commandParts[] = $majorVersionFlag; + if (null !== $channelFlag) { + $commandParts[] = $channelFlag; } $this->passthru( @@ -428,29 +430,27 @@ if (!class_exists('ComposerWrapper')) { private function getSelfUpdateFlags($filename) { - $forceVersionRequested = $this->params->getForceMajorVersion(); + $channelRequested = $this->params->getChannel(); $flags = array(); - if (null === $forceVersionRequested) { + if (null === $channelRequested) { return $flags; } - $commandParts = array( + $selfUpdateHelpCommand = array( \escapeshellarg($filename), '--no-ansi', 'help', 'self-update', ); - $command = implode(' ', $commandParts); - - if ($this->supportsForceVersionFlag($command, $forceVersionRequested)) { - $flags[] = "--$forceVersionRequested"; - } elseif (1 == $forceVersionRequested) { - // 1.10.5 supports flags, so should be a good intermediate version + if ($this->supportsChannelFlag($selfUpdateHelpCommand, $channelRequested)) { + $flags[] = "--$channelRequested"; + } elseif (1 == $channelRequested) { + // 1.10.5 supports channel flags, so should be a good intermediate version $flags[] = '1.10.5'; } else { $this->showError( - "Forcing version $forceVersionRequested is requested but current composer version doesn't support --$forceVersionRequested flag, so nothing will be forced." + "Forcing channel $channelRequested is requested but current composer version doesn't support --$channelRequested flag, so nothing will be forced." ); } @@ -524,7 +524,6 @@ if (!class_exists('ComposerWrapper')) { */ public function run($cliArguments) { - $this->params->loadReal(); $composerPathName = "{$this->params->getComposerDir()}/composer.phar"; $this->ensureInstalled($composerPathName); diff --git a/tests/ComposerWrapperParamsTest.php b/tests/ComposerWrapperParamsTest.php index 74dd476..49f42bf 100644 --- a/tests/ComposerWrapperParamsTest.php +++ b/tests/ComposerWrapperParamsTest.php @@ -19,14 +19,14 @@ function () use ($params) { }, array( "COMPOSER_UPDATE_FREQ" => "101 days", - "COMPOSER_FORCE_MAJOR_VERSION" => 2, + "COMPOSER_CHANNEL" => 2, "COMPOSER_DIR" => 'dir_from_env', ), __DIR__ . '/composer.json_read_config_examples/envVariablesHasBiggerPriority' ); self::assertSame("101 days", $params->getUpdateFreq()); - self::assertSame(2, $params->getForceMajorVersion()); + self::assertSame("2", $params->getChannel()); self::assertSame("dir_from_env", $params->getComposerDir()); } @@ -48,7 +48,7 @@ function () use (&$params) { ); self::assertSame('101 days', $params->getUpdateFreq()); - self::assertSame(2, $params->getForceMajorVersion()); + self::assertSame('2', $params->getChannel()); self::assertSame('dir_from_composer-from-env.json', $params->getComposerDir()); } @@ -108,51 +108,9 @@ public function setUpdateFreqThrowsOnBadValues($input) public function forceMajorVersionLoadDefault() { $params = $this->loadParamsDefault(); - self::assertNull($params->getForceMajorVersion()); + self::assertNull($params->getChannel()); } - public function forceMajorVersionGoodDataProvider() - { - return array( - "1 as int" => array(1, 1), - "1 as string" => array("1", 1), - "2 as int" => array(2, 2), - "2 as string" => array("2", 2), - ); - } - - /** - * @test - * @dataProvider forceMajorVersionGoodDataProvider - */ - public function setForceMajorVersionHandlesGoodValues($input, $expected) - { - $params = new ComposerWrapperParams(); - self::callNonPublic($params, 'setForceMajorVersion', array($input)); - $actual = $params->getForceMajorVersion(); - self::assertSame($expected, $actual); - } - - public function forceMajorVersionBadDataProvider() - { - return array( - "negative" => array(-1), - "allowed versions but not in float" => array(1.0), - "positive more than 2 " => array(3), - "zero " => array(0), - ); - } - - /** - * @test - * @dataProvider forceMajorVersionBadDataProvider - */ - public function forceMajorVersionThrowsOnBadValues($input) - { - $this->expectExceptionMessageRegExpCompat('\Exception', '/Wrong major version is requested:.*/'); - $params = new ComposerWrapperParams(); - self::callNonPublic($params, 'setForceMajorVersion', array($input)); - } /** * @test diff --git a/tests/ComposerWrapperTest.php b/tests/ComposerWrapperTest.php index 4b84a93..13637e7 100644 --- a/tests/ComposerWrapperTest.php +++ b/tests/ComposerWrapperTest.php @@ -8,7 +8,6 @@ class ComposerWrapperTest extends TestCase { const WRAPPER_CLASS = 'ComposerWrapper'; - const WRAPPER_PARAMS_CLASS = 'ComposerWrapperParams'; const INSTALLER = 'getMockBuilder(self::WRAPPER_PARAMS_CLASS) - ->setMethods(array('getForceMajorVersion')) - ->getMock(); - $params->expects(self::any())->method('getForceMajorVersion')->willReturn($requestedVersion); + $params = new ComposerWrapperParams(); + $params->setChannel($requestedChannel); $wrapper = $this->getMockBuilder(self::WRAPPER_CLASS) - ->setMethods(array('showError', 'copy', 'verifyChecksum', 'unlink', 'supportsForceVersionFlag')) + ->setMethods(array('showError', 'copy', 'verifyChecksum', 'unlink', 'supportsChannelFlag')) ->setConstructorArgs(array($params)) ->getMock(); - if ($supportsMajorVersionFlag) { + if ($supportsChannelFlag) { $showErrorExpectation = self::never(); } else { $showErrorExpectation = self::once(); @@ -79,7 +76,7 @@ public function installsRequestedMajorVersion($dir, $supportsMajorVersionFlag, $ $wrapper->expects(self::once())->method('copy')->willReturn(true); $wrapper->expects(self::once())->method('verifyChecksum')->willReturn(null); $wrapper->expects(self::once())->method('unlink')->willReturn(null); - $wrapper->expects(self::once())->method('supportsForceVersionFlag')->willReturn($supportsMajorVersionFlag); + $wrapper->expects(self::once())->method('supportsChannelFlag')->willReturn($supportsChannelFlag); self::callNonPublic( $wrapper, 'installComposer', @@ -87,17 +84,17 @@ public function installsRequestedMajorVersion($dir, $supportsMajorVersionFlag, $ ); } - public static function installsRequestedMajorVersionExamples() + public static function installsRequestedChannelExamples() { return array( 'version 1 is requested; installed supports flag' => array( 'dir' => __DIR__ . '/installer_stub_with_major_version_flags', - 'supportsMajorVersionFlags' => true, + 'supportsChannelFlags' => true, 'requestedVersion' => 1, ), 'version 1 is requested; installed doesn\'t support flag' => array( 'dir' => __DIR__ . '/installer_stub_without_major_version_flags', - 'supportsMajorVersionFlags' => false, + 'supportsChannelFlags' => false, 'requestedVersion' => 1, ), ); @@ -452,10 +449,10 @@ public function doesNotTryToSelfUpdateWhenUpToDate() public function addsForceVersionFlag($version, $supportsFlags, $flag, $expectError = false) { $wrapper = $this->getMockBuilder(self::WRAPPER_CLASS) - ->setMethods(array('supportsForceVersionFlag', 'touch', 'passthru', 'showError')) + ->setMethods(array('supportsChannelFlag', 'touch', 'passthru', 'showError')) ->getMock(); - $wrapper->expects($this->once())->method('supportsForceVersionFlag')->willReturn($supportsFlags); + $wrapper->expects($this->once())->method('supportsChannelFlag')->willReturn($supportsFlags); $wrapper->expects($this->once())->method('touch')->willReturn(null); $wrapper->expects($expectError ? $this->once() : $this->never())->method('showError'); $self = $this; @@ -468,7 +465,7 @@ function($command, &$exitCode) use ($self, $flag) { ); $params = new ComposerWrapperParams(); - $params->setForceMajorVersion($version); + $params->setChannel($version); self::setNonPublic($wrapper, 'params', $params); self::callNonPublic($wrapper, 'selfUpdate', array(__FILE__)); @@ -631,7 +628,7 @@ public function detectsSupportForForceVersionFlags($helpOutput, $versions, $expe $this->assertSame( $expectedResult, - self::callNonPublic($mock, 'supportsForceVersionFlag', array('composer', $version)) + self::callNonPublic($mock, 'supportsChannelFlag', array(array('composer'), $version)) ); } } diff --git a/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer-from-env.json b/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer-from-env.json index 4ab21a9..e720d81 100644 --- a/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer-from-env.json +++ b/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer-from-env.json @@ -2,7 +2,7 @@ "extra": { "wrapper": { "update-freq": "101 days", - "major-version": 2, + "channel": 2, "composer-dir": "dir_from_composer-from-env.json" } } diff --git a/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer.json b/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer.json index 045da55..83a03f2 100644 --- a/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer.json +++ b/tests/composer.json_read_config_examples/composer.json_is_ignored_when_overridden/composer.json @@ -2,7 +2,7 @@ "extra": { "wrapper": { "update-freq": "100 days", - "major-version": 1, + "channel": 1, "composer-dir": "dir_from_composer.json" } } diff --git a/tests/composer.json_read_config_examples/envVariablesHasBiggerPriority/composer.json b/tests/composer.json_read_config_examples/envVariablesHasBiggerPriority/composer.json index 045da55..83a03f2 100644 --- a/tests/composer.json_read_config_examples/envVariablesHasBiggerPriority/composer.json +++ b/tests/composer.json_read_config_examples/envVariablesHasBiggerPriority/composer.json @@ -2,7 +2,7 @@ "extra": { "wrapper": { "update-freq": "100 days", - "major-version": 1, + "channel": 1, "composer-dir": "dir_from_composer.json" } }