feat(josh-sync): rename --subfolder now git mv's the actual directory
Previously --subfolder only repointed .josh-sync.yml, leaving the working tree out of sync with the new path until a later filter-change reconciliation happened to catch it. Now validates the old subfolder exists and is tracked by git (proof it's actually managed by josh-sync) and the new one doesn't already exist, then git mv's it — staged, not committed, alongside the config edit. Idempotent on resume. Bumps to v2.4.0. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TNXgcFWVgSh3wkQS55cCX6
This commit is contained in:
@@ -89,6 +89,43 @@ _rename_check_url_reachable() {
|
||||
return "$ok"
|
||||
}
|
||||
|
||||
# ─── Subfolder Move ──────────────────────────────────────────────
|
||||
# Renaming a subfolder must move the actual directory in the monorepo
|
||||
# working tree via `git mv`, not just repoint the config — otherwise the
|
||||
# tree stops matching `.josh-sync.yml` until a later sync's filter-change
|
||||
# reconciliation happens to catch it. Both functions are idempotent against
|
||||
# a resumed run: if new_subfolder already exists and old_subfolder doesn't,
|
||||
# the move already happened, so there's nothing left to validate or do.
|
||||
|
||||
# Usage: _rename_validate_subfolder_move <old_subfolder> <new_subfolder>
|
||||
_rename_validate_subfolder_move() {
|
||||
local old_subfolder="$1" new_subfolder="$2"
|
||||
|
||||
if [ -e "$new_subfolder" ] && [ ! -e "$old_subfolder" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
[ -e "$old_subfolder" ] || die "Old subfolder '${old_subfolder}' does not exist in the working tree"
|
||||
[ -n "$(git ls-files -- "$old_subfolder")" ] \
|
||||
|| die "Old subfolder '${old_subfolder}' has no files tracked by git — not managed by josh-sync"
|
||||
[ ! -e "$new_subfolder" ] || die "New subfolder '${new_subfolder}' already exists — refusing to overwrite"
|
||||
}
|
||||
|
||||
# Usage: _rename_move_subfolder <old_subfolder> <new_subfolder>
|
||||
_rename_move_subfolder() {
|
||||
local old_subfolder="$1" new_subfolder="$2"
|
||||
|
||||
if [ -e "$new_subfolder" ] && [ ! -e "$old_subfolder" ]; then
|
||||
log "INFO" "Subfolder already moved to '${new_subfolder}' — skipping git mv"
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$new_subfolder")"
|
||||
git mv "$old_subfolder" "$new_subfolder" \
|
||||
|| die "Failed to git mv '${old_subfolder}' -> '${new_subfolder}'"
|
||||
log "INFO" "Moved ${old_subfolder} -> ${new_subfolder} (git mv, uncommitted)"
|
||||
}
|
||||
|
||||
# ─── Stale Import-Branch Warning (best-effort, never fails) ────────
|
||||
# Onboarding's initial_import (lib/sync.sh) pushes staging branches named
|
||||
# auto-sync/import-<target>-<timestamp> to the MONOREPO. These are normally
|
||||
@@ -223,6 +260,10 @@ rename_target() {
|
||||
[ -z "$existing" ] || die "State already exists for target '${new_name}' on ${STATE_BRANCH} — refusing to overwrite. Resolve manually (e.g. 'josh-sync state reset ${new_name} <branch>') before retrying."
|
||||
fi
|
||||
|
||||
if [ "$subfolder_changed" = true ]; then
|
||||
_rename_validate_subfolder_move "$old_subfolder" "$new_subfolder"
|
||||
fi
|
||||
|
||||
if [ "$dry_run" = true ]; then
|
||||
log "INFO" "--dry-run: no changes written"
|
||||
return 0
|
||||
@@ -235,6 +276,10 @@ rename_target() {
|
||||
[ "$confirm" = "y" ] || [ "$confirm" = "Y" ] || die "Aborted"
|
||||
fi
|
||||
|
||||
if [ "$subfolder_changed" = true ]; then
|
||||
_rename_move_subfolder "$old_subfolder" "$new_subfolder"
|
||||
fi
|
||||
|
||||
if [ "$already_configured" != true ]; then
|
||||
log "INFO" "Updating ${config_file}..."
|
||||
# mikefarah/yq (v4, Go) has no jq-style --arg; pass values via env vars and
|
||||
|
||||
Reference in New Issue
Block a user