OLD | NEW |
| (Empty) |
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 | |
7 | |
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' | |
17 | |
18 def __init__(self, command, **kwargs): | |
19 BuildStep.__init__(self, **kwargs) | |
20 self.addFactoryArguments(command=command) | |
21 self.command=command | |
22 | |
23 class LocalPP(ProcessProtocol): | |
24 def __init__(self, step): | |
25 self.step = step | |
26 | |
27 def outReceived(self, data): | |
28 self.step.stdio_log.addStdout(data) | |
29 | |
30 def errReceived(self, data): | |
31 self.step.stdio_log.addStderr(data) | |
32 | |
33 def processEnded(self, status_object): | |
34 self.step.stdio_log.addHeader("exit status %d\n" % status_object.val
ue.exitCode) | |
35 self.step.processEnded(status_object) | |
36 | |
37 def start(self): | |
38 # render properties | |
39 properties = self.build.getProperties() | |
40 command = properties.render(self.command) | |
41 # set up argv | |
42 if type(command) in types.StringTypes: | |
43 if runtime.platformType == 'win32': | |
44 argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have a
rgs | |
45 if '/c' not in argv: argv += ['/c'] | |
46 argv += [command] | |
47 else: | |
48 # for posix, use /bin/sh. for other non-posix, well, doesn't | |
49 # hurt to try | |
50 argv = ['/bin/sh', '-c', command] | |
51 else: | |
52 if runtime.platformType == 'win32': | |
53 argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have a
rgs | |
54 if '/c' not in argv: argv += ['/c'] | |
55 argv += list(command) | |
56 else: | |
57 argv = command | |
58 | |
59 self.stdio_log = stdio_log = self.addLog("stdio") | |
60 | |
61 if type(command) in types.StringTypes: | |
62 stdio_log.addHeader(command.strip() + "\n\n") | |
63 else: | |
64 stdio_log.addHeader(" ".join(command) + "\n\n") | |
65 stdio_log.addHeader("** RUNNING ON BUILDMASTER **\n") | |
66 stdio_log.addHeader(" in dir %s\n" % os.getcwd()) | |
67 stdio_log.addHeader(" argv: %s\n" % (argv,)) | |
68 | |
69 # TODO add a timeout? | |
70 proc = reactor.spawnProcess(self.LocalPP(self), argv[0], argv) | |
71 # (the LocalPP object will call processEnded for us) | |
72 | |
73 def processEnded(self, status_object): | |
74 if status_object.value.exitCode != 0: | |
75 self.step_status.setText(["failed (%d)" % status_object.value.exitCo
de]) | |
76 self.finished(FAILURE) | |
77 else: | |
78 self.step_status.setText(["succeeded"]) | |
79 self.finished(SUCCESS) | |
OLD | NEW |