Skip to content

Commit

Permalink
improve Git support, plus docs and tests. Thanks to Haavard Skinnemoe…
Browse files Browse the repository at this point in the history
…n for the amazing patch. Closes buildbot#130.
  • Loading branch information
warner committed Nov 22, 2007
1 parent 92aa140 commit bc53d76
Show file tree
Hide file tree
Showing 7 changed files with 595 additions and 42 deletions.
15 changes: 15 additions & 0 deletions ChangeLog
@@ -1,5 +1,20 @@
2007-11-21 Brian Warner <warner@lothar.com>

* lots: improve Git support, AMAZING patch from Haavard
Skinnemoen, complete with unit tests and docs, thanks! Closes #130.
* buildbot/scripts/tryclient.py (GitExtractor): add 'try' support
* buildbot/slave/commands.py (Git): accept branch and revisions,
and use 'git' instead of the 'cogito' wrapper
* buildbot/steps/source.py (Git.__init__): same
* buildbot/test/test_vc.py (BaseHelper.runCommand): offer control
over env=
(BaseHelper.do): same
(BaseHelper.dovc): same
(Git): unit tests for Git support. Wow!
* docs/buildbot.texinfo (Git): docs for Git support. Double Wow!
* contrib/git_buildbot.py: commit-hook script for git


* buildbot/changes/p4poller.py (P4Source._finished): don't let a
failure cause us to stop polling. Thanks to John Backstrand for
the patch. Closes #135.
Expand Down
28 changes: 28 additions & 0 deletions buildbot/scripts/tryclient.py
Expand Up @@ -203,6 +203,32 @@ def getPatch(self, res):
d.addCallback(self.readPatch, self.patchlevel)
return d

class GitExtractor(SourceStampExtractor):
patchlevel = 1
vcexe = "git"

def getBaseRevision(self):
d = self.dovc(["branch", "--no-color", "-v", "--no-abbrev"])
d.addCallback(self.parseStatus)
return d

def parseStatus(self, res):
# The current branch is marked by '*' at the start of the
# line, followed by the branch name and the SHA1.
#
# Branch names may contain pretty much anything but whitespace.
m = re.search(r'^\* (\S+)\s+([0-9a-f]{40})', res, re.MULTILINE)
if m:
self.branch = m.group(1)
self.baserev = m.group(2)
return
raise IndexError("Could not find current GIT branch: %s" % res)

def getPatch(self, res):
d = self.dovc(["diff", self.baserev])
d.addCallback(self.readPatch, self.patchlevel)
return d

def getSourceStamp(vctype, treetop, branch=None):
if vctype == "cvs":
e = CVSExtractor(treetop, branch)
Expand All @@ -218,6 +244,8 @@ def getSourceStamp(vctype, treetop, branch=None):
e = MercurialExtractor(treetop, branch)
elif vctype == "darcs":
e = DarcsExtractor(treetop, branch)
elif vctype == "git":
e = GitExtractor(treetop, branch)
else:
raise KeyError("unknown vctype '%s'" % vctype)
return e.get()
Expand Down
83 changes: 65 additions & 18 deletions buildbot/slave/commands.py
Expand Up @@ -15,7 +15,7 @@
# this used to be a CVS $-style "Revision" auto-updated keyword, but since I
# moved to Darcs as the primary repository, this is updated manually each
# time this file is changed. The last cvs_ver that was here was 1.51 .
command_version = "2.3"
command_version = "2.4"

# version history:
# >=1.17: commands are interruptable
Expand All @@ -35,6 +35,7 @@
# (release 0.7.4)
# >= 2.2: added monotone, uploadFile, and downloadFile (release 0.7.5)
# >= 2.3: added bzr
# >= 2.4: Git understands 'revision' and branches

class CommandInterrupted(Exception):
pass
Expand Down Expand Up @@ -707,7 +708,7 @@ def setup(self, args):
self.rc = 0

def start(self):
if self.debug:
if self.debug:
log.msg('SlaveFileUploadCommand started')

# Open file
Expand Down Expand Up @@ -819,7 +820,7 @@ def setup(self, args):
self.rc = 0

def start(self):
if self.debug:
if self.debug:
log.msg('SlaveFileDownloadCommand starting')

