Commitd0f9618bRecorded22 Sep 2026Repositorydocket

docket wrapper: tolerate a concurrent move of the shadowing (sigil args), refuse anything else

Message

Two docket commands started together can both see args.sgb and race to move it; the loser's mv failed and set -e killed a command whose load path was already clean. The move now tolerates exactly that case (the file is gone) and dies loudly if the file is still in the load path.

Tested: fresh build, four concurrent 'docket fold' calls, all rc=0 with identical output. With the aside directory made read-only, the command refuses naming the file and t-de026a (rc=1).

Changed
 docket | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
Diff
docketmodified
@@ -48,8 +48,15 @@ unshadow_cli_modules() {
48
for f in "$lib/args.sgb" "$lib/args.sgb.sgci" "$lib/args.json" "$lib/args.sgs"; do
49
[[ -e $f ]] || continue
50
mkdir -p "$aside"
−51
mv -f "$f" "$aside/"
−52
moved="$moved ${f##*/}"
+51
# Two docket commands started together can both see the file and race to
+52
# move it. The loser's mv fails, and under `set -e' that would kill a
+53
# command over a file that is already where it should be. Tolerate exactly
+54
# that case -- the file is gone from the load path -- and nothing else.
+55
if mv -f "$f" "$aside/" 2>/dev/null; then
+56
moved="$moved ${f##*/}"
+57
elif [[ -e $f ]]; then
+58
die "could not move $f out of the load path (t-de026a workaround)"
+59
fi
60
done
61
if [[ -n $moved ]]; then
62
echo "docket: moved (sigil args) out of build/dev/lib into ${aside##*/}/ --$moved" >&2