Oops, earlier state.mark() stuff was a little too radical.

If someone else built and marked one of our dependencies, then that
dependency would show up as *clean* in a later redo-ifchange, so other
dependents of that file wouldn't be rebuilt.

We actually have to track two session-specific variables: whether the file
has been checked, and whether it was rebuilt.  (Or alternatively, whether it
was dirty when we checked it the first time.  But we store the former.)
This commit is contained in:
Avery Pennarun 2010-11-21 04:14:52 -08:00
commit 0652bc9911
2 changed files with 36 additions and 5 deletions

View file

@ -5,9 +5,14 @@ from helpers import debug, err, mkdirp, unlink
def _dirty_deps(t, depth, fromdir): def _dirty_deps(t, depth, fromdir):
if state.ismarked(t, fromdir):
return False # has already been checked during this session
debug('%s?%s\n' % (depth, t)) debug('%s?%s\n' % (depth, t))
if state.isbuilt(t, fromdir):
debug('%s-- DIRTY (built)\n' % depth)
return True # has already been built during this session
if state.ismarked(t, fromdir):
debug('%s-- CLEAN (marked)\n' % depth)
return False # has already been checked during this session
stamptime = state.stamped(t, fromdir) stamptime = state.stamped(t, fromdir)
if stamptime == None: if stamptime == None:
debug('%s-- DIRTY (no stamp)\n' % depth) debug('%s-- DIRTY (no stamp)\n' % depth)
@ -29,7 +34,7 @@ def _dirty_deps(t, depth, fromdir):
return True return True
elif mode == 'm': elif mode == 'm':
if dirty_deps(name, depth + ' ', fromdir=vars.BASE): if dirty_deps(name, depth + ' ', fromdir=vars.BASE):
#debug('%s-- DIRTY (sub)\n' % depth) debug('%s-- DIRTY (sub)\n' % depth)
return True return True
state.mark(t, fromdir) state.mark(t, fromdir)
return False return False
@ -42,8 +47,12 @@ def dirty_deps(t, depth, fromdir=None):
return False return False
def should_build(t):
return not state.isbuilt(t) and dirty_deps(t, depth = '')
def maybe_build(t): def maybe_build(t):
if dirty_deps(t, depth = ''): if should_build(t):
builder.build(t) builder.build(t)
@ -56,7 +65,7 @@ try:
want_build = [] want_build = []
for t in sys.argv[1:]: for t in sys.argv[1:]:
state.add_dep(vars.TARGET, 'm', t) state.add_dep(vars.TARGET, 'm', t)
if dirty_deps(t, depth = ''): if should_build(t):
want_build.append(t) want_build.append(t)
rv = builder.main(want_build, maybe_build) rv = builder.main(want_build, maybe_build)

View file

@ -13,6 +13,8 @@ def init():
os.unlink(f) os.unlink(f)
for f in glob.glob('%s/.redo/mark^*' % vars.BASE): for f in glob.glob('%s/.redo/mark^*' % vars.BASE):
os.unlink(f) os.unlink(f)
for f in glob.glob('%s/.redo/built^*' % vars.BASE):
os.unlink(f)
def _sname(typ, t, fromdir=None): def _sname(typ, t, fromdir=None):
@ -46,6 +48,7 @@ def _stampname(t, fromdir=None):
def stamp(t): def stamp(t):
built(t)
mark(t) mark(t)
stampfile = _stampname(t) stampfile = _stampname(t)
newstampfile = _sname('stamp' + str(os.getpid()), t) newstampfile = _sname('stamp' + str(os.getpid()), t)
@ -78,6 +81,25 @@ def stamped(t, fromdir=None):
return stamptime return stamptime
def built(t, fromdir=None):
try:
open(_sname('built', t, fromdir), 'w').close()
except IOError, e:
if e.errno == errno.ENOENT:
pass # may happen if someone deletes our .redo dir
else:
raise
_builts = {}
def isbuilt(t, fromdir=None):
if _builts.get((t,fromdir)):
return True
if os.path.exists(_sname('built', t, fromdir)):
_builts[(t,fromdir)] = True
return True
def mark(t, fromdir=None): def mark(t, fromdir=None):
try: try:
open(_sname('mark', t, fromdir), 'w').close() open(_sname('mark', t, fromdir), 'w').close()