Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ mkdir -p /tmp/gtr-test && cd /tmp/gtr-test && git init && git commit --allow-emp

### Binary Structure

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

### Module Structure

Expand Down Expand Up @@ -134,7 +134,7 @@ cmd_editor() → resolve_target() → load_editor_adapter() → editor_open()

### Updating the Version

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

### Shell Completion Updates

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

## Critical Gotcha: `set -e`

`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`:
`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`:

```bash
result=$(my_func) || true # Prevents silent exit
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ We welcome feature suggestions! Please:

```
git-worktree-runner/
├── bin/gtr # Main executable (~105 lines: sources libs, dispatches commands)
├── bin/git-gtr # Main executable (sources libs, dispatches commands)
├── bin/gtr # Convenience wrapper (exec bin/git-gtr)
├── lib/ # Core functionality
│ ├── ui.sh # User interface (logging, prompts)
│ ├── config.sh # Configuration (git-config wrapper)
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ gtr cd my-feature
gtr cd 1
```

> **Note:** If `gtr` conflicts with another command (e.g., GNU `tr` from coreutils), use `--as` to pick a different name:
>
> ```bash
> eval "$(git gtr init zsh --as gwtr)"
> gwtr cd my-feature
> ```

### `git gtr run <branch> <command...>`

Execute command in worktree directory.
Expand Down
127 changes: 115 additions & 12 deletions bin/git-gtr
Original file line number Diff line number Diff line change
@@ -1,15 +1,118 @@
#!/usr/bin/env bash
# git-gtr - Git worktree runner (git subcommand wrapper)
# Allows running as: git gtr <command>

# Find this script's real location (resolve symlinks)
SRC="${BASH_SOURCE[0]}"
while [ -h "$SRC" ]; do
DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
SRC="$(readlink "$SRC")"
[[ $SRC != /* ]] && SRC="$DIR/$SRC"
# git-gtr - Git worktree runner
# Portable, cross-platform git worktree management
# Invoked as: git gtr <command> (git subcommand via PATH discovery)

set -e

# Debug: show file:line:function on set -e failures
if [ -n "${GTR_DEBUG:-}" ]; then
trap 'printf "ERROR at %s:%s in %s()\n" "${BASH_SOURCE[0]}" "$LINENO" "${FUNCNAME[0]:-main}" >&2' ERR
fi

# Version
GTR_VERSION="2.3.0"

# Find the script directory (resolve symlinks; allow env override)
resolve_script_dir() {
local src="${BASH_SOURCE[0]}"
while [ -h "$src" ]; do
local dir
dir="$(cd -P "$(dirname "$src")" && pwd)"
src="$(readlink "$src")"
[[ "$src" != /* ]] && src="$dir/$src"
done
cd -P "$(dirname "$src")/.." && pwd
}
: "${GTR_DIR:=$(resolve_script_dir)}"

# Source library files
. "$GTR_DIR/lib/ui.sh"
. "$GTR_DIR/lib/args.sh"
. "$GTR_DIR/lib/config.sh"
_ui_apply_color_config
. "$GTR_DIR/lib/platform.sh"
. "$GTR_DIR/lib/core.sh"
. "$GTR_DIR/lib/copy.sh"
. "$GTR_DIR/lib/hooks.sh"
. "$GTR_DIR/lib/provider.sh"
. "$GTR_DIR/lib/adapters.sh"
. "$GTR_DIR/lib/launch.sh"

# Source command handlers
for _cmd_file in "$GTR_DIR"/lib/commands/*.sh; do
# shellcheck disable=SC1090
. "$_cmd_file"
done
SCRIPT_DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
unset _cmd_file

# Main dispatcher
main() {
local cmd="${1:-help}"
shift 2>/dev/null || true

# Set for per-command help (used by show_command_help in ui.sh)
_GTR_CURRENT_COMMAND="$cmd"

case "$cmd" in
new)
cmd_create "$@"
;;
rm)
cmd_remove "$@"
;;
mv|rename)
cmd_rename "$@"
;;
go)
cmd_go "$@"
;;
run)
cmd_run "$@"
;;
editor)
cmd_editor "$@"
;;
ai)
cmd_ai "$@"
;;
copy)
cmd_copy "$@"
;;
ls|list)
cmd_list "$@"
;;
clean)
cmd_clean "$@"
;;
doctor)
cmd_doctor "$@"
;;
adapter|adapters)
cmd_adapter "$@"
;;
config)
cmd_config "$@"
;;
completion)
cmd_completion "$@"
;;
init)
cmd_init "$@"
;;
version|--version|-v)
echo "git gtr version $GTR_VERSION"
;;
help|--help|-h)
cmd_help "$@"
;;
*)
log_error "Unknown command: $cmd"
echo "Use 'git gtr help' for available commands"
exit 1
;;
esac
}

# Execute the main gtr script
exec "$SCRIPT_DIR/gtr" "$@"
# Run main
main "$@"
126 changes: 12 additions & 114 deletions bin/gtr
Original file line number Diff line number Diff line change
@@ -1,117 +1,15 @@
#!/usr/bin/env bash
# gtr - Git worktree runner
# Portable, cross-platform git worktree management

set -e

# Debug: show file:line:function on set -e failures
if [ -n "${GTR_DEBUG:-}" ]; then
trap 'printf "ERROR at %s:%s in %s()\n" "${BASH_SOURCE[0]}" "$LINENO" "${FUNCNAME[0]:-main}" >&2' ERR
fi

# Version
GTR_VERSION="2.3.0"

# Find the script directory (resolve symlinks; allow env override)
resolve_script_dir() {
local src="${BASH_SOURCE[0]}"
while [ -h "$src" ]; do
local dir
dir="$(cd -P "$(dirname "$src")" && pwd)"
src="$(readlink "$src")"
[[ $src != /* ]] && src="$dir/$src"
done
cd -P "$(dirname "$src")/.." && pwd
}
: "${GTR_DIR:=$(resolve_script_dir)}"

# Source library files
. "$GTR_DIR/lib/ui.sh"
. "$GTR_DIR/lib/args.sh"
. "$GTR_DIR/lib/config.sh"
_ui_apply_color_config
. "$GTR_DIR/lib/platform.sh"
. "$GTR_DIR/lib/core.sh"
. "$GTR_DIR/lib/copy.sh"
. "$GTR_DIR/lib/hooks.sh"
. "$GTR_DIR/lib/provider.sh"
. "$GTR_DIR/lib/adapters.sh"
. "$GTR_DIR/lib/launch.sh"

# Source command handlers
for _cmd_file in "$GTR_DIR"/lib/commands/*.sh; do
# shellcheck disable=SC1090
. "$_cmd_file"
# gtr - Convenience wrapper for git-gtr
# The main binary is bin/git-gtr; this wrapper allows ./bin/gtr for development.

# Find this script's real location (resolve symlinks)
SRC="${BASH_SOURCE[0]}"
while [ -h "$SRC" ]; do
DIR="$(cd -P "$(dirname "$SRC")" && pwd)"
SRC="$(readlink "$SRC")"
[[ $SRC != /* ]] && SRC="$DIR/$SRC"
done
unset _cmd_file

# Main dispatcher
main() {
local cmd="${1:-help}"
shift 2>/dev/null || true

# Set for per-command help (used by show_command_help in ui.sh)
_GTR_CURRENT_COMMAND="$cmd"

case "$cmd" in
new)
cmd_create "$@"
;;
rm)
cmd_remove "$@"
;;
mv|rename)
cmd_rename "$@"
;;
go)
cmd_go "$@"
;;
run)
cmd_run "$@"
;;
editor)
cmd_editor "$@"
;;
ai)
cmd_ai "$@"
;;
copy)
cmd_copy "$@"
;;
ls|list)
cmd_list "$@"
;;
clean)
cmd_clean "$@"
;;
doctor)
cmd_doctor "$@"
;;
adapter|adapters)
cmd_adapter "$@"
;;
config)
cmd_config "$@"
;;
completion)
cmd_completion "$@"
;;
init)
cmd_init "$@"
;;
version|--version|-v)
echo "git gtr version $GTR_VERSION"
;;
help|--help|-h)
cmd_help "$@"
;;
*)
log_error "Unknown command: $cmd"
echo "Use 'git gtr help' for available commands"
exit 1
;;
esac
}
SCRIPT_DIR="$(cd -P "$(dirname "$SRC")" && pwd)"

# Run main
main "$@"
# Execute the main git-gtr script
exec "$SCRIPT_DIR/git-gtr" "$@"
9 changes: 8 additions & 1 deletion completions/_git-gtr
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ _git-gtr() {
# Complete action or scope flags
_values 'config action' list get set add unset --local --global --system
;;
completion|init)
completion)
# Complete shell names
_values 'shell' bash zsh fish
;;
init)
# Complete shell names
_values 'shell' bash zsh fish
;;
Expand Down Expand Up @@ -149,6 +153,9 @@ _git-gtr() {
worktrees) _describe 'branch names' all_options ;;
esac
;;
init)
_arguments '--as[Custom function name]:name:'
;;
config)
# Find action by scanning all config args (handles flexible flag positioning)
# Use offset 3 to start from words[4] (first arg after 'config')
Expand Down
1 change: 1 addition & 0 deletions completions/git-gtr.fish
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ complete -f -c git -n '__fish_git_gtr_needs_command' -a completion -d 'Generate
complete -f -c git -n '__fish_git_gtr_using_command completion' -a 'bash zsh fish' -d 'Shell type'
complete -f -c git -n '__fish_git_gtr_needs_command' -a init -d 'Generate shell integration for cd support'
complete -f -c git -n '__fish_git_gtr_using_command init' -a 'bash zsh fish' -d 'Shell type'
complete -c git -n '__fish_git_gtr_using_command init' -l as -d 'Custom function name' -r
complete -f -c git -n '__fish_git_gtr_needs_command' -a version -d 'Show version'
complete -f -c git -n '__fish_git_gtr_needs_command' -a help -d 'Show help'

Expand Down
9 changes: 8 additions & 1 deletion completions/gtr.bash
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,19 @@ _git_gtr() {
COMPREPLY=($(compgen -W "auto remote local none" -- "$cur"))
fi
;;
completion|init)
completion)
# Complete with shell names
if [ "$cword" -eq 3 ]; then
COMPREPLY=($(compgen -W "bash zsh fish" -- "$cur"))
fi
;;
init)
if [ "$cword" -eq 3 ]; then
COMPREPLY=($(compgen -W "bash zsh fish" -- "$cur"))
elif [[ "$cur" == -* ]]; then
COMPREPLY=($(compgen -W "--as" -- "$cur"))
fi
;;
config)
# Find action by scanning all config args (handles flexible flag positioning)
local config_action=""
Expand Down
Loading