Don't crash on targets in directories that don't exist yet.
The reason we'd crash is that we tried to pre-create a file called $target.redo.tmp, which wouldn't work because the directory containing $target didn't exist. We now try to generate a smarter filename by using the innermost directory of target that *does* exist. It's a little messy, but the idea is to make sure we won't have to rename() across a filesystem boundary if, for example, there's a mounted filesystem in the middle of the hierarchy somewhere.
This commit is contained in:
parent
07af5d83f9
commit
2efbbc26b9
3 changed files with 47 additions and 16 deletions
12
builder.py
12
builder.py
|
|
@ -71,8 +71,13 @@ class BuildJob:
|
||||||
def __init__(self, t, sf, lock, shouldbuildfunc, donefunc):
|
def __init__(self, t, sf, lock, shouldbuildfunc, donefunc):
|
||||||
self.t = t # original target name, not relative to vars.BASE
|
self.t = t # original target name, not relative to vars.BASE
|
||||||
self.sf = sf
|
self.sf = sf
|
||||||
self.tmpname1 = '%s.redo1.tmp' % t
|
tmpbase = t
|
||||||
self.tmpname2 = '%s.redo2.tmp' % t
|
while not os.path.isdir(os.path.dirname(tmpbase) or '.'):
|
||||||
|
ofs = tmpbase.rfind('/')
|
||||||
|
assert(ofs >= 0)
|
||||||
|
tmpbase = tmpbase[:ofs] + '__' + tmpbase[ofs+1:]
|
||||||
|
self.tmpname1 = '%s.redo1.tmp' % tmpbase
|
||||||
|
self.tmpname2 = '%s.redo2.tmp' % tmpbase
|
||||||
self.lock = lock
|
self.lock = lock
|
||||||
self.shouldbuildfunc = shouldbuildfunc
|
self.shouldbuildfunc = shouldbuildfunc
|
||||||
self.donefunc = donefunc
|
self.donefunc = donefunc
|
||||||
|
|
@ -141,7 +146,8 @@ class BuildJob:
|
||||||
dofile,
|
dofile,
|
||||||
basename, # target name (no extension)
|
basename, # target name (no extension)
|
||||||
ext, # extension (if any), including leading dot
|
ext, # extension (if any), including leading dot
|
||||||
os.path.join(basedir, os.path.basename(self.tmpname2)) # temp output file name
|
# temp output file name
|
||||||
|
state.relpath(os.path.abspath(self.tmpname2), dodir),
|
||||||
]
|
]
|
||||||
if vars.VERBOSE: argv[1] += 'v'
|
if vars.VERBOSE: argv[1] += 'v'
|
||||||
if vars.XTRACE: argv[1] += 'x'
|
if vars.XTRACE: argv[1] += 'x'
|
||||||
|
|
|
||||||
2
clean.do
2
clean.do
|
|
@ -1,7 +1,7 @@
|
||||||
rm -rf t/.redo redo-sh
|
rm -rf t/.redo redo-sh
|
||||||
if [ -e .do_built ]; then
|
if [ -e .do_built ]; then
|
||||||
while read x; do
|
while read x; do
|
||||||
rm -f "$x"
|
[ -d "$x" ] || rm -f "$x"
|
||||||
done <.do_built
|
done <.do_built
|
||||||
fi
|
fi
|
||||||
[ -z "$DO_BUILT" ] && rm -rf .do_built .do_built.dir
|
[ -z "$DO_BUILT" ] && rm -rf .do_built .do_built.dir
|
||||||
|
|
|
||||||
49
minimal/do
49
minimal/do
|
|
@ -24,6 +24,13 @@ _dirsplit()
|
||||||
dir=${1%$base}
|
dir=${1%$base}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dirname()
|
||||||
|
(
|
||||||
|
_dirsplit "$1"
|
||||||
|
dir=${dir%/}
|
||||||
|
echo "${dir:-.}"
|
||||||
|
)
|
||||||
|
|
||||||
_dirsplit "$0"
|
_dirsplit "$0"
|
||||||
export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
|
export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
|
||||||
|
|
||||||
|
|
@ -73,6 +80,7 @@ _find_dofile()
|
||||||
[ -e "$dofile" ] && break
|
[ -e "$dofile" ] && break
|
||||||
[ "$PWD" = "/" ] && break
|
[ "$PWD" = "/" ] && break
|
||||||
target=${PWD##*/}/$target
|
target=${PWD##*/}/$target
|
||||||
|
tmp=${PWD##*/}/$tmp
|
||||||
prefix=${PWD##*/}/$prefix
|
prefix=${PWD##*/}/$prefix
|
||||||
cd ..
|
cd ..
|
||||||
done
|
done
|
||||||
|
|
@ -89,17 +97,17 @@ _run_dofile()
|
||||||
read line1 <"$PWD/$dofile"
|
read line1 <"$PWD/$dofile"
|
||||||
cmd=${line1#"#!/"}
|
cmd=${line1#"#!/"}
|
||||||
if [ "$cmd" != "$line1" ]; then
|
if [ "$cmd" != "$line1" ]; then
|
||||||
/$cmd "$PWD/$dofile" "$@" >"$target.tmp2"
|
/$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2"
|
||||||
else
|
else
|
||||||
:; . "$PWD/$dofile" >"$target.tmp2"
|
:; . "$PWD/$dofile" >"$tmp.tmp2"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_do()
|
_do()
|
||||||
{
|
{
|
||||||
local dir=$1 target=$2
|
local dir=$1 target=$2 tmp=$3
|
||||||
if [ ! -e "$target" ] || [ -d "$target/." -a ! -e "$target.did" ]; then
|
if [ ! -e "$target" ] || [ -d "$target" -a ! -e "$target.did" ]; then
|
||||||
printf '%sdo %s%s%s%s\n' \
|
printf '%sdo %s%s%s%s\n' \
|
||||||
"$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2
|
"$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2
|
||||||
echo "$PWD/$target" >>"$DO_BUILT"
|
echo "$PWD/$target" >>"$DO_BUILT"
|
||||||
|
|
@ -111,30 +119,47 @@ _do()
|
||||||
echo "do: $target: no .do file" >&2
|
echo "do: $target: no .do file" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
[ ! -e "$DO_BUILT" ] || : >>"$target.did"
|
[ ! -e "$DO_BUILT" ] || [ ! -d "$(dirname "$target")" ] ||
|
||||||
( _run_dofile "$base" "$ext" "$target.tmp" )
|
: >>"$target.did"
|
||||||
|
( _run_dofile "$base" "$ext" "$tmp.tmp" )
|
||||||
rv=$?
|
rv=$?
|
||||||
if [ $rv != 0 ]; then
|
if [ $rv != 0 ]; then
|
||||||
printf "do: %s%s\n" "$DO_DEPTH" \
|
printf "do: %s%s\n" "$DO_DEPTH" \
|
||||||
"$dir$target: got exit code $rv" >&2
|
"$dir$target: got exit code $rv" >&2
|
||||||
rm -f "$target.tmp" "$target.tmp2"
|
rm -f "$tmp.tmp" "$tmp.tmp2"
|
||||||
return $rv
|
return $rv
|
||||||
fi
|
fi
|
||||||
mv "$target.tmp" "$target" 2>/dev/null ||
|
mv "$tmp.tmp" "$target" 2>/dev/null ||
|
||||||
! test -s "$target.tmp2" ||
|
! test -s "$tmp.tmp2" ||
|
||||||
mv "$target.tmp2" "$target" 2>/dev/null
|
mv "$tmp.tmp2" "$target" 2>/dev/null
|
||||||
rm -f "$target.tmp2"
|
rm -f "$tmp.tmp2"
|
||||||
else
|
else
|
||||||
echo "do $DO_DEPTH$target exists." >&2
|
echo "do $DO_DEPTH$target exists." >&2
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Make corrections for directories that don't actually exist yet.
|
||||||
|
_dir_shovel()
|
||||||
|
{
|
||||||
|
local dir base
|
||||||
|
xdir=$1 xbase=$2 xbasetmp=$2
|
||||||
|
while [ ! -d "$xdir" -a -n "$xdir" ]; do
|
||||||
|
_dirsplit "${xdir%/}"
|
||||||
|
xbasetmp=${base}__$xbase
|
||||||
|
xdir=$dir xbase=$base/$xbase
|
||||||
|
echo "xbasetmp='$xbasetmp'" >&2
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
redo()
|
redo()
|
||||||
{
|
{
|
||||||
for i in "$@"; do
|
for i in "$@"; do
|
||||||
_dirsplit "$i"
|
_dirsplit "$i"
|
||||||
( cd "$dir" && _do "$dir" "$base" ) || return 1
|
_dir_shovel "$dir" "$base"
|
||||||
|
dir=$xdir base=$xbase basetmp=$xbasetmp
|
||||||
|
( cd "$dir" && _do "$dir" "$base" "$basetmp" ) || return 1
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue