Merge branch 'search-parent-dirs'

* search-parent-dirs:
  minimal/do: support searching parent dirs for .do files.
  Search parent directories for default*.do.
This commit is contained in:
Avery Pennarun 2011-01-15 21:45:59 -08:00
commit de94c09048
17 changed files with 134 additions and 34 deletions

View file

@ -1,32 +1,48 @@
import sys, os, errno, stat
import vars, jwack, state
from helpers import unlink, close_on_exec
from helpers import unlink, close_on_exec, join
from log import log, log_, debug, debug2, err, warn
def _possible_do_files(t):
t = os.path.join(vars.BASE, t)
yield "%s.do" % t, t, ''
dirname,filename = os.path.split(t)
def _default_do_files(filename):
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:])
basename = join('.', l[:i])
ext = join('.', l[i:])
if ext: ext = '.' + ext
yield (os.path.join(dirname, "default%s.do" % ext),
os.path.join(dirname, basename), ext)
yield ("default%s.do" % ext), basename, ext
def _possible_do_files(t):
dirname,filename = os.path.split(t)
yield os.path.join(vars.BASE, dirname), "%s.do" % filename, filename, ''
# It's important to try every possibility in a directory before resorting
# to a parent directory. Think about nested projects: I don't want
# ../../default.o.do to take precedence over ../default.do, because
# the former one might just be an artifact of someone embedding my project
# into theirs as a subdir. When they do, my rules should still be used
# for building my project in *all* cases.
t = os.path.normpath(os.path.join(vars.BASE, t))
dirname,filename = os.path.split(t)
dirbits = dirname.split('/')
for i in range(len(dirbits), -1, -1):
basedir = join('/', dirbits[:i])
subdir = join('/', dirbits[i:])
for dofile,basename,ext in _default_do_files(filename):
yield basedir, dofile, os.path.join(subdir, basename), ext
def _find_do_file(f):
for dofile,basename,ext in _possible_do_files(f.name):
debug2('%s: %s ?\n' % (f.name, dofile))
if os.path.exists(dofile):
f.add_dep('m', dofile)
return dofile,basename,ext
for dodir,dofile,basename,ext in _possible_do_files(f.name):
dopath = os.path.join(dodir, dofile)
debug2('%s: %s:%s ?\n' % (f.name, dodir, dofile))
if os.path.exists(dopath):
f.add_dep('m', dopath)
return dodir,dofile,basename,ext
else:
f.add_dep('c', dofile)
return None,None,None
f.add_dep('c', dopath)
return None,None,None,None
def _nice(t):
@ -104,7 +120,7 @@ class BuildJob:
sf.save()
return self._after2(0)
sf.zap_deps1()
(dofile, basename, ext) = _find_do_file(sf)
(dodir, dofile, basename, ext) = _find_do_file(sf)
if not dofile:
if os.path.exists(t):
sf.set_static()
@ -120,18 +136,21 @@ class BuildJob:
self.f = os.fdopen(ffd, 'w+')
# this will run in the dofile's directory, so use only basenames here
argv = ['sh', '-e',
os.path.basename(dofile),
os.path.basename(basename), # target name (extension removed)
dofile,
basename, # target name (no extension)
ext, # extension (if any), including leading dot
os.path.basename(self.tmpname2) # randomized output file name
]
if vars.VERBOSE: argv[1] += 'v'
if vars.XTRACE: argv[1] += 'x'
if vars.VERBOSE or vars.XTRACE: log_('\n')
firstline = open(dofile).readline().strip()
firstline = open(os.path.join(dodir, dofile)).readline().strip()
if firstline.startswith('#!/'):
argv[0:2] = firstline[2:].split(' ')
log('%s\n' % _nice(t))
self.dodir = dodir
self.basename = basename
self.ext = ext
self.argv = argv
sf.is_generated = True
sf.save()
@ -171,10 +190,10 @@ class BuildJob:
# redo-ifchange, and it might have done it from a different directory
# than we started it in. So os.getcwd() might be != REDO_PWD right
# now.
dn = os.path.dirname(self.t)
dn = self.dodir
newp = os.path.realpath(dn)
os.environ['REDO_PWD'] = state.relpath(newp, vars.STARTDIR)
os.environ['REDO_TARGET'] = os.path.basename(self.t)
os.environ['REDO_TARGET'] = self.basename + self.ext
os.environ['REDO_DEPTH'] = vars.DEPTH + ' '
if dn:
os.chdir(dn)

View file

