|
| 1 | +#!/usr/bin/env bash |
| 2 | +# requires: |
| 3 | +# 210_local_index_addressing_on_every_host.sh — a `[indices]` path must address |
| 4 | +# the same directory on every host, whether it is written absolute or inherited |
| 5 | +# from a workspace root. |
| 6 | +# |
| 7 | +# This exists because the tests that covered local-index addressing all needed |
| 8 | +# a compiler or a fresh sandbox, and Windows has neither capability — so the |
| 9 | +# platform where path SEMANTICS actually differ was the one platform never |
| 10 | +# asserting them. A fixture wrote an MSYS path into mcpp.toml, a native |
| 11 | +# mcpp.exe read the leading `/` as "root of the current drive", and the |
| 12 | +# resulting "package not found in any configured index" was chased for a day |
| 13 | +# through the workspace inheritance code, which was not involved at all. |
| 14 | +# |
| 15 | +# So: no compiler, no sandbox bootstrap, no network. Everything here is |
| 16 | +# assertable at the resolution layer, which is exactly the layer that was |
| 17 | +# broken. `mcpp add` is the probe because its existence gate reads through the |
| 18 | +# same routing `mcpp build` resolves dependencies with. |
| 19 | +set -euo pipefail |
| 20 | +source "$(dirname "$0")/_host_path.sh" |
| 21 | + |
| 22 | +TMP=$(mktemp -d) |
| 23 | +trap 'rm -rf "$TMP"' EXIT |
| 24 | + |
| 25 | +make_index() { # make_index <dir> |
| 26 | + mkdir -p "$1/pkgs/a" |
| 27 | + cat > "$1/pkgs/a/acme.util.lua" <<'EOF' |
| 28 | +package = { |
| 29 | + spec = "1", |
| 30 | + namespace = "acme", |
| 31 | + name = "util", |
| 32 | + description = "local index fixture", |
| 33 | + licenses = {"MIT"}, |
| 34 | + type = "package", |
| 35 | + xpm = { |
| 36 | + linux = { ["2.0.0"] = { url = "https://example.invalid/u.tar.gz" } }, |
| 37 | + macosx = { ["2.0.0"] = { url = "https://example.invalid/u.tar.gz" } }, |
| 38 | + windows = { ["2.0.0"] = { url = "https://example.invalid/u.zip" } }, |
| 39 | + }, |
| 40 | +} |
| 41 | +EOF |
| 42 | +} |
| 43 | + |
| 44 | +# ── 1. an ABSOLUTE [indices] path ─────────────────────────────────── |
| 45 | +make_index "$TMP/abs-index" |
| 46 | +INDEX_HOST="$(host_path "$TMP/abs-index")" |
| 47 | +mkdir -p "$TMP/abs-app" |
| 48 | +cat > "$TMP/abs-app/mcpp.toml" <<EOF |
| 49 | +[package] |
| 50 | +name = "absapp" |
| 51 | +version = "0.1.0" |
| 52 | +
|
| 53 | +[indices] |
| 54 | +acme = { path = "$INDEX_HOST" } |
| 55 | +EOF |
| 56 | +cd "$TMP/abs-app" |
| 57 | + |
| 58 | +"$MCPP" add acme.util@2.0.0 > /dev/null || { |
| 59 | + echo "FAIL: an absolute local index path did not resolve on this host" |
| 60 | + "$MCPP" add acme.util@2.0.0 2>&1 | sed 's/^/ /' |
| 61 | + exit 1 |
| 62 | +} |
| 63 | +grep -qE '^util = "2\.0\.0"$' mcpp.toml || { |
| 64 | + cat mcpp.toml; echo "FAIL: dependency was not written"; exit 1; } |
| 65 | + |
| 66 | +# A miss must report the index as READABLE. "root absent" here would mean the |
| 67 | +# path was addressed but does not exist — the exact fingerprint of a path |
| 68 | +# written in the wrong spelling. |
| 69 | +err=$("$MCPP" add acme.nope@1.0.0 2>&1) && { |
| 70 | + echo "FAIL: expected a miss for acme.nope"; exit 1; } |
| 71 | +[[ "$err" == *"route: local index 'acme': root present, pkgs present"* ]] || { |
| 72 | + echo "$err" |
| 73 | + echo "FAIL: the absolute index is not being addressed as a readable root" |
| 74 | + exit 1 |
| 75 | +} |
| 76 | + |
| 77 | +# ── 2. a workspace member inheriting a ROOT-RELATIVE index ────────── |
| 78 | +# The member sees no [indices] of its own; the root's relative `path = "index"` |
| 79 | +# is anchored at the ROOT, not at the member's directory. |
| 80 | +mkdir -p "$TMP/ws" |
| 81 | +make_index "$TMP/ws/index" |
| 82 | +cat > "$TMP/ws/mcpp.toml" <<'EOF' |
| 83 | +[workspace] |
| 84 | +members = ["m1"] |
| 85 | +
|
| 86 | +[indices] |
| 87 | +acme = { path = "index" } |
| 88 | +EOF |
| 89 | +mkdir -p "$TMP/ws/m1" |
| 90 | +cat > "$TMP/ws/m1/mcpp.toml" <<'EOF' |
| 91 | +[package] |
| 92 | +name = "m1" |
| 93 | +version = "0.1.0" |
| 94 | +EOF |
| 95 | +cd "$TMP/ws/m1" |
| 96 | + |
| 97 | +"$MCPP" add acme.util@2.0.0 > /dev/null || { |
| 98 | + echo "FAIL: a workspace member could not read its root-owned local index" |
| 99 | + "$MCPP" add acme.util@2.0.0 2>&1 | sed 's/^/ /' |
| 100 | + exit 1 |
| 101 | +} |
| 102 | +grep -qE '^util = "2\.0\.0"$' mcpp.toml || { |
| 103 | + cat mcpp.toml; echo "FAIL: member did not inherit the workspace [indices]"; exit 1; } |
| 104 | + |
| 105 | +err=$("$MCPP" add acme.nope@1.0.0 2>&1) && { |
| 106 | + echo "FAIL: expected a miss inside the workspace member"; exit 1; } |
| 107 | +[[ "$err" == *"route: local index 'acme': root present, pkgs present"* ]] || { |
| 108 | + echo "$err" |
| 109 | + echo "FAIL: the inherited index was anchored somewhere unreadable" |
| 110 | + exit 1 |
| 111 | +} |
| 112 | + |
| 113 | +# ── 3. the route diagnostic stays privacy-safe ────────────────────── |
| 114 | +# It is what makes a wrong path diagnosable at all, so it must be printed — and |
| 115 | +# it must not print the path, which is why it says present/absent instead. |
| 116 | +case "$err" in |
| 117 | + *"$TMP"* | *"$(host_path "$TMP")"*) |
| 118 | + echo "FAIL: the route diagnostic leaked a filesystem path" |
| 119 | + exit 1 |
| 120 | + ;; |
| 121 | +esac |
| 122 | + |
| 123 | +echo "OK" |
0 commit comments