From warner at users.sourceforge.net Thu Jan 18 01:24:12 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Thu, 18 Jan 2007 01:24:12 +0000 Subject: [Buildbot-commits] buildbot/buildbot/clients sendchange.py, 1.4, 1.5 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/clients In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv24369/buildbot/clients Modified Files: sendchange.py Log Message: [project @ darcs_buildbot.py: enhance to handle multiple patches in a single push. Fixes SF#1534049] Original author: warner at lothar.com Date: 2007-01-17 23:59:03 Index: sendchange.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/clients/sendchange.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- sendchange.py 6 Sep 2006 00:41:55 -0000 1.4 +++ sendchange.py 18 Jan 2007 01:24:10 -0000 1.5 @@ -4,14 +4,18 @@ from twisted.internet import reactor class Sender: - def __init__(self, master, user): + def __init__(self, master, user=None): self.user = user self.host, self.port = master.split(":") self.port = int(self.port) + self.num_changes = 0 - def send(self, branch, revision, comments, files): - change = {'who': self.user, 'files': files, 'comments': comments, + def send(self, branch, revision, comments, files, user=None): + if user is None: + user = self.user + change = {'who': user, 'files': files, 'comments': comments, 'branch': branch, 'revision': revision} + self.num_changes += 1 f = pb.PBClientFactory() d = f.login(credentials.UsernamePassword("change", "changepw")) @@ -25,9 +29,15 @@ return d def printSuccess(self, res): - print "change sent successfully" + if self.num_changes > 1: + print "%d changes sent successfully" % self.num_changes + elif self.num_changes == 1: + print "change sent successfully" + else: + print "no changes to send" + def printFailure(self, why): - print "change NOT sent" + print "change(s) NOT sent, something went wrong:" print why def stop(self, res): From warner at users.sourceforge.net Thu Jan 18 01:24:12 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Thu, 18 Jan 2007 01:24:12 +0000 Subject: [Buildbot-commits] buildbot/contrib darcs_buildbot.py,1.2,1.3 Message-ID: Update of /cvsroot/buildbot/buildbot/contrib In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv24369/contrib Modified Files: darcs_buildbot.py Log Message: [project @ darcs_buildbot.py: enhance to handle multiple patches in a single push. Fixes SF#1534049] Original author: warner at lothar.com Date: 2007-01-17 23:59:03 Index: darcs_buildbot.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/contrib/darcs_buildbot.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- darcs_buildbot.py 28 May 2006 07:59:32 -0000 1.2 +++ darcs_buildbot.py 18 Jan 2007 01:24:10 -0000 1.3 @@ -17,29 +17,11 @@ # "python2.3-xml" package under debian). import os, sys, commands -from StringIO import StringIO -from buildbot.scripts import runner +from buildbot.clients import sendchange +from twisted.internet import defer, reactor import xml from xml.dom import minidom -MASTER = sys.argv[1] - -out = commands.getoutput("darcs changes --last=1 --xml-output --summary") -#out = commands.getoutput("darcs changes -p 'project @ 2006-05-21 19:07:27 by warner' --xml-output --summary") -try: - doc = minidom.parseString(out) -except xml.parsers.expat.ExpatError, e: - print "failed to parse XML" - print str(e) - print "purported XML is:" - print "--BEGIN--" - print out - print "--END--" - sys.exit(1) - -c = doc.getElementsByTagName("changelog")[0] -p = c.getElementsByTagName("patch")[0] - def getText(node): return "".join([cn.data for cn in node.childNodes @@ -50,37 +32,111 @@ return "" return getText(children[0]) +def makeChange(p): -author = p.getAttribute("author") -revision = p.getAttribute("hash") -comments = getTextFromChild(p, "name") + "\n" + getTextFromChild(p, "comment") + author = p.getAttribute("author") + revision = p.getAttribute("hash") + comments = (getTextFromChild(p, "name") + "\n" + + getTextFromChild(p, "comment")) -summary = c.getElementsByTagName("summary")[0] -files = [] -for filenode in summary.childNodes: - if filenode.nodeName in ("add_file", "modify_file", "remove_file"): - filename = getText(filenode).strip() - files.append(filename) + summary = p.getElementsByTagName("summary")[0] + files = [] + for filenode in summary.childNodes: + if filenode.nodeName in ("add_file", "modify_file", "remove_file"): + filename = getText(filenode).strip() + files.append(filename) -# note that these are all unicode. Because PB can't handle unicode, we encode -# them into ascii, which will blow up early if there's anything we can't get -# to the far side. When we move to something that *can* handle unicode (like -# newpb), remove this. -author = author.encode("ascii") -comments = comments.encode("ascii") -files = [f.encode("ascii") for f in files] -revision = revision.encode("ascii") + # note that these are all unicode. Because PB can't handle unicode, we + # encode them into ascii, which will blow up early if there's anything we + # can't get to the far side. When we move to something that *can* handle + # unicode (like newpb), remove this. + author = author.encode("ascii") + comments = comments.encode("ascii") + files = [f.encode("ascii") for f in files] + revision = revision.encode("ascii") -change = { - 'master': MASTER, - # note: this is more likely to be a full email address, which would make - # the left-hand "Changes" column kind of wide. The buildmaster should - # probably be improved to display an abbreviation of the username. - 'username': author, - 'revision': revision, - 'comments': comments, - 'files': files, - } + change = { + # note: this is more likely to be a full email address, which would + # make the left-hand "Changes" column kind of wide. The buildmaster + # should probably be improved to display an abbreviation of the + # username. + 'username': author, + 'revision': revision, + 'comments': comments, + 'files': files, + } + return change -runner.sendchange(change, True) + + +MASTER = sys.argv[1] +LASTCHANGEFILE = ".darcs_buildbot-lastchange" + +def getSomeChanges(count): + out = commands.getoutput("darcs changes --last=%d --xml-output --summary" + % count) + try: + doc = minidom.parseString(out) + except xml.parsers.expat.ExpatError, e: + print "failed to parse XML" + print str(e) + print "purported XML is:" + print "--BEGIN--" + print out + print "--END--" + sys.exit(1) + + c = doc.getElementsByTagName("changelog")[0] + changes = [] + for i,p in enumerate(c.getElementsByTagName("patch")): + if i >= count: + break + changes.append(makeChange(p)) + return changes + +def findNewChanges(): + if os.path.exists(LASTCHANGEFILE): + f = open(LASTCHANGEFILE, "r") + lastchange = f.read() + f.close() + else: + return getSomeChanges(1) + lookback = 10 + while True: + changes = getSomeChanges(lookback) + # getSomeChanges returns newest-first, so changes[0] is the newest. + # we want to scan the newest first until we find the changes we sent + # last time, then deliver everything newer than that (and send them + # oldest-first). + for i,c in enumerate(changes): + if c['revision'] == lastchange: + newchanges = changes[:i] + newchanges.reverse() + return newchanges + if 2*lookback > 100: + raise RuntimeError("unable to find our most recent change " + "(%s) in the last %d changes" % (lastchange, + lookback)) + lookback = 2*lookback + +changes = findNewChanges() +s = sendchange.Sender(MASTER, None) +d = defer.Deferred() +reactor.callLater(0, d.callback, None) +def _send(res, c): + branch = None + print "sending", c['revision'], "to buildbot" + return s.send(branch, c['revision'], c['comments'], c['files'], + c['username']) +for c in changes: + d.addCallback(_send, c) +d.addCallbacks(s.printSuccess, s.printFailure) +d.addBoth(s.stop) +s.run() + +if changes: + lastchange = changes[-1]['revision'] + f = open(LASTCHANGEFILE, "w") + f.write(lastchange) + f.close() From warner at users.sourceforge.net Thu Jan 18 01:24:12 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Thu, 18 Jan 2007 01:24:12 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.821,1.822 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv24369 Modified Files: ChangeLog Log Message: [project @ darcs_buildbot.py: enhance to handle multiple patches in a single push. Fixes SF#1534049] Original author: warner at lothar.com Date: 2007-01-17 23:59:03 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.821 retrieving revision 1.822 diff -u -d -r1.821 -r1.822 --- ChangeLog 12 Dec 2006 03:44:37 -0000 1.821 +++ ChangeLog 18 Jan 2007 01:24:10 -0000 1.822 @@ -1,3 +1,12 @@ +2007-01-17 Brian Warner + + * contrib/darcs_buildbot.py: enhance to handle multiple patches + being pushed at a time. This keeps state in the repository in a + small file named .darcs_buildbot-lastchange, but that shouldn't + interfere with normal repository operations. Fixes SF#1534049. + * buildbot/clients/sendchange.py (Sender): make a single Sender + capable of sending Changes with different usernames. + 2006-12-11 Brian Warner * buildbot/changes/freshcvsmail.py: mark this file as deprecated, From warner at users.sourceforge.net Sat Jan 20 10:18:51 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Sat, 20 Jan 2007 10:18:51 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.822,1.823 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv12532 Modified Files: ChangeLog Log Message: [project @ darcs_buildbot.py: tidy up the progress messages] Original author: warner at lothar.com Date: 2007-01-20 10:18:08 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.822 retrieving revision 1.823 diff -u -d -r1.822 -r1.823 --- ChangeLog 18 Jan 2007 01:24:10 -0000 1.822 +++ ChangeLog 20 Jan 2007 10:18:48 -0000 1.823 @@ -1,3 +1,7 @@ +2007-01-20 Brian Warner + + * contrib/darcs_buildbot.py: tidy up the progress messages + 2007-01-17 Brian Warner * contrib/darcs_buildbot.py: enhance to handle multiple patches From warner at users.sourceforge.net Sat Jan 20 10:18:51 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Sat, 20 Jan 2007 10:18:51 +0000 Subject: [Buildbot-commits] buildbot/contrib darcs_buildbot.py,1.3,1.4 Message-ID: Update of /cvsroot/buildbot/buildbot/contrib In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv12532/contrib Modified Files: darcs_buildbot.py Log Message: [project @ darcs_buildbot.py: tidy up the progress messages] Original author: warner at lothar.com Date: 2007-01-20 10:18:08 Index: darcs_buildbot.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/contrib/darcs_buildbot.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- darcs_buildbot.py 18 Jan 2007 01:24:10 -0000 1.3 +++ darcs_buildbot.py 20 Jan 2007 10:18:49 -0000 1.4 @@ -121,15 +121,25 @@ changes = findNewChanges() s = sendchange.Sender(MASTER, None) + d = defer.Deferred() reactor.callLater(0, d.callback, None) + +if not changes: + print "darcs_buildbot.py: weird, no changes to send" +elif len(changes) == 1: + print "sending 1 change to buildmaster:" +else: + print "sending %d changes to buildmaster:" % len(changes) + def _send(res, c): branch = None - print "sending", c['revision'], "to buildbot" + print " %s" % c['revision'] return s.send(branch, c['revision'], c['comments'], c['files'], c['username']) for c in changes: d.addCallback(_send, c) + d.addCallbacks(s.printSuccess, s.printFailure) d.addBoth(s.stop) s.run() From warner at users.sourceforge.net Tue Jan 23 05:50:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:00 +0000 Subject: [Buildbot-commits] buildbot/buildbot/steps source.py,1.3,1.4 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/steps In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1130/buildbot/steps Modified Files: source.py Log Message: [project @ add support for bzr (bazaar-ng)] Original author: warner at lothar.com Date: 2007-01-11 00:57:02 Index: source.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/steps/source.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- source.py 25 Sep 2006 07:46:56 -0000 1.3 +++ source.py 23 Jan 2007 05:49:58 -0000 1.4 @@ -735,6 +735,72 @@ cmd = LoggedRemoteCommand("bazaar", self.args) self.startCommand(cmd, warnings) +class Bzr(Source): + """Check out a source tree from a bzr (Bazaar) repository at 'repourl'. + + """ + + name = "bzr" + + def __init__(self, repourl=None, baseURL=None, defaultBranch=None, + **kwargs): + """ + @type repourl: string + @param repourl: the URL which points at the bzr repository. This + is used as the default branch. Using C{repourl} does + not enable builds of alternate branches: use + C{baseURL} to enable this. Use either C{repourl} or + C{baseURL}, not both. + + @param baseURL: if branches are enabled, this is the base URL to + which a branch name will be appended. It should + probably end in a slash. Use exactly one of + C{repourl} and C{baseURL}. + + @param defaultBranch: if branches are enabled, this is the branch + to use if the Build does not specify one + explicitly. It will simply be appended to + C{baseURL} and the result handed to the + 'bzr checkout pull' command. + """ + self.repourl = repourl + self.baseURL = baseURL + self.branch = defaultBranch + Source.__init__(self, **kwargs) + if (not repourl and not baseURL) or (repourl and baseURL): + raise ValueError("you must provide exactly one of repourl and" + " baseURL") + + def computeSourceRevision(self, changes): + if not changes: + return None + lastChange = max([int(c.revision) for c in changes]) + return lastChange + + def startVC(self, branch, revision, patch): + slavever = self.slaveVersion("bzr") + if not slavever: + m = "slave is too old, does not know about bzr" + raise BuildSlaveTooOldError(m) + + if self.repourl: + assert not branch # we need baseURL= to use branches + self.args['repourl'] = self.repourl + else: + self.args['repourl'] = self.baseURL + branch + self.args['revision'] = revision + self.args['patch'] = patch + + revstuff = [] + if branch is not None and branch != self.branch: + revstuff.append("[branch]") + self.description.extend(revstuff) + self.descriptionDone.extend(revstuff) + + cmd = LoggedRemoteCommand("bzr", self.args) + self.startCommand(cmd) + + class Mercurial(Source): """Check out a source tree from a mercurial repository 'repourl'.""" From warner at users.sourceforge.net Tue Jan 23 05:50:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:00 +0000 Subject: [Buildbot-commits] buildbot Branch.ChangeLog, NONE, 1.1 Branch.notes, NONE, 1.1 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1130 Added Files: Branch.ChangeLog Branch.notes Log Message: [project @ add support for bzr (bazaar-ng)] Original author: warner at lothar.com Date: 2007-01-11 00:57:02 --- NEW FILE: Branch.ChangeLog --- 2007-01-10 Brian Warner * buildbot/steps/source.py (Bzr): add Bazaar-ng support * buildbot/slave/commands.py (Bzr): same * buildbot/scripts/tryclient.py (BzrExtractor): same (SourceStampExtractor.dovc): modify this to allow non-zero exit status, since 'bzr diff' does that * buildbot/test/test_vc.py (Bzr): same * docs/buildbot.texinfo (How Different VC Systems Specify Sources): add notes on bzr (Bzr): document it --- NEW FILE: Branch.notes --- still to do: repourl vs repoURL, make it consistent in docs and code it would be nice to name this Bazaar, instead of Bzr. Need a transition plan for the old baz step. old: Arch (tla), Bazaar (baz) new?: Arch (tla), Baz (baz), Bazaar (bzr) use of 'bzr version-info' vs 'bzr revno', maybe a bzr bug From warner at users.sourceforge.net Tue Jan 23 05:50:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:00 +0000 Subject: [Buildbot-commits] buildbot/buildbot/scripts tryclient.py, 1.17, 1.18 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/scripts In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1130/buildbot/scripts Modified Files: tryclient.py Log Message: [project @ add support for bzr (bazaar-ng)] Original author: warner at lothar.com Date: 2007-01-11 00:57:02 Index: tryclient.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/scripts/tryclient.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- tryclient.py 11 Dec 2006 09:11:26 -0000 1.17 +++ tryclient.py 23 Jan 2007 05:49:58 -0000 1.18 @@ -24,8 +24,15 @@ command itself.""" env = os.environ.copy() env['LC_ALL'] = "C" - return utils.getProcessOutput(self.exe, cmd, env=env, - path=self.treetop) + d = utils.getProcessOutputAndValue(self.exe, cmd, env=env, + path=self.treetop) + d.addCallback(self._didvc, cmd) + return d + def _didvc(self, res, cmd): + (stdout, stderr, code) = res + # 'bzr diff' sets rc=1 if there were any differences. tla, baz, and + # cvs do something similar, so don't bother requring rc=0. + return stdout def get(self): """Return a Deferred that fires with a SourceStamp instance.""" @@ -107,6 +114,7 @@ return d class BazExtractor(SourceStampExtractor): + patchlevel = 1 vcexe = "baz" def getBaseRevision(self): d = self.dovc(["tree-id"]) @@ -120,10 +128,11 @@ self.baserev = tid[dd+2:] def getPatch(self, res): d = self.dovc(["diff"]) - d.addCallback(self.readPatch, 1) + d.addCallback(self.readPatch, self.patchlevel) return d class TlaExtractor(SourceStampExtractor): + patchlevel = 1 vcexe = "tla" def getBaseRevision(self): # 'tla logs --full' gives us ARCHIVE/BRANCH--REVISION @@ -140,7 +149,29 @@ def getPatch(self, res): d = self.dovc(["changes", "--diffs"]) - d.addCallback(self.readPatch, 1) + d.addCallback(self.readPatch, self.patchlevel) + return d + +class BzrExtractor(SourceStampExtractor): + patchlevel = 0 + vcexe = "bzr" + def getBaseRevision(self): + d = self.dovc(["version-info"]) + d.addCallback(self.get_revision_number) + return d + def get_revision_number(self, out): + for line in out.split("\n"): + colon = line.find(":") + if colon != -1: + key, value = line[:colon], line[colon+2:] + if key == "revno": + self.baserev = int(value) + return + raise ValueError("unable to find revno: in bzr output: '%s'" % out) + + def getPatch(self, res): + d = self.dovc(["diff"]) + d.addCallback(self.readPatch, self.patchlevel) return d class MercurialExtractor(SourceStampExtractor): @@ -179,6 +210,8 @@ e = SVNExtractor(treetop, branch) elif vctype == "baz": e = BazExtractor(treetop, branch) + elif vctype == "bzr": + e = BzrExtractor(treetop, branch) elif vctype == "tla": e = TlaExtractor(treetop, branch) elif vctype == "hg": From warner at users.sourceforge.net Tue Jan 23 05:50:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:00 +0000 Subject: [Buildbot-commits] buildbot/buildbot/slave commands.py,1.75,1.76 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/slave In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1130/buildbot/slave Modified Files: commands.py Log Message: [project @ add support for bzr (bazaar-ng)] Original author: warner at lothar.com Date: 2007-01-11 00:57:02 Index: commands.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/slave/commands.py,v retrieving revision 1.75 retrieving revision 1.76 diff -u -d -r1.75 -r1.76 --- commands.py 11 Dec 2006 09:11:26 -0000 1.75 +++ commands.py 23 Jan 2007 05:49:58 -0000 1.76 @@ -1932,6 +1932,128 @@ registerSlaveCommand("bazaar", Bazaar, command_version) +class Bzr(SourceBase): + """bzr-specific VC operation. In addition to the arguments + handled by SourceBase, this command reads the following keys: + + ['repourl'] (required): the Bzr repository string + """ + + header = "bzr operation" + + def setup(self, args): + SourceBase.setup(self, args) + self.vcexe = getCommand("bzr") + self.repourl = args['repourl'] + self.sourcedata = "%s\n" % self.repourl + self.revision = self.args.get('revision') + + def sourcedirIsUpdateable(self): + if os.path.exists(os.path.join(self.builder.basedir, + self.srcdir, ".buildbot-patched")): + return False + if self.revision: + # checking out a specific revision requires a full 'bzr checkout' + return False + return os.path.isdir(os.path.join(self.builder.basedir, + self.srcdir, ".bzr")) + + def doVCUpdate(self): + assert not self.revision + # update: possible for mode in ('copy', 'update') + srcdir = os.path.join(self.builder.basedir, self.srcdir) + command = [self.vcexe, 'update'] + c = ShellCommand(self.builder, command, srcdir, + sendRC=False, timeout=self.timeout) + self.command = c + return c.start() + + def doVCFull(self): + # checkout or export + d = self.builder.basedir + if self.mode == "export": + # exporting in bzr requires a separate directory + return self.doVCExport() + # originally I added --lightweight here, but then 'bzr revno' is + # wrong. The revno reported in 'bzr version-info' is correct, + # however. Maybe this is a bzr bug? + # + # In addition, you cannot perform a 'bzr update' on a repo pulled + # from an HTTP repository that used 'bzr checkout --lightweight'. You + # get a "ERROR: Cannot lock: transport is read only" when you try. + # + # So I won't bother using --lightweight for now. + + command = [self.vcexe, 'checkout'] + if self.revision: + command.append('--revision') + command.append(str(self.revision)) + command.append(self.repourl) + command.append(self.srcdir) + + c = ShellCommand(self.builder, command, d, + sendRC=False, timeout=self.timeout) + self.command = c + d = c.start() + return d + + def doVCExport(self): + tmpdir = os.path.join(self.builder.basedir, "export-temp") + srcdir = os.path.join(self.builder.basedir, self.srcdir) + command = [self.vcexe, 'checkout', '--lightweight'] + if self.revision: + command.append('--revision') + command.append(str(self.revision)) + command.append(self.repourl) + command.append(tmpdir) + c = ShellCommand(self.builder, command, self.builder.basedir, + sendRC=False, timeout=self.timeout) + self.command = c + d = c.start() + def _export(res): + command = [self.vcexe, 'export', srcdir] + c = ShellCommand(self.builder, command, tmpdir, + sendRC=False, timeout=self.timeout) + self.command = c + return c.start() + d.addCallback(_export) + return d + + def get_revision_number(self, out): + # it feels like 'bzr revno' sometimes gives different results than + # the 'revno:' line from 'bzr version-info', and the one from + # version-info is more likely to be correct. + for line in out.split("\n"): + colon = line.find(":") + if colon != -1: + key, value = line[:colon], line[colon+2:] + if key == "revno": + return int(value) + raise ValueError("unable to find revno: in bzr output: '%s'" % out) + + def parseGotRevision(self): + command = [self.vcexe, "version-info"] + c = ShellCommand(self.builder, command, + os.path.join(self.builder.basedir, self.srcdir), + environ=self.env, + sendStdout=False, sendStderr=False, sendRC=False, + keepStdout=True) + c.usePTY = False + d = c.start() + def _parse(res): + try: + return self.get_revision_number(c.stdout) + except ValueError: + msg =("Bzr.parseGotRevision unable to parse output " + "of bzr version-info: '%s'" % c.stdout.strip()) + log.msg(msg) + self.sendStatus({'header': msg + "\n"}) + return None + d.addCallback(_parse) + return d + +registerSlaveCommand("bzr", Bzr, command_version) + class Mercurial(SourceBase): """Mercurial specific VC operation. In addition to the arguments handled by SourceBase, this command reads the following keys: From warner at users.sourceforge.net Tue Jan 23 05:50:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:00 +0000 Subject: [Buildbot-commits] buildbot/buildbot/test test_vc.py,1.71,1.72 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1130/buildbot/test Modified Files: test_vc.py Log Message: [project @ add support for bzr (bazaar-ng)] Original author: warner at lothar.com Date: 2007-01-11 00:57:02 Index: test_vc.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/test/test_vc.py,v retrieving revision 1.71 retrieving revision 1.72 diff -u -d -r1.71 -r1.72 --- test_vc.py 11 Dec 2006 09:11:27 -0000 1.71 +++ test_vc.py 23 Jan 2007 05:49:58 -0000 1.72 @@ -329,7 +329,8 @@ raise NotImplementedError def populate(self, basedir): - os.makedirs(basedir) + if not os.path.exists(basedir): + os.makedirs(basedir) os.makedirs(os.path.join(basedir, "subdir")) open(os.path.join(basedir, "main.c"), "w").write(MAIN_C) self.version = 1 @@ -2133,6 +2134,202 @@ VCS.registerVC(Bazaar.vc_name, BazaarHelper()) +class BzrHelper(BaseHelper): + branchname = "branch" + try_branchname = "branch" + + def capable(self): + bzrpaths = which('bzr') + if not bzrpaths: + return (False, "bzr is not installed") + self.vcexe = bzrpaths[0] + return (True, None) + + def get_revision_number(self, out): + for line in out.split("\n"): + colon = line.index(":") + key, value = line[:colon], line[colon+2:] + if key == "revno": + return int(value) + raise RuntimeError("unable to find revno: in bzr output: '%s'" % out) + + def createRepository(self): + self.createBasedir() + self.bzr_base = os.path.join(self.repbase, "Bzr-Repository") + self.rep_trunk = os.path.join(self.bzr_base, "trunk") + self.rep_branch = os.path.join(self.bzr_base, "branch") + tmp = os.path.join(self.repbase, "bzrtmp") + btmp = os.path.join(self.repbase, "bzrtmp-branch") + + os.makedirs(self.rep_trunk) + w = self.dovc(self.rep_trunk, ["init"]) + yield w; w.getResult() + w = self.dovc(self.bzr_base, + ["branch", self.rep_trunk, self.rep_branch]) + yield w; w.getResult() + + w = self.dovc(self.repbase, ["checkout", self.rep_trunk, tmp]) + yield w; w.getResult() + self.populate(tmp) + w = self.dovc(tmp, qw("add")) + yield w; w.getResult() + w = self.dovc(tmp, qw("commit -m initial_import")) + yield w; w.getResult() + w = self.dovc(tmp, qw("version-info")) + yield w; out = w.getResult() + self.addTrunkRev(self.get_revision_number(out)) + rmdirRecursive(tmp) + + # pull all trunk revisions to the branch + w = self.dovc(self.rep_branch, qw("pull")) + yield w; w.getResult() + # obtain a branch tree + w = self.dovc(self.repbase, ["checkout", self.rep_branch, btmp]) + yield w; w.getResult() + # modify it + self.populate_branch(btmp) + w = self.dovc(btmp, qw("add")) + yield w; w.getResult() + w = self.dovc(btmp, qw("commit -m commit_on_branch")) + yield w; w.getResult() + w = self.dovc(btmp, qw("version-info")) + yield w; out = w.getResult() + self.addBranchRev(self.get_revision_number(out)) + rmdirRecursive(btmp) + createRepository = deferredGenerator(createRepository) + + def vc_revise(self): + tmp = os.path.join(self.repbase, "bzrtmp") + w = self.dovc(self.repbase, ["checkout", self.rep_trunk, tmp]) + yield w; w.getResult() + + self.version += 1 + version_c = VERSION_C % self.version + open(os.path.join(tmp, "version.c"), "w").write(version_c) + w = self.dovc(tmp, qw("commit -m revised_to_%d" % self.version)) + yield w; w.getResult() + w = self.dovc(tmp, qw("version-info")) + yield w; out = w.getResult() + self.addTrunkRev(self.get_revision_number(out)) + rmdirRecursive(tmp) + vc_revise = deferredGenerator(vc_revise) + + def vc_try_checkout(self, workdir, rev, branch=None): + assert os.path.abspath(workdir) == workdir + if os.path.exists(workdir): + rmdirRecursive(workdir) + #os.makedirs(workdir) + if not branch: + rep = self.rep_trunk + else: + rep = os.path.join(self.bzr_base, branch) + w = self.dovc(self.bzr_base, ["checkout", rep, workdir]) + yield w; w.getResult() + open(os.path.join(workdir, "subdir", "subdir.c"), "w").write(TRY_C) + vc_try_checkout = deferredGenerator(vc_try_checkout) + + def vc_try_finish(self, workdir): + rmdirRecursive(workdir) + +class Bzr(VCBase, unittest.TestCase): + vc_name = "bzr" + + metadir = ".bzr" + vctype = "source.Bzr" + vctype_try = "bzr" + has_got_revision = True + + def testCheckout(self): + self.helper.vcargs = { 'repourl': self.helper.rep_trunk } + d = self.do_vctest(testRetry=False) + + # TODO: testRetry has the same problem with Bzr as it does for + # Arch + return d + + def testPatch(self): + self.helper.vcargs = { 'baseURL': self.helper.bzr_base + "/", + 'defaultBranch': "trunk" } + d = self.do_patch() + return d + + def testCheckoutBranch(self): + self.helper.vcargs = { 'baseURL': self.helper.bzr_base + "/", + 'defaultBranch': "trunk" } + d = self.do_branch() + return d + + def testCheckoutHTTP(self): + self.serveHTTP() + repourl = "http://localhost:%d/Bzr-Repository/trunk" % self.httpPort + self.helper.vcargs = { 'repourl': repourl } + d = self.do_vctest(testRetry=False) + return d + + + def fixRepository(self): + self.fixtimer = None + self.site.resource = self.root + + def testRetry(self): + # this test takes a while to run + self.serveHTTP() + + # break the repository server + from twisted.web import static + self.site.resource = static.Data("Sorry, repository is offline", + "text/plain") + # and arrange to fix it again in 5 seconds, while the test is + # running. + self.fixtimer = reactor.callLater(5, self.fixRepository) + + repourl = "http://localhost:%d/Bzr-Repository/trunk" % self.httpPort + self.helper.vcargs = { 'repourl': repourl, + 'retry': (5.0, 4), + } + d = self.do_vctest_once(True) + d.addCallback(self._testRetry_1) + return d + def _testRetry_1(self, bs): + # make sure there was mention of the retry attempt in the logs + l = bs.getLogs()[0] + self.failUnlessIn("ERROR: Not a branch: ", l.getText(), + "funny, VC operation didn't fail at least once") + self.failUnlessIn("update failed, trying 4 more times after 5 seconds", + l.getTextWithHeaders(), + "funny, VC operation wasn't reattempted") + + def testRetryFails(self): + # make sure that the build eventually gives up on a repository which + # is completely unavailable + + self.serveHTTP() + + # break the repository server, and leave it broken + from twisted.web import static + self.site.resource = static.Data("Sorry, repository is offline", + "text/plain") + + repourl = "http://localhost:%d/Bzr-Repository/trunk" % self.httpPort + self.helper.vcargs = { 'repourl': repourl, + 'retry': (0.5, 3), + } + d = self.do_vctest_once(False) + d.addCallback(self._testRetryFails_1) + return d + def _testRetryFails_1(self, bs): + self.failUnlessEqual(bs.getResults(), FAILURE) + + + def testTry(self): + self.helper.vcargs = { 'baseURL': self.helper.bzr_base + "/", + 'defaultBranch': "trunk" } + d = self.do_getpatch() + return d + +VCS.registerVC(Bzr.vc_name, BzrHelper()) + + class MercurialHelper(BaseHelper): branchname = "branch" try_branchname = "branch" From warner at users.sourceforge.net Tue Jan 23 05:50:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:00 +0000 Subject: [Buildbot-commits] buildbot/docs buildbot.texinfo,1.95,1.96 Message-ID: Update of /cvsroot/buildbot/buildbot/docs In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1130/docs Modified Files: buildbot.texinfo Log Message: [project @ add support for bzr (bazaar-ng)] Original author: warner at lothar.com Date: 2007-01-11 00:57:02 Index: buildbot.texinfo =================================================================== RCS file: /cvsroot/buildbot/buildbot/docs/buildbot.texinfo,v retrieving revision 1.95 retrieving revision 1.96 diff -u -d -r1.95 -r1.96 --- buildbot.texinfo 11 Dec 2006 08:12:21 -0000 1.95 +++ buildbot.texinfo 23 Jan 2007 05:49:58 -0000 1.96 @@ -179,6 +179,7 @@ * Mercurial:: * Arch:: * Bazaar:: +* Bzr:: * P4:: Simple ShellCommand Subclasses @@ -1195,21 +1196,24 @@ systems as having repositories that each provide sources for a variety of projects. Each project is defined as a directory tree with source files. The individual files may each have revisions, but we ignore -that and treat the project as a whole as having a set of revisions. -Each time someone commits a change to the project, a new revision -becomes available. These revisions can be described by a tuple with -two items: the first is a branch tag, and the second is some kind of -timestamp or revision stamp. Complex projects may have multiple branch -tags, but there is always a default branch. The timestamp may be an -actual timestamp (such as the -D option to CVS), or it may be a -monotonically-increasing transaction number (such as the change number -used by SVN and P4, or the revision number used by Arch, or a labeled -tag used in CVS)@footnote{many VC systems provide more complexity than -this: in particular the local views that P4 and ClearCase can assemble -out of various source directories are more complex than we're prepared -to take advantage of here}. The SHA1 revision ID used by Monotone and -Mercurial is also a kind of revision stamp, in that it specifies a -unique copy of the source tree, as does a Darcs ``context'' file. +that and treat the project as a whole as having a set of revisions +(CVS is really the only VC system still in widespread use that has +per-file revisions.. everything modern has moved to atomic tree-wide +changesets). Each time someone commits a change to the project, a new +revision becomes available. These revisions can be described by a +tuple with two items: the first is a branch tag, and the second is +some kind of revision stamp or timestamp. Complex projects may have +multiple branch tags, but there is always a default branch. The +timestamp may be an actual timestamp (such as the -D option to CVS), +or it may be a monotonically-increasing transaction number (such as +the change number used by SVN and P4, or the revision number used by +Arch/Baz/Bazaar, or a labeled tag used in CVS)@footnote{many VC +systems provide more complexity than this: in particular the local +views that P4 and ClearCase can assemble out of various source +directories are more complex than we're prepared to take advantage of +here}. The SHA1 revision ID used by Monotone and Mercurial is also a +kind of revision stamp, in that it specifies a unique copy of the +source tree, as does a Darcs ``context'' file. When we aren't intending to make any changes to the sources we check out (at least not any that need to be committed back upstream), there are two @@ -1354,6 +1358,30 @@ default, as well as a revision number (which is turned into a --patch-NN suffix when performing the checkout). + + at uref{http://bazaar-vcs.org, Bzr} (which is a descendant of +Arch/Bazaar, and is frequently referred to as ``Bazaar'') has the same +sort of repository-vs-workspace model as Arch, but the repository data +can either be stored inside the working directory or kept elsewhere +(either on the same machine or on an entirely different machine). For +the purposes of Buildbot (which never commits changes), the repository +is specified with a URL and a revision number. + +The most common way to obtain read-only access to a bzr tree is via +HTTP, simply by making the repository visible through a web server +like Apache. Bzr can also use FTP and SFTP servers, if the buildslave +process has sufficient privileges to access them. Higher performance +can be obtained by running a special Bazaar-specific server. None of +these matter to the buildbot: the repository URL just has to match the +kind of server being used. The @code{repoURL} argument provides the +location of the repository. + +Branches are expressed as subdirectories of the main central +repository, which means that if branches are being used, the BZR step +is given a @code{baseURL} and @code{defaultBranch} instead of getting +the @code{repoURL} argument. + + @uref{http://abridgegame.org/darcs/, Darcs} doesn't really have the notion of a single master repository. Nor does it really have branches. In Darcs, each working directory is also a repository, and @@ -3347,6 +3375,7 @@ * Mercurial:: * Arch:: * Bazaar:: +* Bzr:: * P4:: @end menu @@ -3631,7 +3660,7 @@ @end table - at node Bazaar, P4, Arch, Source Checkout + at node Bazaar, Bzr, Arch, Source Checkout @subsubsection Bazaar @cindex Bazaar Checkout @@ -3649,7 +3678,40 @@ ourselves). - at node P4, , Bazaar, Source Checkout + at node Bzr, P4, Bazaar, Source Checkout + at subsubsection Bzr + + at cindex Bzr Checkout + at bsindex buildbot.steps.source.Bzr + + at code{bzr} is a descendant of Arch/Baz, and is frequently referred to +as simply ``Bazaar''. The repository-vs-workspace model is similar to +Darcs, but it uses a strictly linear sequence of revisions (one +history per branch) like Arch. Branches are put in subdirectories. +This makes it look very much like Mercurial, so it takes the same +arguments: + + at table @code + + at item repourl +(required unless @code{baseURL} is provided): the URL at which the +Bzr source repository is available. + + at item baseURL +(required unless @code{repourl} is provided): the base repository URL, +to which a branch name will be appended. It should probably end in a +slash. + + at item defaultBranch +(allowed if and only if @code{baseURL} is provided): this specifies +the name of the branch to use when a Build does not provide one of its +own. This will be appended to @code{baseURL} to create the string that +will be passed to the @code{bzr checkout} command. + at end table + + + + at node P4, , Bzr, Source Checkout @subsubsection P4 @cindex Perforce Update From warner at users.sourceforge.net Tue Jan 23 05:50:16 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 05:50:16 +0000 Subject: [Buildbot-commits] buildbot ChangeLog, 1.823, 1.824 Branch.ChangeLog, 1.1, NONE Branch.notes, 1.1, NONE Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv1558 Modified Files: ChangeLog Removed Files: Branch.ChangeLog Branch.notes Log Message: [project @ merge in Bazaar (bzr) support. There are still a few unresolved issues.] Original author: warner at lothar.com Date: 2007-01-23 05:47:39 --- Branch.ChangeLog DELETED --- --- Branch.notes DELETED --- Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.823 retrieving revision 1.824 diff -u -d -r1.823 -r1.824 --- ChangeLog 20 Jan 2007 10:18:48 -0000 1.823 +++ ChangeLog 23 Jan 2007 05:50:14 -0000 1.824 @@ -1,3 +1,15 @@ +2007-01-22 Brian Warner + + * buildbot/steps/source.py (Bzr): add Bazaar-ng support + * buildbot/slave/commands.py (Bzr): same + * buildbot/scripts/tryclient.py (BzrExtractor): same + (SourceStampExtractor.dovc): modify this to allow non-zero exit + status, since 'bzr diff' does that + * buildbot/test/test_vc.py (Bzr): same + * docs/buildbot.texinfo (How Different VC Systems Specify Sources): + add notes on bzr + (Bzr): document it + 2007-01-20 Brian Warner * contrib/darcs_buildbot.py: tidy up the progress messages From warner at users.sourceforge.net Tue Jan 23 07:19:58 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 07:19:58 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.824,1.825 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4159 Modified Files: ChangeLog Log Message: [project @ add a gnome-panel status applet] Original author: warner at lothar.com Date: 2007-01-23 07:18:12 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.824 retrieving revision 1.825 diff -u -d -r1.824 -r1.825 --- ChangeLog 23 Jan 2007 05:50:14 -0000 1.824 +++ ChangeLog 23 Jan 2007 07:19:56 -0000 1.825 @@ -1,5 +1,11 @@ 2007-01-22 Brian Warner + * contrib/bb_applet.py: add a simple gnome-panel applet, to + display a terse summary of buildbot status. + * docs/hexnut32.png, docs/hexnut48.png, docs/hexnut64.png: add + some icons, small versions of the Blender object that lives in + docs/images/icon.blend + * buildbot/steps/source.py (Bzr): add Bazaar-ng support * buildbot/slave/commands.py (Bzr): same * buildbot/scripts/tryclient.py (BzrExtractor): same From warner at users.sourceforge.net Tue Jan 23 07:19:59 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 07:19:59 +0000 Subject: [Buildbot-commits] buildbot/docs hexnut32.png, NONE, 1.1 hexnut48.png, NONE, 1.1 hexnut64.png, NONE, 1.1 Message-ID: Update of /cvsroot/buildbot/buildbot/docs In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4159/docs Added Files: hexnut32.png hexnut48.png hexnut64.png Log Message: [project @ add a gnome-panel status applet] Original author: warner at lothar.com Date: 2007-01-23 07:18:12 --- NEW FILE: hexnut32.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: hexnut48.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: hexnut64.png --- (This appears to be a binary file; contents omitted.) From warner at users.sourceforge.net Tue Jan 23 07:19:58 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 07:19:58 +0000 Subject: [Buildbot-commits] buildbot/contrib bb_applet.py,NONE,1.1 Message-ID: Update of /cvsroot/buildbot/buildbot/contrib In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4159/contrib Added Files: bb_applet.py Log Message: [project @ add a gnome-panel status applet] Original author: warner at lothar.com Date: 2007-01-23 07:18:12 --- NEW FILE: bb_applet.py --- #! /usr/bin/python # This is a Gnome-2 panel applet that uses the # buildbot.status.client.PBListener interface to display a terse summary of # the buildmaster. It displays one column per builder, with a box on top for # the status of the most recent build (red, green, or orange), and a somewhat # smaller box on the bottom for the current state of the builder (white for # idle, yellow for building, red for offline). There are tooltips available # to tell you which box is which. # Edit the line at the beginning of the MyApplet class to fill in the host # and portnumber of your buildmaster's PBListener status port. Eventually # this will move into a preferences dialog, but first we must create a # preferences dialog. # See the notes at the end for installation hints and support files (you # cannot simply run this script from the shell). You must create a bonobo # .server file that points to this script, and put the .server file somewhere # that bonobo will look for it. Only then will this applet appear in the # panel's "Add Applet" menu. # Note: These applets are run in an environment that throws away stdout and # stderr. Any logging must be done with syslog or explicitly to a file. # Exceptions are particularly annoying in such an environment. # -Brian Warner, warner at lothar.com if 0: import sys dpipe = open("/tmp/applet.log", "a", 1) sys.stdout = dpipe sys.stderr = dpipe print "starting" from twisted.internet import gtk2reactor gtk2reactor.install() import gtk import gnomeapplet # preferences are not yet implemented MENU = """ """ from twisted.spread import pb from twisted.cred import credentials # sigh, these constants should cross the wire as strings, not integers SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION = range(5) Results = ["success", "warnings", "failure", "skipped", "exception"] class Box: def __init__(self, buildername, hbox, tips, size, hslice): self.buildername = buildername self.hbox = hbox self.tips = tips self.state = "idle" self.eta = None self.last_results = None self.last_text = None self.size = size self.hslice = hslice def create(self): self.vbox = gtk.VBox(False) l = gtk.Label("") self.current_box = box = gtk.EventBox() # these size requests are somewhat non-deterministic. I think it # depends upon how large label is, or how much space was already # consumed when the box is added. self.current_box.set_size_request(self.hslice, self.size * 0.75) box.add(l) self.vbox.pack_end(box) self.current_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("gray50")) l2 = gtk.Label("") self.last_box = gtk.EventBox() self.current_box.set_size_request(self.hslice, self.size * 0.25) self.last_box.add(l2) self.vbox.pack_end(self.last_box, True, True) self.vbox.show_all() self.hbox.pack_end(self.vbox, True, True) def remove(self): self.hbox.remove(self.box) def set_state(self, state): self.state = state self.update() def set_eta(self, eta): self.eta = eta self.update() def set_last_build_results(self, results): self.last_results = results self.update() def set_last_build_text(self, text): self.last_text = text self.update() def update(self): currentmap = {"offline": "red", "idle": "white", "waiting": "yellow", "interlocked": "yellow", "building": "yellow",} color = currentmap[self.state] self.current_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) lastmap = {None: "gray50", SUCCESS: "green", WARNINGS: "orange", FAILURE: "red", EXCEPTION: "purple", } last_color = lastmap[self.last_results] self.last_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(last_color)) current_tip = "%s:\n%s" % (self.buildername, self.state) if self.eta is not None: current_tip += " (ETA=%ds)" % self.eta self.tips.set_tip(self.current_box, current_tip) last_tip = "%s:\n" % self.buildername if self.last_text: last_tip += "\n".join(self.last_text) else: last_tip += "no builds" self.tips.set_tip(self.last_box, last_tip) class MyApplet(pb.Referenceable): # CHANGE THIS TO POINT TO YOUR BUILDMASTER buildmaster = "buildmaster.example.org", 12345 filled = None def __init__(self, container): self.applet = container self.size = container.get_size() self.hslice = self.size / 4 container.set_size_request(self.size, self.size) self.fill_nut() verbs = [ ("Props", self.menu_preferences), ] container.setup_menu(MENU, verbs) self.boxes = {} self.connect() def fill(self, what): if self.filled: self.applet.remove(self.filled) self.filled = None self.applet.add(what) self.filled = what self.applet.show_all() def fill_nut(self): i = gtk.Image() i.set_from_file("/tmp/nut32.png") self.fill(i) def fill_hbox(self): self.hbox = gtk.HBox(True) self.fill(self.hbox) def connect(self): host, port = self.buildmaster cf = pb.PBClientFactory() creds = credentials.UsernamePassword("statusClient", "clientpw") d = cf.login(creds) reactor.connectTCP(host, port, cf) d.addCallback(self.connected) return d def connected(self, ref): print "connected" ref.notifyOnDisconnect(self.disconnected) self.remote = ref self.remote.callRemote("subscribe", "steps", 5, self) self.fill_hbox() self.tips = gtk.Tooltips() self.tips.enable() def disconnected(self): print "disconnected" self.fill_nut() def remote_builderAdded(self, buildername, builder): print "builderAdded", buildername box = Box(buildername, self.hbox, self.tips, self.size, self.hslice) self.boxes[buildername] = box box.create() self.applet.set_size_request(self.hslice * len(self.boxes), self.size) d = builder.callRemote("getLastFinishedBuild") def _got(build): if build: d1 = build.callRemote("getResults") d1.addCallback(box.set_last_build_results) d2 = build.callRemote("getText") d2.addCallback(box.set_last_build_text) d.addCallback(_got) def remote_builderRemoved(self, buildername): self.boxes[buildername].remove() del self.boxes[buildername] self.applet.set_size_request(self.hslice * len(self.boxes), self.size) def remote_builderChangedState(self, buildername, state, eta): self.boxes[buildername].set_state(state) self.boxes[buildername].set_eta(eta) print "change", buildername, state, eta def remote_buildStarted(self, buildername, build): print "buildStarted", buildername def remote_buildFinished(self, buildername, build, results): print "buildFinished", results box = self.boxes[buildername] box.set_eta(None) d1 = build.callRemote("getResults") d1.addCallback(box.set_last_build_results) d2 = build.callRemote("getText") d2.addCallback(box.set_last_build_text) def remote_buildETAUpdate(self, buildername, build, eta): self.boxes[buildername].set_eta(eta) print "ETA", buildername, eta def remote_stepStarted(self, buildername, build, stepname, step): print "stepStarted", buildername, stepname def remote_stepFinished(self, buildername, build, stepname, step, results): pass def menu_preferences(self, event, data=None): print "prefs!" def factory(applet, iid): MyApplet(applet) applet.show_all() return True from twisted.internet import reactor # instead of reactor.run(), we do the following: reactor.startRunning() reactor.simulate() gnomeapplet.bonobo_factory("OAFIID:GNOME_Buildbot_Factory", gnomeapplet.Applet.__gtype__, "buildbot", "0", factory) # code ends here: bonobo_factory runs gtk.mainloop() internally and # doesn't return until the program ends # SUPPORTING FILES: # save the following as ~/lib/bonobo/servers/bb_applet.server, and update all # the pathnames to match your system bb_applet_server = """ """ # a quick rundown on the Gnome2 applet scheme (probably wrong: there are # better docs out there that you should be following instead) # http://www.pycage.de/howto_bonobo.html describes a lot of # the base Bonobo stuff. # http://www.daa.com.au/pipermail/pygtk/2002-September/003393.html # bb_applet.server must be in your $BONOBO_ACTIVATION_PATH . I use # ~/lib/bonobo/servers . This environment variable is read by # bonobo-activation-server, so it must be set before you start any Gnome # stuff. I set it in ~/.bash_profile . You can also put it in # /usr/lib/bonobo/servers/ , which is probably on the default # $BONOBO_ACTIVATION_PATH, so you won't have to update anything. # It is safest to put this in place before bonobo-activation-server is # started, which may mean before any Gnome program is running. It may or may # not detect bb_applet.server if it is installed afterwards.. there seem to # be hooks, some of which involve FAM, but I never managed to make them work. # The file must have a name that ends in .server or it will be ignored. # The .server file registers two OAF ids and tells the activation-server how # to create those objects. The first is the GNOME_Buildbot_Factory, and is # created by running the bb_applet.py script. The second is the # GNOME_Buildbot applet itself, and is created by asking the # GNOME_Buildbot_Factory to make it. # gnome-panel's "Add To Panel" menu will gather all the OAF ids that claim # to implement the "IDL:GNOME/Vertigo/PanelAppletShell:1.0" in its # "repo_ids" attribute. The sub-menu is determined by the "panel:category" # attribute. The icon comes from "panel:icon", the text displayed in the # menu comes from "name", the text in the tool-tip comes from "description". # The factory() function is called when a new applet is created. It receives # a container that should be populated with the actual applet contents (in # this case a Button). # If you're hacking on the code, just modify bb_applet.py and then kill -9 # the running applet: the panel will ask you if you'd like to re-load the # applet, and when you say 'yes', bb_applet.py will be re-executed. Note that # 'kill PID' won't work because the program is sitting in C code, and SIGINT # isn't delivered until after it surfaces to python, which will be never. # Running bb_applet.py by itself will result in a factory instance being # created and then sitting around forever waiting for the activation-server # to ask it to make an applet. This isn't very useful. # The "location" filename in bb_applet.server must point to bb_applet.py, and # bb_applet.py must be executable. # Enjoy! # -Brian Warner From warner at users.sourceforge.net Tue Jan 23 08:01:37 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 08:01:37 +0000 Subject: [Buildbot-commits] buildbot/contrib bb_applet.py,1.1,1.2 Message-ID: Update of /cvsroot/buildbot/buildbot/contrib In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv20622/contrib Modified Files: bb_applet.py Log Message: [project @ bb_applet.py: add dots, swap columns left-right] Original author: warner at lothar.com Date: 2007-01-23 07:28:57 Index: bb_applet.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/contrib/bb_applet.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- bb_applet.py 23 Jan 2007 07:19:56 -0000 1.1 +++ bb_applet.py 23 Jan 2007 08:01:35 -0000 1.2 @@ -67,7 +67,7 @@ def create(self): self.vbox = gtk.VBox(False) - l = gtk.Label("") + l = gtk.Label(".") self.current_box = box = gtk.EventBox() # these size requests are somewhat non-deterministic. I think it # depends upon how large label is, or how much space was already @@ -78,13 +78,13 @@ self.current_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("gray50")) - l2 = gtk.Label("") + l2 = gtk.Label(".") self.last_box = gtk.EventBox() self.current_box.set_size_request(self.hslice, self.size * 0.25) self.last_box.add(l2) self.vbox.pack_end(self.last_box, True, True) self.vbox.show_all() - self.hbox.pack_end(self.vbox, True, True) + self.hbox.pack_start(self.vbox, True, True) def remove(self): self.hbox.remove(self.box) From warner at users.sourceforge.net Tue Jan 23 08:01:47 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 08:01:47 +0000 Subject: [Buildbot-commits] buildbot/buildbot/process builder.py,1.42,1.43 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/process In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv20644/buildbot/process Modified Files: builder.py Log Message: [project @ buildbot/process/builder.py: don't use 'with', since it will be a reserved word in python2.6] Original author: warner at lothar.com Date: 2007-01-23 07:57:27 Index: builder.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/process/builder.py,v retrieving revision 1.42 retrieving revision 1.43 diff -u -d -r1.42 -r1.43 --- builder.py 12 Dec 2006 03:24:03 -0000 1.42 +++ builder.py 23 Jan 2007 08:01:45 -0000 1.43 @@ -380,13 +380,13 @@ return # all done - def fireTestEvent(self, name, with=None): - if with is None: - with = self + def fireTestEvent(self, name, fire_with=None): + if fire_with is None: + fire_with = self watchers = self.watchers[name] self.watchers[name] = [] for w in watchers: - reactor.callLater(0, w.callback, with) + reactor.callLater(0, w.callback, fire_with) def attached(self, slave, remote, commands): """This is invoked by the BotPerspective when the self.slavename bot From warner at users.sourceforge.net Tue Jan 23 08:01:47 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 08:01:47 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.825,1.826 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv20644 Modified Files: ChangeLog Log Message: [project @ buildbot/process/builder.py: don't use 'with', since it will be a reserved word in python2.6] Original author: warner at lothar.com Date: 2007-01-23 07:57:27 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.825 retrieving revision 1.826 diff -u -d -r1.825 -r1.826 --- ChangeLog 23 Jan 2007 07:19:56 -0000 1.825 +++ ChangeLog 23 Jan 2007 08:01:44 -0000 1.826 @@ -1,5 +1,8 @@ 2007-01-22 Brian Warner + * buildbot/process/builder.py (Builder.fireTestEvent): don't use + 'with', it will become a reserved work in python2.6 . + * contrib/bb_applet.py: add a simple gnome-panel applet, to display a terse summary of buildbot status. * docs/hexnut32.png, docs/hexnut48.png, docs/hexnut64.png: add From warner at users.sourceforge.net Tue Jan 23 19:24:13 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 19:24:13 +0000 Subject: [Buildbot-commits] buildbot/buildbot/slave commands.py,1.76,1.77 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/slave In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv9314/buildbot/slave Modified Files: commands.py Log Message: [project @ bump command_version to indicate bzr support] Original author: warner at lothar.com Date: 2007-01-23 19:23:31 Index: commands.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/slave/commands.py,v retrieving revision 1.76 retrieving revision 1.77 diff -u -d -r1.76 -r1.77 --- commands.py 23 Jan 2007 05:49:58 -0000 1.76 +++ commands.py 23 Jan 2007 19:24:11 -0000 1.77 @@ -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.2" +command_version = "2.3" # version history: # >=1.17: commands are interruptable @@ -34,6 +34,7 @@ # keepStdinOpen=) and no longer accepts stdin=) # (release 0.7.4) # >= 2.2: added monotone, uploadFile, and downloadFile (release 0.7.5) +# >= 2.3: added bzr class CommandInterrupted(Exception): pass From warner at users.sourceforge.net Tue Jan 23 19:24:13 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 19:24:13 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.826,1.827 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv9314 Modified Files: ChangeLog Log Message: [project @ bump command_version to indicate bzr support] Original author: warner at lothar.com Date: 2007-01-23 19:23:31 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.826 retrieving revision 1.827 diff -u -d -r1.826 -r1.827 --- ChangeLog 23 Jan 2007 08:01:44 -0000 1.826 +++ ChangeLog 23 Jan 2007 19:24:10 -0000 1.827 @@ -1,3 +1,8 @@ +2007-01-23 Brian Warner + + * buildbot/slave/commands.py (command_version): bump to "2.3" to + indicate that the buildslave knows about the 'bzr' command + 2007-01-22 Brian Warner * buildbot/process/builder.py (Builder.fireTestEvent): don't use From warner at users.sourceforge.net Tue Jan 23 21:04:34 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 21:04:34 +0000 Subject: [Buildbot-commits] buildbot/buildbot scheduler.py,1.24,1.25 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15423/buildbot Modified Files: scheduler.py Log Message: [project @ clean up maildir usage, remove a use of reactor.iterate from tests] Original author: warner at lothar.com Date: 2007-01-23 21:02:10 Index: scheduler.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/scheduler.py,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- scheduler.py 11 Dec 2006 09:06:34 -0000 1.24 +++ scheduler.py 23 Jan 2007 21:04:32 -0000 1.25 @@ -13,7 +13,7 @@ from buildbot import interfaces, buildset, util, pbutil from buildbot.status import builder from buildbot.sourcestamp import SourceStamp -from buildbot.changes import maildirtwisted +from buildbot.changes.maildir import MaildirService class BaseScheduler(service.MultiService, util.ComparableMixin): @@ -550,7 +550,7 @@ def __init__(self, name, builderNames, jobdir): TryBase.__init__(self, name, builderNames) self.jobdir = jobdir - self.watcher = maildirtwisted.MaildirService() + self.watcher = MaildirService() self.watcher.setServiceParent(self) def setServiceParent(self, parent): From warner at users.sourceforge.net Tue Jan 23 21:04:34 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 21:04:34 +0000 Subject: [Buildbot-commits] buildbot/buildbot/changes mail.py, 1.23, 1.24 maildir.py, 1.8, 1.9 maildirgtk.py, 1.1, NONE maildirtwisted.py, 1.3, NONE Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/changes In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15423/buildbot/changes Modified Files: mail.py maildir.py Removed Files: maildirgtk.py maildirtwisted.py Log Message: [project @ clean up maildir usage, remove a use of reactor.iterate from tests] Original author: warner at lothar.com Date: 2007-01-23 21:02:10 Index: mail.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/mail.py,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- mail.py 11 Dec 2006 09:06:34 -0000 1.23 +++ mail.py 23 Jan 2007 21:04:32 -0000 1.24 @@ -6,8 +6,11 @@ import os, re from rfc822 import Message +from zope.interface import implements from buildbot import util -from buildbot.changes import base, changes, maildirtwisted +from buildbot.interfaces import IChangeSource +from buildbot.changes import changes +from buildbot.changes.maildir import MaildirService def parseFreshCVSMail(self, fd, prefix=None, sep="/"): """Parse mail sent by FreshCVS""" @@ -294,16 +297,18 @@ -class MaildirSource(maildirtwisted.MaildirTwisted, base.ChangeSource): +class MaildirSource(MaildirService, util.ComparableMixin): """This source will watch a maildir that is subscribed to a FreshCVS change-announcement mailing list. """ - compare_attrs = ["basedir", "newdir", "pollinterval", "parser"] + implements(IChangeSource) + + compare_attrs = ["basedir", "pollinterval", "parser"] parser = None name = None def __init__(self, maildir, prefix=None, sep="/"): - maildirtwisted.MaildirTwisted.__init__(self, maildir) + MaildirService.__init__(self, maildir) self.prefix = prefix self.sep = sep Index: maildir.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/maildir.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- maildir.py 6 Sep 2006 00:41:54 -0000 1.8 +++ maildir.py 23 Jan 2007 21:04:32 -0000 1.9 @@ -3,80 +3,94 @@ # This is a class which watches a maildir for new messages. It uses the # linux dirwatcher API (if available) to look for new files. The # .messageReceived method is invoked with the filename of the new message, -# relative to the 'new' directory of the maildir. - -# this is an abstract base class. It must be subclassed by something to -# provide a delay function (which polls in the case that DNotify isn't -# available) and a way to safely schedule code to run after a signal handler -# has fired. See maildirgtk.py and maildirtwisted.py for forms that use the -# event loops provided by Gtk+ and Twisted. +# relative to the top of the maildir (so it will look like "new/blahblah"). +import os +from twisted.python import log +from twisted.application import service, internet +from twisted.internet import reactor +dnotify = None try: - from dnotify import DNotify - have_dnotify = 1 + import dnotify except: - have_dnotify = 0 -import os + # I'm not actually sure this log message gets recorded + log.msg("unable to import dnotify, so Maildir will use polling instead") -class Maildir: - """This is a class which watches a maildir for new messages. Once - started, it will run its .messageReceived method when a message is - available. +class NoSuchMaildir(Exception): + pass + +class MaildirService(service.MultiService): + """I watch a maildir for new messages. I should be placed as the service + child of some MultiService instance. When running, I use the linux + dirwatcher API (if available) or poll for new files in the 'new' + subdirectory of my maildir path. When I discover a new message, I invoke + my .messageReceived() method with the short filename of the new message, + so the full name of the new file can be obtained with + os.path.join(maildir, 'new', filename). messageReceived() should be + overridden by a subclass to do something useful. I will not move or + delete the file on my own: the subclass's messageReceived() should + probably do that. """ + pollinterval = 10 # only used if we don't have DNotify + def __init__(self, basedir=None): """Create the Maildir watcher. BASEDIR is the maildir directory (the one which contains new/ and tmp/) """ + service.MultiService.__init__(self) self.basedir = basedir self.files = [] - self.pollinterval = 10 # only used if we don't have DNotify - self.running = 0 self.dnotify = None def setBasedir(self, basedir): + # some users of MaildirService (scheduler.Try_Jobdir, in particular) + # don't know their basedir until setServiceParent, since it is + # relative to the buildmaster's basedir. So let them set it late. We + # don't actually need it until our own startService. self.basedir = basedir - def start(self): - """You must run start to receive any messages.""" - assert self.basedir + def startService(self): + service.MultiService.startService(self) self.newdir = os.path.join(self.basedir, "new") - if self.running: - return - self.running = 1 if not os.path.isdir(self.basedir) or not os.path.isdir(self.newdir): - raise "invalid maildir '%s'" % self.basedir - # we must hold an fd open on the directory, so we can get notified - # when it changes. - global have_dnotify - if have_dnotify: - try: - self.dnotify = DNotify(self.newdir, self.dnotify_callback, - [DNotify.DN_CREATE]) - except (IOError, OverflowError): - # IOError is probably linux<2.4.19, which doesn't support - # dnotify. OverflowError will occur on some 64-bit machines - # because of a python bug - print "DNotify failed, falling back to polling" - have_dnotify = 0 - + raise NoSuchMaildir("invalid maildir '%s'" % self.basedir) + try: + if dnotify: + # we must hold an fd open on the directory, so we can get + # notified when it changes. + self.dnotify = dnotify.DNotify(self.newdir, + self.dnotify_callback, + [dnotify.DNotify.DN_CREATE]) + except (IOError, OverflowError): + # IOError is probably linux<2.4.19, which doesn't support + # dnotify. OverflowError will occur on some 64-bit machines + # because of a python bug + log.msg("DNotify failed, falling back to polling") + if not self.dnotify: + t = internet.TimerService(self.pollinterval, self.poll) + t.setServiceParent(self) self.poll() - def startTimeout(self): - raise NotImplemented - def stopTimeout(self): - raise NotImplemented def dnotify_callback(self): - print "callback" - self.poll() - raise NotImplemented - - def stop(self): + log.msg("dnotify noticed something, now polling") + + # give it a moment. I found that qmail had problems when the message + # was removed from the maildir instantly. It shouldn't, that's what + # maildirs are made for. I wasn't able to eyeball any reason for the + # problem, and safecat didn't behave the same way, but qmail reports + # "Temporary_error_on_maildir_delivery" (qmail-local.c:165, + # maildir_child() process exited with rc not in 0,2,3,4). Not sure + # why, and I'd have to hack qmail to investigate further, so it's + # easier to just wait a second before yanking the message out of new/ + + reactor.callLater(0.1, self.poll) + + + def stopService(self): if self.dnotify: self.dnotify.remove() self.dnotify = None - else: - self.stopTimeout() - self.running = 0 + return service.MultiService.stopService(self) def poll(self): assert self.basedir @@ -94,22 +108,10 @@ for n in newfiles: # TODO: consider catching exceptions in messageReceived self.messageReceived(n) - if not have_dnotify: - self.startTimeout() def messageReceived(self, filename): - """Called when a new file is noticed. Override it in subclasses. - Will receive path relative to maildir/new.""" - print filename - + """Called when a new file is noticed. Will call + self.parent.messageReceived() with a path relative to maildir/new. + Should probably be overridden in subclasses.""" + self.parent.messageReceived(filename) -def test1(): - m = Maildir("ddir") - m.start() - import signal - while 1: - signal.pause() - -if __name__ == '__main__': - test1() - --- maildirgtk.py DELETED --- --- maildirtwisted.py DELETED --- From warner at users.sourceforge.net Tue Jan 23 21:04:35 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 21:04:35 +0000 Subject: [Buildbot-commits] buildbot/buildbot/test test_maildir.py,1.5,1.6 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/test In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15423/buildbot/test Modified Files: test_maildir.py Log Message: [project @ clean up maildir usage, remove a use of reactor.iterate from tests] Original author: warner at lothar.com Date: 2007-01-23 21:02:10 Index: test_maildir.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/test/test_maildir.py,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- test_maildir.py 13 Mar 2006 05:48:35 -0000 1.5 +++ test_maildir.py 23 Jan 2007 21:04:32 -0000 1.6 @@ -3,43 +3,48 @@ from twisted.trial import unittest import os, shutil from buildbot.changes.mail import FCMaildirSource -from twisted.internet import reactor -from twisted.python import util +from twisted.internet import defer, reactor, task +from twisted.python import util, log + +class TimeOutError(Exception): + """The message were not received in a timely fashion""" class MaildirTest(unittest.TestCase): + SECONDS_PER_MESSAGE = 1.0 + def setUp(self): - print "creating empty maildir" + log.msg("creating empty maildir") self.maildir = "test-maildir" if os.path.isdir(self.maildir): shutil.rmtree(self.maildir) - print "removing stale maildir" + log.msg("removing stale maildir") os.mkdir(self.maildir) os.mkdir(os.path.join(self.maildir, "cur")) os.mkdir(os.path.join(self.maildir, "new")) os.mkdir(os.path.join(self.maildir, "tmp")) self.source = None - self.done = 0 def tearDown(self): - print "removing old maildir" + log.msg("removing old maildir") shutil.rmtree(self.maildir) if self.source: - self.source.stopService() + return self.source.stopService() def addChange(self, c): # NOTE: this assumes every message results in a Change, which isn't # true for msg8-prefix - print "got change" + log.msg("got change") self.changes.append(c) def deliverMail(self, msg): - print "delivering", msg + log.msg("delivering", msg) newdir = os.path.join(self.maildir, "new") # to do this right, use safecat shutil.copy(msg, newdir) - def do_timeout(self): - self.done = 1 + def poll(self, changes, count, d): + if len(changes) == count: + d.callback("passed") def testMaildir(self): self.changes = [] @@ -51,29 +56,35 @@ if msg.startswith("msg")] testfiles.sort() count = len(testfiles) + d = defer.Deferred() + for i in range(count): msg = testfiles[i] - reactor.callLater(2*i, self.deliverMail, + reactor.callLater(self.SECONDS_PER_MESSAGE*i, self.deliverMail, os.path.join(testfiles_dir, msg)) - t = reactor.callLater(2*i + 15, self.do_timeout) - while not (self.done or len(self.changes) == count): - reactor.iterate(0.1) - s.stopService() - if self.done: - return self.fail("timeout: messages weren't received on time") - t.cancel() + self.loop = task.LoopingCall(self.poll, self.changes, count, d) + self.loop.start(0.1) + t = reactor.callLater(self.SECONDS_PER_MESSAGE*i + 15, + d.errback, TimeOutError) # TODO: verify the messages, should use code from test_mailparse but # I'm not sure how to factor the verification routines out in a # useful fashion + #for i in range(count): # msg, check = test_messages[i] # check(self, self.changes[i]) - -if __name__ == '__main__': - suite = unittest.TestSuite() - suite.addTestClass(MaildirTest) - import sys - reporter = unittest.TextReporter(sys.stdout) - suite.run(reporter) - + def _shutdown(res): + if t.active(): + t.cancel() + self.loop.stop() + return res + d.addBoth(_shutdown) + + return d + + # TODO: it would be nice to set this timeout after counting the number of + # messages in buildbot/test/mail/msg*, but I suspect trial wants to have + # this number before the method starts, and maybe even before setUp() + testMaildir.timeout = SECONDS_PER_MESSAGE*9 + 15 + From warner at users.sourceforge.net Tue Jan 23 21:04:34 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 21:04:34 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.827,1.828 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15423 Modified Files: ChangeLog Log Message: [project @ clean up maildir usage, remove a use of reactor.iterate from tests] Original author: warner at lothar.com Date: 2007-01-23 21:02:10 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.827 retrieving revision 1.828 diff -u -d -r1.827 -r1.828 --- ChangeLog 23 Jan 2007 19:24:10 -0000 1.827 +++ ChangeLog 23 Jan 2007 21:04:31 -0000 1.828 @@ -1,5 +1,14 @@ 2007-01-23 Brian Warner + * buildbot/changes/maildir.py: combine several files into one, + clean up maildir.py to use Services properly. + * buildbot/changes/maildirtwisted.py: remove + * buildbot/changes/maildirgtk.py: remove, it wasn't used by + buildbot anyways. + * buildbot/changes/mail.py: match the change + * buildbot/scheduler.py: same, since Try_Jobdir uses a maildir + * buildbot/test/test_maildir.py: remove use of reactor.iterate() + * buildbot/slave/commands.py (command_version): bump to "2.3" to indicate that the buildslave knows about the 'bzr' command From warner at users.sourceforge.net Tue Jan 23 21:04:42 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 21:04:42 +0000 Subject: [Buildbot-commits] buildbot/buildbot/changes freshcvsmail.py, 1.4, 1.5 monotone.py, 1.1, 1.2 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/changes In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15455/buildbot/changes Modified Files: freshcvsmail.py monotone.py Log Message: [project @ hush some pyflakes warnings] Original author: warner at lothar.com Date: 2007-01-23 21:03:46 Index: freshcvsmail.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/freshcvsmail.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- freshcvsmail.py 12 Dec 2006 03:44:37 -0000 1.4 +++ freshcvsmail.py 23 Jan 2007 21:04:40 -0000 1.5 @@ -8,3 +8,5 @@ DeprecationWarning) from buildbot.changes.mail import FCMaildirSource + +hush_pyflakes = FCMaildirSource Index: monotone.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/monotone.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- monotone.py 25 Sep 2006 07:46:56 -0000 1.1 +++ monotone.py 23 Jan 2007 21:04:40 -0000 1.2 @@ -1,7 +1,6 @@ import tempfile import os -import os.path from cStringIO import StringIO from twisted.python import log From warner at users.sourceforge.net Tue Jan 23 21:04:42 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Tue, 23 Jan 2007 21:04:42 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.828,1.829 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15455 Modified Files: ChangeLog Log Message: [project @ hush some pyflakes warnings] Original author: warner at lothar.com Date: 2007-01-23 21:03:46 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.828 retrieving revision 1.829 diff -u -d -r1.828 -r1.829 --- ChangeLog 23 Jan 2007 21:04:31 -0000 1.828 +++ ChangeLog 23 Jan 2007 21:04:40 -0000 1.829 @@ -1,5 +1,8 @@ 2007-01-23 Brian Warner + * buildbot/changes/freshcvsmail.py: hush a pyflakes warning + * buildbot/changes/monotone.py: same + * buildbot/changes/maildir.py: combine several files into one, clean up maildir.py to use Services properly. * buildbot/changes/maildirtwisted.py: remove From warner at users.sourceforge.net Sat Jan 27 21:14:14 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Sat, 27 Jan 2007 21:14:14 +0000 Subject: [Buildbot-commits] buildbot ChangeLog, 1.829, 1.830 Makefile, 1.21, 1.22 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv12821 Modified Files: ChangeLog Makefile Log Message: [project @ produce both .tar.gz and .zip source bundles. Closes SF#1222216] Original author: warner at lothar.com Date: 2007-01-27 21:13:30 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.829 retrieving revision 1.830 diff -u -d -r1.829 -r1.830 --- ChangeLog 23 Jan 2007 21:04:40 -0000 1.829 +++ ChangeLog 27 Jan 2007 21:14:12 -0000 1.830 @@ -1,3 +1,8 @@ +2007-01-27 Brian Warner + + * Makefile (release): produce both .tar.gz and .zip source bundles. + Closes SF#1222216. + 2007-01-23 Brian Warner * buildbot/changes/freshcvsmail.py: hush a pyflakes warning Index: Makefile =================================================================== RCS file: /cvsroot/buildbot/buildbot/Makefile,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- Makefile 6 Sep 2006 00:41:54 -0000 1.21 +++ Makefile 27 Jan 2007 21:14:12 -0000 1.22 @@ -50,7 +50,7 @@ rm -rf _trial_temp python ./setup.py clean rm -f MANIFEST - python ./setup.py sdist + python ./setup.py sdist --formats gztar,zip FLAKES=buildbot pyflakes: From warner at users.sourceforge.net Wed Jan 31 00:46:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Wed, 31 Jan 2007 00:46:00 +0000 Subject: [Buildbot-commits] buildbot/buildbot/changes bonsaipoller.py, 1.4, 1.5 Message-ID: Update of /cvsroot/buildbot/buildbot/buildbot/changes In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv26939/buildbot/changes Modified Files: bonsaipoller.py Log Message: [project @ BonsaiPoller: handle non-ascii characters. Patch from Ben Hearsum, closes SF#1632641] Original author: warner at lothar.com Date: 2007-01-31 00:43:15 Index: bonsaipoller.py =================================================================== RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/bonsaipoller.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- bonsaipoller.py 12 Dec 2006 03:24:03 -0000 1.4 +++ bonsaipoller.py 31 Jan 2007 00:45:58 -0000 1.5 @@ -66,7 +66,16 @@ def __init__(self, bonsaiQuery): try: - self.dom = minidom.parse(bonsaiQuery) + # this is a fix for non-ascii characters + # readlines() + join is being used because read() is not guaranteed + # to work. because bonsai does not give us an encoding to work with + # it impossible to be 100% sure what to decode it as but latin1 covers + # the broadest base + data = "".join(bonsaiQuery.readlines()) + data = data.decode("latin1") + data = data.encode("ascii", "replace") + self.dom = minidom.parseString(data) + log.msg(data) except: raise InvalidResultError("Malformed XML in result") From warner at users.sourceforge.net Wed Jan 31 00:46:00 2007 From: warner at users.sourceforge.net (Brian Warner) Date: Wed, 31 Jan 2007 00:46:00 +0000 Subject: [Buildbot-commits] buildbot ChangeLog,1.830,1.831 Message-ID: Update of /cvsroot/buildbot/buildbot In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv26939 Modified Files: ChangeLog Log Message: [project @ BonsaiPoller: handle non-ascii characters. Patch from Ben Hearsum, closes SF#1632641] Original author: warner at lothar.com Date: 2007-01-31 00:43:15 Index: ChangeLog =================================================================== RCS file: /cvsroot/buildbot/buildbot/ChangeLog,v retrieving revision 1.830 retrieving revision 1.831 diff -u -d -r1.830 -r1.831 --- ChangeLog 27 Jan 2007 21:14:12 -0000 1.830 +++ ChangeLog 31 Jan 2007 00:45:57 -0000 1.831 @@ -1,3 +1,9 @@ +2007-01-30 Brian Warner + + * buildbot/changes/bonsaipoller.py (BonsaiParser.__init__): Ben + Hearsum contributed a patch to let BonsaiPoller work with results + that contain non-ascii characters. Closes SF#1632641. + 2007-01-27 Brian Warner * Makefile (release): produce both .tar.gz and .zip source bundles.