feat(josh-sync): add rename command for safe target renames

Adds `josh-sync rename <target>` (PE-12): safely rename a sync target's
name, subfolder, and/or subrepo_url in one resumable operation, editing
.josh-sync.yml and migrating its state-branch files atomically instead of
orphaning them. Bumps josh-sync to v2.3.0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNXgcFWVgSh3wkQS55cCX6
This commit is contained in:
2026-07-16 10:10:40 +01:00
co-authored by Claude Sonnet 5
parent c4bcbbdd4f
commit 27b0e2acaa
11 changed files with 1089 additions and 2 deletions
+56
View File
@@ -11,6 +11,7 @@
# onboard <target> Interactive onboarding (auto-picks reset|adopt strategy)
# adopt <target> Alias for `onboard --mode=adopt`
# reset <target> Reset subrepo to josh-filtered view
# rename <target> Rename a target's name/subfolder/subrepo_url, migrating state
# migrate-pr <target> [PR#...] [--all] Move PRs from archived to new subrepo
# status Show target config and sync state
# state show|reset Manage sync state directly
@@ -46,6 +47,8 @@ source "${JOSH_LIB_DIR}/sync.sh"
source "${JOSH_LIB_DIR}/adopt.sh"
# shellcheck source=../lib/onboard.sh
source "${JOSH_LIB_DIR}/onboard.sh"
# shellcheck source=../lib/rename.sh
source "${JOSH_LIB_DIR}/rename.sh"
# ─── Version ────────────────────────────────────────────────────────
@@ -82,6 +85,10 @@ Commands:
via ls-remote (heads → adopt, empty → reset).
adopt <target> Alias for 'onboard --mode=adopt' (kept for back-compat)
reset <target> Reset subrepo to josh-filtered view (after merging import PR)
rename <target> Rename a target's name/subfolder/subrepo_url. Edits
.josh-sync.yml and migrates state on the josh-sync-state
branch in one resumable operation. Requires at least one
of --name/--subfolder/--subrepo-url.
migrate-pr <target> [PR#...] [--all] Move PRs from archived to new subrepo
status Show target config and sync state
state show <target> [branch] Show sync state JSON
@@ -103,6 +110,14 @@ Sync flags:
Onboard flags:
--mode={reset,adopt} Override the onboarding strategy
Rename flags:
--name NAME New target name
--subfolder PATH New monorepo subfolder (re-derives josh_filter)
--subrepo-url URL New subrepo git URL
--dry-run Print the planned changes without writing anything
--yes Skip the confirmation prompt
--force Bypass the concurrency-heuristic warning (only)
Environment:
JOSH_SYNC_TARGET Restrict to a single target name
JOSH_SYNC_STATE_BRANCH State branch name (default: josh-sync-state)
@@ -619,6 +634,46 @@ cmd_reset() {
done
}
# ─── Rename Command ─────────────────────────────────────────────────
cmd_rename() {
local config_file=".josh-sync.yml"
local target_name=""
local new_name="" new_subfolder="" new_subrepo_url=""
local dry_run=false assume_yes=false force=false
while [ $# -gt 0 ]; do
case "$1" in
--config) config_file="$2"; shift 2 ;;
--debug) export JOSH_SYNC_DEBUG=1; shift ;;
--name) [ $# -ge 2 ] || die "--name requires a value"; new_name="$2"; shift 2 ;;
--subfolder) [ $# -ge 2 ] || die "--subfolder requires a value"; new_subfolder="$2"; shift 2 ;;
--subrepo-url) [ $# -ge 2 ] || die "--subrepo-url requires a value"; new_subrepo_url="$2"; shift 2 ;;
--dry-run) dry_run=true; shift ;;
--yes) assume_yes=true; shift ;;
--force) force=true; shift ;;
-*) die "Unknown flag: $1" ;;
*) target_name="$1"; shift ;;
esac
done
if [ -z "$target_name" ]; then
echo "Usage: josh-sync rename <target> [--name NEW] [--subfolder PATH] [--subrepo-url URL] [--dry-run] [--yes] [--force]" >&2
parse_config "$config_file"
echo "Available targets:" >&2
echo "$JOSH_SYNC_TARGETS" | jq -r '.[].name' | sed 's/^/ /' >&2
exit 1
fi
if [ -z "$new_name" ] && [ -z "$new_subfolder" ] && [ -z "$new_subrepo_url" ]; then
die "At least one of --name, --subfolder, or --subrepo-url is required"
fi
parse_config "$config_file"
rename_target "$target_name" "$new_name" "$new_subfolder" "$new_subrepo_url" \
"$config_file" "$dry_run" "$assume_yes" "$force"
}
# ─── Status Command ────────────────────────────────────────────────
cmd_status() {
@@ -934,6 +989,7 @@ main() {
import) cmd_import "$@" ;;
adopt) cmd_adopt "$@" ;;
reset) cmd_reset "$@" ;;
rename) cmd_rename "$@" ;;
onboard) cmd_onboard "$@" ;;
migrate-pr) cmd_migrate_pr "$@" ;;
status) cmd_status "$@" ;;