mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-07 18:25:59 +08:00
144 lines
4.0 KiB
Bash
Executable File
144 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
BINARY="$PROJECT_ROOT/target/debug/openshell"
|
|
STATE_FILE="$PROJECT_ROOT/.cache/openshell-build.state"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Fingerprint-based rebuild check
|
|
#
|
|
# Mirrors the approach in tasks/scripts/cluster-deploy-fast.sh: collect dirty
|
|
# files from git, filter to paths in the navigator-cli dependency closure,
|
|
# hash their contents, and compare against a persisted state file. We also
|
|
# track HEAD so that branch switches / pulls are detected.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
needs_build=0
|
|
|
|
if [[ ! -x "$BINARY" ]]; then
|
|
needs_build=1
|
|
else
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Current HEAD commit (detects branch switches, pulls, rebases)
|
|
current_head=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
|
|
|
|
# Collect dirty (modified, staged, untracked) files
|
|
mapfile -t changed_files < <(
|
|
{
|
|
git diff --name-only 2>/dev/null
|
|
git diff --name-only --cached 2>/dev/null
|
|
git ls-files --others --exclude-standard 2>/dev/null
|
|
} | sort -u
|
|
)
|
|
|
|
# Filter to paths that can affect the navigator-cli binary
|
|
matches_cli() {
|
|
local path=$1
|
|
case "$path" in
|
|
Cargo.toml|Cargo.lock|proto/*)
|
|
return 0 ;;
|
|
crates/navigator-cli/*|crates/navigator-core/*|crates/navigator-bootstrap/*)
|
|
return 0 ;;
|
|
crates/navigator-policy/*|crates/navigator-providers/*|crates/navigator-tui/*)
|
|
return 0 ;;
|
|
*)
|
|
return 1 ;;
|
|
esac
|
|
}
|
|
|
|
# Compute a composite fingerprint of matching dirty files
|
|
payload=""
|
|
for path in "${changed_files[@]}"; do
|
|
matches_cli "$path" || continue
|
|
if [[ -e "$path" ]]; then
|
|
digest=$(shasum -a 256 "$path" | cut -d ' ' -f 1)
|
|
else
|
|
digest="__MISSING__"
|
|
fi
|
|
payload+="${path}:${digest}"$'\n'
|
|
done
|
|
|
|
if [[ -n "$payload" ]]; then
|
|
current_fingerprint=$(printf '%s' "$payload" | shasum -a 256 | cut -d ' ' -f 1)
|
|
else
|
|
current_fingerprint=""
|
|
fi
|
|
|
|
# Load previous state
|
|
previous_head=""
|
|
previous_fingerprint=""
|
|
if [[ -f "$STATE_FILE" ]]; then
|
|
while IFS='=' read -r key value; do
|
|
case "$key" in
|
|
head) previous_head=$value ;;
|
|
fingerprint) previous_fingerprint=$value ;;
|
|
esac
|
|
done < "$STATE_FILE"
|
|
fi
|
|
|
|
# Decide whether to rebuild
|
|
if [[ "$current_head" != "$previous_head" ]]; then
|
|
needs_build=1
|
|
elif [[ "$current_fingerprint" != "$previous_fingerprint" ]]; then
|
|
needs_build=1
|
|
fi
|
|
fi
|
|
|
|
if [[ "$needs_build" == "1" ]]; then
|
|
echo "Recompiling openshell..." >&2
|
|
cargo build --package navigator-cli --quiet
|
|
# Persist state after successful build
|
|
mkdir -p "$(dirname "$STATE_FILE")"
|
|
cd "$PROJECT_ROOT"
|
|
new_head=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
|
|
# Recompute fingerprint of remaining dirty files (build may not change them)
|
|
mapfile -t post_files < <(
|
|
{
|
|
git diff --name-only 2>/dev/null
|
|
git diff --name-only --cached 2>/dev/null
|
|
git ls-files --others --exclude-standard 2>/dev/null
|
|
} | sort -u
|
|
)
|
|
|
|
matches_cli() {
|
|
local path=$1
|
|
case "$path" in
|
|
Cargo.toml|Cargo.lock|proto/*)
|
|
return 0 ;;
|
|
crates/navigator-cli/*|crates/navigator-core/*|crates/navigator-bootstrap/*)
|
|
return 0 ;;
|
|
crates/navigator-policy/*|crates/navigator-providers/*|crates/navigator-tui/*)
|
|
return 0 ;;
|
|
*)
|
|
return 1 ;;
|
|
esac
|
|
}
|
|
|
|
post_payload=""
|
|
for path in "${post_files[@]}"; do
|
|
matches_cli "$path" || continue
|
|
if [[ -e "$path" ]]; then
|
|
digest=$(shasum -a 256 "$path" | cut -d ' ' -f 1)
|
|
else
|
|
digest="__MISSING__"
|
|
fi
|
|
post_payload+="${path}:${digest}"$'\n'
|
|
done
|
|
|
|
if [[ -n "$post_payload" ]]; then
|
|
new_fingerprint=$(printf '%s' "$post_payload" | shasum -a 256 | cut -d ' ' -f 1)
|
|
else
|
|
new_fingerprint=""
|
|
fi
|
|
|
|
cat > "$STATE_FILE" <<EOF
|
|
head=${new_head}
|
|
fingerprint=${new_fingerprint}
|
|
EOF
|
|
fi
|
|
|
|
exec "$BINARY" "$@"
|