aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-07-11 11:01:12 +0200
committerDanilo M. <danix@danix.xyz>2026-07-11 11:01:12 +0200
commit3acd48aad8be07754581650ee6400de88073290c (patch)
treea34ebe848e67bf37ff817f2af67b81d65a07d9b1
parente6d0da3f80aac688929c41db37e7233ca7c429cb (diff)
downloadsbo-batch-tester-3acd48aad8be07754581650ee6400de88073290c.tar.gz
sbo-batch-tester-3acd48aad8be07754581650ee6400de88073290c.zip
Add collect_shadows dup detection + self-check
Finds upstream SBo packages shadowed by a personal-tree twin, read-only, no removal. Personal package = subdir with matching <name>.SlackBuild; prune array excludes every SBO_PERSONAL_TREES path from the search so a personal package never lists itself. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-rwxr-xr-xsbo-batch-test26
-rwxr-xr-xtest-logic.sh22
2 files changed, 48 insertions, 0 deletions
diff --git a/sbo-batch-test b/sbo-batch-test
index f2b9c14..c028df1 100755
--- a/sbo-batch-test
+++ b/sbo-batch-test
@@ -343,6 +343,32 @@ rsync_tree() {
"$SBO_RSYNC_URL/" "$root/"
}
+# Echo (one per line) the <root>-relative dirs of upstream packages that
+# duplicate a package in a personal subtree. Reads only, never removes. A
+# personal package is a subdir with a matching <name>.SlackBuild; an upstream
+# dup is a same-named depth-2 dir anywhere under <root> outside the personal
+# trees.
+collect_shadows() {
+ local root="$1"
+ local -a personal_dirs=() prune=()
+ local dir
+ for dir in "${!SBO_PERSONAL_TREES[@]}"; do
+ [[ -d "$root/$dir" ]] || continue
+ personal_dirs+=("$root/$dir")
+ prune+=(! -path "$root/$dir/*")
+ done
+ [[ ${#personal_dirs[@]} -eq 0 ]] && return
+ local pkgdir pkg match
+ while IFS= read -r pkgdir; do
+ pkg=$(basename "$pkgdir")
+ [[ -f "$pkgdir/$pkg.SlackBuild" ]] || continue
+ while IFS= read -r match; do
+ echo "${match#"$root"/}"
+ done < <(find "$root" -mindepth 2 -maxdepth 2 -type d \
+ -name "$pkg" "${prune[@]}")
+ done < <(find "${personal_dirs[@]}" -mindepth 1 -maxdepth 1 -type d)
+}
+
# =============================================================================
# Package cache. Persistent, on-disk store of built packages so unchanged deps
# are installed from cache instead of rebuilt. Layout mirrors the SBo tree:
diff --git a/test-logic.sh b/test-logic.sh
index 423d2b5..cbdef9d 100755
--- a/test-logic.sh
+++ b/test-logic.sh
@@ -152,6 +152,28 @@ echo "$ex" | grep -qx -- "--exclude=/pentesting/" && ok "rsync_excludes pentesti
declare -A SBO_PERSONAL_TREES=()
[[ -z "$(rsync_excludes)" ]] && ok "rsync_excludes empty for no trees" || bad "rsync_excludes should be empty, got [$(rsync_excludes)]"
+# --- collect_shadows: upstream dups of personal packages -------------------
+S=$(mktemp -d)
+mkslb() { mkdir -p "$S/$1/$2"; : > "$S/$1/$2/$2.SlackBuild"; }
+# upstream copies
+mkslb academic foo
+mkslb network bar
+# personal copies (win)
+mkslb personal foo
+mkslb pentesting bar
+# decoy: personal pkg with no upstream twin
+mkslb personal nomatch
+# decoy: personal subdir without a .SlackBuild (ignored)
+mkdir -p "$S/personal/noslb"
+declare -A SBO_PERSONAL_TREES=([personal]=u1 [pentesting]=u2)
+
+got="$(collect_shadows "$S" | sort)"
+want="$(printf 'academic/foo\nnetwork/bar\n' | sort)"
+[[ "$got" == "$want" ]] && ok "collect_shadows finds upstream dups only" || bad "collect_shadows wrong; got [$got] want [$want]"
+echo "$got" | grep -q "personal/" && bad "collect_shadows returned a personal path" || ok "collect_shadows excludes personal trees"
+echo "$got" | grep -q "nomatch" && bad "collect_shadows invented a match for nomatch" || ok "collect_shadows ignores no-twin pkg"
+rm -rf "$S"
+
# --- result -----------------------------------------------------------------
echo
echo "$pass passed, $fail failed"