[Buildbot-commits] buildbot/contrib svn_buildbot.py,1.10,1.11
Brian Warner
warner at users.sourceforge.net
Wed Mar 22 20:53:33 UTC 2006
Update of /cvsroot/buildbot/buildbot/contrib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6651/contrib
Modified Files:
svn_buildbot.py
Log Message:
rearrange, add an easy-to-change function to turn a repository-relative
pathname into a (branch, branch-relative-filename) tuple. Change this
function to handle the branch naming policy used by your Subversion
repository. Thanks to AllMyData.com for sponsoring this work.
Index: svn_buildbot.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/contrib/svn_buildbot.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- svn_buildbot.py 24 Nov 2005 21:57:29 -0000 1.10
+++ svn_buildbot.py 22 Mar 2006 20:53:30 -0000 1.11
@@ -46,7 +46,7 @@
sys.stderr = f
sys.stdout = f
-from twisted.internet import reactor
+from twisted.internet import defer, reactor
from twisted.python import usage
from twisted.spread import pb
from twisted.cred import credentials
@@ -76,6 +76,9 @@
patterns. Excludes override includes, that is, patterns that match both an
include and an exclude will be excluded.'''],
]
+ optFlags = [
+ ['dryrun', 'n', "Do not actually send changes"],
+ ]
def __init__(self):
usage.Options.__init__(self)
@@ -99,78 +102,149 @@
if self._excludes:
self['excludes'] = '(%s)' % ('|'.join(self._excludes),)
+def split_file_dummy(changed_file):
+ """Split the repository-relative filename into a tuple of (branchname,
+ branch_relative_filename). If you have no branches, this should just
+ return (None, changed_file).
+ """
+ return (None, changed_file)
-def main(opts):
- repo = opts['repository']
- print "Repo:", repo
- rev_arg = ''
- if opts['revision']:
- rev_arg = '-r %s' % (opts['revision'],)
- changed = commands.getoutput('svnlook changed %s "%s"' % (rev_arg, repo)
- ).split('\n')
- changed = [x[1:].strip() for x in changed]
- message = commands.getoutput('svnlook log %s "%s"' % (rev_arg, repo))
- who = commands.getoutput('svnlook author %s "%s"' % (rev_arg, repo))
- revision = opts.get('revision')
- if revision is not None:
- revision = int(revision)
+# this version handles repository layouts that look like:
+# trunk/files.. -> trunk
+# branches/branch1/files.. -> branches/branch1
+# branches/branch2/files.. -> branches/branch2
+#
+def split_file_branches(changed_file):
+ pieces = changed_file.split(os.sep)
+ if pieces[0] == 'branches':
+ return (os.path.join(*pieces[:2]),
+ os.path.join(*pieces[2:]))
+ if pieces[0] == 'trunk':
+ return (pieces[0], os.path.join(*pieces[1:]))
+ ## there are other sibilings of 'trunk' and 'branches'. Pretend they are
+ ## all just funny-named branches, and let the Schedulers ignore them.
+ #return (pieces[0], os.path.join(*pieces[1:]))
- # see if we even need to notify buildbot by looking at filters first
- changestring = '\n'.join(changed)
- fltpat = opts['includes']
- if fltpat:
- included = sets.Set(re.findall(fltpat, changestring))
- else:
- included = sets.Set(changed)
+ raise RuntimeError("cannot determine branch for '%s'" % changed_file)
- expat = opts['excludes']
- if expat:
- excluded = sets.Set(re.findall(expat, changestring))
- else:
- excluded = sets.Set([])
- if len(included.difference(excluded)) == 0:
- print changestring
- print """\
-Buildbot was not interested, no changes matched any of these filters:\n %s
-or all the changes matched these exclusions:\n %s\
-""" % (fltpat, expat)
- sys.exit(0)
+split_file = split_file_dummy
- pbcf = pb.PBClientFactory()
- reactor.connectTCP(opts['bbserver'], int(opts['bbport']),
- pbcf)
- def gotPersp(persp):
- print "who", repr(who)
- print "what", repr(changed)
- print "why", repr(message)
- print "new revision", repr(revision)
- return persp.callRemote('addChange', {'who': who,
- 'files': changed,
- 'comments': message,
- 'revision': revision})
+class ChangeSender:
- def quit(*why):
- print "quitting! because", why
- reactor.stop()
+ def getChanges(self, opts):
+ """Generate and stash a list of Change dictionaries, ready to be sent
+ to the buildmaster's PBChangeSource."""
+ # first we extract information about the files that were changed
+ repo = opts['repository']
+ print "Repo:", repo
+ rev_arg = ''
+ if opts['revision']:
+ rev_arg = '-r %s' % (opts['revision'],)
+ changed = commands.getoutput('svnlook changed %s "%s"' % (rev_arg,
+ repo)
+ ).split('\n')
+ changed = [x[1:].strip() for x in changed]
- pbcf.login(credentials.UsernamePassword('change', 'changepw')
- ).addCallback(gotPersp
- ).addCallback(quit, "SUCCESS"
- ).addErrback(quit, "FAILURE")
+ message = commands.getoutput('svnlook log %s "%s"' % (rev_arg, repo))
+ who = commands.getoutput('svnlook author %s "%s"' % (rev_arg, repo))
+ revision = opts.get('revision')
+ if revision is not None:
+ revision = int(revision)
- # timeout of 60 seconds
- reactor.callLater(60, quit, "TIMEOUT")
+ # see if we even need to notify buildbot by looking at filters first
+ changestring = '\n'.join(changed)
+ fltpat = opts['includes']
+ if fltpat:
+ included = sets.Set(re.findall(fltpat, changestring))
+ else:
+ included = sets.Set(changed)
- reactor.run()
+ expat = opts['excludes']
+ if expat:
+ excluded = sets.Set(re.findall(expat, changestring))
+ else:
+ excluded = sets.Set([])
+ if len(included.difference(excluded)) == 0:
+ print changestring
+ print """\
+ Buildbot was not interested, no changes matched any of these filters:\n %s
+ or all the changes matched these exclusions:\n %s\
+ """ % (fltpat, expat)
+ sys.exit(0)
+
+ # now see which branches are involved
+ files_per_branch = {}
+ for f in changed:
+ branch, filename = split_file(f)
+ if files_per_branch.has_key(branch):
+ files_per_branch[branch].append(filename)
+ else:
+ files_per_branch[branch] = [filename]
+
+ # now create the Change dictionaries
+ changes = []
+ for branch in files_per_branch.keys():
+ d = {'who': who,
+ 'branch': branch,
+ 'files': files_per_branch[branch],
+ 'comments': message,
+ 'revision': revision}
+ changes.append(d)
+
+ return changes
+
+ def sendChanges(self, opts, changes):
+ pbcf = pb.PBClientFactory()
+ reactor.connectTCP(opts['bbserver'], int(opts['bbport']), pbcf)
+ d = pbcf.login(credentials.UsernamePassword('change', 'changepw'))
+ d.addCallback(self.sendAllChanges, changes)
+ return d
+
+ def sendAllChanges(self, remote, changes):
+ dl = [remote.callRemote('addChange', change)
+ for change in changes]
+ return defer.DeferredList(dl)
+
+ def run(self):
+ opts = Options()
+ try:
+ opts.parseOptions()
+ except usage.error, ue:
+ print opts
+ print "%s: %s" % (sys.argv[0], ue)
+ sys.exit()
+
+ changes = self.getChanges(opts)
+ if opts['dryrun']:
+ for i,c in enumerate(changes):
+ print "CHANGE #%d" % (i+1)
+ keys = c.keys()
+ keys.sort()
+ for k in keys:
+ print "[%10s]: %s" % (k, c[k])
+ print "*NOT* sending any changes"
+ return
+
+ d = self.sendChanges(opts, changes)
+
+ def quit(*why):
+ print "quitting! because", why
+ reactor.stop()
+
+ def failed(f):
+ print "FAILURE"
+ print f
+ reactor.stop()
+
+ d.addCallback(quit, "SUCCESS")
+ d.addErrback(failed)
+ reactor.callLater(60, quit, "TIMEOUT")
+ reactor.run()
if __name__ == '__main__':
- opts = Options()
- try:
- opts.parseOptions()
- except usage.error, ue:
- print opts
- print "%s: %s" % (sys.argv[0], ue)
- sys.exit()
- main(opts)
+ s = ChangeSender()
+ s.run()
+
+
More information about the Commits
mailing list