Browse Source

Add support for feature-branches setting

A negative list of non-feature-branches names
is already supported - this patch adds a list of
branches names which *will* be considered as
feature branches.

Allows changing the currently hardcoded set of
expected feature branch names, from:

* master|trunk|default|develop

To any set of names or patterns that you desire.
Claus Due 7 years ago
parent
commit
965f1f42d1

+ 43 - 0
doc/04-schema.md

@@ -893,4 +893,47 @@ Then "composer show -s" will give you `versions : * dev-latest-testing`.
 
 Optional.
 
+### feature-branches
+
+If your feature branch names are other than the default names:
+
+* master
+* trunk
+* default
+* develop
+
+You can use this setting to declare the list of branch names which should be considered
+feature branches in your package. For example, if you do not use `develop` but rather use
+a name like `development` and have no `trunk` or `default` branches, you can change this
+setting to:
+
+
+```json
+{
+    "feature-branches": ["master", "development"]
+}
+```
+
+And Composer will consider those two branches (plus any numeric branches) as your only
+feature branches. This allows Composer to recognise when you create a new branch based
+on such a non-standard named feature branch, that your new branch is based on that "version".
+
+In practice this allows you to have `my/package:dev-oddname` in your dependency
+section and still have `my/package:dev-branchofoddname` be recognised as compatible.
+Without overriding this configuration option, Composer would instead demand that you
+explicitly install `my/package:dev-oddname` or change the dependency to the explicit
+name `my/package:dev-branchofoddname`.
+
+Particularly useful when combined with local repositories of type `path` where Composer
+will read the checked-out branch name to determine the version. Without this setting, if you
+used non-standard names, Composer would reject creating a symlink to the path and will
+instead force `git clone`. With the setting, symlink creation is allowed when your local
+branches are based on such non-standard named feature branches.
+
+Note that this is only the case when your branch names are other than the above mentioned
+four default branch names. When you use default names you never need to declare this list -
+Composer will then detect your feature branches based on the default set of names.
+
+Optional.
+
 ← [Command-line interface](03-cli.md)  |  [Repositories](05-repositories.md) →

+ 7 - 0
res/composer-schema.json

@@ -488,6 +488,13 @@
                 }
             }
         },
+        "feature-branches": {
+            "type": ["array"],
+            "description": "A set of string or regex patterns for non-numeric branch names that will be handled as feature branches. Overrides default feature branch names \"master\", \"trunk\", \"default\" and \"develop\" when declared.",
+            "items": {
+                "type": "string"
+            }
+        },
         "non-feature-branches": {
             "type": ["array"],
             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",

+ 6 - 1
src/Composer/Package/Version/VersionGuesser.php

@@ -211,6 +211,11 @@ class VersionGuesser
                 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
             }
 
+            $featureBranches = 'master|trunk|default|develop';
+            if (!empty($packageConfig['feature-branches'])) {
+                $featureBranches = implode('|', $packageConfig['feature-branches']);
+            }
+
             foreach ($branches as $candidate) {
                 // return directly, if branch is configured to be non-feature branch
                 if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
@@ -218,7 +223,7 @@ class VersionGuesser
                 }
 
                 // do not compare against other feature branches
-                if ($candidate === $branch || !preg_match('{^(master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
+                if ($candidate === $branch || !preg_match('{^(' . $featureBranches . '|\d+\..+)$}', $candidate, $match)) {
                     continue;
                 }
 

+ 45 - 0
tests/Composer/Test/Package/Version/VersionGuesserTest.php

@@ -126,6 +126,51 @@ class VersionGuesserTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($commitHash, $versionArray['commit']);
     }
 
+    public function testGuessVersionReadsAndRespectsFeatureBranchesConfigurationForArbitraryNaming()
+    {
+        $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
+        $anotherCommitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';
+
+        $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor')
+            ->setMethods(array('execute'))
+            ->disableArgumentCloning()
+            ->disableOriginalConstructor()
+            ->getMock()
+        ;
+
+        $self = $this;
+
+        $executor
+            ->expects($this->at(0))
+            ->method('execute')
+            ->willReturnCallback(function ($command, &$output) use ($self, $commitHash, $anotherCommitHash) {
+                $self->assertEquals('git branch --no-color --no-abbrev -v', $command);
+                $output = "  arbitrary $commitHash Commit message\n* current $anotherCommitHash Another message\n";
+
+                return 0;
+            })
+        ;
+
+        $executor
+            ->expects($this->at(1))
+            ->method('execute')
+            ->willReturnCallback(function ($command, &$output, $path) use ($self, $anotherCommitHash) {
+                $self->assertEquals('git rev-list arbitrary..current', $command);
+                $output = "$anotherCommitHash\n";
+
+                return 0;
+            })
+        ;
+
+        $config = new Config;
+        $config->merge(array('repositories' => array('packagist' => false)));
+        $guesser = new VersionGuesser($config, $executor, new VersionParser());
+        $versionArray = $guesser->guessVersion(array('version' => 'self.version', 'feature-branches' => array('arbitrary')), 'dummy/path');
+
+        $this->assertEquals("dev-arbitrary", $versionArray['version']);
+        $this->assertEquals($anotherCommitHash, $versionArray['commit']);
+    }
+
     public function testDetachedHeadBecomesDevHash()
     {
         $commitHash = '03a15d220da53c52eddd5f32ffca64a7b3801bea';