(refs #35) fix dependent scheduler re-checking: make calculation of upstream lazier
[buildbot.git] / buildbot / steps / master.py
blobda8a664617a8fd03c895b791a2c3ef0f7e30b766
1 import os, types
2 from twisted.python import log, failure, runtime
3 from twisted.internet import reactor, defer, task
4 from buildbot.process.buildstep import RemoteCommand, BuildStep
5 from buildbot.process.buildstep import SUCCESS, FAILURE
6 from twisted.internet.protocol import ProcessProtocol
8 class MasterShellCommand(BuildStep):
9 """
10 Run a shell command locally - on the buildmaster. The shell command
11 COMMAND is specified just as for a RemoteShellCommand. Note that extra
12 logfiles are not sopported.
13 """
14 name='MasterShellCommand'
15 description='Running'
16 descriptionDone='Ran'
18 def __init__(self, command, **kwargs):
19 BuildStep.__init__(self, **kwargs)
20 self.addFactoryArguments(command=command)
21 self.command=command
23 class LocalPP(ProcessProtocol):
24 def __init__(self, step):
25 self.step = step
27 def outReceived(self, data):
28 self.step.stdio_log.addStdout(data)
30 def errReceived(self, data):
31 self.step.stdio_log.addStderr(data)
33 def processEnded(self, status_object):
34 self.step.stdio_log.addHeader("exit status %d\n" % status_object.value.exitCode)
35 self.step.processEnded(status_object)
37 def start(self):
38 # set up argv
39 if type(self.command) in types.StringTypes:
40 if runtime.platformType == 'win32':
41 argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args
42 if '/c' not in argv: argv += ['/c']
43 argv += [self.command]
44 else:
45 # for posix, use /bin/sh. for other non-posix, well, doesn't
46 # hurt to try
47 argv = ['/bin/sh', '-c', self.command]
48 else:
49 if runtime.platformType == 'win32':
50 argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args
51 if '/c' not in argv: argv += ['/c']
52 argv += list(self.command)
53 else:
54 argv = self.command
56 self.stdio_log = stdio_log = self.addLog("stdio")
58 if type(self.command) in types.StringTypes:
59 stdio_log.addHeader(self.command.strip() + "\n\n")
60 else:
61 stdio_log.addHeader(" ".join(self.command) + "\n\n")
62 stdio_log.addHeader("** RUNNING ON BUILDMASTER **\n")
63 stdio_log.addHeader(" in dir %s\n" % os.getcwd())
64 stdio_log.addHeader(" argv: %s\n" % (argv,))
66 # TODO add a timeout?
67 proc = reactor.spawnProcess(self.LocalPP(self), argv[0], argv)
68 # (the LocalPP object will call processEnded for us)
70 def processEnded(self, status_object):
71 if status_object.value.exitCode != 0:
72 self.step_status.setText(["failed (%d)" % status_object.value.exitCode])
73 self.finished(FAILURE)
74 else:
75 self.step_status.setText(["succeeded"])
76 self.finished(SUCCESS)