[Buildbot-commits] buildbot/buildbot/process step.py,1.92,1.93
Brian Warner
warner at users.sourceforge.net
Tue Jun 20 08:09:00 UTC 2006
Update of /cvsroot/buildbot/buildbot/buildbot/process
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv14657/buildbot/process
Modified Files:
step.py
Log Message:
[project @ add support for following multiple LogFiles in a ShellCommand]
Original author: warner at lothar.com
Date: 2006-06-20 04:17:18
Index: step.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/process/step.py,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -d -r1.92 -r1.93
--- step.py 16 Jun 2006 05:27:59 -0000 1.92
+++ step.py 20 Jun 2006 08:08:58 -0000 1.93
@@ -30,7 +30,7 @@
of reliably gathering status updates from the slave (acknowledging each),
and (eventually, in a future release) recovering from interrupted builds.
This is the master-side object that is known to the slave-side
- L{buildbot.slave.bot.SlaveBuilder}, to which status update are sent.
+ L{buildbot.slave.bot.SlaveBuilder}, to which status updates are sent.
My command should be started by calling .run(), which returns a
Deferred that will fire when the command has finished, or will
@@ -234,18 +234,18 @@
"""
I am a L{RemoteCommand} which gathers output from the remote command into
- one or more local log files. These L{buildbot.status.builder.Logfile}
- instances live in C{self.logs}. If the slave sends back
- stdout/stderr/header updates, these will be put into
- C{self.logs['stdio']}, if present. If the remote command uses other log
- channels, they will go into other entries in C{self.logs}.
+ one or more local log files. My C{self.logs} dictionary contains
+ references to these L{buildbot.status.builder.LogFile} instances. Any
+ stdout/stderr/header updates from the slave will be put into
+ C{self.logs['stdio']}, if it exists. If the remote command uses other log
+ files, they will go into other entries in C{self.logs}.
- If you want to use stdout, you should create a LogFile named 'stdio' and
- pass it to my useLog() message. Otherwise stdout/stderr will be ignored,
- which is probably not what you want.
+ If you want to use stdout or stderr, you should create a LogFile named
+ 'stdio' and pass it to my useLog() message. Otherwise stdout/stderr will
+ be ignored, which is probably not what you want.
- Unless you tell me otherwise, I will close all logs when the command is
- complete.
+ Unless you tell me otherwise, when my command completes I will close all
+ the LogFiles that I know about.
@ivar logs: maps logname to a LogFile instance
@ivar _closeWhenFinished: maps logname to a boolean. If true, this
@@ -292,21 +292,34 @@
if 'stdio' in self.logs:
self.logs['stdio'].addHeader(data)
+ def addToLog(self, logname, data):
+ if logname in self.logs:
+ self.logs[logname].addStdout(data)
+ else:
+ log.msg("%s.addToLog: no such log %s" % (self, logname))
+
def remoteUpdate(self, update):
if self.debug:
for k,v in update.items():
log.msg("Update[%s]: %s" % (k,v))
if update.has_key('stdout'):
+ # 'stdout': data
self.addStdout(update['stdout'])
if update.has_key('stderr'):
+ # 'stderr': data
self.addStderr(update['stderr'])
if update.has_key('header'):
+ # 'header': data
self.addHeader(update['header'])
+ if update.has_key('log'):
+ # 'log': (logname, data)
+ logname, data = update['log']
+ self.addToLog(logname, data)
if update.has_key('rc'):
rc = self.rc = update['rc']
log.msg("%s rc=%s" % (self, rc))
self.addHeader("program finished with exit code %d\n" % rc)
- # TODO: other log channels
+
for k in update:
if k not in ('stdout', 'stderr', 'header', 'rc'):
if k not in self.updates:
@@ -394,7 +407,7 @@
def __init__(self, workdir, command, env=None,
want_stdout=1, want_stderr=1,
- timeout=20*60, **kwargs):
+ timeout=20*60, logfiles={}, **kwargs):
"""
@type workdir: string
@param workdir: directory where the command ought to run,
@@ -434,6 +447,7 @@
the command is hung and should be killed. Use
None to disable the timeout.
"""
+
self.command = command # stash .command, set it later
if env is not None:
# avoid mutating the original master.cfg dictionary. Each
@@ -485,7 +499,7 @@
C{self.step_status}. It can also feed progress data (like how much text
is output by a shell command) to the
L{buildbot.status.progress.StepProgress} object that lives in
- C{self.progress}, by calling C{progress.setProgress(metric, value)} as it
+ C{self.progress}, by calling C{self.setProgress(metric, value)} as it
runs.
@type build: L{buildbot.process.base.Build}
@@ -834,8 +848,9 @@
class LoggingBuildStep(BuildStep):
- # This is an abstract base class, suitable for inheritance by all
- # BuildSteps that invoke RemoteCommands which emit stdout/stderr messages
+ """This is an abstract base class, suitable for inheritance by all
+ BuildSteps that invoke RemoteCommands which emit stdout/stderr messages.
+ """
progressMetrics = ('output',)
@@ -854,12 +869,12 @@
self.cmd = cmd # so we can interrupt it
self.step_status.setColor("yellow")
self.step_status.setText(self.describe(False))
- loog = self.addLog("stdio")
- log.msg("ShellCommand.start using log", loog)
+ stdio_log = self.addLog("stdio")
+ log.msg("ShellCommand.start using log", stdio_log)
log.msg(" for cmd", cmd)
- cmd.useLog(loog, True)
+ cmd.useLog(stdio_log, True)
for em in errorMessages:
- loog.addHeader(em)
+ stdio_log.addHeader(em)
d = self.runCommand(cmd)
d.addCallbacks(self._commandComplete, self.checkDisconnect)
d.addErrback(self.failed)
@@ -1046,6 +1061,7 @@
description = None # set this to a list of short strings to override
descriptionDone = None # alternate description when the step is complete
command = None # set this to a command, or set in kwargs
+ logfiles = {}
# override this on a specific ShellCommand if you want to let it fail
# without dooming the entire build to a status of FAILURE
@@ -1053,7 +1069,7 @@
def __init__(self, workdir,
description=None, descriptionDone=None,
- command=None,
+ command=None, logfiles={},
**kwargs):
# most of our arguments get passed through to the RemoteShellCommand
# that we create, but first strip out the ones that we pass to
@@ -1066,6 +1082,10 @@
self.descriptionDone = descriptionDone
if command:
self.command = command
+ # merge a class-level 'logfiles' attribute with one passed in as an
+ # argument
+ self.logfiles = self.logfiles.copy()
+ self.logfiles.update(logfiles)
# pull out the ones that BuildStep wants, then upcall
buildstep_kwargs = {}
@@ -1142,13 +1162,23 @@
# note that each RemoteShellCommand gets its own copy of the
# dictionary, so we shouldn't be affecting anyone but ourselves.
+ def setupLogfiles(self, cmd, logfiles):
+ if logfiles:
+ for logname,remotefilename in logfiles.items():
+ # tell the BuildStepStatus to add a LogFile
+ newlog = self.addLog(logname)
+ # and tell the LoggedRemoteCommand to feed it
+ cmd.useLog(newlog, True)
+
def start(self):
command = self._interpolateProperties(self.command)
# create the actual RemoteShellCommand instance now
kwargs = self.remote_kwargs
kwargs['command'] = command
+ kwargs['logfiles'] = self.logfiles
cmd = RemoteShellCommand(**kwargs)
self.setupEnvironment(cmd)
+ self.setupLogfiles(cmd, self.logfiles)
self.startCommand(cmd)
More information about the Commits
mailing list