update
This commit is contained in:
190
config/shared/bin/wt
Executable file
190
config/shared/bin/wt
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
########################################
|
||||
# Utilities
|
||||
########################################
|
||||
|
||||
fail() {
|
||||
echo "Error: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
ensure_repo() {
|
||||
git rev-parse --is-inside-work-tree >/dev/null 2>&1 ||
|
||||
fail "Not inside a git repository"
|
||||
}
|
||||
|
||||
repo_root() {
|
||||
git rev-parse --show-toplevel
|
||||
}
|
||||
|
||||
detect_base() {
|
||||
if git show-ref --verify --quiet refs/heads/main; then
|
||||
echo "main"
|
||||
elif git show-ref --verify --quiet refs/heads/master; then
|
||||
echo "master"
|
||||
else
|
||||
git branch --show-current
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_clean() {
|
||||
git diff --quiet || fail "Working tree is dirty"
|
||||
git diff --cached --quiet || fail "Index is dirty"
|
||||
}
|
||||
|
||||
########################################
|
||||
# Core Paths
|
||||
########################################
|
||||
|
||||
ROOT=$(repo_root)
|
||||
WT_DIR="$ROOT/.worktrees"
|
||||
|
||||
########################################
|
||||
# Commands
|
||||
########################################
|
||||
|
||||
cmd_new() {
|
||||
local name="$1"
|
||||
local base="${2:-$(detect_base)}"
|
||||
local path="$WT_DIR/$name"
|
||||
|
||||
[ -d "$path" ] && fail "Worktree directory already exists"
|
||||
git show-ref --verify --quiet "refs/heads/$name" &&
|
||||
fail "Branch '$name' already exists"
|
||||
|
||||
mkdir -p "$WT_DIR"
|
||||
|
||||
git worktree add -b "$name" "$path" "$base"
|
||||
|
||||
echo "Created worktree:"
|
||||
echo " branch: $name"
|
||||
echo " path: $path"
|
||||
}
|
||||
|
||||
cmd_list() {
|
||||
git worktree list
|
||||
}
|
||||
|
||||
cmd_path() {
|
||||
echo "$WT_DIR/$1"
|
||||
}
|
||||
|
||||
cmd_rm() {
|
||||
local name="$1"
|
||||
local path="$WT_DIR/$name"
|
||||
|
||||
[ -d "$path" ] || fail "Worktree not found"
|
||||
|
||||
git worktree remove "$path"
|
||||
git branch -D "$name" >/dev/null 2>&1 || true
|
||||
|
||||
echo "Removed worktree '$name'"
|
||||
}
|
||||
|
||||
cmd_finish() {
|
||||
local name="$1"
|
||||
shift
|
||||
local keep_worktree=0
|
||||
local path="$WT_DIR/$name"
|
||||
local base
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--keep-worktree)
|
||||
keep_worktree=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
fail "Unknown option for finish: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -d "$path" ] || fail "Worktree not found"
|
||||
git show-ref --verify --quiet "refs/heads/$name" ||
|
||||
fail "Branch '$name' not found"
|
||||
|
||||
base=$(detect_base)
|
||||
|
||||
echo "Base branch: $base"
|
||||
echo "Feature branch: $name"
|
||||
|
||||
git checkout "$base" >/dev/null
|
||||
ensure_clean
|
||||
|
||||
if ! git merge --squash "$name"; then
|
||||
echo
|
||||
echo "Resolve conflicts, then run:"
|
||||
echo " git commit"
|
||||
echo " wt rm $name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git commit -m "$name"
|
||||
|
||||
if [ -d "$path" ] && [ "$keep_worktree" -eq 0 ]; then
|
||||
if ! git worktree remove "$path"; then
|
||||
git worktree remove --force "$path" || fail "Failed to remove worktree '$name'"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$keep_worktree" -eq 0 ]; then
|
||||
git branch -D "$name"
|
||||
fi
|
||||
|
||||
if [ "$keep_worktree" -eq 1 ]; then
|
||||
echo "Merged (squash) into '$base' and kept worktree '$path'"
|
||||
else
|
||||
echo "Merged (squash) and removed '$name'"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_prune() {
|
||||
git worktree prune
|
||||
echo "Pruned stale worktree metadata"
|
||||
}
|
||||
|
||||
########################################
|
||||
# Entry
|
||||
########################################
|
||||
|
||||
ensure_repo
|
||||
|
||||
case "${1:-}" in
|
||||
new)
|
||||
[ $# -lt 2 ] && fail "Usage: wt new <name> [base]"
|
||||
cmd_new "$2" "${3:-}"
|
||||
;;
|
||||
list)
|
||||
cmd_list
|
||||
;;
|
||||
path)
|
||||
[ $# -lt 2 ] && fail "Usage: wt path <name>"
|
||||
cmd_path "$2"
|
||||
;;
|
||||
finish)
|
||||
[ $# -lt 2 ] && fail "Usage: wt finish <name>"
|
||||
cmd_finish "$2" "${@:3}"
|
||||
;;
|
||||
rm)
|
||||
[ $# -lt 2 ] && fail "Usage: wt rm <name>"
|
||||
cmd_rm "$2"
|
||||
;;
|
||||
prune)
|
||||
cmd_prune
|
||||
;;
|
||||
*)
|
||||
cat <<EOF
|
||||
Usage:
|
||||
wt new <name> [base]
|
||||
wt list
|
||||
wt path <name>
|
||||
wt finish <name> [--keep-worktree]
|
||||
wt rm <name>
|
||||
wt prune
|
||||
EOF
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user