Files
RedBear-OS/local/scripts/sync-versions.sh
T
vasilito 54de45d461 docs/scripts: enforce single-repo policy and +rb build-metadata suffix
- Update AGENTS.md single-repo rule to explicitly forbid creating any new
  Gitea repositories and to require deleting per-component repos.
- Change version suffix policy from pre-release -rb to build-metadata +rb
  in AGENTS.md, sync-versions.sh, apply-rb-suffix.sh, verify-fork-versions.sh.
- Update migration instructions to push to existing submodule/<component>
  branches inside RedBear-OS, not create new repos.
- Update BUILD-SYSTEM-IMPROVEMENTS.md and SLEEP-IMPLEMENTATION-PLAN.md to
  reference submodule/* branches instead of defunct per-component repos.
- Fix delete-per-component-repos.sh example to use a real historical repo.
2026-07-05 22:50:33 +03:00

217 lines
6.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# sync-versions.sh — Synchronise ALL Red Bear crate versions to match the
# current git branch.
#
# Handles BOTH version categories (local/AGENTS.md § "Version conventions"):
#
# Cat 1 — In-house Red Bear crates (local/recipes/*/source/):
# version = "<branch>" (e.g. "0.2.5")
#
# Cat 2 — Upstream Redox forks (local/sources/*/):
# version = "<upstream-base>+rb<branch>" (e.g. "0.9.0+rb0.2.5")
#
# The `+rb` suffix is Cargo build metadata, not a pre-release identifier.
# Using `-rb` is a policy violation.
#
# When the branch changes (e.g. 0.2.5 → 0.2.6), running this script bumps
# Cat 1 versions to the new branch version AND updates Cat 2 suffixes to
# match the new branch version. The upstream base versions are preserved.
#
# Exclusions:
# - zbus (upstream zbus fork, keeps its own versioning)
# - tlc (established project with independent versioning)
# - Meson test-case crates
#
# Usage:
# ./local/scripts/sync-versions.sh # Apply
# ./local/scripts/sync-versions.sh --check # Check only, exit 1 if drift found
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$ROOT"
CHECK_ONLY=0
[[ "${1:-}" == "--check" ]] && CHECK_ONLY=1
# ---- Determine target version from branch ----
BRANCH="$(git branch --show-current 2>/dev/null || echo "")"
if [[ -z "$BRANCH" ]]; then
echo "ERROR: cannot determine current git branch" >&2
exit 1
fi
# Extract semantic version from branch name (e.g. "0.2.5" from "0.2.5")
TARGET_VERSION="$(echo "$BRANCH" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || true)"
if [[ -z "$TARGET_VERSION" ]]; then
echo "ERROR: branch '$BRANCH' does not contain a semantic version" >&2
exit 1
fi
echo "Target version: $TARGET_VERSION (from branch '$BRANCH')"
echo "Cat 2 suffix: +rb$TARGET_VERSION"
echo ""
# ---- Exclusions ----
# Crates that keep their own versioning (not branch-tracked)
EXCLUDE_NAMES=(
"zbus" # upstream zbus fork
"tlc" # established project with independent versioning
)
# Paths to exclude (substring match)
EXCLUDE_PATHS=(
"test cases" # meson test crates
"/target/" # build artifacts
)
should_exclude() {
local name="$1"
local path="$2"
for ex in "${EXCLUDE_NAMES[@]}"; do
[[ "$name" == "$ex" ]] && return 0
done
for ex in "${EXCLUDE_PATHS[@]}"; do
[[ "$path" == *"$ex"* ]] && return 0
done
return 1
}
# ---- Helper: extract upstream base from a Cat 2 version ----
# Strips any existing +rb<x.y.z> build-metadata suffix to get the upstream base version.
strip_rb_suffix() {
echo "$1" | sed -E 's/(\+rb[0-9]+(\.[0-9]+\.[0-9]+)?)+$//'
}
# ---- Phase 1: Cat 1 — In-house crates (local/recipes/*/source/) ----
echo "=== Phase 1: Cat 1 — In-house crates ==="
CAT1_CHANGED=0
CAT1_CHECKED=0
CAT1_DRIFT=0
while IFS= read -r f; do
name="$(grep '^name = ' "$f" 2>/dev/null | head -1 | sed 's/name = "//;s/"//' || true)"
if should_exclude "$name" "$f"; then
continue
fi
CAT1_CHECKED=$((CAT1_CHECKED + 1))
# Case 1: [package] version = "x.y.z"
if grep -q '^version = "' "$f" 2>/dev/null; then
current="$(grep '^version = "' "$f" | head -1 | sed 's/version = "//;s/"//' || true)"
if [[ "$current" != "$TARGET_VERSION" ]]; then
if [[ $CHECK_ONLY -eq 1 ]]; then
echo " DRIFT: $name $current$TARGET_VERSION ($f)"
CAT1_DRIFT=$((CAT1_DRIFT + 1))
else
sed -i "s/^version = \"$current\"/version = \"$TARGET_VERSION\"/" "$f"
echo " UPDATED: $name $current$TARGET_VERSION ($f)"
CAT1_CHANGED=$((CAT1_CHANGED + 1))
fi
fi
fi
# Case 2: [workspace.package] version = "x.y.z"
if grep -A1 '^\[workspace\.package\]' "$f" 2>/dev/null | grep -q '^version = "' 2>/dev/null; then
current="$(grep -A1 '^\[workspace\.package\]' "$f" | grep '^version = "' | sed 's/version = "//;s/"//' || true)"
if [[ "$current" != "$TARGET_VERSION" ]]; then
if [[ $CHECK_ONLY -eq 1 ]]; then
echo " DRIFT (workspace): $current$TARGET_VERSION ($f)"
CAT1_DRIFT=$((CAT1_DRIFT + 1))
else
awk -v new="$TARGET_VERSION" '
/^\[workspace\.package\]/ { in_wp=1 }
/^\[/ && !/^\[workspace\.package\]/ { in_wp=0 }
in_ws==0 && in_wp==1 && /^version = / { print "version = \"" new "\""; next }
{ print }
' "$f" > "${f}.tmp" && mv "${f}.tmp" "$f"
echo " UPDATED (workspace): $current$TARGET_VERSION ($f)"
CAT1_CHANGED=$((CAT1_CHANGED + 1))
fi
fi
fi
done < <(find local/recipes/ -name "Cargo.toml" -not -path "*/target/*" -path "*/source/*" | sort)
echo ""
# ---- Phase 2: Cat 2 — Upstream forks (local/sources/*/) ----
echo "=== Phase 2: Cat 2 — Upstream forks ==="
CAT2_CHANGED=0
CAT2_CHECKED=0
CAT2_DRIFT=0
RB_SUFFIX="+rb${TARGET_VERSION}"
update_cat2_version() {
local f="$1"
local fork_name="$2"
if ! grep -qE '^[[:space:]]*\[(package|workspace\.package)\]' "$f" 2>/dev/null; then
return 0
fi
local current target base
current="$(grep -E '^version\s*=' "$f" | head -1 | sed 's/.*"\(.*\)".*/\1/' || true)"
[[ -n "$current" ]] || return 0
# Strip any existing +rb<x.y.z> build-metadata suffix to get upstream base
base="$(strip_rb_suffix "$current")"
target="${base}${RB_SUFFIX}"
if [[ "$current" == "$target" ]]; then
return 0
fi
CAT2_CHECKED=$((CAT2_CHECKED + 1))
if [[ $CHECK_ONLY -eq 1 ]]; then
echo " DRIFT: $fork_name $current$target ($f)"
CAT2_DRIFT=$((CAT2_DRIFT + 1))
else
sed -i "s|^version = \"${current}\"|version = \"${target}\"|" "$f"
echo " UPDATED: $fork_name $current$target ($f)"
CAT2_CHANGED=$((CAT2_CHANGED + 1))
fi
}
for fork_dir in local/sources/*/; do
[ -d "$fork_dir" ] || continue
fork_name=$(basename "$fork_dir")
# Skip non-submodule dirs (ctrlc, libpciaccess, redox-drm, sysinfo — empty stubs)
[ -f "${fork_dir}Cargo.toml" ] || continue
# Try root Cargo.toml first
update_cat2_version "${fork_dir}Cargo.toml" "$fork_name"
done
echo ""
# ---- Summary ----
if [[ $CHECK_ONLY -eq 1 ]]; then
echo "Cat 1: checked $CAT1_CHECKED, drift $CAT1_DRIFT"
echo "Cat 2: checked $CAT2_CHECKED, drift $CAT2_DRIFT"
TOTAL_DRIFT=$((CAT1_DRIFT + CAT2_DRIFT))
if [[ $TOTAL_DRIFT -gt 0 ]]; then
echo "FAIL: $TOTAL_DRIFT version drift(s) found"
exit 1
fi
echo "All crates are at correct versions for branch '$BRANCH'"
else
echo "Cat 1: updated $CAT1_CHANGED (checked $CAT1_CHECKED)"
echo "Cat 2: updated $CAT2_CHANGED"
echo "All versions synced to branch '$BRANCH'"
fi