Skip to content

Commit 3c09a8b

Browse files
committed
fix: resolve gtr/coreutils naming conflict and add cd completions
Closes #124 - Reverse binary relationship: bin/git-gtr is now the main entry point, bin/gtr becomes a convenience wrapper. This allows the Homebrew formula to stop installing bin/gtr, eliminating the conflict with coreutils. - Add --as flag to git gtr init so users can choose a custom function name (e.g. eval "$(git gtr init zsh --as gwtr)") to avoid shadowing coreutils gtr in their shell. - Add cd completions to init output for all three shells (bash, zsh, fish). Worktree names are completed via git gtr list --porcelain. - Add 26 BATS tests for the init command covering --as flag, name validation, cd completions, and shell output correctness.
1 parent 4858fb6 commit 3c09a8b

File tree

12 files changed

+533
-199
lines changed

12 files changed

+533
-199
lines changed

CLAUDE.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ mkdir -p /tmp/gtr-test && cd /tmp/gtr-test && git init && git commit --allow-emp
4545

4646
### Binary Structure
4747

48-
- `bin/git-gtr`Thin wrapper enabling `git gtr` subcommand invocation
49-
- `bin/gtr`Entry point: sources libraries and commands, contains `main()` dispatcher
48+
- `bin/git-gtr`Main entry point: sources libraries and commands, contains `main()` dispatcher
49+
- `bin/gtr`Convenience wrapper for development (`exec bin/git-gtr`)
5050

5151
### Module Structure
5252

@@ -134,7 +134,7 @@ cmd_editor() → resolve_target() → load_editor_adapter() → editor_open()
134134

135135
### Updating the Version
136136

137-
Update `GTR_VERSION` in `bin/gtr` (line 8).
137+
Update `GTR_VERSION` in `bin/git-gtr`.
138138

139139
### Shell Completion Updates
140140

@@ -146,7 +146,7 @@ When adding commands or flags, update all three files:
146146

147147
## Critical Gotcha: `set -e`
148148

149-
`bin/gtr` runs with `set -e`. Any unguarded non-zero return silently exits the entire script. When calling functions that may `return 1`, guard with `|| true`:
149+
`bin/git-gtr` runs with `set -e`. Any unguarded non-zero return silently exits the entire script. When calling functions that may `return 1`, guard with `|| true`:
150150

