D7: editor multi-cursor support
Add secondary_cursors field to Editor with insert_char_multi, delete_back_multi, delete_forward_multi methods. Right-to-left processing ensures position shifts don't corrupt earlier insertions. 7 new tests: add/clear, all_positions, insert, delete_back, delete_forward, unicode, duplicate-add.
This commit is contained in:
+105
-25
@@ -1,12 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# sync-versions.sh — Synchronise all in-house Red Bear crate versions to match
|
||||
# the current git branch name (e.g. branch "0.2.4" → version "0.2.4").
|
||||
# sync-versions.sh — Synchronise ALL Red Bear crate versions to match the
|
||||
# current git branch.
|
||||
#
|
||||
# Policy:
|
||||
# - In-house Red Bear crates (local/recipes/) MUST use the branch version.
|
||||
# - Upstream Redox forks (local/sources/) keep their upstream versioning.
|
||||
# - Established projects with their own versioning (tlc, zbus) are excluded.
|
||||
# - Meson test-case crates are excluded.
|
||||
# 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")
|
||||
#
|
||||
# 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
|
||||
@@ -28,7 +39,7 @@ if [[ -z "$BRANCH" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract semantic version from branch name (e.g. "0.2.4" from "0.2.4")
|
||||
# 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
|
||||
@@ -36,6 +47,7 @@ if [[ -z "$TARGET_VERSION" ]]; then
|
||||
fi
|
||||
|
||||
echo "Target version: $TARGET_VERSION (from branch '$BRANCH')"
|
||||
echo "Cat 2 suffix: -rb$TARGET_VERSION"
|
||||
echo ""
|
||||
|
||||
# ---- Exclusions ----
|
||||
@@ -67,22 +79,28 @@ should_exclude() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# ---- Find and update Cargo.toml files ----
|
||||
# ---- Helper: extract upstream base from a Cat 2 version ----
|
||||
# Strips any existing -rb<x.y.z> suffix to get the upstream base version.
|
||||
strip_rb_suffix() {
|
||||
echo "$1" | sed -E 's/(-rb[0-9]+(\.[0-9]+\.[0-9]+)?)+$//'
|
||||
}
|
||||
|
||||
CHANGED=0
|
||||
CHECKED=0
|
||||
DRIFT=0
|
||||
# ---- 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
|
||||
|
||||
# Find all Cargo.toml in local/recipes/ (source dirs only, skip target/)
|
||||
while IFS= read -r f; do
|
||||
# Extract crate name (if present)
|
||||
name="$(grep '^name = ' "$f" 2>/dev/null | head -1 | sed 's/name = "//;s/"//' || true)"
|
||||
|
||||
if should_exclude "$name" "$f"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
CHECKED=$((CHECKED + 1))
|
||||
CAT1_CHECKED=$((CAT1_CHECKED + 1))
|
||||
|
||||
# Case 1: [package] version = "x.y.z"
|
||||
if grep -q '^version = "' "$f" 2>/dev/null; then
|
||||
@@ -90,11 +108,11 @@ while IFS= read -r f; do
|
||||
if [[ "$current" != "$TARGET_VERSION" ]]; then
|
||||
if [[ $CHECK_ONLY -eq 1 ]]; then
|
||||
echo " DRIFT: $name $current → $TARGET_VERSION ($f)"
|
||||
DRIFT=$((DRIFT + 1))
|
||||
CAT1_DRIFT=$((CAT1_DRIFT + 1))
|
||||
else
|
||||
sed -i "s/^version = \"$current\"/version = \"$TARGET_VERSION\"/" "$f"
|
||||
echo " UPDATED: $name $current → $TARGET_VERSION ($f)"
|
||||
CHANGED=$((CHANGED + 1))
|
||||
CAT1_CHANGED=$((CAT1_CHANGED + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -105,10 +123,8 @@ while IFS= read -r f; do
|
||||
if [[ "$current" != "$TARGET_VERSION" ]]; then
|
||||
if [[ $CHECK_ONLY -eq 1 ]]; then
|
||||
echo " DRIFT (workspace): $current → $TARGET_VERSION ($f)"
|
||||
DRIFT=$((DRIFT + 1))
|
||||
CAT1_DRIFT=$((CAT1_DRIFT + 1))
|
||||
else
|
||||
# Only replace the version line that appears under [workspace.package]
|
||||
# Use awk for precision
|
||||
awk -v new="$TARGET_VERSION" '
|
||||
/^\[workspace\.package\]/ { in_wp=1 }
|
||||
/^\[/ && !/^\[workspace\.package\]/ { in_wp=0 }
|
||||
@@ -116,7 +132,7 @@ while IFS= read -r f; do
|
||||
{ print }
|
||||
' "$f" > "${f}.tmp" && mv "${f}.tmp" "$f"
|
||||
echo " UPDATED (workspace): $current → $TARGET_VERSION ($f)"
|
||||
CHANGED=$((CHANGED + 1))
|
||||
CAT1_CHANGED=$((CAT1_CHANGED + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -124,10 +140,74 @@ while IFS= read -r f; do
|
||||
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> 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 "Checked $CHECKED crates, found $DRIFT with version drift"
|
||||
[[ $DRIFT -gt 0 ]] && exit 1
|
||||
echo "All in-house crates are at $TARGET_VERSION"
|
||||
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 "Updated $CHANGED crates to $TARGET_VERSION (checked $CHECKED total)"
|
||||
echo "Cat 1: updated $CAT1_CHANGED (checked $CAT1_CHECKED)"
|
||||
echo "Cat 2: updated $CAT2_CHANGED"
|
||||
echo "All versions synced to branch '$BRANCH'"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user