From f2d34fa685be2947f35eecad730460dd57ca3ece Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Sun, 19 Dec 2010 01:38:38 -0800 Subject: [PATCH] New redo-sources and redo-targets commands. Suggested by djb in personal email, and on the mailing list. redo-targets lists all the targets in the database; redo-sources lists all the existing sources (ie. files that are referred to but which aren't targets). redo-ifcreate filenames aren't included in the redo-sources list. --- helpers.py | 4 ++++ redo-sources | 1 + redo-sources.py | 18 ++++++++++++++++++ redo-targets | 1 + redo-targets.py | 16 ++++++++++++++++ state.py | 35 +++++++++++++++++------------------ 6 files changed, 57 insertions(+), 18 deletions(-) create mode 120000 redo-sources create mode 100755 redo-sources.py create mode 120000 redo-targets create mode 100755 redo-targets.py diff --git a/helpers.py b/helpers.py index 75f0d6b..c192673 100644 --- a/helpers.py +++ b/helpers.py @@ -2,6 +2,10 @@ import os, errno, fcntl from atoi import atoi +def join(between, l): + return between.join(l) + + def unlink(f): """Delete a file at path 'f' if it currently exists. diff --git a/redo-sources b/redo-sources new file mode 120000 index 0000000..18c452d --- /dev/null +++ b/redo-sources @@ -0,0 +1 @@ +redo-sources.py \ No newline at end of file diff --git a/redo-sources.py b/redo-sources.py new file mode 100755 index 0000000..7197fae --- /dev/null +++ b/redo-sources.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +import sys, os + +import vars_init +vars_init.init([]) + +import state +from log import err + +if len(sys.argv[1:]) != 0: + err('%s: no arguments expected.\n' % sys.argv[0]) + sys.exit(1) + +for f in state.files(): + if f.name.startswith('//'): + continue # special name, ignore + if not f.is_generated and f.read_stamp() != state.STAMP_MISSING: + print f.nicename() diff --git a/redo-targets b/redo-targets new file mode 120000 index 0000000..0816d62 --- /dev/null +++ b/redo-targets @@ -0,0 +1 @@ +redo-targets.py \ No newline at end of file diff --git a/redo-targets.py b/redo-targets.py new file mode 100755 index 0000000..4b74e31 --- /dev/null +++ b/redo-targets.py @@ -0,0 +1,16 @@ +#!/usr/bin/python +import sys, os + +import vars_init +vars_init.init([]) + +import state +from log import err + +if len(sys.argv[1:]) != 0: + err('%s: no arguments expected.\n' % sys.argv[0]) + sys.exit(1) + +for f in state.files(): + if f.is_generated and f.read_stamp() != state.STAMP_MISSING: + print f.nicename() diff --git a/state.py b/state.py index 10f7260..6d8b137 100644 --- a/state.py +++ b/state.py @@ -1,6 +1,6 @@ import sys, os, errno, glob, stat, fcntl, sqlite3 import vars -from helpers import unlink, close_on_exec +from helpers import unlink, close_on_exec, join from log import err, debug2, debug3 SCHEMA_VER=1 @@ -129,20 +129,18 @@ def relpath(t, base): while bparts: tparts.insert(0, '..') bparts.pop(0) - return '/'.join(tparts) + return join('/', tparts) +_file_cols = ['rowid', 'name', 'is_generated', 'is_override', + 'checked_runid', 'changed_runid', 'failed_runid', + 'stamp', 'csum'] class File(object): # use this mostly to avoid accidentally assigning to typos - __slots__ = ['id', 'name', 'is_generated', 'is_override', - 'checked_runid', 'changed_runid', 'failed_runid', - 'stamp', 'csum'] + __slots__ = ['id'] + _file_cols[1:] def _init_from_idname(self, id, name): - q = ('select rowid, name, is_generated, is_override, ' - ' checked_runid, changed_runid, failed_runid, ' - ' stamp, csum ' - ' from Files ') + q = ('select %s from Files ' % join(', ', _file_cols)) if id != None: q += 'where rowid=?' l = [id] @@ -185,11 +183,10 @@ class File(object): self._init_from_idname(self.id, None) def save(self): + cols = join(', ', ['%s=?'%i for i in _file_cols[2:]]) _write('update Files set ' - ' is_generated=?, is_override=?, ' - ' checked_runid=?, changed_runid=?, failed_runid=?, ' - ' stamp=?, csum=? ' - ' where rowid=?', + ' %s ' + ' where rowid=?' % cols, [self.is_generated, self.is_override, self.checked_runid, self.changed_runid, self.failed_runid, self.stamp, self.csum, @@ -236,13 +233,10 @@ class File(object): return self.failed_runid and self.failed_runid >= vars.RUNID def deps(self): - q = ('select Deps.mode, Deps.source, ' - ' name, is_generated, is_override, ' - ' checked_runid, changed_runid, failed_runid, ' - ' stamp, csum ' + q = ('select Deps.mode, Deps.source, %s ' ' from Files ' ' join Deps on Files.rowid = Deps.source ' - ' where target=?') + ' where target=?' % join(', ', _file_cols[1:])) for row in db().execute(q, [self.id]).fetchall(): mode = row[0] cols = row[1:] @@ -280,6 +274,11 @@ class File(object): return relpath(os.path.join(vars.BASE, self.name), vars.STARTDIR) +def files(): + q = ('select %s from Files order by name' % join(', ', _file_cols)) + for cols in db().execute(q).fetchall(): + yield File(cols=cols) + # FIXME: I really want to use fcntl F_SETLK, F_SETLKW, etc here. But python # doesn't do the lockdata structure in a portable way, so we have to use