Move 'redo --ifchange' into 'redo-ifchange' to match djb's style.

It does simplify the logic of both redo.py and redo-ifchange.py, I suppose.
This commit is contained in:
Avery Pennarun 2010-11-13 00:45:49 -08:00
commit c57de820fb
12 changed files with 103 additions and 87 deletions

85
redo.py
View file

@ -8,8 +8,6 @@ redo [targets...]
--
d,debug print dependency checks as they happen
v,verbose print commands as they are run
ifchange only redo if the file is modified or deleted
ifcreate only redo if the file is created
"""
o = options.Options('redo', optspec)
(opt, flags, extra) = o.parse(sys.argv[1:])
@ -17,90 +15,24 @@ o = options.Options('redo', optspec)
targets = extra or ['it']
def relpath(t, base):
t = os.path.abspath(t)
tparts = t.split('/')
bparts = base.split('/')
for tp,bp in zip(tparts,bparts):
if tp != bp:
break
tparts.pop(0)
bparts.pop(0)
while bparts:
tparts.insert(0, '..')
bparts.pop(0)
return '/'.join(tparts)
def sname(typ, t):
# FIXME: t.replace(...) is non-reversible and non-unique here!
tnew = relpath(t, vars.BASE)
#log('sname: (%r) %r -> %r\n' % (vars.BASE, t, tnew))
return vars.BASE + ('/.redo/%s^%s' % (typ, tnew.replace('/', '^')))
def add_dep(t, mode, dep):
open(sname('dep', t), 'a').write('%s %s\n' % (mode, dep))
def find_do_file(t):
dofile = '%s.do' % t
if os.path.exists(dofile):
add_dep(t, 'm', dofile)
if dirty_deps(dofile, depth = ''):
build(dofile)
return dofile
else:
add_dep(t, 'c', dofile)
return None
def _dirty_deps(t, depth):
debug('%s?%s\n' % (depth, t))
if not os.path.exists(sname('stamp', t)):
debug('%s-- DIRTY (no stamp)\n' % depth)
return True
stamptime = os.stat(sname('stamp', t)).st_mtime
try:
realtime = os.stat(t).st_mtime
except OSError:
realtime = 0
if stamptime != realtime:
debug('%s-- DIRTY (mtime)\n' % depth)
return True
for sub in open(sname('dep', t)).readlines():
assert(sub[0] in ('c','m'))
assert(sub[1] == ' ')
assert(sub[-1] == '\n')
mode = sub[0]
name = sub[2:-1]
if mode == 'c':
if os.path.exists(name):
debug('%s-- DIRTY (created)\n' % depth)
return True
elif mode == 'm':
if dirty_deps(name, depth + ' '):
#debug('%s-- DIRTY (sub)\n' % depth)
return True
return False
def dirty_deps(t, depth):
if _dirty_deps(t, depth):
unlink(sname('stamp', t)) # short circuit future checks
return True
return False
def stamp(t):
stampfile = sname('stamp', t)
depfile = sname('dep', t)
if not os.path.exists(vars.BASE + '/.redo'):
# .redo might not exist in a 'make clean' target
return
open(stampfile, 'w').close()
open(depfile, 'a').close()
try:
mtime = os.stat(t).st_mtime
except OSError:
@ -126,6 +58,7 @@ def build(t):
return # success
else:
raise Exception('no rule to make %r' % t)
stamp(dofile)
unlink(t)
tmpname = '%s.redo.tmp' % t
unlink(tmpname)
@ -158,7 +91,6 @@ if opt.debug:
os.environ['REDO_DEBUG'] = '1'
if opt.verbose:
os.environ['REDO_VERBOSE'] = '1'
assert(not (opt.ifchange and opt.ifcreate))
if not os.environ.get('REDO_BASE', ''):
base = os.path.commonprefix([os.path.abspath(os.path.dirname(t))
@ -173,6 +105,7 @@ if not os.environ.get('REDO_BASE', ''):
import vars
from log import *
from libdo import *
if not vars.DEPTH:
# toplevel call to redo
@ -188,11 +121,5 @@ for t in targets:
os.chdir(startdir)
if vars.TARGET:
add_dep(vars.TARGET, opt.ifcreate and 'c' or 'm', t)
if opt.ifcreate:
pass # just adding the dependency (above) is enough
elif opt.ifchange:
if dirty_deps(t, depth = ''):
build(t)
else:
build(t)
add_dep(vars.TARGET, 'm', t)
build(t)