scripts/deps-accept.sh: 8 checks over local file:// remotes built at run time (network-free) — cold fetch + lock + use <dep>/<dep>/sub + app-entry- wins (the dep's fn main returns 99 and must never run), offline rebuild with the remote deleted, lock-beats-moved-tag, --update-deps refresh, cache/lock drift WO-E106, transitive refusal, WO-E107 collision, missing-rev manifest shape. `just deps-accept` wired. 8/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
165 lines
5.2 KiB
Bash
Executable file
165 lines
5.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# scripts/deps-accept.sh — iteration 15's acceptance gate: wo.toml [deps] +
|
|
# git fetch + wo.lock, proven against local file:// remotes built at run time
|
|
# (network-free). One check per spec behavior, log-watcher-accept style.
|
|
set -uo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
WOC="$ROOT/compiler/_build/default/bin/woc"
|
|
WOVM="$ROOT/runtime/wovm"
|
|
|
|
pass=0
|
|
fail=0
|
|
ok() { echo "ok $1"; pass=$((pass + 1)); }
|
|
bad() { echo "FAIL $1 -- $2"; fail=$((fail + 1)); }
|
|
|
|
if [[ ! -x "$WOC" || ! -x "$WOVM" ]]; then
|
|
echo "deps-accept: build woc and wovm first (just woc-build; just wovm-build)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
W="$(mktemp -d "${TMPDIR:-/tmp}/deps-accept.XXXXXX")"
|
|
cleanup() { [[ -n "${DEPS_ACCEPT_KEEP:-}" ]] && echo "kept $W" || rm -rf "$W"; }
|
|
trap cleanup EXIT
|
|
G() { git -C "$1" -c user.email=t@t -c user.name=t "${@:2}"; }
|
|
|
|
# ---- the framework remote: a real git repo with a tag ----
|
|
mkdir -p "$W/fwsrc/strutil"
|
|
cat > "$W/fwsrc/wo.toml" <<'EOF'
|
|
name = "niceframework"
|
|
version = "0.1.0"
|
|
EOF
|
|
cat > "$W/fwsrc/greet.wo" <<'EOF'
|
|
pub fn greeting(who: Text) -> Text {
|
|
return "hello, " .. who
|
|
}
|
|
fn main(args: multi Text) -> Int {
|
|
return 99
|
|
}
|
|
EOF
|
|
cat > "$W/fwsrc/strutil/shout.wo" <<'EOF'
|
|
pub fn quiet(t: Text) -> Text {
|
|
return to_lower(t)
|
|
}
|
|
EOF
|
|
git -C "$W/fwsrc" init -q
|
|
G "$W/fwsrc" add -A
|
|
G "$W/fwsrc" commit -qm one
|
|
G "$W/fwsrc" tag v0.1.0
|
|
|
|
# ---- the consuming app ----
|
|
mkdir -p "$W/app"
|
|
cat > "$W/app/wo.toml" <<EOF
|
|
name = "app"
|
|
version = "0.1.0"
|
|
[build]
|
|
runtime = "$WOVM"
|
|
[deps]
|
|
niceframework = { git = "file://$W/fwsrc", rev = "v0.1.0" }
|
|
EOF
|
|
cat > "$W/app/main.wo" <<'EOF'
|
|
use niceframework
|
|
use niceframework/strutil
|
|
|
|
fn main(args: multi Text) -> Int {
|
|
print(greeting("web"));
|
|
print(quiet("QUIET"));
|
|
return 0;
|
|
}
|
|
EOF
|
|
|
|
# ---- 1. cold fetch + lock + build + run (dep main must NOT be the entry:
|
|
# the dep's main returns 99; the app's prints and returns 0) ----
|
|
out="$(cd /tmp && "$WOC" "$W/app" 2>&1 && "$W/app/target/app")"
|
|
rc=$?
|
|
if [[ $rc -eq 0 && "$out" == "hello, web
|
|
quiet" && -f "$W/app/wo.lock" ]]; then
|
|
ok "cold fetch + lock + use <dep> and <dep>/sub + app entry wins"
|
|
else
|
|
bad "cold build" "rc=$rc out=$(printf '%s' "$out" | tr '\n' '|')"
|
|
fi
|
|
locked_sha="$(awk '!/^#/ {print $2}' "$W/app/wo.lock")"
|
|
|
|
# ---- 2. offline rebuild: remote removed, lock + cache satisfy ----
|
|
mv "$W/fwsrc" "$W/fwsrc.hidden"
|
|
rm -rf "$W/app/target"
|
|
if "$WOC" "$W/app" >/dev/null 2>&1 && [[ "$("$W/app/target/app")" == "hello, web
|
|
quiet" ]]; then
|
|
ok "offline rebuild (remote deleted, lock satisfied)"
|
|
else
|
|
bad "offline rebuild" "failed with the remote gone"
|
|
fi
|
|
mv "$W/fwsrc.hidden" "$W/fwsrc"
|
|
|
|
# ---- 3. moved tag: cold cache + lock -> rebuilt at the LOCKED sha ----
|
|
G "$W/fwsrc" commit -qm two --allow-empty
|
|
G "$W/fwsrc" tag -f v0.1.0 >/dev/null 2>&1
|
|
rm -rf "$W/app/.wo-deps"
|
|
"$WOC" "$W/app" >/dev/null 2>&1
|
|
now_sha="$(git -C "$W/app/.wo-deps/niceframework" rev-parse HEAD 2>/dev/null)"
|
|
if [[ "$now_sha" == "$locked_sha" ]]; then
|
|
ok "moved tag: lock wins (checkout pinned to the locked SHA)"
|
|
else
|
|
bad "moved tag" "expected $locked_sha got $now_sha"
|
|
fi
|
|
|
|
# ---- 4. --update-deps follows the tag and rewrites the lock ----
|
|
"$WOC" --update-deps "$W/app" >/dev/null 2>&1
|
|
new_lock="$(awk '!/^#/ {print $2}' "$W/app/wo.lock")"
|
|
tag_sha="$(git -C "$W/fwsrc" rev-parse v0.1.0)"
|
|
if [[ "$new_lock" == "$tag_sha" && "$new_lock" != "$locked_sha" ]]; then
|
|
ok "--update-deps refreshes the lock to the moved tag"
|
|
else
|
|
bad "--update-deps" "lock=$new_lock tag=$tag_sha"
|
|
fi
|
|
|
|
# ---- 5. cache/lock drift is a named diagnostic ----
|
|
G "$W/app/.wo-deps/niceframework" commit -qm local --allow-empty
|
|
out="$("$WOC" "$W/app" 2>&1)"
|
|
if [[ "$out" == *"WO-E106"* && "$out" == *"lock drift"* ]]; then
|
|
ok "cache/lock drift diagnosed (WO-E106)"
|
|
else
|
|
bad "drift" "$(printf '%s' "$out" | head -1)"
|
|
fi
|
|
git -C "$W/app/.wo-deps/niceframework" reset -q --hard HEAD~1
|
|
|
|
# ---- 6. transitive [deps] refused ----
|
|
printf '[deps]\nx = { git = "file:///nowhere", rev = "v1" }\n' >> "$W/fwsrc/wo.toml"
|
|
G "$W/fwsrc" commit -qam trans
|
|
G "$W/fwsrc" tag -f v0.1.0 >/dev/null 2>&1
|
|
rm -rf "$W/app/.wo-deps" "$W/app/wo.lock"
|
|
out="$("$WOC" "$W/app" 2>&1)"
|
|
if [[ "$out" == *"WO-E106"* && "$out" == *"transitive"* ]]; then
|
|
ok "transitive [deps] refused (flat-only)"
|
|
else
|
|
bad "transitive" "$(printf '%s' "$out" | head -1)"
|
|
fi
|
|
G "$W/fwsrc" revert --no-edit HEAD >/dev/null 2>&1
|
|
G "$W/fwsrc" tag -f v0.1.0 >/dev/null 2>&1
|
|
|
|
# ---- 7. dep name colliding with a local module directory ----
|
|
mkdir -p "$W/app/niceframework"
|
|
touch "$W/app/niceframework/x.wo"
|
|
rm -rf "$W/app/.wo-deps" "$W/app/wo.lock"
|
|
out="$("$WOC" "$W/app" 2>&1)"
|
|
if [[ "$out" == *"WO-E107"* ]]; then
|
|
ok "dep/local module-name collision diagnosed (WO-E107)"
|
|
else
|
|
bad "collision" "$(printf '%s' "$out" | head -1)"
|
|
fi
|
|
rm -rf "$W/app/niceframework"
|
|
|
|
# ---- 8. manifest shape: a dep without `rev` is refused at parse ----
|
|
mkdir -p "$W/norev"
|
|
printf 'name = "norev"\n[deps]\nfw = { git = "file:///x" }\n' > "$W/norev/wo.toml"
|
|
printf 'fn main(args: multi Text) -> Int { return 0 }\n' > "$W/norev/main.wo"
|
|
out="$("$WOC" "$W/norev" 2>&1)"
|
|
if [[ "$out" == *"needs both"* ]]; then
|
|
ok "missing rev refused at manifest parse"
|
|
else
|
|
bad "missing rev" "$(printf '%s' "$out" | head -1)"
|
|
fi
|
|
|
|
echo
|
|
printf 'deps-accept: %d checks, %d failures\n' "$((pass + fail))" "$fail"
|
|
[[ $fail -eq 0 ]]
|