Don't wipe the timestamp when a target fails to redo.

It's really a separate condition.  And since we're not removing the target
*file* in case of error - we update it atomically, and keeping it is better
than losing it - there's no reason to wipe the timestamp in that case
either.

However, we do need to know that the build failed, so that anybody else
(especially in a parallel build) who looks at that target knows that it
died.  So add a separate flag just for that.
This commit is contained in:
Avery Pennarun 2010-12-10 20:53:31 -08:00
commit 0126f6be1e
4 changed files with 39 additions and 17 deletions

View file

@ -42,6 +42,12 @@ def _try_stat(filename):
raise
class ImmediateReturn(Exception):
def __init__(self, rv):
Exception.__init__(self, "immediate return with exit code %d" % rv)
self.rv = rv
class BuildJob:
def __init__(self, t, sf, lock, shouldbuildfunc, donefunc):
self.t = t # original target name, not relative to vars.BASE
@ -57,9 +63,12 @@ class BuildJob:
t = self.t
sf = self.sf
tmpname = self.tmpname
try:
if not self.shouldbuildfunc(t):
# target doesn't need to be built; skip the whole task
return self._after2(0)
except ImmediateReturn, e:
return self._after2(e.rv)
if (os.path.exists(t) and not os.path.exists(t + '/.')
and not sf.is_generated):
# an existing source file that was not generated by us.
@ -174,8 +183,7 @@ class BuildJob:
else:
unlink(tmpname)
sf = self.sf
sf.stamp = None
sf.set_changed()
sf.set_failed()
sf.save()
f.close()
if rv != 0:
@ -259,7 +267,7 @@ def main(targets, shouldbuildfunc):
assert(lock.owned)
if vars.DEBUG_LOCKS:
log('%s (...unlocked!)\n' % _nice(t))
if state.File(name=t).stamp == None:
if state.File(name=t).is_failed():
err('%s: failed in another thread\n' % _nice(t))
retcode[0] = 2
lock.unlock()

View file

@ -42,6 +42,8 @@ def dirty_deps(f, depth, max_changed):
def should_build(t):
f = state.File(name=t)
if f.is_failed():
raise builder.ImmediateReturn(32)
return dirty_deps(f, depth = '', max_changed = vars.RUNID)

View file

@ -59,6 +59,7 @@ def db():
" is_generated int, "
" checked_runid int, "
" changed_runid int, "
" failed_runid int, "
" stamp, "
" csum)")
_db.execute("create table Deps "
@ -134,18 +135,19 @@ def relpath(t, base):
class File(object):
# use this mostly to avoid accidentally assigning to typos
__slots__ = ['id', 'name', 'is_generated',
'checked_runid', 'changed_runid',
'checked_runid', 'changed_runid', 'failed_runid',
'stamp', 'csum']
def _init_from_cols(self, cols):
(self.id, self.name, self.is_generated,
self.checked_runid, self.changed_runid,
self.checked_runid, self.changed_runid, self.failed_runid,
self.stamp, self.csum) = cols
def __init__(self, id=None, name=None, cols=None):
if cols:
return self._init_from_cols(cols)
q = ('select rowid, name, is_generated, checked_runid, changed_runid, '
q = ('select rowid, name, is_generated, '
' checked_runid, changed_runid, failed_runid, '
' stamp, csum '
' from Files ')
if id != None:
@ -175,11 +177,12 @@ class File(object):
def save(self):
_write('update Files set '
' is_generated=?, checked_runid=?, changed_runid=?, '
' is_generated=?, '
' checked_runid=?, changed_runid=?, failed_runid=?, '
' stamp=?, csum=? '
' where rowid=?',
[self.is_generated,
self.checked_runid, self.changed_runid,
self.checked_runid, self.changed_runid, self.failed_runid,
self.stamp, self.csum,
self.id])
@ -190,6 +193,10 @@ class File(object):
debug2('BUILT: %r (%r)\n' % (self.name, self.stamp))
self.changed_runid = vars.RUNID
def set_failed(self):
debug2('FAILED: %r\n' % self.name)
self.failed_runid = vars.RUNID
def set_static(self):
self.update_stamp()
@ -200,15 +207,19 @@ class File(object):
self.stamp = newstamp
self.set_changed()
def is_changed(self):
return self.changed_runid and self.changed_runid >= vars.RUNID
def is_checked(self):
return self.checked_runid and self.checked_runid >= vars.RUNID
def is_changed(self):
return self.changed_runid and self.changed_runid >= vars.RUNID
def is_failed(self):
return self.failed_runid and self.failed_runid >= vars.RUNID
def deps(self):
q = ('select Deps.mode, Deps.source, '
' name, is_generated, checked_runid, changed_runid, '
' name, is_generated, '
' checked_runid, changed_runid, failed_runid, '
' stamp, csum '
' from Files '
' join Deps on Files.rowid = Deps.source '

View file

@ -4,5 +4,6 @@
echo ".timeout 5000"
echo "pragma synchronous = off;"
echo "update Files set checked_runid=null, " \
" changed_runid=changed_runid-1;"
" changed_runid=changed_runid-1, " \
" failed_runid=null;"
) | sqlite3 "$REDO_BASE/.redo/db.sqlite3"