quickshell: converge live trees without root replacement
This commit is contained in:
parent
b0a1304ba1
commit
9c27504009
3 changed files with 75 additions and 16 deletions
|
|
@ -158,7 +158,7 @@ if [[ "${1:-}" == "--manifest" ]]; then
|
|||
fi
|
||||
|
||||
if [[ "${1:-}" == "--phone" ]]; then
|
||||
ssh_i=(ssh -i "$HOME/.ssh/ani" -o ConnectTimeout=5)
|
||||
ssh_i=(ssh -F /dev/null -i "$HOME/.ssh/ani" -o ConnectTimeout=5)
|
||||
deployed_revision="unknown"
|
||||
if repo_root="$(git -C "$SRC" rev-parse --show-toplevel 2>/dev/null)"; then
|
||||
deployed_revision="$(git -C "$repo_root" rev-parse HEAD)"
|
||||
|
|
@ -168,7 +168,7 @@ if [[ "${1:-}" == "--phone" ]]; then
|
|||
fi
|
||||
fi
|
||||
"${ssh_i[@]}" "$PHONE_USB" "mkdir -p ~/$PHONE_DEST"
|
||||
rsync -a --delete -e "ssh -i $HOME/.ssh/ani" "$SRC/" "$PHONE_USB:$PHONE_DEST/"
|
||||
rsync -a --delete -e "ssh -F /dev/null -i $HOME/.ssh/ani" "$SRC/" "$PHONE_USB:$PHONE_DEST/"
|
||||
printf '%s\n' "$deployed_revision" \
|
||||
| "${ssh_i[@]}" "$PHONE_USB" "cat > ~/$PHONE_DEST/DEPLOYED-REVISION"
|
||||
"${ssh_i[@]}" "$PHONE_USB" "bash ~/$PHONE_DEST/deploy.sh"
|
||||
|
|
@ -201,17 +201,60 @@ if [[ "${1:-}" == "--legacy-clean" ]]; then
|
|||
fi
|
||||
|
||||
# --- Sync the pinned ii base --------------------------------------------
|
||||
# --exclude .git: the pin carries no VCS dirs, and any nested .git already
|
||||
# on a device (e.g. widgets/shapes) is left alone rather than deleted.
|
||||
# Build both trees away from their live paths, then converge the stable live
|
||||
# directories with delayed renames. Quickshell's watcher follows the config
|
||||
# directory inode and does not tolerate replacing that root, even atomically.
|
||||
# The three-phase order keeps every symlink valid throughout the update:
|
||||
# add/update ii files, switch the composed surface, then delete stale ii files.
|
||||
mkdir -p "$QS"
|
||||
rsync -a --delete --exclude='.git' "$SRC/ii-base/" "$II/"
|
||||
|
||||
clear_generated_tree() {
|
||||
local path="$1"
|
||||
case "$path" in
|
||||
"$QS/.ii-previous"|"$QS/.souveraine-previous"|"$QS"/.ii-next.*|"$QS"/.souveraine-next.*)
|
||||
[[ ! -e "$path" && ! -L "$path" ]] || find "$path" -depth -delete
|
||||
;;
|
||||
*)
|
||||
echo "refusing to clear unexpected rollback path: $path" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
snapshot_tree() { # live rollback
|
||||
local live="$1" rollback="$2"
|
||||
clear_generated_tree "$rollback"
|
||||
if [[ -e "$live" || -L "$live" ]]; then
|
||||
mkdir -p "$rollback"
|
||||
rsync -a --delete --exclude='.git' "$live/" "$rollback/"
|
||||
fi
|
||||
}
|
||||
|
||||
II_NEXT="$QS/.ii-next.$$"
|
||||
SV_NEXT="$QS/.souveraine-next.$$"
|
||||
[[ ! -e "$II_NEXT" && ! -e "$SV_NEXT" ]] || {
|
||||
echo "staging path already exists; refusing: $II_NEXT or $SV_NEXT" >&2
|
||||
exit 1
|
||||
}
|
||||
cleanup_staging() {
|
||||
clear_generated_tree "$II_NEXT"
|
||||
clear_generated_tree "$SV_NEXT"
|
||||
}
|
||||
trap cleanup_staging EXIT
|
||||
mkdir -p "$II_NEXT"
|
||||
rsync -a --delete --exclude='.git' "$SRC/ii-base/" "$II_NEXT/"
|
||||
if [[ "$TARGET_ARCH" == "aarch64" ]]; then
|
||||
rsync -a "$SRC/ii-phone/" "$II/"
|
||||
echo "ii synced from pin + phone overlay"
|
||||
rsync -a "$SRC/ii-phone/" "$II_NEXT/"
|
||||
ii_description="pin + phone overlay"
|
||||
else
|
||||
echo "ii synced from pin"
|
||||
ii_description="pin"
|
||||
fi
|
||||
install -m 0644 "$SRC/ii-base.pin" "$II/.souveraine-upstream-pin"
|
||||
install -m 0644 "$SRC/ii-base.pin" "$II_NEXT/.souveraine-upstream-pin"
|
||||
snapshot_tree "$II" "$QS/.ii-previous"
|
||||
mkdir -p "$II"
|
||||
# Phase 1: make every path the new composition can reference available, but
|
||||
# retain old extras until their Souveraine override/symlink has switched.
|
||||
rsync -a --delay-updates "$II_NEXT/" "$II/"
|
||||
|
||||
# --- Compose -------------------------------------------------------------
|
||||
# Targets under souveraine/, relative to $SV
|
||||
|
|
@ -226,8 +269,8 @@ is_touched() { # dir contains an override somewhere below
|
|||
|
||||
compose_dir() { # $1 = path relative to ii root ("" for root)
|
||||
local rel="$1" entry name erel
|
||||
mkdir -p "$SV${rel:+/$rel}"
|
||||
for entry in "$II${rel:+/$rel}"/*; do
|
||||
mkdir -p "$SV_NEXT${rel:+/$rel}"
|
||||
for entry in "$II_NEXT${rel:+/$rel}"/*; do
|
||||
[[ -e "$entry" ]] || continue
|
||||
name="$(basename "$entry")"
|
||||
[[ "$name" == *.upstream ]] && continue
|
||||
|
|
@ -236,19 +279,18 @@ compose_dir() { # $1 = path relative to ii root ("" for root)
|
|||
if is_touched "$erel"; then
|
||||
compose_dir "$erel"
|
||||
else
|
||||
ln -sfn "$II/$erel" "$SV/$erel"
|
||||
ln -sfn "$II/$erel" "$SV_NEXT/$erel"
|
||||
fi
|
||||
else
|
||||
# root files and files inside touched dirs: link individually,
|
||||
# skipping ones our manifest replaces
|
||||
is_replaced "$erel" && continue
|
||||
ln -sf "$II/$erel" "$SV/$erel"
|
||||
ln -sf "$II/$erel" "$SV_NEXT/$erel"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Rebuild from scratch each run: cheap, and guarantees no stale links.
|
||||
rm -rf "$SV"
|
||||
# Build from scratch at the staging path: cheap, with no stale links.
|
||||
compose_dir ""
|
||||
|
||||
# Our files on top (this also creates dirs that exist only in our tree,
|
||||
|
|
@ -256,12 +298,25 @@ compose_dir ""
|
|||
mkdir -p "$QS/pill"
|
||||
while read -r rel target; do
|
||||
[[ -z "$rel" ]] && continue
|
||||
src="$SRC/$rel"; t="$QS/$target"
|
||||
src="$SRC/$rel"; t="$SV_NEXT/${target#souveraine/}"
|
||||
[[ -f "$src" ]] || { echo "missing $src" >&2; exit 1; }
|
||||
mkdir -p "$(dirname "$t")"
|
||||
ln -sf "$src" "$t"
|
||||
done < <(manifest_lines)
|
||||
|
||||
snapshot_tree "$SV" "$QS/.souveraine-previous"
|
||||
mkdir -p "$SV"
|
||||
# Phase 2: switch the composed tree using delayed per-entry renames while its
|
||||
# root directory remains stable for Quickshell's recursive watcher.
|
||||
rsync -a --delete-delay --delay-updates "$SV_NEXT/" "$SV/"
|
||||
# Phase 3: the composition no longer points at obsolete ii-only paths, so it
|
||||
# is now safe to remove them and finish exact convergence with the pin.
|
||||
rsync -a --delete-delay --delay-updates "$II_NEXT/" "$II/"
|
||||
clear_generated_tree "$II_NEXT"
|
||||
clear_generated_tree "$SV_NEXT"
|
||||
trap - EXIT
|
||||
echo "ii synced from $ii_description (rollback: $QS/.ii-previous)"
|
||||
|
||||
n_ours=$(manifest_lines | grep -c .)
|
||||
n_borrowed_dirs=$(find "$SV" -maxdepth 3 -type l -xtype d | wc -l)
|
||||
echo "souveraine config composed at $SV ($n_ours files ours, $n_borrowed_dirs dirs borrowed from ii)"
|
||||
|
|
|
|||
Loading…
Reference in a new issue