diff options
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/clients/tryclient.py')
-rw-r--r-- | lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/clients/tryclient.py | 891 |
1 files changed, 0 insertions, 891 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/clients/tryclient.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/clients/tryclient.py deleted file mode 100644 index d48f8088..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/clients/tryclient.py +++ /dev/null @@ -1,891 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -from __future__ import with_statement - - -import os -import random -import re -import sys -import time - -from twisted.cred import credentials -from twisted.internet import defer -from twisted.internet import protocol -from twisted.internet import reactor -from twisted.internet import task -from twisted.internet import utils -from twisted.python import log -from twisted.python.procutils import which -from twisted.spread import pb - -from buildbot.sourcestamp import SourceStamp -from buildbot.status import builder -from buildbot.util import json -from buildbot.util import now -from buildbot.util.eventual import fireEventually - - -class SourceStampExtractor: - - def __init__(self, treetop, branch, repository): - self.treetop = treetop - self.repository = repository - self.branch = branch - exes = which(self.vcexe) - if not exes: - print "Could not find executable '%s'." % self.vcexe - sys.exit(1) - self.exe = exes[0] - - def dovc(self, cmd): - """This accepts the arguments of a command, without the actual - command itself.""" - env = os.environ.copy() - env['LC_ALL'] = "C" - 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. - # cvs does something similar, so don't bother requring rc=0. - return stdout - - def get(self): - """Return a Deferred that fires with a SourceStamp instance.""" - d = self.getBaseRevision() - d.addCallback(self.getPatch) - d.addCallback(self.done) - return d - - def readPatch(self, diff, patchlevel): - if not diff: - diff = None - self.patch = (patchlevel, diff) - - def done(self, res): - if not self.repository: - self.repository = self.treetop - # TODO: figure out the branch and project too - ss = SourceStamp(self.branch, self.baserev, self.patch, - repository=self.repository) - return ss - - -class CVSExtractor(SourceStampExtractor): - patchlevel = 0 - vcexe = "cvs" - - def getBaseRevision(self): - # this depends upon our local clock and the repository's clock being - # reasonably synchronized with each other. We express everything in - # UTC because the '%z' format specifier for strftime doesn't always - # work. - self.baserev = time.strftime("%Y-%m-%d %H:%M:%S +0000", - time.gmtime(now())) - return defer.succeed(None) - - def getPatch(self, res): - # the -q tells CVS to not announce each directory as it works - if self.branch is not None: - # 'cvs diff' won't take both -r and -D at the same time (it - # ignores the -r). As best I can tell, there is no way to make - # cvs give you a diff relative to a timestamp on the non-trunk - # branch. A bare 'cvs diff' will tell you about the changes - # relative to your checked-out versions, but I know of no way to - # find out what those checked-out versions are. - print "Sorry, CVS 'try' builds don't work with branches" - sys.exit(1) - args = ['-q', 'diff', '-u', '-D', self.baserev] - d = self.dovc(args) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class SVNExtractor(SourceStampExtractor): - patchlevel = 0 - vcexe = "svn" - - def getBaseRevision(self): - d = self.dovc(["status", "-u"]) - d.addCallback(self.parseStatus) - return d - - def parseStatus(self, res): - # svn shows the base revision for each file that has been modified or - # which needs an update. You can update each file to a different - # version, so each file is displayed with its individual base - # revision. It also shows the repository-wide latest revision number - # on the last line ("Status against revision: \d+"). - - # for our purposes, we use the latest revision number as the "base" - # revision, and get a diff against that. This means we will get - # reverse-diffs for local files that need updating, but the resulting - # tree will still be correct. The only weirdness is that the baserev - # that we emit may be different than the version of the tree that we - # first checked out. - - # to do this differently would probably involve scanning the revision - # numbers to find the max (or perhaps the min) revision, and then - # using that as a base. - - for line in res.split("\n"): - m = re.search(r'^Status against revision:\s+(\d+)', line) - if m: - self.baserev = int(m.group(1)) - return - print "Could not find 'Status against revision' in SVN output: %s" % res - sys.exit(1) - - def getPatch(self, res): - d = self.dovc(["diff", "-r%d" % self.baserev]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class BzrExtractor(SourceStampExtractor): - patchlevel = 0 - vcexe = "bzr" - - def getBaseRevision(self): - d = self.dovc(["revision-info", "-rsubmit:"]) - d.addCallback(self.get_revision_number) - return d - - def get_revision_number(self, out): - revno, revid = out.split() - self.baserev = 'revid:' + revid - return - - def getPatch(self, res): - d = self.dovc(["diff", "-r%s.." % self.baserev]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class MercurialExtractor(SourceStampExtractor): - patchlevel = 1 - vcexe = "hg" - - def getBaseRevision(self): - upstream = "" - if self.repository: - upstream = "r'%s'" % self.repository - d = self.dovc(["log", "--template", "{node}\\n", "-r", "limit(parents(outgoing(%s) and branch(parents())) or parents(), 1)" % upstream]) - d.addCallback(self.parseStatus) - return d - - def parseStatus(self, output): - m = re.search(r'^(\w+)', output) - self.baserev = m.group(0) - - def getPatch(self, res): - d = self.dovc(["diff", "-r", self.baserev]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class PerforceExtractor(SourceStampExtractor): - patchlevel = 0 - vcexe = "p4" - - def getBaseRevision(self): - d = self.dovc(["changes", "-m1", "..."]) - d.addCallback(self.parseStatus) - return d - - def parseStatus(self, res): - # - # extract the base change number - # - m = re.search(r'Change (\d+)', res) - if m: - self.baserev = m.group(1) - return - - print "Could not find change number in output: %s" % res - sys.exit(1) - - def readPatch(self, res, patchlevel): - # - # extract the actual patch from "res" - # - if not self.branch: - print "you must specify a branch" - sys.exit(1) - mpatch = "" - found = False - for line in res.split("\n"): - m = re.search('==== //depot/' + self.branch - + r'/([\w\/\.\d\-\_]+)#(\d+) -', line) - if m: - mpatch += "--- %s#%s\n" % (m.group(1), m.group(2)) - mpatch += "+++ %s\n" % (m.group(1)) - found = True - else: - mpatch += line - mpatch += "\n" - if not found: - print "could not parse patch file" - sys.exit(1) - self.patch = (patchlevel, mpatch) - - def getPatch(self, res): - d = self.dovc(["diff"]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class DarcsExtractor(SourceStampExtractor): - patchlevel = 1 - vcexe = "darcs" - - def getBaseRevision(self): - d = self.dovc(["changes", "--context"]) - d.addCallback(self.parseStatus) - return d - - def parseStatus(self, res): - self.baserev = res # the whole context file - - def getPatch(self, res): - d = self.dovc(["diff", "-u"]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class GitExtractor(SourceStampExtractor): - patchlevel = 1 - vcexe = "git" - config = None - - def getBaseRevision(self): - # If a branch is specified, parse out the rev it points to - # and extract the local name (assuming it has a slash). - # This may break if someone specifies the name of a local - # branch that has a slash in it and has no corresponding - # remote branch (or something similarly contrived). - if self.branch: - d = self.dovc(["rev-parse", self.branch]) - if '/' in self.branch: - self.branch = self.branch.split('/', 1)[1] - d.addCallback(self.override_baserev) - return d - d = self.dovc(["branch", "--no-color", "-v", "--no-abbrev"]) - d.addCallback(self.parseStatus) - return d - - def readConfig(self): - if self.config: - return defer.succeed(self.config) - d = self.dovc(["config", "-l"]) - d.addCallback(self.parseConfig) - return d - - def parseConfig(self, res): - self.config = {} - for l in res.split("\n"): - if l.strip(): - parts = l.strip().split("=", 2) - self.config[parts[0]] = parts[1] - return self.config - - def parseTrackingBranch(self, res): - # If we're tracking a remote, consider that the base. - remote = self.config.get("branch." + self.branch + ".remote") - ref = self.config.get("branch." + self.branch + ".merge") - if remote and ref: - remote_branch = ref.split("/", 3)[-1] - d = self.dovc(["rev-parse", remote + "/" + remote_branch]) - d.addCallback(self.override_baserev) - return d - - def override_baserev(self, res): - self.baserev = res.strip() - - 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.baserev = m.group(2) - self.branch = m.group(1) - d = self.readConfig() - d.addCallback(self.parseTrackingBranch) - return d - print "Could not find current GIT branch: %s" % res - sys.exit(1) - - def getPatch(self, res): - d = self.dovc(["diff", self.baserev]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -class MonotoneExtractor(SourceStampExtractor): - patchlevel = 0 - vcexe = "mtn" - - def getBaseRevision(self): - d = self.dovc(["automate", "get_base_revision_id"]) - d.addCallback(self.parseStatus) - return d - - def parseStatus(self, output): - hash = output.strip() - if len(hash) != 40: - self.baserev = None - self.baserev = hash - - def getPatch(self, res): - d = self.dovc(["diff"]) - d.addCallback(self.readPatch, self.patchlevel) - return d - - -def getSourceStamp(vctype, treetop, branch=None, repository=None): - if vctype == "cvs": - cls = CVSExtractor - elif vctype == "svn": - cls = SVNExtractor - elif vctype == "bzr": - cls = BzrExtractor - elif vctype == "hg": - cls = MercurialExtractor - elif vctype == "p4": - cls = PerforceExtractor - elif vctype == "darcs": - cls = DarcsExtractor - elif vctype == "git": - cls = GitExtractor - elif vctype == "mtn": - cls = MonotoneExtractor - else: - print "unknown vctype '%s'" % vctype - sys.exit(1) - return cls(treetop, branch, repository).get() - - -def ns(s): - return "%d:%s," % (len(s), s) - - -def createJobfile(jobid, branch, baserev, patch_level, patch_body, repository, - project, who, comment, builderNames, properties): - #Determine job file version from provided arguments - if properties: - version = 5 - elif comment: - version = 4 - elif who: - version = 3 - else: - version = 2 - job = "" - job += ns(str(version)) - if version < 5: - job += ns(jobid) - job += ns(branch) - job += ns(str(baserev)) - job += ns("%d" % patch_level) - job += ns(patch_body) - job += ns(repository) - job += ns(project) - if (version >= 3): - job += ns(who) - if (version >= 4): - job += ns(comment) - for bn in builderNames: - job += ns(bn) - else: - job += ns( - json.dumps({ - 'jobid': jobid, 'branch': branch, 'baserev': str(baserev), - 'patch_level': patch_level, 'patch_body': patch_body, - 'repository': repository, 'project': project, 'who': who, - 'comment': comment, 'builderNames': builderNames, - 'properties': properties, - })) - return job - - -def getTopdir(topfile, start=None): - """walk upwards from the current directory until we find this topfile""" - if not start: - start = os.getcwd() - here = start - toomany = 20 - while toomany > 0: - if os.path.exists(os.path.join(here, topfile)): - return here - next = os.path.dirname(here) - if next == here: - break # we've hit the root - here = next - toomany -= 1 - print ("Unable to find topfile '%s' anywhere from %s upwards" - % (topfile, start)) - sys.exit(1) - - -class RemoteTryPP(protocol.ProcessProtocol): - def __init__(self, job): - self.job = job - self.d = defer.Deferred() - - def connectionMade(self): - self.transport.write(self.job) - self.transport.closeStdin() - - def outReceived(self, data): - sys.stdout.write(data) - - def errReceived(self, data): - sys.stderr.write(data) - - def processEnded(self, status_object): - sig = status_object.value.signal - rc = status_object.value.exitCode - if sig != None or rc != 0: - self.d.errback(RuntimeError("remote 'buildbot tryserver' failed" - ": sig=%s, rc=%s" % (sig, rc))) - return - self.d.callback((sig, rc)) - - -class BuildSetStatusGrabber: - retryCount = 5 # how many times to we try to grab the BuildSetStatus? - retryDelay = 3 # seconds to wait between attempts - - def __init__(self, status, bsid): - self.status = status - self.bsid = bsid - - def grab(self): - # return a Deferred that either fires with the BuildSetStatus - # reference or errbacks because we were unable to grab it - self.d = defer.Deferred() - # wait a second before querying to give the master's maildir watcher - # a chance to see the job - reactor.callLater(1, self.go) - return self.d - - def go(self, dummy=None): - if self.retryCount == 0: - print "couldn't find matching buildset" - sys.exit(1) - self.retryCount -= 1 - d = self.status.callRemote("getBuildSets") - d.addCallback(self._gotSets) - - def _gotSets(self, buildsets): - for bs, bsid in buildsets: - if bsid == self.bsid: - # got it - self.d.callback(bs) - return - d = defer.Deferred() - d.addCallback(self.go) - reactor.callLater(self.retryDelay, d.callback, None) - - -class Try(pb.Referenceable): - buildsetStatus = None - quiet = False - printloop = False - - def __init__(self, config): - self.config = config - self.connect = self.getopt('connect') - if self.connect not in ['ssh', 'pb']: - print "you must specify a connect style: ssh or pb" - sys.exit(1) - self.builderNames = self.getopt('builders') - self.project = self.getopt('project', '') - self.who = self.getopt('who') - self.comment = self.getopt('comment') - - def getopt(self, config_name, default=None): - value = self.config.get(config_name) - if value is None or value == []: - value = default - return value - - def createJob(self): - # returns a Deferred which fires when the job parameters have been - # created - - # generate a random (unique) string. It would make sense to add a - # hostname and process ID here, but a) I suspect that would cause - # windows portability problems, and b) really this is good enough - self.bsid = "%d-%s" % (time.time(), random.randint(0, 1000000)) - - # common options - branch = self.getopt("branch") - - difffile = self.config.get("diff") - if difffile: - baserev = self.config.get("baserev") - if difffile == "-": - diff = sys.stdin.read() - else: - with open(difffile, "r") as f: - diff = f.read() - if not diff: - diff = None - patch = (self.config['patchlevel'], diff) - ss = SourceStamp( - branch, baserev, patch, repository=self.getopt("repository")) - d = defer.succeed(ss) - else: - vc = self.getopt("vc") - if vc in ("cvs", "svn"): - # we need to find the tree-top - topdir = self.getopt("topdir") - if topdir: - treedir = os.path.expanduser(topdir) - else: - topfile = self.getopt("topfile") - if topfile: - treedir = getTopdir(topfile) - else: - print "Must specify topdir or topfile." - sys.exit(1) - else: - treedir = os.getcwd() - d = getSourceStamp(vc, treedir, branch, self.getopt("repository")) - d.addCallback(self._createJob_1) - return d - - def _createJob_1(self, ss): - self.sourcestamp = ss - if self.connect == "ssh": - patchlevel, diff = ss.patch - revspec = ss.revision - if revspec is None: - revspec = "" - self.jobfile = createJobfile( - self.bsid, ss.branch or "", revspec, patchlevel, diff, - ss.repository, self.project, self.who, self.comment, - self.builderNames, self.config.get('properties', {})) - - def fakeDeliverJob(self): - # Display the job to be delivered, but don't perform delivery. - ss = self.sourcestamp - print ("Job:\n\tRepository: %s\n\tProject: %s\n\tBranch: %s\n\t" - "Revision: %s\n\tBuilders: %s\n%s" - % (ss.repository, self.project, ss.branch, - ss.revision, - self.builderNames, - ss.patch[1])) - d = defer.Deferred() - d.callback(True) - return d - - def deliverJob(self): - # returns a Deferred that fires when the job has been delivered - if self.connect == "ssh": - tryhost = self.getopt("host") - tryuser = self.getopt("username") - trydir = self.getopt("jobdir") - buildbotbin = self.getopt("buildbotbin") - argv = ["ssh", "-l", tryuser, tryhost, - buildbotbin, "tryserver", "--jobdir", trydir] - pp = RemoteTryPP(self.jobfile) - reactor.spawnProcess(pp, argv[0], argv, os.environ) - d = pp.d - return d - if self.connect == "pb": - user = self.getopt("username") - passwd = self.getopt("passwd") - master = self.getopt("master") - tryhost, tryport = master.split(":") - tryport = int(tryport) - f = pb.PBClientFactory() - d = f.login(credentials.UsernamePassword(user, passwd)) - reactor.connectTCP(tryhost, tryport, f) - d.addCallback(self._deliverJob_pb) - return d - raise RuntimeError("unknown connecttype '%s', should be 'ssh' or 'pb'" - % self.connect) - - def _deliverJob_pb(self, remote): - ss = self.sourcestamp - print "Delivering job; comment=", self.comment - - d = remote.callRemote("try", - ss.branch, - ss.revision, - ss.patch, - ss.repository, - self.project, - self.builderNames, - self.who, - self.comment, - self.config.get('properties', {})) - d.addCallback(self._deliverJob_pb2) - return d - - def _deliverJob_pb2(self, status): - self.buildsetStatus = status - return status - - def getStatus(self): - # returns a Deferred that fires when the builds have finished, and - # may emit status messages while we wait - wait = bool(self.getopt("wait")) - if not wait: - # TODO: emit the URL where they can follow the builds. This - # requires contacting the Status server over PB and doing - # getURLForThing() on the BuildSetStatus. To get URLs for - # individual builds would require we wait for the builds to - # start. - print "not waiting for builds to finish" - return - d = self.running = defer.Deferred() - if self.buildsetStatus: - self._getStatus_1() - return self.running - # contact the status port - # we're probably using the ssh style - master = self.getopt("master") - host, port = master.split(":") - port = int(port) - self.announce("contacting the status port at %s:%d" % (host, port)) - f = pb.PBClientFactory() - creds = credentials.UsernamePassword("statusClient", "clientpw") - d = f.login(creds) - reactor.connectTCP(host, port, f) - d.addCallback(self._getStatus_ssh_1) - return self.running - - def _getStatus_ssh_1(self, remote): - # find a remotereference to the corresponding BuildSetStatus object - self.announce("waiting for job to be accepted") - g = BuildSetStatusGrabber(remote, self.bsid) - d = g.grab() - d.addCallback(self._getStatus_1) - return d - - def _getStatus_1(self, res=None): - if res: - self.buildsetStatus = res - # gather the set of BuildRequests - d = self.buildsetStatus.callRemote("getBuildRequests") - d.addCallback(self._getStatus_2) - - def _getStatus_2(self, brs): - self.builderNames = [] - self.buildRequests = {} - - # self.builds holds the current BuildStatus object for each one - self.builds = {} - - # self.outstanding holds the list of builderNames which haven't - # finished yet - self.outstanding = [] - - # self.results holds the list of build results. It holds a tuple of - # (result, text) - self.results = {} - - # self.currentStep holds the name of the Step that each build is - # currently running - self.currentStep = {} - - # self.ETA holds the expected finishing time (absolute time since - # epoch) - self.ETA = {} - - for n, br in brs: - self.builderNames.append(n) - self.buildRequests[n] = br - self.builds[n] = None - self.outstanding.append(n) - self.results[n] = [None, None] - self.currentStep[n] = None - self.ETA[n] = None - # get new Builds for this buildrequest. We follow each one until - # it finishes or is interrupted. - br.callRemote("subscribe", self) - - # now that those queries are in transit, we can start the - # display-status-every-30-seconds loop - if not self.getopt("quiet"): - self.printloop = task.LoopingCall(self.printStatus) - self.printloop.start(3, now=False) - - # these methods are invoked by the status objects we've subscribed to - - def remote_newbuild(self, bs, builderName): - if self.builds[builderName]: - self.builds[builderName].callRemote("unsubscribe", self) - self.builds[builderName] = bs - bs.callRemote("subscribe", self, 20) - d = bs.callRemote("waitUntilFinished") - d.addCallback(self._build_finished, builderName) - - def remote_stepStarted(self, buildername, build, stepname, step): - self.currentStep[buildername] = stepname - - def remote_stepFinished(self, buildername, build, stepname, step, results): - pass - - def remote_buildETAUpdate(self, buildername, build, eta): - self.ETA[buildername] = now() + eta - - def _build_finished(self, bs, builderName): - # we need to collect status from the newly-finished build. We don't - # remove the build from self.outstanding until we've collected - # everything we want. - self.builds[builderName] = None - self.ETA[builderName] = None - self.currentStep[builderName] = "finished" - d = bs.callRemote("getResults") - d.addCallback(self._build_finished_2, bs, builderName) - return d - - def _build_finished_2(self, results, bs, builderName): - self.results[builderName][0] = results - d = bs.callRemote("getText") - d.addCallback(self._build_finished_3, builderName) - return d - - def _build_finished_3(self, text, builderName): - self.results[builderName][1] = text - - self.outstanding.remove(builderName) - if not self.outstanding: - # all done - return self.statusDone() - - def printStatus(self): - try: - names = self.buildRequests.keys() - names.sort() - for n in names: - if n not in self.outstanding: - # the build is finished, and we have results - code, text = self.results[n] - t = builder.Results[code] - if text: - t += " (%s)" % " ".join(text) - elif self.builds[n]: - t = self.currentStep[n] or "building" - if self.ETA[n]: - t += " [ETA %ds]" % (self.ETA[n] - now()) - else: - t = "no build" - self.announce("%s: %s" % (n, t)) - self.announce("") - except Exception: - log.err(None, "printing status") - - def statusDone(self): - if self.printloop: - self.printloop.stop() - print "All Builds Complete" - # TODO: include a URL for all failing builds - names = self.buildRequests.keys() - names.sort() - happy = True - for n in names: - code, text = self.results[n] - t = "%s: %s" % (n, builder.Results[code]) - if text: - t += " (%s)" % " ".join(text) - print t - if code != builder.SUCCESS: - happy = False - - if happy: - self.exitcode = 0 - else: - self.exitcode = 1 - self.running.callback(self.exitcode) - - def getAvailableBuilderNames(self): - # This logs into the master using the PB protocol to - # get the names of the configured builders that can - # be used for the --builder argument - if self.connect == "pb": - user = self.getopt("username") - passwd = self.getopt("passwd") - master = self.getopt("master") - tryhost, tryport = master.split(":") - tryport = int(tryport) - f = pb.PBClientFactory() - d = f.login(credentials.UsernamePassword(user, passwd)) - reactor.connectTCP(tryhost, tryport, f) - d.addCallback(self._getBuilderNames, self._getBuilderNames2) - return d - if self.connect == "ssh": - print "Cannot get availble builders over ssh." - sys.exit(1) - raise RuntimeError( - "unknown connecttype '%s', should be 'pb'" % self.connect) - - def _getBuilderNames(self, remote, output): - d = remote.callRemote("getAvailableBuilderNames") - d.addCallback(self._getBuilderNames2) - return d - - def _getBuilderNames2(self, buildernames): - print "The following builders are available for the try scheduler: " - for buildername in buildernames: - print buildername - - def announce(self, message): - if not self.quiet: - print message - - def run(self): - # we can't do spawnProcess until we're inside reactor.run(), so get - # funky - print "using '%s' connect method" % self.connect - self.exitcode = 0 - d = fireEventually(None) - if bool(self.config.get("get-builder-names")): - d.addCallback(lambda res: self.getAvailableBuilderNames()) - else: - d.addCallback(lambda res: self.createJob()) - d.addCallback(lambda res: self.announce("job created")) - deliver = self.deliverJob - if bool(self.config.get("dryrun")): - deliver = self.fakeDeliverJob - d.addCallback(lambda res: deliver()) - d.addCallback(lambda res: self.announce("job has been delivered")) - d.addCallback(lambda res: self.getStatus()) - d.addErrback(self.trapSystemExit) - d.addErrback(log.err) - d.addCallback(self.cleanup) - d.addCallback(lambda res: reactor.stop()) - - reactor.run() - sys.exit(self.exitcode) - - def trapSystemExit(self, why): - why.trap(SystemExit) - self.exitcode = why.value.code - - def cleanup(self, res=None): - if self.buildsetStatus: - self.buildsetStatus.broker.transport.loseConnection() |