@ -51,7 +51,7 @@ if [ -z "$DO_BUILT" ]; then
fi
_find_dofile()
_find_dofile_pwd()
{
DOFILE=default.$1.do
while :; do
@ -64,6 +64,21 @@ _find_dofile()
}
_find_dofile()
{
PREFIX=
while :; do
_find_dofile_pwd "$1"
[ -e "$DOFILE" ] && break
[ "$PWD" = "/" ] && break
TARGET=${PWD##*/}/$TARGET
PREFIX=${PWD##*/}/$PREFIX
cd ..
done
BASE=$PREFIX$BASE
}
_run_dofile()
{
export DO_DEPTH="$DO_DEPTH "

View file

@ -261,7 +261,7 @@ class File(object):
def add_dep(self, mode, dep):
src = File(name=dep)
debug2('add-dep: %r < %s %r\n' % (self.name, mode, src.name))
debug3('add-dep: "%s" < %s "%s"\n' % (self.name, mode, src.name))
assert(self.id != src.id)
_write("insert or replace into Deps "
" (target, mode, source, delete_me) values (?,?,?,?)",

6
t/.gitignore vendored
View file

@ -1,9 +1,3 @@
c
c.c
c.c.c
c.c.c.b
c.c.c.b.b
d
test.args
test2.args
/passfail

View file

@ -1,2 +1,2 @@
redo-ifchange hello yellow bellow defaults-flat/all example/all
redo-ifchange hello yellow bellow defaults-flat/all defaults-nested/all \
example/all

View file

@ -1,5 +1,5 @@
redo example/clean curse/clean deps/clean "space dir/clean" stamp/clean \
defaults-flat/clean
defaults-flat/clean defaults-nested/clean
rm -f broken nonshelltest shellfile mode1 makedir.log chdir1 deltest2 \
hello [by]ellow *.o *~ .*~ *.log CC LD passfail silence silence.do \
touch1 touch1.do always1 ifcreate[12].dep ifcreate[12]

6
t/defaults-flat/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
c
c.c
c.c.c
c.c.c.b
c.c.c.b.b
d

15
t/defaults-nested/.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
/a/b/file
/a/b/file.x.y.z
/a/b/file.y.z
/a/b/file.z
/a/d/file
/a/d/file.x.y.z
/a/d/file.y.z
/a/d/file.z
/a/file
/a/file.x.y.z
/a/file.y.z
/a/file.z
/file.x.y.z
/file.z
/file

View file

@ -0,0 +1 @@
echo default.y.z $1 $2

View file

@ -0,0 +1 @@
echo file $1 $2

View file

@ -0,0 +1 @@
echo default $1 $2

View file

@ -0,0 +1,2 @@
echo default.x.y.z $1 $2

View file

@ -0,0 +1 @@
echo default.z $1 $2

1
t/defaults-nested/all.do Normal file
View file

@ -0,0 +1 @@
redo test

View file

@ -0,0 +1,6 @@
exec >&2
find -name '*~' -exec rm -f {} \;
rm -f a/b/file a/b/file.x.y.z a/b/file.y.z a/b/file.z \
a/d/file a/d/file.x.y.z a/d/file.y.z a/d/file.z \
a/file a/file.x.y.z a/file.y.z a/file.z \
file.x.y.z file.z file

View file

@ -0,0 +1,2 @@
echo root $1 $2

36
t/defaults-nested/test.do Normal file
View file

@ -0,0 +1,36 @@
exec >&2
redo-ifchange \
file.x.y.z file.z file \
a/b/file.x.y.z a/b/file.y.z a/b/file.z a/b/file \
a/d/file.x.y.z a/d/file.y.z a/d/file.z a/d/file
(cd a/b && redo-ifchange ../file.x.y.z ../file.y.z ../file.z ../file)
check()
{
if [ "$(cat $1)" != "$2" ]; then
echo "$1 should contain '$2'"
echo " ...got '$(cat $1)'"
exit 44
fi
}
check file.x.y.z "root file.x.y.z"
check file.z "root file.z"
check file "root file"
check a/file.x.y.z "default.x.y.z file .x.y.z"
check a/file.y.z "default.z file.y .z"
check a/file.z "default.z file .z"
check a/file "root a/file"
check a/b/file.x.y.z "file file.x.y.z"
check a/b/file.y.z "default.y.z file .y.z"
check a/b/file.z "default.z b/file .z"
check a/b/file "root a/b/file"
check a/d/file.x.y.z "default file.x.y.z"
check a/d/file.y.z "default file.y.z"
check a/d/file.z "default file.z"
check a/d/file "default file"