cache: git-tracked build cache — 16 packages, survives make clean + clone
Red Bear is a fork/overlay on top of Redox. The upstream build
system wasn't designed for forks — it loses all cached stages on
make clean with no recovery path.
This commit adds a git-tracked build cache:
- local/cache/pkgar/{pkg}/stage.pkgar — per-package cache files
- cache-sync.sh: sync built packages → git-tracked cache
- cache-sync.sh --restore: restore cache → recipe targets
- cache-sync.sh --commit: sync + git commit
- Auto-restore before build, auto-sync after build
Cache survives: make clean, make distclean, git clone, upstream rebase.
Recovery from clean: seconds (restore from git) vs hours (full rebuild).
This commit is contained in:
@@ -76,3 +76,8 @@ TASK_COMPLETION_SUMMARY.md
|
||||
__pycache__/
|
||||
extra.img: 1073741824 bytes
|
||||
extra.img
|
||||
local/cache/pkgar/
|
||||
|
||||
# Red Bear git-tracked build cache (survives make clean)
|
||||
!local/cache/pkgar/
|
||||
!local/cache/pkgar/**
|
||||
|
||||
@@ -9,41 +9,63 @@ all: $(BUILD)/harddrive.img
|
||||
|
||||
# ── Red Bear OS Build Cache ──────────────────────────────────────────────
|
||||
# The upstream Redox build system loses cached stages on make clean.
|
||||
# Red Bear provides snapshot/restore so the build can recover quickly.
|
||||
# Essential package caches are tracked in git under local/cache/essential/.
|
||||
# Red Bear provides a git-tracked cache that survives everything.
|
||||
#
|
||||
# Architecture:
|
||||
# local/cache/pkgar/{pkgname}/stage.pkgar — committed to git
|
||||
# local/cache/rbos-cache-*/ — timestamped snapshots
|
||||
#
|
||||
# Usage:
|
||||
# make cache-save Save full cache snapshot
|
||||
# make cache-save-essential Save only essential (boot) packages
|
||||
# make cache-restore Auto-restore latest cache before build
|
||||
# make cache-verify Check cache integrity
|
||||
# make cache-sync Sync built packages → git-tracked cache
|
||||
# make cache-commit Sync + git commit
|
||||
# make cache-restore Restore from git-tracked cache
|
||||
# make cache-save Full timestamped snapshot (local only)
|
||||
# make cache-status Compare cache vs build state
|
||||
# make cache-list List available snapshots
|
||||
|
||||
CACHE_SCRIPT = local/scripts/snapshot-cache.sh
|
||||
RESTORE_SCRIPT = local/scripts/restore-cache.sh
|
||||
CACHE_SYNC = local/scripts/cache-sync.sh
|
||||
CACHE_SAVE = local/scripts/snapshot-cache.sh
|
||||
CACHE_RESTORE = local/scripts/restore-cache.sh
|
||||
|
||||
cache-save:
|
||||
@bash $(CACHE_SCRIPT)
|
||||
cache-sync:
|
||||
@bash $(CACHE_SYNC)
|
||||
|
||||
cache-save-essential:
|
||||
@bash $(CACHE_SCRIPT) --essential
|
||||
cache-commit:
|
||||
@bash $(CACHE_SYNC) --commit
|
||||
|
||||
cache-restore:
|
||||
@bash $(RESTORE_SCRIPT)
|
||||
@echo "Red Bear: restoring from git-tracked cache..."
|
||||
@bash $(CACHE_SYNC) --restore
|
||||
@bash $(CACHE_RESTORE) 2>/dev/null || true
|
||||
|
||||
cache-save:
|
||||
@bash $(CACHE_SAVE)
|
||||
|
||||
cache-save-essential:
|
||||
@bash $(CACHE_SAVE) --essential
|
||||
|
||||
cache-verify:
|
||||
@bash $(RESTORE_SCRIPT) --verify
|
||||
@bash $(CACHE_RESTORE) --verify
|
||||
|
||||
cache-list:
|
||||
@bash $(CACHE_SCRIPT) --list
|
||||
@bash $(CACHE_SAVE) --list
|
||||
|
||||
# Auto-restore cache if available (runs before all builds)
|
||||
cache-status:
|
||||
@bash $(CACHE_SYNC) --status
|
||||
|
||||
# Auto-restore cache before build, sync after successful build
|
||||
cache-auto:
|
||||
@if [ -d local/cache ] && ls local/cache/rbos-cache-* >/dev/null 2>&1; then \
|
||||
echo "Red Bear: restoring build cache..."; \
|
||||
bash $(RESTORE_SCRIPT); \
|
||||
@if [ ! -f $(BUILD)/repo.tag ]; then \
|
||||
if ls local/cache/pkgar/*/stage.pkgar >/dev/null 2>&1; then \
|
||||
echo "Red Bear: build cache found, restoring..."; \
|
||||
bash $(CACHE_SYNC) --restore; \
|
||||
fi; \
|
||||
fi
|
||||
@if [ -f $(BUILD)/harddrive.img ]; then \
|
||||
echo "Red Bear: build complete, syncing cache..."; \
|
||||
bash $(CACHE_SYNC); \
|
||||
fi
|
||||
|
||||
# Ensure cache is restored before build
|
||||
$(BUILD)/harddrive.img: cache-auto
|
||||
|
||||
live:
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
*
|
||||
!essential/
|
||||
!.gitignore
|
||||
!.gitkeep
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
# Red Bear git-tracked cache — survives make clean and git clone
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
# Red Bear package caches — committed to git
|
||||
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Vendored
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Vendored
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
Vendored
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Vendored
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = ["ncursesw"]
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
[snapshot]
|
||||
name = "rbos-cache-20260428-080713"
|
||||
timestamp = "20260428-080713"
|
||||
mode = "--full"
|
||||
packages = 16
|
||||
total_size = 129468786
|
||||
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = ["ncursesw"]
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
packages = []
|
||||
Binary file not shown.
Executable
+127
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env bash
|
||||
# Red Bear OS — Git-Tracked Build Cache
|
||||
# Automatically syncs recipe stage.pkgar files to local/cache/pkgar/
|
||||
# and commits them to git so the cache survives make clean AND git clone.
|
||||
#
|
||||
# The cache is organized as: local/cache/pkgar/{pkgname}/stage.pkgar
|
||||
# This keeps individual files small enough for git (<100MB each).
|
||||
#
|
||||
# Usage:
|
||||
# ./local/scripts/cache-sync.sh # Sync all built packages to cache
|
||||
# ./local/scripts/cache-sync.sh --commit # Sync + git commit
|
||||
# ./local/scripts/cache-sync.sh --restore # Restore cache to recipe targets
|
||||
# ./local/scripts/cache-sync.sh --status # Show cache vs build state
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
CACHE_ROOT="local/cache/pkgar"
|
||||
mkdir -p "${CACHE_ROOT}"
|
||||
|
||||
MODE="${1:-}"
|
||||
|
||||
if [ "$MODE" = "--status" ]; then
|
||||
echo "=== Red Bear Cache Status ==="
|
||||
cached=0; stale=0; missing=0
|
||||
for pkgar in "${CACHE_ROOT}"/*/stage.pkgar; do
|
||||
[ -f "$pkgar" ] || continue
|
||||
pkg=$(basename "$(dirname "$pkgar")")
|
||||
recipe_dir=$(find recipes -maxdepth 3 -name "$pkg" -type d 2>/dev/null | head -1)
|
||||
if [ -z "$recipe_dir" ]; then
|
||||
echo " ORPHAN $pkg (no recipe)"
|
||||
stale=$((stale + 1))
|
||||
continue
|
||||
fi
|
||||
target="${recipe_dir}/target/x86_64-unknown-redox/stage.pkgar"
|
||||
if [ -f "$target" ]; then
|
||||
if [ "$pkgar" -nt "$target" ]; then
|
||||
echo " STALE $pkg (cache newer than build)"
|
||||
stale=$((stale + 1))
|
||||
else
|
||||
echo " SYNCED $pkg"
|
||||
cached=$((cached + 1))
|
||||
fi
|
||||
else
|
||||
echo " CACHED $pkg (no build)"
|
||||
cached=$((cached + 1))
|
||||
fi
|
||||
done
|
||||
# Check built but not cached
|
||||
while IFS= read -r target; do
|
||||
pkg=$(echo "$target" | sed 's|recipes/[^/]*/[^/]*/||; s|/target/.*||')
|
||||
if [ ! -f "${CACHE_ROOT}/${pkg}/stage.pkgar" ]; then
|
||||
size=$(stat -c%s "$target" 2>/dev/null || echo 0)
|
||||
echo " UNCACHED $pkg ($(numfmt --to=iec $size 2>/dev/null || echo ${size}B))"
|
||||
missing=$((missing + 1))
|
||||
fi
|
||||
done < <(find recipes -name "stage.pkgar" -path "*/target/x86_64-unknown-redox/*" 2>/dev/null | head -100)
|
||||
echo ""
|
||||
echo "Synced: $cached Stale: $stale Uncached: $missing"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "--restore" ]; then
|
||||
echo "=== Restoring Cache to Recipes ==="
|
||||
count=0
|
||||
for pkgar in "${CACHE_ROOT}"/*/stage.pkgar; do
|
||||
[ -f "$pkgar" ] || continue
|
||||
pkg=$(basename "$(dirname "$pkgar")")
|
||||
recipe_dir=$(find recipes -maxdepth 4 -name "$pkg" -type d 2>/dev/null | head -1)
|
||||
if [ -z "$recipe_dir" ]; then continue; fi
|
||||
target="${recipe_dir}/target/x86_64-unknown-redox/stage.pkgar"
|
||||
if [ ! -f "$target" ] || [ "$pkgar" -nt "$target" ]; then
|
||||
mkdir -p "$(dirname "$target")"
|
||||
cp "$pkgar" "$target"
|
||||
count=$((count + 1))
|
||||
fi
|
||||
done
|
||||
echo "Restored $count packages"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Default: --sync mode
|
||||
echo "=== Syncing Build Cache ==="
|
||||
synced=0
|
||||
while IFS= read -r target; do
|
||||
pkg_path="${target%/target/x86_64-unknown-redox/stage.pkgar}"
|
||||
# Extract package name: recipes/{category}/{name}/target/... → {name}
|
||||
pkg=$(basename "$pkg_path")
|
||||
[ -z "$pkg" ] && continue
|
||||
|
||||
cache_dir="${CACHE_ROOT}/${pkg}"
|
||||
cache_file="${cache_dir}/stage.pkgar"
|
||||
|
||||
# Only copy if build is newer
|
||||
if [ -f "$cache_file" ] && [ ! "$target" -nt "$cache_file" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
mkdir -p "$cache_dir"
|
||||
cp "$target" "$cache_file"
|
||||
|
||||
# Also save auto_deps
|
||||
deps_file="${pkg_path}/target/x86_64-unknown-redox/auto_deps.toml"
|
||||
if [ -f "$deps_file" ]; then
|
||||
cp "$deps_file" "${cache_dir}/auto_deps.toml"
|
||||
fi
|
||||
|
||||
synced=$((synced + 1))
|
||||
done < <(find recipes -name "stage.pkgar" -path "*/target/x86_64-unknown-redox/*" 2>/dev/null)
|
||||
|
||||
echo "Synced $synced packages to ${CACHE_ROOT}/"
|
||||
|
||||
if [ "$MODE" = "--commit" ] && [ $synced -gt 0 ]; then
|
||||
echo ""
|
||||
echo "=== Committing Cache ==="
|
||||
git add "${CACHE_ROOT}/"
|
||||
|
||||
# Only commit if there are staged changes
|
||||
if git diff --cached --quiet; then
|
||||
echo "No cache changes to commit"
|
||||
else
|
||||
commit_msg="cache: $(date +%Y-%m-%d) — ${synced} packages"
|
||||
git commit -m "$commit_msg"
|
||||
echo "Committed: $commit_msg"
|
||||
echo "To push: git push"
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user