4e88d1915f
- check-fork-drift.sh: compares each submodule HEAD against upstream/master, reports behind/ahead counts, exits 1 if any fork exceeds threshold - upgrade-forks.sh: fetches latest upstream, saves RB commits, resets to upstream, cherry-picks RB patches with conflict handling and backups - build-preflight.sh: wired drift check into preflight (threshold=50, suppressible via REDBEAR_SKIP_DRIFT_CHECK=1) - bootloader submodule pointer updated to latest upstream rebase
166 lines
6.0 KiB
Bash
Executable File
166 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# check-fork-drift.sh — Detect upstream drift in Red Bear OS local forks.
|
|
#
|
|
# For each submodule in local/sources/, fetches upstream and reports:
|
|
# - Commits behind upstream (new upstream commits we don't have)
|
|
# - Commits ahead of upstream (our Red Bear patches)
|
|
# - Upstream HEAD date vs our HEAD date
|
|
#
|
|
# Exits 1 if any fork is behind upstream beyond the threshold.
|
|
#
|
|
# Usage:
|
|
# ./local/scripts/check-fork-drift.sh # Report all
|
|
# ./local/scripts/check-fork-drift.sh --threshold=20 # Fail if any fork >20 behind
|
|
# ./local/scripts/check-fork-drift.sh --fetch-depth=100 # Deeper fetch (default: 200)
|
|
# ./local/scripts/check-fork-drift.sh --no-fetch # Skip network fetch (use cached refs)
|
|
# ./local/scripts/check-fork-drift.sh --json Machine-readable output
|
|
# ./local/scripts/check-fork-drift.sh --quiet Only print violations
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
THRESHOLD=10
|
|
FETCH_DEPTH=200
|
|
NO_FETCH=0
|
|
JSON=0
|
|
QUIET=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--threshold=*) THRESHOLD="${1#*=}" ;;
|
|
--fetch-depth=*) FETCH_DEPTH="${1#*=}" ;;
|
|
--no-fetch) NO_FETCH=1 ;;
|
|
--json) JSON=1 ;;
|
|
--quiet) QUIET=1 ;;
|
|
-h|--help)
|
|
echo "Usage: $0 [--threshold=N] [--fetch-depth=N] [--no-fetch] [--json] [--quiet]"
|
|
exit 0
|
|
;;
|
|
*) echo "Unknown: $1" >&2; exit 1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Submodules that have upstream remotes
|
|
declare -a FORKS=()
|
|
declare -A FORK_PATHS
|
|
while IFS= read -r line; do
|
|
name=$(basename "$line")
|
|
FORKS+=("$name")
|
|
FORK_PATHS["$name"]="$line"
|
|
done < <(find local/sources -maxdepth 1 -mindepth 1 -type d -o -type l 2>/dev/null | sort)
|
|
|
|
if [[ ${#FORKS[@]} -eq 0 ]]; then
|
|
echo "No local forks found under local/sources/" >&2
|
|
exit 0
|
|
fi
|
|
|
|
VIOLATIONS=0
|
|
declare -a JSON_LINES=()
|
|
|
|
if [[ "$JSON" -eq 0 && "$QUIET" -eq 0 ]]; then
|
|
printf "%-16s %-8s %-8s %-12s %-12s %s\n" "FORK" "BEHIND" "AHEAD" "UPSTREAM" "OUR_HEAD" "STATUS"
|
|
printf "%-16s %-8s %-8s %-12s %-12s %s\n" "----" "-------" "------" "--------" "--------" "------"
|
|
fi
|
|
|
|
for fork in "${FORKS[@]}"; do
|
|
fork_dir="${FORK_PATHS[$fork]}"
|
|
if [[ ! -d "$fork_dir/.git" ]]; then
|
|
continue
|
|
fi
|
|
|
|
upstream_remote=$(cd "$fork_dir" && git remote get-url upstream 2>/dev/null || true)
|
|
if [[ -z "$upstream_remote" ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Determine upstream branch (master or main)
|
|
upstream_branch="master"
|
|
if ! (cd "$fork_dir" && git rev-parse --verify upstream/master >/dev/null 2>&1); then
|
|
if (cd "$fork_dir" && git rev-parse --verify upstream/main >/dev/null 2>&1); then
|
|
upstream_branch="main"
|
|
else
|
|
# Need to fetch first
|
|
if [[ "$NO_FETCH" -eq 0 ]]; then
|
|
(cd "$fork_dir" && git fetch upstream --depth="$FETCH_DEPTH" --quiet 2>/dev/null) || true
|
|
fi
|
|
if (cd "$fork_dir" && git rev-parse --verify upstream/master >/dev/null 2>&1); then
|
|
upstream_branch="master"
|
|
elif (cd "$fork_dir" && git rev-parse --verify upstream/main >/dev/null 2>&1); then
|
|
upstream_branch="main"
|
|
else
|
|
continue
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Fetch if needed
|
|
if [[ "$NO_FETCH" -eq 0 ]]; then
|
|
(cd "$fork_dir" && git fetch upstream --depth="$FETCH_DEPTH" --quiet 2>/dev/null) || true
|
|
fi
|
|
|
|
ref="upstream/$upstream_branch"
|
|
behind=$(cd "$fork_dir" && git log --oneline "HEAD..$ref" 2>/dev/null | wc -l)
|
|
ahead=$(cd "$fork_dir" && git log --oneline "$ref..HEAD" 2>/dev/null | wc -l)
|
|
upstream_sha=$(cd "$fork_dir" && git rev-parse --short "$ref" 2>/dev/null || echo "?")
|
|
our_sha=$(cd "$fork_dir" && git rev-parse --short HEAD 2>/dev/null || echo "?")
|
|
upstream_date=$(cd "$fork_dir" && git log -1 --format='%ci' "$ref" 2>/dev/null | cut -d' ' -f1 || echo "?")
|
|
our_date=$(cd "$fork_dir" && git log -1 --format='%ci' HEAD 2>/dev/null | cut -d' ' -f1 || echo "?")
|
|
|
|
status="OK"
|
|
if [[ "$behind" -gt "$THRESHOLD" ]]; then
|
|
status="DRIFT"
|
|
VIOLATIONS=$((VIOLATIONS + 1))
|
|
elif [[ "$behind" -gt 0 ]]; then
|
|
status="MINOR"
|
|
fi
|
|
|
|
if [[ "$JSON" -eq 1 ]]; then
|
|
json_line=$(printf '{"fork":"%s","behind":%d,"ahead":%d,"upstream_sha":"%s","our_sha":"%s","upstream_date":"%s","our_date":"%s","status":"%s"}' \
|
|
"$fork" "$behind" "$ahead" "$upstream_sha" "$our_sha" "$upstream_date" "$our_date" "$status")
|
|
JSON_LINES+=("$json_line")
|
|
elif [[ "$QUIET" -eq 0 ]] || [[ "$status" != "OK" ]]; then
|
|
if [[ "$status" == "DRIFT" ]]; then
|
|
printf "%-16s \033[1;31m%-8s\033[0m %-8s %-12s %-12s %s\n" "$fork" "$behind" "$ahead" "$upstream_sha" "$our_sha" "$status"
|
|
elif [[ "$status" == "MINOR" ]]; then
|
|
printf "%-16s \033[1;33m%-8s\033[0m %-8s %-12s %-12s %s\n" "$fork" "$behind" "$ahead" "$upstream_sha" "$our_sha" "$status"
|
|
else
|
|
printf "%-16s \033[1;32m%-8s\033[0m %-8s %-12s %-12s %s\n" "$fork" "$behind" "$ahead" "$upstream_sha" "$our_sha" "$status"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [[ "$JSON" -eq 1 ]]; then
|
|
echo "["
|
|
for i in "${!JSON_LINES[@]}"; do
|
|
if [[ $i -lt $((${#JSON_LINES[@]} - 1)) ]]; then
|
|
echo " ${JSON_LINES[$i]},"
|
|
else
|
|
echo " ${JSON_LINES[$i]}"
|
|
fi
|
|
done
|
|
echo "]"
|
|
else
|
|
echo ""
|
|
if [[ "$VIOLATIONS" -gt 0 ]]; then
|
|
echo -e "\033[1;31mDRIFT DETECTED: $VIOLATIONS fork(s) exceed threshold ($THRESHOLD commits behind upstream).\033[0m"
|
|
echo ""
|
|
echo "To upgrade forks to latest upstream:"
|
|
echo " ./local/scripts/upgrade-forks.sh"
|
|
echo ""
|
|
echo "To suppress this check in builds:"
|
|
echo " REDBEAR_SKIP_DRIFT_CHECK=1"
|
|
else
|
|
echo -e "\033[1;32mAll forks within drift threshold ($THRESHOLD commits).\033[0m"
|
|
fi
|
|
fi
|
|
|
|
if [[ "$VIOLATIONS" -gt 0 ]]; then
|
|
exit 1
|
|
fi
|
|
exit 0
|