If a user manually changes a generated file, don't ever overwrite it.

That way the user can modify an auto-generated 'compile' script, for
example, and it'll stay modified.

If they delete the file, we can then generate it for them again.

Also, we have to warn whenever we're doing this, or people might think it's
a bug.
This commit is contained in:
Avery Pennarun 2010-12-10 22:42:33 -08:00
commit f6d11d5411
4 changed files with 44 additions and 11 deletions

View file

@ -42,6 +42,10 @@ def _try_stat(filename):
raise
def warn_override(name):
warn('%s - you modified it; skipping\n' % name)
class ImmediateReturn(Exception):
def __init__(self, rv):
Exception.__init__(self, "immediate return with exit code %d" % rv)
@ -69,6 +73,16 @@ class BuildJob:
return self._after2(0)
except ImmediateReturn, e:
return self._after2(e.rv)
newstamp = sf.read_stamp()
if (sf.is_generated and
not sf.failed_runid and
newstamp != state.STAMP_MISSING and
(sf.stamp != newstamp or sf.is_override)):
warn_override(_nice(t))
sf.set_override()
sf.set_checked()
sf.save()
return self._after2(0)
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.
@ -87,7 +101,6 @@ class BuildJob:
(dofile, basename, ext) = _find_do_file(sf)
if not dofile:
if os.path.exists(t):
sf.is_generated = False
sf.set_static()
sf.save()
return self._after2(0)

View file

@ -7,6 +7,9 @@ from helpers import debug, debug2, err, unlink
def dirty_deps(f, depth, max_changed):
if vars.DEBUG >= 1: debug('%s?%s\n' % (depth, f.name))
if f.failed_runid:
debug('%s-- DIRTY (failed last time)\n' % depth)
return True
if f.changed_runid == None:
debug('%s-- DIRTY (never built)\n' % depth)
return True
@ -35,6 +38,8 @@ def dirty_deps(f, depth, max_changed):
max_changed = f.changed_runid):
debug('%s-- DIRTY (sub)\n' % depth)
return True
if f.is_override:
builder.warn_override(f.name)
f.set_checked()
f.save()
return False

View file

@ -6,6 +6,10 @@ import helpers
SCHEMA_VER=1
TIMEOUT=60
STAMP_DIR='dir' # the stamp of a directory; mtime is unhelpful
STAMP_MISSING='0' # the stamp of a nonexistent file
def _connect(dbfile):
_db = sqlite3.connect(dbfile, timeout=TIMEOUT)
_db.execute("pragma synchronous = off")
@ -57,6 +61,7 @@ def db():
_db.execute("create table Files "
" (name not null primary key, "
" is_generated int, "
" is_override int, "
" checked_runid int, "
" changed_runid int, "
" failed_runid int, "
@ -134,19 +139,19 @@ def relpath(t, base):
class File(object):
# use this mostly to avoid accidentally assigning to typos
__slots__ = ['id', 'name', 'is_generated',
__slots__ = ['id', 'name', 'is_generated', 'is_override',
'checked_runid', 'changed_runid', 'failed_runid',
'stamp', 'csum']
def _init_from_cols(self, cols):
(self.id, self.name, self.is_generated,
(self.id, self.name, self.is_generated, self.is_override,
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, '
q = ('select rowid, name, is_generated, is_override, '
' checked_runid, changed_runid, failed_runid, '
' stamp, csum '
' from Files ')
@ -177,11 +182,11 @@ class File(object):
def save(self):
_write('update Files set '
' is_generated=?, '
' is_generated=?, is_override=?, '
' checked_runid=?, changed_runid=?, failed_runid=?, '
' stamp=?, csum=? '
' where rowid=?',
[self.is_generated,
[self.is_generated, self.is_override,
self.checked_runid, self.changed_runid, self.failed_runid,
self.stamp, self.csum,
self.id])
@ -192,13 +197,23 @@ class File(object):
def set_changed(self):
debug2('BUILT: %r (%r)\n' % (self.name, self.stamp))
self.changed_runid = vars.RUNID
self.failed_runid = None
self.is_override = False
def set_failed(self):
debug2('FAILED: %r\n' % self.name)
self.update_stamp()
self.failed_runid = vars.RUNID
self.is_generated = True
def set_static(self):
self.update_stamp()
self.is_override = False
self.is_generated = False
def set_override(self):
self.update_stamp()
self.is_override = True
def update_stamp(self):
newstamp = self.read_stamp()
@ -218,7 +233,7 @@ class File(object):
def deps(self):
q = ('select Deps.mode, Deps.source, '
' name, is_generated, '
' name, is_generated, is_override, '
' checked_runid, changed_runid, failed_runid, '
' stamp, csum '
' from Files '
@ -247,9 +262,9 @@ class File(object):
try:
st = os.stat(os.path.join(vars.BASE, self.name))
except OSError:
return '0' # does not exist
return STAMP_MISSING
if stat.S_ISDIR(st.st_mode):
return 'dir' # the timestamp of a directory is meaningless
return STAMP_DIR
else:
# a "unique identifier" stamp for a regular file
return str((st.st_ctime, st.st_mtime, st.st_size, st.st_ino))

View file

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