151151
```bash
152152
result=$(my_func) || true # Prevents silent exit

CONTRIBUTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ We welcome feature suggestions! Please:
3232

3333
```
3434
git-worktree-runner/
35-
├── bin/gtr # Main executable (~105 lines: sources libs, dispatches commands)
35+
├── bin/git-gtr # Main executable (sources libs, dispatches commands)
36+
├── bin/gtr # Convenience wrapper (exec bin/git-gtr)
3637
├── lib/ # Core functionality
3738
│ ├── ui.sh # User interface (logging, prompts)
3839
│ ├── config.sh # Configuration (git-config wrapper)

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,13 @@ gtr cd my-feature
221221
gtr cd 1
222222
```
223223

224+
> **Note:** If `gtr` conflicts with another command (e.g., GNU `tr` from coreutils), use `--as` to pick a different name:
225+
>
226+
> ```bash
227+
> eval "$(git gtr init zsh --as gwtr)"
228+
> gwtr cd my-feature
229+
> ```
230+
224231
### `git gtr run <branch> <command...>`
225232
226233
Execute command in worktree directory.

bin/git-gtr

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,118 @@
11
#!/usr/bin/env bash
2-
# git-gtr - Git worktree runner (git subcommand wrapper)
3-
# Allows running as: git gtr <command>
4-
5-
# Find this script's real location (resolve symlinks)
6-
SRC="${BASH_SOURCE[0]}"
7-
while [ -h "$SRC" ]; do
8-
DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
9-
SRC="$(readlink "$SRC")"
10-
[[ $SRC != /* ]] && SRC="$DIR/$SRC"
2+
# git-gtr - Git worktree runner
3+
# Portable, cross-platform git worktree management
4+
# Invoked as: git gtr <command> (git subcommand via PATH discovery)
5+
6+
set -e
7+
8+
# Debug: show file:line:function on set -e failures
9+
if [ -n "${GTR_DEBUG:-}" ]; then
10+
trap 'printf "ERROR at %s:%s in %s()\n" "${BASH_SOURCE[0]}" "$LINENO" "${FUNCNAME[0]:-main}" >&2' ERR
11+
fi
12+
13+
# Version
14+
GTR_VERSION="2.3.0"
15+
16+
# Find the script directory (resolve symlinks; allow env override)
17+
resolve_script_dir() {
18+
local src="${BASH_SOURCE[0]}"
19+
while [ -h "$src" ]; do
20+
local dir
21+
dir="$(cd -P "$(dirname "$src")" && pwd)"
22+
src="$(readlink "$src")"
23+
[[ $src != /* ]] && src="$dir/$src"
24+
done
25+
cd -P "$(dirname "$src")/.." && pwd
26+
}
27+
: "${GTR_DIR:=$(resolve_script_dir)}"
28+
29+
# Source library files
30+
. "$GTR_DIR/lib/ui.sh"
31+
. "$GTR_DIR/lib/args.sh"
32+
. "$GTR_DIR/lib/config.sh"
33+
_ui_apply_color_config
34+
. "$GTR_DIR/lib/platform.sh"
35+
. "$GTR_DIR/lib/core.sh"
36+
. "$GTR_DIR/lib/copy.sh"
37+
. "$GTR_DIR/lib/hooks.sh"
38+
. "$GTR_DIR/lib/provider.sh"
39+
. "$GTR_DIR/lib/adapters.sh"
40+
. "$GTR_DIR/lib/launch.sh"
41+
42+
# Source command handlers
43+
for _cmd_file in "$GTR_DIR"/lib/commands/*.sh; do
44+
# shellcheck disable=SC1090
45+
. "$_cmd_file"
1146
done
12-
SCRIPT_DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
47+
unset _cmd_file
48+
49+
# Main dispatcher
50+
main() {
51+
local cmd="${1:-help}"
52+
shift 2>/dev/null || true
53+
54+
# Set for per-command help (used by show_command_help in ui.sh)
55+
_GTR_CURRENT_COMMAND="$cmd"
56+
57+
case "$cmd" in
58+
new)
59+
cmd_create "$@"
60+
;;
61+
rm)
62+
cmd_remove "$@"
63+
;;
64+
mv|rename)
65+
cmd_rename "$@"
66+
;;
67+
go)
68+
cmd_go "$@"
69+
;;
70+
run)
71+
cmd_run "$@"
72+
;;
73+
editor)
74+
cmd_editor "$@"
75+
;;
76+
ai)
77+
cmd_ai "$@"
78+
;;
79+
copy)
80+
cmd_copy "$@"
81+
;;
82+
ls|list)
83+
cmd_list "$@"
84+
;;
85+
clean)
86+
cmd_clean "$@"
87+
;;
88+
doctor)
89+
cmd_doctor "$@"
90+
;;
91+
adapter|adapters)
92+
cmd_adapter "$@"
93+
;;
94+
config)
95+
cmd_config "$@"
96+
;;
97+
completion)
98+
cmd_completion "$@"
99+
;;
100+
init)
101+
cmd_init "$@"
102+
;;
103+
version|--version|-v)
104+
echo "git gtr version $GTR_VERSION"
105+
;;
106+
help|--help|-h)
107+
cmd_help "$@"
108+
;;
109+
*)
110+
log_error "Unknown command: $cmd"
111+
echo "Use 'git gtr help' for available commands"
112+
exit 1
113+
;;
114+
esac
115+
}
13116

14-
# Execute the main gtr script
15-
exec "$SCRIPT_DIR/gtr" "$@"
117+
# Run main
118+
main "$@"

bin/gtr

Lines changed: 12 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,15 @@
11
#!/usr/bin/env bash
2-
# gtr - Git worktree runner
3-
# Portable, cross-platform git worktree management
4-
5-
set -e
6-
7-
# Debug: show file:line:function on set -e failures
8-
if [ -n "${GTR_DEBUG:-}" ]; then
9-
trap 'printf "ERROR at %s:%s in %s()\n" "${BASH_SOURCE[0]}" "$LINENO" "${FUNCNAME[0]:-main}" >&2' ERR
10-
fi
11-
12-
# Version
13-
GTR_VERSION="2.3.0"
14-
15-
# Find the script directory (resolve symlinks; allow env override)
16-
resolve_script_dir() {
17-
local src="${BASH_SOURCE[0]}"
18-
while [ -h "$src" ]; do
19-
local dir
20-
dir="$(cd -P "$(dirname "$src")" && pwd)"
21-
src="$(readlink "$src")"
22-
[[ $src != /* ]] && src="$dir/$src"
23-
done
24-
cd -P "$(dirname "$src")/.." && pwd
25-
}
26-
: "${GTR_DIR:=$(resolve_script_dir)}"
27-
28-
# Source library files
29-
. "$GTR_DIR/lib/ui.sh"
30-
. "$GTR_DIR/lib/args.sh"
31-
. "$GTR_DIR/lib/config.sh"
32-
_ui_apply_color_config
33-
. "$GTR_DIR/lib/platform.sh"
34-
. "$GTR_DIR/lib/core.sh"
35-
. "$GTR_DIR/lib/copy.sh"
36-
. "$GTR_DIR/lib/hooks.sh"
37-
. "$GTR_DIR/lib/provider.sh"
38-
. "$GTR_DIR/lib/adapters.sh"
39-
. "$GTR_DIR/lib/launch.sh"
40-
41-
# Source command handlers
42-
for _cmd_file in "$GTR_DIR"/lib/commands/*.sh; do
43-
# shellcheck disable=SC1090
44-
. "$_cmd_file"
2+
# gtr - Convenience wrapper for git-gtr
3+
# The main binary is bin/git-gtr; this wrapper allows ./bin/gtr for development.
4+
5+
# Find this script's real location (resolve symlinks)
6+
SRC="${BASH_SOURCE[0]}"
7+
while [ -h "$SRC" ]; do
8+
DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
9+
SRC="$(readlink "$SRC")"
10+
[[ $SRC != /* ]] && SRC="$DIR/$SRC"
4511
done
46-
unset _cmd_file
47-
48-
# Main dispatcher
49-
main() {
50-
local cmd="${1:-help}"
51-
shift 2>/dev/null || true
52-
53-
# Set for per-command help (used by show_command_help in ui.sh)
54-
_GTR_CURRENT_COMMAND="$cmd"
55-
56-
case "$cmd" in
57-
new)
58-
cmd_create "$@"
59-
;;
60-
rm)
61-
cmd_remove "$@"
62-
;;
63-
mv|rename)
64-
cmd_rename "$@"
65-
;;
66-
go)
67-
cmd_go "$@"
68-
;;
69-
run)
70-
cmd_run "$@"
71-
;;
72-
editor)
73-
cmd_editor "$@"
74-
;;
75-
ai)
76-
cmd_ai "$@"
77-
;;
78-
copy)
79-
cmd_copy "$@"
80-
;;
81-
ls|list)
82-
cmd_list "$@"
83-
;;
84-
clean)
85-
cmd_clean "$@"
86-
;;
87-
doctor)
88-
cmd_doctor "$@"
89-
;;
90-
adapter|adapters)
91-
cmd_adapter "$@"
92-
;;
93-
config)
94-
cmd_config "$@"
95-
;;
96-
completion)
97-
cmd_completion "$@"
98-
;;
99-
init)
100-
cmd_init "$@"
101-
;;
102-
version|--version|-v)
103-
echo "git gtr version $GTR_VERSION"
104-
;;
105-
help|--help|-h)
106-
cmd_help "$@"
107-
;;
108-
*)
109-
log_error "Unknown command: $cmd"
110-
echo "Use 'git gtr help' for available commands"
111-
exit 1
112-
;;
113-
esac
114-
}
12+
SCRIPT_DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
11513

116-
# Run main
117-
main "$@"
14+
# Execute the main git-gtr script
15+
exec "$SCRIPT_DIR/git-gtr" "$@"

completions/_git-gtr

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ _git-gtr() {
112112
# Complete action or scope flags
113113
_values 'config action' list get set add unset --local --global --system
114114
;;
115-
completion|init)
115+
completion)
116+
# Complete shell names
117+
_values 'shell' bash zsh fish
118+
;;
119+
init)
116120
# Complete shell names
117121
_values 'shell' bash zsh fish
118122
;;
@@ -149,6 +153,9 @@ _git-gtr() {
149153
worktrees) _describe 'branch names' all_options ;;
150154
esac
151155
;;
156+
init)
157+
_arguments '--as[Custom function name]:name:'
158+
;;
152159
config)
153160
# Find action by scanning all config args (handles flexible flag positioning)
154161
# Use offset 3 to start from words[4] (first arg after 'config')

completions/git-gtr.fish

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ complete -f -c git -n '__fish_git_gtr_needs_command' -a completion -d 'Generate
5353
complete -f -c git -n '__fish_git_gtr_using_command completion' -a 'bash zsh fish' -d 'Shell type'
5454
complete -f -c git -n '__fish_git_gtr_needs_command' -a init -d 'Generate shell integration for cd support'
5555
complete -f -c git -n '__fish_git_gtr_using_command init' -a 'bash zsh fish' -d 'Shell type'
56+
complete -c git -n '__fish_git_gtr_using_command init' -l as -d 'Custom function name' -r
5657
complete -f -c git -n '__fish_git_gtr_needs_command' -a version -d 'Show version'
5758
complete -f -c git -n '__fish_git_gtr_needs_command' -a help -d 'Show help'
5859

@@ -139,7 +140,7 @@ complete -f -c git -n '__fish_git_gtr_using_command config' -a "
139140
gtr.worktrees.prefix 'Worktree folder prefix'
140141
gtr.defaultBranch 'Default branch'
141142
gtr.provider 'Hosting provider (github, gitlab)'
142-
gtr.ui.color 'Color output mode (auto, always, never)'
143+
gtr.ui.color 'gtr.ui.color'
143144
"
144145

145146
# Helper function to get branch names and special '1' for main repo

completions/gtr.bash

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,19 @@ _git_gtr() {
104104
COMPREPLY=($(compgen -W "auto remote local none" -- "$cur"))
105105
fi
106106
;;
107-
completion|init)
107+
completion)
108108
# Complete with shell names
109109
if [ "$cword" -eq 3 ]; then
110110
COMPREPLY=($(compgen -W "bash zsh fish" -- "$cur"))
111111
fi
112112
;;
113+
init)
114+
if [ "$cword" -eq 3 ]; then
115+
COMPREPLY=($(compgen -W "bash zsh fish" -- "$cur"))
116+
elif [[ "$cur" == -* ]]; then
117+
COMPREPLY=($(compgen -W "--as" -- "$cur"))
118+
fi
119+
;;
113120
config)
114121
# Find action by scanning all config args (handles flexible flag positioning)
115122
local config_action=""

0 commit comments

Comments
 (0)