From c1f09f564bb1f17d6dbfacecd4fe7a3a4082256e Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Tue, 16 Nov 2010 01:59:32 -0800 Subject: [PATCH] Support for default.*.do rules. I *think* this was the last missing part from djb's spec. Certainly it's an important one for any real project. --- clean.do | 3 ++- redo.py | 51 +++++++++++++++++++++++++++++++++++------------- t/.gitignore | 6 ++++++ t/all.do | 2 +- t/c.c.c.b.b.a | 1 + t/c.do | 3 +++ t/clean.do | 3 +++ t/default.b.do | 10 ++++++++++ t/default.c.c.do | 4 ++++ t/default.c.do | 4 ++++ t/default.do | 4 ++++ 11 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 t/.gitignore create mode 100644 t/c.c.c.b.b.a create mode 100644 t/c.do create mode 100644 t/clean.do create mode 100644 t/default.b.do create mode 100644 t/default.c.c.do create mode 100644 t/default.c.do create mode 100644 t/default.do diff --git a/clean.do b/clean.do index 1125a69..4f59048 100644 --- a/clean.do +++ b/clean.do @@ -1,2 +1,3 @@ -rm -f t/hello t/[by]ellow t/*.o *~ .*~ t/*~ t/.*~ *.pyc t/CC t/LD +redo t/clean +rm -f t/hello t/[by]ellow t/*.o *~ .*~ */*~ */.*~ *.pyc t/CC t/LD rm -rf .redo t/.redo diff --git a/redo.py b/redo.py index c28b217..90ad46e 100755 --- a/redo.py +++ b/redo.py @@ -42,6 +42,7 @@ if not os.environ.get('REDO_BASE', ''): for f in glob.glob('%s/.redo/lock^*' % base): os.unlink(f) + import vars from helpers import * @@ -52,14 +53,26 @@ class BuildLocked(Exception): pass +def _possible_do_files(t): + yield "%s.do" % t, t, '' + dirname,filename = os.path.split(t) + l = filename.split('.') + l[0] = os.path.join(dirname, l[0]) + for i in range(1,len(l)+1): + basename = '.'.join(l[:i]) + ext = '.'.join(l[i:]) + if ext: ext = '.' + ext + yield "default%s.do" % ext, basename, ext + + def find_do_file(t): - dofile = '%s.do' % t - if os.path.exists(dofile): - add_dep(t, 'm', dofile) - return dofile - else: - add_dep(t, 'c', dofile) - return None + for dofile,basename,ext in _possible_do_files(t): + if os.path.exists(dofile): + add_dep(t, 'm', dofile) + return dofile,basename,ext + else: + add_dep(t, 'c', dofile) + return None,None,None def stamp(t): @@ -86,23 +99,33 @@ def _preexec(t): def _build(t): + if os.path.exists(t) and not os.path.exists(sname('gen', t)): + # an existing source file that is not marked as a generated file. + # This step is mentioned by djb in his notes. It turns out to be + # important to prevent infinite recursion. For example, a rule + # called default.o.do could be used to try to produce hello.c.o, + # which is stupid since hello.c is a static file. + stamp(t) + return # success unlink(sname('dep', t)) open(sname('dep', t), 'w').close() - dofile = find_do_file(t) + open(sname('gen', t), 'w').close() # it's definitely a generated file + (dofile, basename, ext) = find_do_file(t) if not dofile: - if os.path.exists(t): # an existing source file - stamp(t) - return # success - else: - raise BuildError('no rule to make %r' % t) + raise BuildError('no rule to make %r' % t) stamp(dofile) unlink(t) tmpname = '%s.redo.tmp' % t unlink(tmpname) f = open(tmpname, 'w+') + + # this will run in the dofile's directory, so use only basenames here argv = ['sh', '-e', os.path.basename(dofile), - os.path.basename(t), 'FIXME', os.path.basename(tmpname)] + os.path.basename(basename), # target name (extension removed) + ext, # extension (if any), including leading dot + os.path.basename(tmpname) # randomized output file name + ] if vars.VERBOSE: argv[1] += 'v' log('%s\n' % relpath(t, vars.STARTDIR)) diff --git a/t/.gitignore b/t/.gitignore new file mode 100644 index 0000000..580e8c9 --- /dev/null +++ b/t/.gitignore @@ -0,0 +1,6 @@ +c +c.c +c.c.c +c.c.c.b +c.c.c.b.b +d diff --git a/t/all.do b/t/all.do index da328b3..2b876ff 100644 --- a/t/all.do +++ b/t/all.do @@ -1,2 +1,2 @@ -redo-ifchange hello yellow bellow +redo-ifchange hello yellow bellow c d diff --git a/t/c.c.c.b.b.a b/t/c.c.c.b.b.a new file mode 100644 index 0000000..4768c08 --- /dev/null +++ b/t/c.c.c.b.b.a @@ -0,0 +1 @@ +chicken diff --git a/t/c.do b/t/c.do new file mode 100644 index 0000000..05fe36f --- /dev/null +++ b/t/c.do @@ -0,0 +1,3 @@ +redo-ifchange $1$2.c +echo c.do +cat $1$2.c diff --git a/t/clean.do b/t/clean.do new file mode 100644 index 0000000..59dd83f --- /dev/null +++ b/t/clean.do @@ -0,0 +1,3 @@ +rm -f c c.c c.c.c c.c.c.b c.c.c.b.b d + + diff --git a/t/default.b.do b/t/default.b.do new file mode 100644 index 0000000..3c533bb --- /dev/null +++ b/t/default.b.do @@ -0,0 +1,10 @@ +if [ -e "$1$2.a" -o -e "default$2.a" ]; then + redo-ifchange "$1$2.a" + echo a-to-b + cat "$1$2.a" +else + redo-ifchange "$1$2.b" + echo b-to-b + cat "$1$2.b" +fi +./sleep 1.1 diff --git a/t/default.c.c.do b/t/default.c.c.do new file mode 100644 index 0000000..c7d83c1 --- /dev/null +++ b/t/default.c.c.do @@ -0,0 +1,4 @@ +redo-ifchange $1$2.b +echo b-to-cc +cat $1$2.b +./sleep 1.2 diff --git a/t/default.c.do b/t/default.c.do new file mode 100644 index 0000000..ad1e84b --- /dev/null +++ b/t/default.c.do @@ -0,0 +1,4 @@ +redo-ifchange $1$2.c +echo c-to-c +cat $1$2.c +./sleep 1.3 diff --git a/t/default.do b/t/default.do new file mode 100644 index 0000000..b82ef97 --- /dev/null +++ b/t/default.do @@ -0,0 +1,4 @@ +redo-ifchange c +echo default-rule +cat c +./sleep 1.4