Files
OpenShell/scripts/bin/openshell

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" "$@"