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
):
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.
14 name
='MasterShellCommand'
18 def __init__(self
, command
, **kwargs
):
19 BuildStep
.__init
__(self
, **kwargs
)
20 self
.addFactoryArguments(command
=command
)
23 class LocalPP(ProcessProtocol
):
24 def __init__(self
, 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
)
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
]
45 # for posix, use /bin/sh. for other non-posix, well, doesn't
47 argv
= ['/bin/sh', '-c', self
.command
]
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
)
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")
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
,))
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
)
75 self
.step_status
.setText(["succeeded"])
76 self
.finished(SUCCESS
)