Raw logs contain @@REDO lines instead of formatted data.
This makes them more reliable to parse. redo-log can parse each line, format and print it, then recurse if necessary. This got a little ugly because I wanted 'redo --raw-logs' to work, which we want to format the output nicely, but not call redo-log. (As a result, --raw-logs has a different meaning to redo and redo-log, which is kinda dumb. I should fix that.) As an added bonus, redo-log now handles indenting of recursive logs, so if the build was a -> a/b -> a/b/c, and you look at the log for a/b, it can still start at the top level indentation.
This commit is contained in:
parent
e1f30c2765
commit
5c4f710f4e
18 changed files with 221 additions and 101 deletions
38
builder.py
38
builder.py
|
|
@ -1,7 +1,8 @@
|
||||||
import sys, os, errno, random, stat, signal, time
|
import sys, os, errno, random, stat, signal, time
|
||||||
import vars, jwack, state, paths
|
import vars, jwack, state, paths
|
||||||
from helpers import unlink, close_on_exec, join
|
from helpers import unlink, close_on_exec, join
|
||||||
from log import log, log_, debug, debug2, err, warn, check_tty
|
import logs
|
||||||
|
from logs import debug, debug2, err, warn, meta, check_tty
|
||||||
|
|
||||||
|
|
||||||
def _nice(t):
|
def _nice(t):
|
||||||
|
|
@ -58,7 +59,7 @@ def start_stdin_log_reader(status, details):
|
||||||
'redo-log',
|
'redo-log',
|
||||||
'--recursive', '--follow',
|
'--recursive', '--follow',
|
||||||
'--ack-fd', str(aw),
|
'--ack-fd', str(aw),
|
||||||
('--status' if status else '--no-status'),
|
('--status' if status and os.isatty(2) else '--no-status'),
|
||||||
('--details' if details else '--no-details'),
|
('--details' if details else '--no-details'),
|
||||||
'-'
|
'-'
|
||||||
]
|
]
|
||||||
|
|
@ -116,8 +117,8 @@ class BuildJob:
|
||||||
raise ImmediateReturn(208)
|
raise ImmediateReturn(208)
|
||||||
if not dirty:
|
if not dirty:
|
||||||
# target doesn't need to be built; skip the whole task
|
# target doesn't need to be built; skip the whole task
|
||||||
if is_target and vars.DEBUG_LOCKS:
|
if is_target:
|
||||||
log('[unchanged] %s\n' % _nice(self.t))
|
meta('unchanged', _nice(self.t))
|
||||||
return self._after2(0)
|
return self._after2(0)
|
||||||
except ImmediateReturn, e:
|
except ImmediateReturn, e:
|
||||||
return self._after2(e.rv)
|
return self._after2(e.rv)
|
||||||
|
|
@ -162,7 +163,7 @@ class BuildJob:
|
||||||
sf.save()
|
sf.save()
|
||||||
return self._after2(0)
|
return self._after2(0)
|
||||||
else:
|
else:
|
||||||
err('no rule to make %r\n' % t)
|
err('no rule to redo %r\n' % t)
|
||||||
return self._after2(1)
|
return self._after2(1)
|
||||||
unlink(self.tmpname1)
|
unlink(self.tmpname1)
|
||||||
unlink(self.tmpname2)
|
unlink(self.tmpname2)
|
||||||
|
|
@ -181,14 +182,14 @@ class BuildJob:
|
||||||
]
|
]
|
||||||
if vars.VERBOSE: argv[1] += 'v'
|
if vars.VERBOSE: argv[1] += 'v'
|
||||||
if vars.XTRACE: argv[1] += 'x'
|
if vars.XTRACE: argv[1] += 'x'
|
||||||
if vars.VERBOSE or vars.XTRACE: log_('\n')
|
if vars.VERBOSE or vars.XTRACE: logs.write('\n')
|
||||||
firstline = open(os.path.join(dodir, dofile)).readline().strip()
|
firstline = open(os.path.join(dodir, dofile)).readline().strip()
|
||||||
if firstline.startswith('#!/'):
|
if firstline.startswith('#!/'):
|
||||||
argv[0:2] = firstline[2:].split(' ')
|
argv[0:2] = firstline[2:].split(' ')
|
||||||
# make sure to create the logfile *before* writing the log about it.
|
# make sure to create the logfile *before* writing the log about it.
|
||||||
# that way redo-log won't trace into an obsolete logfile.
|
# that way redo-log won't trace into an obsolete logfile.
|
||||||
if not vars.RAW_LOGS: open(state.logname(self.sf.id), 'w')
|
if not vars.RAW_LOGS: open(state.logname(self.sf.id), 'w')
|
||||||
log('%s\n' % _nice(t))
|
meta('do', _nice(t))
|
||||||
self.dodir = dodir
|
self.dodir = dodir
|
||||||
self.basename = basename
|
self.basename = basename
|
||||||
self.ext = ext
|
self.ext = ext
|
||||||
|
|
@ -213,7 +214,7 @@ class BuildJob:
|
||||||
# condition; that's why it's called redo-unlocked, because it doesn't
|
# condition; that's why it's called redo-unlocked, because it doesn't
|
||||||
# grab a lock.
|
# grab a lock.
|
||||||
argv = ['redo-unlocked', self.sf.name] + [d.name for d in dirty]
|
argv = ['redo-unlocked', self.sf.name] + [d.name for d in dirty]
|
||||||
log('(%s)\n' % _nice(self.t))
|
meta('check', _nice(self.t))
|
||||||
state.commit()
|
state.commit()
|
||||||
def run():
|
def run():
|
||||||
os.chdir(vars.BASE)
|
os.chdir(vars.BASE)
|
||||||
|
|
@ -250,8 +251,12 @@ class BuildJob:
|
||||||
close_on_exec(2, False)
|
close_on_exec(2, False)
|
||||||
logf.close()
|
logf.close()
|
||||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # python ignores SIGPIPE
|
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # python ignores SIGPIPE
|
||||||
if vars.VERBOSE or vars.XTRACE: log_('* %s\n' % ' '.join(self.argv))
|
if vars.VERBOSE or vars.XTRACE:
|
||||||
|
logs.write('* %s\n' % ' '.join(self.argv).replace('\n', ' '))
|
||||||
os.execvp(self.argv[0], self.argv)
|
os.execvp(self.argv[0], self.argv)
|
||||||
|
# FIXME: it would be nice to log the exit code to logf.
|
||||||
|
# But that would have to happen in the parent process, which doesn't
|
||||||
|
# have logf open.
|
||||||
assert(0)
|
assert(0)
|
||||||
# returns only if there's an exception
|
# returns only if there's an exception
|
||||||
|
|
||||||
|
|
@ -326,11 +331,7 @@ class BuildJob:
|
||||||
sf.zap_deps2()
|
sf.zap_deps2()
|
||||||
sf.save()
|
sf.save()
|
||||||
f.close()
|
f.close()
|
||||||
if rv != 0:
|
meta('done', '%d %s' % (rv, self.t))
|
||||||
err('%s: exit code %r\n' % (_nice(t),rv))
|
|
||||||
else:
|
|
||||||
if vars.VERBOSE or vars.XTRACE or vars.DEBUG:
|
|
||||||
log('%s (done)\n\n' % _nice(t))
|
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def _after2(self, rv):
|
def _after2(self, rv):
|
||||||
|
|
@ -382,8 +383,7 @@ def main(targets, shouldbuildfunc):
|
||||||
else:
|
else:
|
||||||
lock.trylock()
|
lock.trylock()
|
||||||
if not lock.owned:
|
if not lock.owned:
|
||||||
if vars.DEBUG_LOCKS:
|
meta('locked', _nice(t))
|
||||||
log('%s (locked...)\n' % _nice(t))
|
|
||||||
locked.append((f.id,t))
|
locked.append((f.id,t))
|
||||||
else:
|
else:
|
||||||
# We had to create f before we had a lock, because we need f.id
|
# We had to create f before we had a lock, because we need f.id
|
||||||
|
|
@ -427,8 +427,7 @@ def main(targets, shouldbuildfunc):
|
||||||
import random
|
import random
|
||||||
time.sleep(random.random() * min(backoff, 1.0))
|
time.sleep(random.random() * min(backoff, 1.0))
|
||||||
backoff *= 2
|
backoff *= 2
|
||||||
if vars.DEBUG_LOCKS:
|
meta('waiting', _nice(t))
|
||||||
warn('%s (WAITING)\n' % _nice(t))
|
|
||||||
try:
|
try:
|
||||||
lock.check()
|
lock.check()
|
||||||
except state.CyclicDependencyError:
|
except state.CyclicDependencyError:
|
||||||
|
|
@ -445,8 +444,7 @@ def main(targets, shouldbuildfunc):
|
||||||
jwack.get_token(t)
|
jwack.get_token(t)
|
||||||
lock.trylock()
|
lock.trylock()
|
||||||
assert(lock.owned)
|
assert(lock.owned)
|
||||||
if vars.DEBUG_LOCKS:
|
meta('unlocked', _nice(t))
|
||||||
log('%s (...unlocked!)\n' % _nice(t))
|
|
||||||
if state.File(name=t).is_failed():
|
if state.File(name=t).is_failed():
|
||||||
err('%s: failed in another thread\n' % _nice(t))
|
err('%s: failed in another thread\n' % _nice(t))
|
||||||
retcode[0] = 2
|
retcode[0] = 2
|
||||||
|
|
|
||||||
2
deps.py
2
deps.py
|
|
@ -1,6 +1,6 @@
|
||||||
import sys, os
|
import sys, os
|
||||||
import vars, state, builder
|
import vars, state, builder
|
||||||
from log import debug
|
from logs import debug
|
||||||
|
|
||||||
CLEAN = 0
|
CLEAN = 0
|
||||||
DIRTY = 1
|
DIRTY = 1
|
||||||
|
|
|
||||||
51
log.py
51
log.py
|
|
@ -1,51 +0,0 @@
|
||||||
import sys, os
|
|
||||||
import vars
|
|
||||||
|
|
||||||
|
|
||||||
def check_tty():
|
|
||||||
global RED, GREEN, YELLOW, BOLD, PLAIN
|
|
||||||
if sys.stderr.isatty() and (os.environ.get('TERM') or 'dumb') != 'dumb':
|
|
||||||
# ...use ANSI formatting codes.
|
|
||||||
RED = "\x1b[31m"
|
|
||||||
GREEN = "\x1b[32m"
|
|
||||||
YELLOW = "\x1b[33m"
|
|
||||||
BOLD = "\x1b[1m"
|
|
||||||
PLAIN = "\x1b[m"
|
|
||||||
else:
|
|
||||||
RED = ""
|
|
||||||
GREEN = ""
|
|
||||||
YELLOW = ""
|
|
||||||
BOLD = ""
|
|
||||||
PLAIN = ""
|
|
||||||
|
|
||||||
check_tty()
|
|
||||||
|
|
||||||
|
|
||||||
def log_(s):
|
|
||||||
sys.stdout.flush()
|
|
||||||
if vars.DEBUG_PIDS:
|
|
||||||
sys.stderr.write('%d %s' % (os.getpid(), s))
|
|
||||||
else:
|
|
||||||
sys.stderr.write(s)
|
|
||||||
sys.stderr.flush()
|
|
||||||
|
|
||||||
|
|
||||||
def log(s):
|
|
||||||
log_(''.join([GREEN, "redo ", vars.DEPTH, BOLD, s, PLAIN]))
|
|
||||||
|
|
||||||
def err(s):
|
|
||||||
log_(''.join([RED, "redo ", vars.DEPTH, BOLD, s, PLAIN]))
|
|
||||||
|
|
||||||
def warn(s):
|
|
||||||
log_(''.join([YELLOW, "redo ", vars.DEPTH, BOLD, s, PLAIN]))
|
|
||||||
|
|
||||||
|
|
||||||
def debug(s):
|
|
||||||
if vars.DEBUG >= 1:
|
|
||||||
log_('redo: %s%s' % (vars.DEPTH, s))
|
|
||||||
def debug2(s):
|
|
||||||
if vars.DEBUG >= 2:
|
|
||||||
log_('redo: %s%s' % (vars.DEPTH, s))
|
|
||||||
def debug3(s):
|
|
||||||
if vars.DEBUG >= 3:
|
|
||||||
log_('redo: %s%s' % (vars.DEPTH, s))
|
|
||||||
151
logs.py
Normal file
151
logs.py
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
import os, re, sys, time
|
||||||
|
import vars
|
||||||
|
|
||||||
|
|
||||||
|
def check_tty():
|
||||||
|
global RED, GREEN, YELLOW, BOLD, PLAIN
|
||||||
|
if sys.stderr.isatty() and (os.environ.get('TERM') or 'dumb') != 'dumb':
|
||||||
|
# ...use ANSI formatting codes.
|
||||||
|
RED = "\x1b[31m"
|
||||||
|
GREEN = "\x1b[32m"
|
||||||
|
YELLOW = "\x1b[33m"
|
||||||
|
BOLD = "\x1b[1m"
|
||||||
|
PLAIN = "\x1b[m"
|
||||||
|
else:
|
||||||
|
RED = ""
|
||||||
|
GREEN = ""
|
||||||
|
YELLOW = ""
|
||||||
|
BOLD = ""
|
||||||
|
PLAIN = ""
|
||||||
|
|
||||||
|
|
||||||
|
class RawLog(object):
|
||||||
|
def __init__(self, file):
|
||||||
|
self.file = file
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
assert('\n' not in s)
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
self.file.write(s + '\n')
|
||||||
|
self.file.flush()
|
||||||
|
|
||||||
|
|
||||||
|
REDO_RE = re.compile(r'@@REDO:([^@]+)@@ (.*)$')
|
||||||
|
|
||||||
|
|
||||||
|
class PrettyLog(object):
|
||||||
|
def __init__(self, file):
|
||||||
|
self.file = file
|
||||||
|
|
||||||
|
def _pretty(self, pid, color, s):
|
||||||
|
if vars.DEBUG_PIDS:
|
||||||
|
redo = '%d redo ' % pid
|
||||||
|
else:
|
||||||
|
redo = 'redo '
|
||||||
|
self.file.write(''.join([color, redo, vars.DEPTH,
|
||||||
|
BOLD if color else '', s, PLAIN, '\n']))
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
assert('\n' not in s)
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
g = REDO_RE.match(s)
|
||||||
|
if g:
|
||||||
|
# FIXME: support vars.DEBUG_PIDS somewhere
|
||||||
|
all = g.group(0)
|
||||||
|
self.file.write(s[:-len(all)])
|
||||||
|
words = g.group(1).split(':')
|
||||||
|
text = g.group(2)
|
||||||
|
kind, pid, when = words[0:3]
|
||||||
|
if kind == 'unchanged':
|
||||||
|
if vars.DEBUG >= 1:
|
||||||
|
self._pretty(pid, '', '%s (unchanged)' % text)
|
||||||
|
elif kind == 'check':
|
||||||
|
self._pretty(pid, GREEN, '(%s)' % text)
|
||||||
|
elif kind == 'do':
|
||||||
|
self._pretty(pid, GREEN, text)
|
||||||
|
elif kind == 'done':
|
||||||
|
rv, name = text.split(' ', 1)
|
||||||
|
rv = int(rv)
|
||||||
|
if rv:
|
||||||
|
self._pretty(pid, RED, '%s (exit %d)' % (name, rv))
|
||||||
|
elif vars.VERBOSE or vars.XTRACE or vars.DEBUG:
|
||||||
|
self._pretty(pid, GREEN, '%s (done)' % name)
|
||||||
|
self.file.write('\n')
|
||||||
|
elif kind == 'locked':
|
||||||
|
if vars.DEBUG_LOCKS:
|
||||||
|
self._pretty(pid, GREEN, '%s (locked...)' % text)
|
||||||
|
elif kind == 'waiting':
|
||||||
|
if vars.DEBUG_LOCKS:
|
||||||
|
self._pretty(pid, GREEN, '%s (WAITING)' % text)
|
||||||
|
elif kind == 'unlocked':
|
||||||
|
if vars.DEBUG_LOCKS:
|
||||||
|
self._pretty(pid, GREEN, '%s (...unlocked!)' % text)
|
||||||
|
elif kind == 'error':
|
||||||
|
self.file.write(''.join([RED, 'redo: ',
|
||||||
|
BOLD, text, PLAIN, '\n']))
|
||||||
|
elif kind == 'warning':
|
||||||
|
self.file.write(''.join([YELLOW, 'redo: ',
|
||||||
|
BOLD, text, PLAIN, '\n']))
|
||||||
|
elif kind == 'debug':
|
||||||
|
self._pretty(pid, '', text)
|
||||||
|
else:
|
||||||
|
assert 0, 'Unexpected @@REDO kind: %r' % kind
|
||||||
|
else:
|
||||||
|
self.file.write(s + '\n')
|
||||||
|
self.file.flush()
|
||||||
|
|
||||||
|
|
||||||
|
_log = None
|
||||||
|
|
||||||
|
def setup(file, pretty):
|
||||||
|
global _log
|
||||||
|
if pretty:
|
||||||
|
check_tty()
|
||||||
|
_log = PrettyLog(file=file)
|
||||||
|
else:
|
||||||
|
_log = RawLog(file=file)
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: explicitly initialize in each program
|
||||||
|
setup(file=sys.stderr, pretty=False)
|
||||||
|
|
||||||
|
|
||||||
|
def write(s):
|
||||||
|
_log.write(s)
|
||||||
|
|
||||||
|
|
||||||
|
def meta(kind, s):
|
||||||
|
_log.meta(kind, s)
|
||||||
|
|
||||||
|
|
||||||
|
def meta(kind, s):
|
||||||
|
assert(':' not in kind)
|
||||||
|
assert('@' not in kind)
|
||||||
|
assert('\n' not in s)
|
||||||
|
write('@@REDO:%s:%d:%.4f@@ %s'
|
||||||
|
% (kind, os.getpid(), time.time(), s))
|
||||||
|
|
||||||
|
def err(s):
|
||||||
|
s = s.rstrip()
|
||||||
|
meta('error', s)
|
||||||
|
|
||||||
|
def warn(s):
|
||||||
|
s = s.rstrip()
|
||||||
|
meta('warning', s)
|
||||||
|
|
||||||
|
def debug(s):
|
||||||
|
if vars.DEBUG >= 1:
|
||||||
|
s = s.rstrip()
|
||||||
|
meta('debug', s)
|
||||||
|
|
||||||
|
def debug2(s):
|
||||||
|
if vars.DEBUG >= 2:
|
||||||
|
s = s.rstrip()
|
||||||
|
meta('debug', s)
|
||||||
|
|
||||||
|
def debug3(s):
|
||||||
|
if vars.DEBUG >= 3:
|
||||||
|
s = s.rstrip()
|
||||||
|
meta('debug', s)
|
||||||
2
paths.py
2
paths.py
|
|
@ -1,6 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import vars
|
import vars
|
||||||
from log import err, debug2
|
from logs import err, debug2
|
||||||
|
|
||||||
|
|
||||||
def _default_do_files(filename):
|
def _default_do_files(filename):
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
import sys, os
|
import sys, os
|
||||||
import vars, state
|
import vars, state
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ vars_init.init(sys.argv[1:])
|
||||||
|
|
||||||
import vars, state, builder, jwack, deps
|
import vars, state, builder, jwack, deps
|
||||||
from helpers import unlink
|
from helpers import unlink
|
||||||
from log import debug, debug2, err
|
from logs import debug, debug2, err
|
||||||
|
|
||||||
def should_build(t):
|
def should_build(t):
|
||||||
f = state.File(name=t)
|
f = state.File(name=t)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
import sys, os
|
import sys, os
|
||||||
import vars, state
|
import vars, state
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
55
redo-log.py
55
redo-log.py
|
|
@ -11,6 +11,7 @@ f,follow keep watching for more lines to be appended (like tail -f)
|
||||||
no-details only show 'redo' recursion trace, not build output
|
no-details only show 'redo' recursion trace, not build output
|
||||||
no-colorize don't colorize 'redo' log messages
|
no-colorize don't colorize 'redo' log messages
|
||||||
no-status don't display build summary line in --follow
|
no-status don't display build summary line in --follow
|
||||||
|
raw-logs don't format logs, just send raw output straight to stdout
|
||||||
ack-fd= (internal use only) print REDO-OK to this fd upon starting
|
ack-fd= (internal use only) print REDO-OK to this fd upon starting
|
||||||
"""
|
"""
|
||||||
o = options.Options(optspec)
|
o = options.Options(optspec)
|
||||||
|
|
@ -20,7 +21,7 @@ targets = extra
|
||||||
import vars_init
|
import vars_init
|
||||||
vars_init.init(list(targets))
|
vars_init.init(list(targets))
|
||||||
|
|
||||||
import vars, state
|
import vars, logs, state
|
||||||
|
|
||||||
already = set()
|
already = set()
|
||||||
queue = []
|
queue = []
|
||||||
|
|
@ -34,10 +35,14 @@ status = None
|
||||||
# redo path/to/target which might have spaces
|
# redo path/to/target which might have spaces
|
||||||
# redo [unchanged] path/to/target which might have spaces
|
# redo [unchanged] path/to/target which might have spaces
|
||||||
# redo path/to/target which might have spaces (comment)
|
# redo path/to/target which might have spaces (comment)
|
||||||
# FIXME: use a more structured format when writing the logs.
|
REDO_LINE_RE = re.compile(r'^@@REDO:([^@]+)@@ (.*)\n$')
|
||||||
# That will prevent false positives and negatives. Then transform the
|
|
||||||
# structured format into a user-friendly format when printing in redo-log.
|
|
||||||
REDO_LINE_RE = re.compile(r'^redo\s+(\[\w+\] )?([^(:]+)( \([^)]+\))?\n$')
|
def _atoi(s):
|
||||||
|
try:
|
||||||
|
return int(s)
|
||||||
|
except TypeError:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _tty_width():
|
def _tty_width():
|
||||||
|
|
@ -55,11 +60,16 @@ def is_locked(fid):
|
||||||
return (fid is not None) and not state.Lock(fid=fid).trylock()
|
return (fid is not None) and not state.Lock(fid=fid).trylock()
|
||||||
|
|
||||||
|
|
||||||
|
def _fix_depth():
|
||||||
|
vars.DEPTH = (len(depth) - 1) * ' '
|
||||||
|
|
||||||
|
|
||||||
def catlog(t):
|
def catlog(t):
|
||||||
global total_lines, status
|
global total_lines, status
|
||||||
if t in already:
|
if t in already:
|
||||||
return
|
return
|
||||||
depth.append(t)
|
depth.append(t)
|
||||||
|
_fix_depth()
|
||||||
already.add(t)
|
already.add(t)
|
||||||
if t == '-':
|
if t == '-':
|
||||||
f = sys.stdin
|
f = sys.stdin
|
||||||
|
|
@ -144,21 +154,26 @@ def catlog(t):
|
||||||
status = None
|
status = None
|
||||||
g = re.match(REDO_LINE_RE, line)
|
g = re.match(REDO_LINE_RE, line)
|
||||||
if g:
|
if g:
|
||||||
attr, name, comment = g.groups()
|
# FIXME: print prefix if @@REDO is not at start of line.
|
||||||
if attr == '[unchanged] ':
|
# logs.PrettyLog does it, but only if we actually call .write().
|
||||||
|
words, text = g.groups()
|
||||||
|
kind, pid, when = words.split(':')[0:3]
|
||||||
|
if kind == 'unchanged':
|
||||||
if opt.unchanged:
|
if opt.unchanged:
|
||||||
if name not in already:
|
if text not in already:
|
||||||
sys.stdout.write(line)
|
logs.write(line.rstrip())
|
||||||
if opt.recursive:
|
if opt.recursive:
|
||||||
catlog(name)
|
catlog(text)
|
||||||
|
elif kind in ('do', 'waiting'):
|
||||||
|
logs.write(line.rstrip())
|
||||||
|
if opt.recursive:
|
||||||
|
assert text
|
||||||
|
catlog(text)
|
||||||
else:
|
else:
|
||||||
sys.stdout.write(line)
|
logs.write(line.rstrip())
|
||||||
if opt.recursive and (not comment or comment == ' (WAITING)'):
|
|
||||||
assert name
|
|
||||||
catlog(name)
|
|
||||||
else:
|
else:
|
||||||
if opt.details:
|
if opt.details:
|
||||||
sys.stdout.write(line)
|
logs.write(line.rstrip())
|
||||||
if status:
|
if status:
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stderr.write('\r%-*.*s\r' % (width, width, ''))
|
sys.stderr.write('\r%-*.*s\r' % (width, width, ''))
|
||||||
|
|
@ -168,6 +183,7 @@ def catlog(t):
|
||||||
print line_head
|
print line_head
|
||||||
assert(depth[-1] == t)
|
assert(depth[-1] == t)
|
||||||
depth.pop(-1)
|
depth.pop(-1)
|
||||||
|
_fix_depth()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not targets:
|
if not targets:
|
||||||
|
|
@ -175,7 +191,14 @@ try:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if opt.status < 2 and not os.isatty(2):
|
if opt.status < 2 and not os.isatty(2):
|
||||||
opt.status = False
|
opt.status = False
|
||||||
|
if opt.raw_logs:
|
||||||
|
logs.setup(file=sys.stdout, pretty=False)
|
||||||
|
else:
|
||||||
|
logs.setup(file=sys.stdout, pretty=True)
|
||||||
if opt.ack_fd:
|
if opt.ack_fd:
|
||||||
|
# Write back to owner, to let them know we started up okay and
|
||||||
|
# will be able to see their error output, so it's okay to close
|
||||||
|
# their old stderr.
|
||||||
ack_fd = int(opt.ack_fd)
|
ack_fd = int(opt.ack_fd)
|
||||||
assert(ack_fd > 2)
|
assert(ack_fd > 2)
|
||||||
if os.write(ack_fd, 'REDO-OK\n') != 8:
|
if os.write(ack_fd, 'REDO-OK\n') != 8:
|
||||||
|
|
@ -185,7 +208,7 @@ try:
|
||||||
while queue:
|
while queue:
|
||||||
t = queue.pop(0)
|
t = queue.pop(0)
|
||||||
if t != '-':
|
if t != '-':
|
||||||
print 'redo %s' % t
|
logs.meta('do', t)
|
||||||
catlog(t)
|
catlog(t)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit(200)
|
sys.exit(200)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import vars_init
|
||||||
vars_init.init([])
|
vars_init.init([])
|
||||||
|
|
||||||
import vars, state, deps
|
import vars, state, deps
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
if len(sys.argv[1:]) != 0:
|
if len(sys.argv[1:]) != 0:
|
||||||
err('%s: no arguments expected.\n' % sys.argv[0])
|
err('%s: no arguments expected.\n' % sys.argv[0])
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import vars_init
|
||||||
vars_init.init([])
|
vars_init.init([])
|
||||||
|
|
||||||
import state
|
import state
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
if len(sys.argv[1:]) != 0:
|
if len(sys.argv[1:]) != 0:
|
||||||
err('%s: no arguments expected.\n' % sys.argv[0])
|
err('%s: no arguments expected.\n' % sys.argv[0])
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
import sys, os
|
import sys, os
|
||||||
import vars, state
|
import vars, state
|
||||||
from log import err, debug2
|
from logs import err, debug2
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
err('%s: no arguments expected.\n' % sys.argv[0])
|
err('%s: no arguments expected.\n' % sys.argv[0])
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import vars_init
|
||||||
vars_init.init([])
|
vars_init.init([])
|
||||||
|
|
||||||
import state
|
import state
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
if len(sys.argv[1:]) != 0:
|
if len(sys.argv[1:]) != 0:
|
||||||
err('%s: no arguments expected.\n' % sys.argv[0])
|
err('%s: no arguments expected.\n' % sys.argv[0])
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
import sys, os
|
import sys, os
|
||||||
import state
|
import state
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
if len(sys.argv[1:]) < 2:
|
if len(sys.argv[1:]) < 2:
|
||||||
err('%s: at least 2 arguments expected.\n' % sys.argv[0])
|
err('%s: at least 2 arguments expected.\n' % sys.argv[0])
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import vars_init
|
||||||
vars_init.init_no_state()
|
vars_init.init_no_state()
|
||||||
|
|
||||||
import paths
|
import paths
|
||||||
from log import err
|
from logs import err
|
||||||
|
|
||||||
if len(sys.argv[1:]) != 1:
|
if len(sys.argv[1:]) != 1:
|
||||||
err('%s: exactly one argument expected.\n' % sys.argv[0])
|
err('%s: exactly one argument expected.\n' % sys.argv[0])
|
||||||
|
|
|
||||||
2
redo.py
2
redo.py
|
|
@ -50,7 +50,7 @@ import vars_init
|
||||||
vars_init.init(targets)
|
vars_init.init(targets)
|
||||||
|
|
||||||
import vars, state, builder, jwack
|
import vars, state, builder, jwack
|
||||||
from log import warn, err
|
from logs import warn, err
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if vars_init.is_toplevel:
|
if vars_init.is_toplevel:
|
||||||
|
|
|
||||||
2
state.py
2
state.py
|
|
@ -1,7 +1,7 @@
|
||||||
import sys, os, errno, glob, stat, fcntl, sqlite3
|
import sys, os, errno, glob, stat, fcntl, sqlite3
|
||||||
import vars
|
import vars
|
||||||
from helpers import unlink, close_on_exec, join
|
from helpers import unlink, close_on_exec, join
|
||||||
from log import warn, err, debug2, debug3
|
from logs import warn, err, debug2, debug3
|
||||||
|
|
||||||
# When the module is imported, change the process title.
|
# When the module is imported, change the process title.
|
||||||
# We do it here because this module is imported by all the scripts.
|
# We do it here because this module is imported by all the scripts.
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
redo-ifchange vars _version.py
|
redo-ifchange vars _version.py
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue