Repository: buildbot/buildbot

Issue:
Git step on Windows does not checkout branch on initial clone
I am currently running Buildbot master 2.8.1-dev721 (89f092e2c1891b28ca84d0acc21a9068dd16a0ad).

While setting up a new Builder I noticed that the Git step did not checkout the specified branch during the initial clone; it was properly checked out in subsequent builds on the same worker though.

I think there might be two related issues there.

First my windows git client returns `git version 2.27.0.windows.1`  for `--version`.
`pkg_resources.parse_version()` apparently considers `2.27.0.windows.1` to be lower than any of the feature test versions.
Specifically `supportsBranch` stays `False` which is why `git clone` is run without the `--branch` option (even though it should be supported).

Secondly `switchToBranch` defaults to `False` and is only set to `True` when `supportsBranch` is `True` but not usable in context.
Hence `git clone` is not followed by a dedicated `git checkout` either.


Discussion:

Resolving patch:
diff --git a/master/buildbot/steps/source/git.py b/master/buildbot/steps/source/git.py
--- a/master/buildbot/steps/source/git.py
+++ b/master/buildbot/steps/source/git.py
@@ -362,14 +362,14 @@ def _clone(self, shallowClone):
         """Retry if clone failed"""
 
         command = ['clone']
-        switchToBranch = False
+        switchToBranch = self.branch != 'HEAD'
         if self.supportsBranch and self.branch != 'HEAD':
             if self.branch.startswith('refs/'):
                 # we can't choose this branch from 'git clone' directly; we
                 # must do so after the clone
-                switchToBranch = True
                 command += ['--no-checkout']
             else:
+                switchToBranch = False
                 command += ['--branch', self.branch]
         if shallowClone:
             command += ['--depth', str(int(shallowClone))]
diff --git a/master/buildbot/util/git.py b/master/buildbot/util/git.py
--- a/master/buildbot/util/git.py
+++ b/master/buildbot/util/git.py
@@ -75,14 +75,11 @@ def setupGit(self, logname=None):
         self.supportsSshPrivateKeyAsConfigOption = False
 
     def parseGitFeatures(self, version_stdout):
-
-        if 'git' not in version_stdout:
+        match = re.match(r"^git version (\d+(\.\d+)*)", version_stdout)
+        if not match:
             return
 
-        try:
-            version = version_stdout.strip().split(' ')[2]
-        except IndexError:
-            return
+        version = match.group(1)
 
         self.gitInstalled = True
         if parse_version(version) >= parse_version("1.6.5"):


Test patch:
diff --git a/master/buildbot/test/unit/steps/test_source_git.py b/master/buildbot/test/unit/steps/test_source_git.py
--- a/master/buildbot/test/unit/steps/test_source_git.py
+++ b/master/buildbot/test/unit/steps/test_source_git.py
@@ -1557,6 +1557,17 @@ def test_mode_full_clobber_no_branch_support(self):
                                  'http://github.com/buildbot/buildbot.git',
                                  '.'])
             + 0,
+            ExpectShell(workdir='wkdir',
+                        command=['git', 'fetch', '-t',
+                                 'http://github.com/buildbot/buildbot.git',
+                                 'test-branch'])
+            + 0,
+            ExpectShell(workdir='wkdir',
+                        command=['git', 'reset', '--hard', 'FETCH_HEAD', '--'])
+            + 0,
+            ExpectShell(workdir='wkdir',
+                        command=['git', 'checkout', '-B', 'test-branch'])
+            + 0,
             ExpectShell(workdir='wkdir',
                         command=['git', 'rev-parse', 'HEAD'])
             + ExpectShell.log('stdio',