71
71
import svnpubsub.client
73
# check_output() is only available in Python 2.7. Allow us to run with
76
check_output = subprocess.check_output
77
except AttributeError:
78
def check_output(args, env): # note: we only use these two args
79
pipe = subprocess.Popen(args, stdout=subprocess.PIPE, env=env)
80
output, _ = pipe.communicate()
82
raise subprocess.CalledProcessError(pipe.returncode, args)
85
74
assert hasattr(subprocess, 'check_call')
86
75
def check_call(*args, **kwds):
87
"""Wrapper around subprocess.check_call() that logs stderr upon failure."""
76
"""Wrapper around subprocess.check_call() that logs stderr upon failure,
77
with an optional list of exit codes to consider non-failure."""
88
78
assert 'stderr' not in kwds
79
if '__okayexits' in kwds:
80
__okayexits = kwds['__okayexits']
81
del kwds['__okayexits']
83
__okayexits = set([0]) # EXIT_SUCCESS
89
84
kwds.update(stderr=subprocess.PIPE)
90
85
pipe = subprocess.Popen(*args, **kwds)
91
86
output, errput = pipe.communicate()
87
if pipe.returncode not in __okayexits:
93
88
cmd = args[0] if len(args) else kwds.get('args', '(no command)')
94
89
# TODO: log stdout too?
95
90
logging.error('Command failed: returncode=%d command=%r stderr=%r',
103
98
def svn_info(svnbin, env, path):
104
99
"Run 'svn info' on the target path, returning a dict of info data."
105
100
args = [svnbin, "info", "--non-interactive", "--", path]
106
output = check_output(args, env=env).strip()
101
output = svnpubsub.util.check_output(args, env=env).strip()
108
103
for line in output.split('\n'):
109
104
idx = line.index(':')
304
299
logging.info("updating: %s", wc.path)
302
HEAD = svn_info(self.svnbin, self.env, wc.url)['Revision']
304
hook_mode = ['pre-update', 'pre-boot'][boot]
305
logging.info('running hook: %s at %s',
307
args = [self.hook, hook_mode, wc.path, HEAD, wc.url]
308
rc = check_call(args, env=self.env, __okayexits=[0, 1])
311
logging.warn('hook denied update of %s at %s',
306
316
### we need to move some of these args into the config. these are
307
317
### still specific to the ASF setup.
308
318
args = [self.svnbin, 'switch',
313
323
'--config-option',
314
324
'config:miscellany:use-commit-times=on',
318
328
check_call(args, env=self.env)
320
330
### check the loglevel before running 'svn info'?
321
331
info = svn_info(self.svnbin, self.env, wc.path)
332
assert info['Revision'] == HEAD
322
333
logging.info("updated: %s now at r%s", wc.path, info['Revision'])
534
545
# We manage the logfile ourselves (along with possible rotation). The
535
546
# daemon process can just drop stdout/stderr into /dev/null.
536
d = Daemon('/dev/null', options.pidfile, options.umask, bdec)
547
d = Daemon('/dev/null', os.path.abspath(options.pidfile),
537
549
if options.daemon:
538
550
# Daemonize the process and call sys.exit() with appropriate code
539
551
d.daemonize_exit()