fix(board): discover dot-prefixed repos (.profile) without dotglob's scope creep
board.sh's discovery loops (for entry in "$root"/*, and the polyrepo container's child loop) never see dot-prefixed directories - measured with a known-positive control: two repos in one root, one dot-prefixed, board found only the other. This makes any dot-repo (e.g. .profile, the Forgejo/GitHub org-profile convention) permanently invisible: not listed, and --dispatch --repo .profile refuses outright. A blanket `shopt -s dotglob` is not the fix: it would also route a dot-prefixed non-repo dir (e.g. .claude) into the container-scan branch, silently expanding what counts as a polyrepo container. Instead, add_dot_repos() picks up only dot-entries that are themselves git repos, at both discovery depths, leaving non-repo dot-dirs untouched. `.*` as a literal glob pattern already matches dot-entries without dotglob, so no shopt toggle is needed. Closes ordre 20260818T124828Z-136209036-from-.claude. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qMr8vZZFwa4dBrheNgAhj
This commit is contained in:
parent
393499c3ee
commit
3e5add0aee
2 changed files with 94 additions and 0 deletions
|
|
@ -1973,6 +1973,71 @@ grep -v '^[[:space:]]*#' "$NRFNR_FIXTURE" | grep -q 'NR==FNR'
|
|||
check "the same filter+grep DOES find a live NR==FNR in a known-positive fixture" $?
|
||||
/bin/rm -f "$NRFNR_FIXTURE" 2>/dev/null
|
||||
|
||||
# --- 22. Dot-prefixed repo discovery (board.sh:265/271 dotglob gap) --------
|
||||
# Ordre 20260818T124828Z-136209036-from-.claude, measured: `for entry in
|
||||
# "$root"/*` has no dotglob, so a dot-prefixed repo directory (the Forgejo/
|
||||
# GitHub `.profile` org-profile convention) is never seen by board at all -
|
||||
# not listed, not dispatchable ("no repo named '.profile' in the scanned
|
||||
# roots"). Known-positive control per the order: two repos in one isolated
|
||||
# root, one dot-prefixed, one not - board must find BOTH, not just the dot
|
||||
# one (a test that only checked the dot-repo would pass even if the fix
|
||||
# broke the ordinary case).
|
||||
DOT_ROOT="$(mktemp -d)"
|
||||
mkrepo "$DOT_ROOT/.dotrepo"
|
||||
{
|
||||
echo "# STATE - .dotrepo"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
|
||||
echo "Dot-prefixed repo, e.g. the .profile org-profile convention."
|
||||
} > "$DOT_ROOT/.dotrepo/STATE.md"
|
||||
mkrepo "$DOT_ROOT/regularrepo"
|
||||
{
|
||||
echo "# STATE - regularrepo"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
|
||||
echo "Ordinary repo, no leading dot."
|
||||
} > "$DOT_ROOT/regularrepo/STATE.md"
|
||||
|
||||
DOT_OUT="$("$BOARD" --roots "$DOT_ROOT" --plain 2>/dev/null)"
|
||||
printf '%s' "$DOT_OUT" | grep -q '\.dotrepo'
|
||||
check "board finds a dot-prefixed repo" $?
|
||||
printf '%s' "$DOT_OUT" | grep -q 'regularrepo'
|
||||
check "board still finds the ordinary repo alongside it (known-positive)" $?
|
||||
printf '%s' "$DOT_OUT" | grep -q '(2 repo'
|
||||
check "board reports both repos, not just one" $?
|
||||
|
||||
# A dot-prefixed directory that is NOT itself a repo must never become a
|
||||
# polyrepo container: a naive `shopt -s dotglob` on the existing else-branch
|
||||
# (board.sh:270-275) would route a dir like .claude there, silently
|
||||
# expanding what counts as a container - unmeasured scope creep the order
|
||||
# explicitly flagged. Its child repo must stay invisible.
|
||||
mkdir -p "$DOT_ROOT/.nonrepo-dotdir"
|
||||
mkrepo "$DOT_ROOT/.nonrepo-dotdir/child-repo"
|
||||
DOT_OUT2="$("$BOARD" --roots "$DOT_ROOT" --plain 2>/dev/null)"
|
||||
printf '%s' "$DOT_OUT2" | grep -q 'child-repo'
|
||||
[ $? -ne 0 ]
|
||||
check "a dot-prefixed NON-repo dir is not turned into a polyrepo container" $?
|
||||
printf '%s' "$DOT_OUT2" | grep -q '(2 repo'
|
||||
check "the non-repo dot-dir does not change the repo count" $?
|
||||
|
||||
# Same glob, second place (board.sh:271): a dot-prefixed repo nested under a
|
||||
# polyrepo container (depth 2) must also be found, for the identical reason
|
||||
# - the order flags this as the same defect class, unmeasured but present in
|
||||
# the code.
|
||||
mkdir -p "$DOT_ROOT/polyrepo-dir"
|
||||
mkrepo "$DOT_ROOT/polyrepo-dir/.dotchild"
|
||||
{
|
||||
echo "# STATE - .dotchild"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
|
||||
echo "Dot-prefixed repo nested under a polyrepo container."
|
||||
} > "$DOT_ROOT/polyrepo-dir/.dotchild/STATE.md"
|
||||
DOT_OUT3="$("$BOARD" --roots "$DOT_ROOT" --plain 2>/dev/null)"
|
||||
printf '%s' "$DOT_OUT3" | grep -q '\.dotchild'
|
||||
check "board finds a dot-prefixed repo nested under a polyrepo container (depth 2)" $?
|
||||
|
||||
/bin/rm -rf "$DOT_ROOT" 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "board-selftest: $PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ] || exit 1
|
||||
|
|
|
|||
|
|
@ -254,6 +254,31 @@ trunc() { printf '%s' "$1" | LC_ALL=en_US.UTF-8 cut -c1-"$2"; }
|
|||
# can CARRY its own STATE.md - a -d test drops it silently. Kept identical in
|
||||
# the rollup builder (catalog) on purpose: two readers, one name.
|
||||
REPOS=""
|
||||
|
||||
# Picks up dot-prefixed git repos directly under $1 - the Forgejo/GitHub
|
||||
# `.profile` org-profile convention, measured invisible to the loops below
|
||||
# (ordre 20260818T124828Z-136209036-from-.claude: `for entry in "$root"/*`
|
||||
# has no dotglob, so a dot-prefixed repo is never seen at all). A blanket
|
||||
# `shopt -s dotglob` on the loops below is deliberately NOT the fix: it
|
||||
# would also route a dot-prefixed NON-repo dir (e.g. .claude) into the
|
||||
# else-branch container-scan, silently expanding what counts as a polyrepo
|
||||
# container - unmeasured scope creep the order explicitly flagged. `.* ` as
|
||||
# a literal glob pattern already matches dot-entries without dotglob (only
|
||||
# a bare `*` needs dotglob to see them), so no shopt toggle is needed here.
|
||||
# Only a dot-entry that IS itself a repo is ever added; one that is not is
|
||||
# silently skipped, never recursed into as a container.
|
||||
add_dot_repos() {
|
||||
for dotentry in "$1"/.*; do
|
||||
dotbase="$(basename "$dotentry")"
|
||||
[ "$dotbase" = "." ] && continue
|
||||
[ "$dotbase" = ".." ] && continue
|
||||
[ -d "$dotentry" ] || continue
|
||||
[ -e "$dotentry/.git" ] || continue
|
||||
REPOS="$REPOS
|
||||
$dotentry"
|
||||
done
|
||||
}
|
||||
|
||||
# Split on comma via IFS + `set --` rather than an unquoted $(...) expansion:
|
||||
# unquoted word-splitting would also split roots containing spaces. Arg parsing
|
||||
# is finished above, so clobbering the positional parameters is safe here.
|
||||
|
|
@ -262,6 +287,7 @@ set -- $ROOTS
|
|||
IFS="$OLD_IFS"
|
||||
for root in "$@"; do
|
||||
[ -d "$root" ] || continue
|
||||
add_dot_repos "$root"
|
||||
for entry in "$root"/*; do
|
||||
[ -d "$entry" ] || continue
|
||||
if [ -e "$entry/.git" ]; then
|
||||
|
|
@ -273,6 +299,9 @@ $entry"
|
|||
REPOS="$REPOS
|
||||
$child"
|
||||
done
|
||||
# Same glob, same gap, one level down (board.sh:271 in the order's
|
||||
# numbering) - a dot-prefixed repo nested under a polyrepo container.
|
||||
add_dot_repos "$entry"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue