update
This commit is contained in:
67
config/shared/bin/catfiles
Executable file
67
config/shared/bin/catfiles
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="."
|
||||
declare -a SKIP_DIRS=()
|
||||
declare -a PATTERNS=()
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [-r root_dir] [-s dir_to_skip]... -p pattern ...
|
||||
|
||||
Options:
|
||||
-r DIR Root directory (default: .)
|
||||
-s DIR Directory name to skip (can repeat)
|
||||
-p PATTERN File pattern (e.g. '*.md', '*.txt') (required, can repeat)
|
||||
|
||||
Example:
|
||||
$0 -p '*.md'
|
||||
$0 -r src -s node_modules -s .git -p '*.md' -p '*.txt'
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
while getopts ":r:s:p:" opt; do
|
||||
case "$opt" in
|
||||
r) ROOT="$OPTARG" ;;
|
||||
s) SKIP_DIRS+=("$OPTARG") ;;
|
||||
p) PATTERNS+=("$OPTARG") ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
# Require at least one pattern
|
||||
(( ${#PATTERNS[@]} > 0 )) || usage
|
||||
|
||||
# Build prune expression
|
||||
PRUNE_EXPR=()
|
||||
if (( ${#SKIP_DIRS[@]} > 0 )); then
|
||||
PRUNE_EXPR+=( \( )
|
||||
for i in "${!SKIP_DIRS[@]}"; do
|
||||
PRUNE_EXPR+=( -type d -name "${SKIP_DIRS[$i]}" -prune )
|
||||
[[ $i -lt $((${#SKIP_DIRS[@]} - 1)) ]] && PRUNE_EXPR+=( -o )
|
||||
done
|
||||
PRUNE_EXPR+=( \) -o )
|
||||
fi
|
||||
|
||||
# Build pattern expression
|
||||
PATTERN_EXPR=( \( )
|
||||
for i in "${!PATTERNS[@]}"; do
|
||||
PATTERN_EXPR+=( -name "${PATTERNS[$i]}" )
|
||||
[[ $i -lt $((${#PATTERNS[@]} - 1)) ]] && PATTERN_EXPR+=( -o )
|
||||
done
|
||||
PATTERN_EXPR+=( \) )
|
||||
|
||||
# Execute
|
||||
find "$ROOT" \
|
||||
"${PRUNE_EXPR[@]}" \
|
||||
-type f \
|
||||
"${PATTERN_EXPR[@]}" \
|
||||
-print0 |
|
||||
while IFS= read -r -d '' file; do
|
||||
printf "\n===== %s =====\n" "$file"
|
||||
cat "$file"
|
||||
done
|
||||
|
||||
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