Skip to content

Commit

Permalink
Allowing getcomposer 2.2 channel (#25)
Browse files Browse the repository at this point in the history
* Remove static validation for forceMajorVersion. Only a dynamic validation is left

* Change logic, readme, to use channels

* Allow PHP 5.3 failures due to infrastructure issues

---------

Co-authored-by: Barys Biankouski <borisb@playtika.com>
  • Loading branch information
benbor and Barys Biankouski committed May 26, 2023
1 parent 307a62d commit a19c67a
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 121 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions README.md
Expand Up @@ -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
Expand All @@ -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
}
}
}
Expand Down
97 changes: 48 additions & 49 deletions composer
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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);
Expand All @@ -77,37 +77,28 @@ 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']);
}
}

/**
* @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;
}

/**
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -217,23 +213,29 @@ 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
);
}

foreach ($output as $line) {
$line = trim($line);
if (0 === strpos($line, "--$version ")) {
if (0 === strpos($line, "--$channel ")) {
return true;
}
}
Expand Down Expand Up @@ -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"
);
}
}
Expand All @@ -304,8 +306,8 @@ if (!class_exists('ComposerWrapper')) {
'--install-dir=' . \escapeshellarg($dir),
);

if (null !== $majorVersionFlag) {
$commandParts[] = $majorVersionFlag;
if (null !== $channelFlag) {
$commandParts[] = $channelFlag;
}

$this->passthru(
Expand Down Expand Up @@ -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."
);
}

Expand Down Expand Up @@ -524,7 +524,6 @@ if (!class_exists('ComposerWrapper')) {
*/
public function run($cliArguments)
{
$this->params->loadReal();
$composerPathName = "{$this->params->getComposerDir()}/composer.phar";

$this->ensureInstalled($composerPathName);
Expand Down
50 changes: 4 additions & 46 deletions tests/ComposerWrapperParamsTest.php
Expand Up @@ -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());
}

Expand All @@ -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());
}

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit a19c67a

Please sign in to comment.