1
0
Fork 0

Support aliases for numeric branches. Fixes #3461

pull/3480/head
Damian Mooyman 2014-12-01 18:09:35 +13:00
parent 2a1a963b00
commit 7bb85ff21e
8 changed files with 102 additions and 5 deletions

View File

@ -38,10 +38,14 @@ specifying a `branch-alias` field under `extra` in `composer.json`:
}
```
The branch version must begin with `dev-` (non-comparable version), the alias
must be a comparable dev version (i.e. start with numbers, and end with
`.x-dev`). The `branch-alias` must be present on the branch that it references.
For `dev-master`, you need to commit it on the `master` branch.
If you alias a non-comparible version (such as dev-develop) `dev-` must prefix the
branch name. You may also alias a comparible version (i.e. start with numbers,
and end with `.x-dev`), but only as a more specific version.
For example, 1.x-dev could be aliased as 1.2.x-dev.
The alias must be a comparable dev version, and the `branch-alias` must be present on
the branch that it references. For `dev-master`, you need to commit it on the
`master` branch.
As a result, anyone can now require `1.0.*` and it will happily install
`dev-master`.

View File

@ -224,7 +224,7 @@ class ArrayLoader implements LoaderInterface
*/
public function getBranchAlias(array $config)
{
if ('dev-' !== substr($config['version'], 0, 4)
if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
|| !isset($config['extra']['branch-alias'])
|| !is_array($config['extra']['branch-alias'])
) {
@ -248,6 +248,14 @@ class ArrayLoader implements LoaderInterface
continue;
}
// If using numeric aliases ensure the alias is a valid subversion
if(($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
&& ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
&& (stripos($targetPrefix, $sourcePrefix) !== 0)
) {
continue;
}
return $validatedTargetBranch;
}
}

View File

@ -251,6 +251,17 @@ class ValidatingArrayLoader implements LoaderInterface
if ('-dev' !== substr($validatedTargetBranch, -4)) {
$this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
unset($this->config['extra']['branch-alias'][$sourceBranch]);
continue;
}
// If using numeric aliases ensure the alias is a valid subversion
if(($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
&& ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
&& (stripos($targetPrefix, $sourcePrefix) !== 0)
) {
$this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
unset($this->config['extra']['branch-alias'][$sourceBranch]);
}
}
}

View File

@ -169,6 +169,21 @@ class VersionParser
throw new \UnexpectedValueException('Invalid version string "'.$version.'"'.$extraMessage);
}
/**
* Extract numeric prefix from alias, if it is in numeric format, suitable for
* version comparison
*
* @param string $branch Branch name (e.g. 2.1.x-dev)
* @return string|false Numeric prefix if present (e.g. 2.1.) or false
*/
public function parseNumericAliasPrefix($branch) {
if(preg_match('/^(?<version>(\d+\\.)*\d+).x-dev$/i', $branch, $matches)) {
return $matches['version'].".";
} else {
return false;
}
}
/**
* Normalizes a branch name to be able to perform comparisons on it
*

View File

@ -138,6 +138,28 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('Composer\Package\AliasPackage', $package);
$this->assertEquals('1.0.x-dev', $package->getPrettyVersion());
$config = array(
'name' => 'B',
'version' => '4.x-dev',
'extra' => array('branch-alias' => array('4.x-dev' => '4.0.x-dev')),
);
$package = $this->loader->load($config);
$this->assertInstanceOf('Composer\Package\AliasPackage', $package);
$this->assertEquals('4.0.x-dev', $package->getPrettyVersion());
$config = array(
'name' => 'C',
'version' => '4.x-dev',
'extra' => array('branch-alias' => array('4.x-dev' => '3.4.x-dev')),
);
$package = $this->loader->load($config);
$this->assertInstanceOf('Composer\Package\CompletePackage', $package);
$this->assertEquals('4.x-dev', $package->getPrettyVersion());
}
public function testAbandoned()

View File

@ -140,6 +140,7 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase
'branch-alias' => array(
'dev-master' => '2.0-dev',
'dev-old' => '1.0.x-dev',
'3.x-dev' => '3.1.x-dev'
),
),
'bin' => array(
@ -324,6 +325,20 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase
),
false
),
array(
array(
'name' => 'foo/bar',
'extra' => array(
'branch-alias' => array(
'5.x-dev' => '3.1.x-dev'
),
)
),
array(
'extra.branch-alias.5.x-dev : the target branch (3.1.x-dev) is not a valid numeric alias for this version'
),
false
),
);
}
}

View File

@ -76,6 +76,26 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase
$this->assertSame($expected, $parser->normalize($input));
}
public function numericAliasVersions() {
return array(
array('0.x-dev', '0.'),
array('1.0.x-dev', '1.0.'),
array('1.x-dev', '1.'),
array('1.2.x-dev', '1.2.'),
array('dev-develop', false),
array('dev-master', false),
);
}
/**
* @dataProvider numericAliasVersions
*/
public function testParseNumericAliasPrefix($input, $expected)
{
$parser = new VersionParser;
$this->assertSame($expected, $parser->parseNumericAliasPrefix($input));
}
public function successfulNormalizedVersions()
{
return array(

View File

@ -115,6 +115,8 @@ class VersionSelectorTest extends \PHPUnit_Framework_TestCase
array('dev-master', true, 'dev', '~2.1@dev', '2.1.x-dev'),
array('dev-master', true, 'dev', '~2.1@dev', '2.1.3.x-dev'),
array('dev-master', true, 'dev', '~2.0@dev', '2.x-dev'),
// numeric alias
array('3.x-dev', true, 'dev', '~3.0@dev', '3.0.x-dev'),
);
}