fix: auto-migrate customized skills to skills-local/ on sync (#359)
This commit was merged in pull request #359.
This commit is contained in:
@@ -56,38 +56,66 @@ if [[ $fetch -eq 1 ]]; then
|
||||
if [[ -d "$SKILLS_REPO_DIR/.git" ]]; then
|
||||
echo "[mosaic-skills] Updating skills source: $SKILLS_REPO_DIR"
|
||||
|
||||
# Detect ANY dirty state: modified, staged, or untracked files.
|
||||
# Use git status --porcelain which catches everything pull --rebase cares about.
|
||||
# ── Detect dirty state ──────────────────────────────────────────────
|
||||
dirty=""
|
||||
dirty="$(git -C "$SKILLS_REPO_DIR" status --porcelain 2>/dev/null || true)"
|
||||
|
||||
if [[ -n "$dirty" ]]; then
|
||||
echo "[mosaic-skills] Stashing local changes (including untracked)..."
|
||||
git -C "$SKILLS_REPO_DIR" stash push -q --include-untracked -m "mosaic-sync-skills auto-stash" 2>/dev/null || {
|
||||
echo "[mosaic-skills] WARN: stash failed — skipping pull, using existing checkout" >&2
|
||||
dirty="skip-pull"
|
||||
}
|
||||
fi
|
||||
# ── Auto-migrate customized skills to skills-local/ ─────────────
|
||||
# Instead of stash/pop (fragile, merge conflicts), we:
|
||||
# 1. Identify which skill dirs contain user edits
|
||||
# 2. Copy those full skill dirs into skills-local/ (preserving edits)
|
||||
# 3. Reset the repo clean so pull always succeeds
|
||||
# 4. skills-local/ takes precedence during linking, so edits win
|
||||
|
||||
if [[ "$dirty" != "skip-pull" ]]; then
|
||||
if ! git -C "$SKILLS_REPO_DIR" pull --rebase 2>/dev/null; then
|
||||
echo "[mosaic-skills] WARN: pull failed — continuing with existing checkout" >&2
|
||||
# Abort any in-progress rebase so the repo isn't left in a broken state
|
||||
git -C "$SKILLS_REPO_DIR" rebase --abort 2>/dev/null || true
|
||||
SOURCE_SKILLS_SUBDIR="$SKILLS_REPO_DIR/skills"
|
||||
migrated=()
|
||||
|
||||
while IFS= read -r line; do
|
||||
# porcelain format: XY <path> — extract the file path
|
||||
file="${line:3}"
|
||||
# Only migrate files under skills/ subdir in the repo
|
||||
if [[ "$file" == skills/* ]]; then
|
||||
# Extract the skill directory name (first path component after skills/)
|
||||
skill_name="${file#skills/}"
|
||||
skill_name="${skill_name%%/*}"
|
||||
|
||||
# Skip if already migrated this skill in this run
|
||||
local_skill_dir="$MOSAIC_LOCAL_SKILLS_DIR/$skill_name"
|
||||
if [[ -d "$local_skill_dir" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Skip if skill_name is empty or hidden
|
||||
if [[ -z "$skill_name" || "$skill_name" == .* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Copy the skill (with user's edits) from repo working tree to skills-local/
|
||||
if [[ -d "$SOURCE_SKILLS_SUBDIR/$skill_name" ]]; then
|
||||
cp -R "$SOURCE_SKILLS_SUBDIR/$skill_name" "$local_skill_dir"
|
||||
migrated+=("$skill_name")
|
||||
fi
|
||||
fi
|
||||
done <<< "$dirty"
|
||||
|
||||
if [[ ${#migrated[@]} -gt 0 ]]; then
|
||||
echo "[mosaic-skills] Migrated ${#migrated[@]} customized skill(s) to skills-local/:"
|
||||
for s in "${migrated[@]}"; do
|
||||
echo " → $MOSAIC_LOCAL_SKILLS_DIR/$s"
|
||||
done
|
||||
echo "[mosaic-skills] Your edits are preserved there and take precedence over canonical."
|
||||
fi
|
||||
|
||||
# Reset repo to clean state so pull always works
|
||||
echo "[mosaic-skills] Resetting source repo to clean state..."
|
||||
git -C "$SKILLS_REPO_DIR" checkout . 2>/dev/null || true
|
||||
git -C "$SKILLS_REPO_DIR" clean -fd 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Restore stashed changes if we stashed anything
|
||||
if [[ -n "$dirty" && "$dirty" != "skip-pull" ]]; then
|
||||
echo "[mosaic-skills] Restoring local changes..."
|
||||
git -C "$SKILLS_REPO_DIR" stash pop -q 2>/dev/null || \
|
||||
echo "[mosaic-skills] WARN: stash pop had conflicts — check $SKILLS_REPO_DIR" >&2
|
||||
fi
|
||||
|
||||
# Hint: customized skills belong in skills-local/, not in the canonical repo
|
||||
if [[ -n "$dirty" ]]; then
|
||||
echo "[mosaic-skills] TIP: Put customized skills in $MOSAIC_LOCAL_SKILLS_DIR/ instead"
|
||||
echo "[mosaic-skills] Files there are never overwritten and take precedence."
|
||||
if ! git -C "$SKILLS_REPO_DIR" pull --rebase 2>/dev/null; then
|
||||
echo "[mosaic-skills] WARN: pull failed — continuing with existing checkout" >&2
|
||||
git -C "$SKILLS_REPO_DIR" rebase --abort 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
echo "[mosaic-skills] Cloning skills source to: $SKILLS_REPO_DIR"
|
||||
|
||||
Reference in New Issue
Block a user