# Open file
Expand Down Expand Up @@ -1718,39 +1719,85 @@ class Git(SourceBase):
"""Git specific VC operation. In addition to the arguments
handled by SourceBase, this command reads the following keys:
['repourl'] (required): the Cogito repository string
['repourl'] (required): the upstream GIT repository string
['branch'] (optional): which version (i.e. branch or tag) to
retrieve. Default: "master".
"""

header = "git operation"

def setup(self, args):
SourceBase.setup(self, args)
self.repourl = args['repourl']
#self.sourcedata = "" # TODO
self.branch = args.get('branch')
if not self.branch:
self.branch = "master"
self.sourcedata = "%s %s\n" % (self.repourl, self.branch)

def _fullSrcdir(self):
return os.path.join(self.builder.basedir, self.srcdir)

def _commitSpec(self):
if self.revision:
return self.revision
return self.branch

def sourcedirIsUpdateable(self):
if os.path.exists(os.path.join(self.builder.basedir,
self.srcdir, ".buildbot-patched")):
if os.path.exists(os.path.join(self._fullSrcdir(),
".buildbot-patched")):
return False
return os.path.isdir(os.path.join(self.builder.basedir,
self.srcdir, ".git"))
return os.path.isdir(os.path.join(self._fullSrcdir(), ".git"))

def doVCUpdate(self):
d = os.path.join(self.builder.basedir, self.srcdir)
command = ['cg-update']
c = ShellCommand(self.builder, command, d,
def _didFetch(self, res):
if self.revision:
head = self.revision
else:
head = 'FETCH_HEAD'

command = ['git-reset', '--hard', head]
c = ShellCommand(self.builder, command, self._fullSrcdir(),
sendRC=False, timeout=self.timeout)
self.command = c
return c.start()

def doVCUpdate(self):
command = ['git-fetch', self.repourl, self.branch]
self.sendStatus({"header": "fetching branch %s from %s\n"
% (self.branch, self.repourl)})
c = ShellCommand(self.builder, command, self._fullSrcdir(),
sendRC=False, timeout=self.timeout)
self.command = c
d = c.start()
d.addCallback(self._abandonOnFailure)
d.addCallback(self._didFetch)
return d

def _didInit(self, res):
return self.doVCUpdate()

def doVCFull(self):
d = os.path.join(self.builder.basedir, self.srcdir)
os.mkdir(d)
command = ['cg-clone', '-s', self.repourl]
c = ShellCommand(self.builder, command, d,
os.mkdir(self._fullSrcdir())
c = ShellCommand(self.builder, ['git-init'], self._fullSrcdir(),
sendRC=False, timeout=self.timeout)
self.command = c
return c.start()
d = c.start()
d.addCallback(self._abandonOnFailure)
d.addCallback(self._didInit)
return d

def parseGotRevision(self):
command = ['git-rev-parse', 'HEAD']
c = ShellCommand(self.builder, command, self._fullSrcdir(),
sendRC=False, keepStdout=True)
c.usePTY = False
d = c.start()
def _parse(res):
hash = c.stdout.strip()
if len(hash) != 40:
return None
return hash
d.addCallback(_parse)
return d

registerSlaveCommand("git", Git, command_version)

Expand Down
18 changes: 14 additions & 4 deletions buildbot/steps/source.py
Expand Up @@ -571,15 +571,25 @@ class Git(Source):

name = "git"

def __init__(self, repourl, **kwargs):
def __init__(self, repourl, branch="master", **kwargs):
"""
@type repourl: string
@param repourl: the URL which points at the git repository
@type branch: string
@param branch: The branch or tag to check out by default. If
a build specifies a different branch, it will
be used instead of this.
"""
self.branch = None # TODO
Source.__init__(self, **kwargs)
self.addFactoryArguments(repourl=repourl)
self.args['repourl'] = repourl
self.addFactoryArguments(repourl=repourl, branch=branch)
self.args.update({'repourl': repourl,
'branch': branch})

def computeSourceRevision(self, changes):
if not changes:
return None
return changes[-1].revision

def startVC(self, branch, revision, patch):
self.args['branch'] = branch
Expand Down

0 comments on commit bc53d76

Please sign in to comment.