Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Comment thread
coderabbitai[bot] marked this conversation as resolved.
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
3 changes: 2 additions & 1 deletion 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 Expand Up @@ -139,7 +140,7 @@ complete -f -c git -n '__fish_git_gtr_using_command config' -a "
gtr.worktrees.prefix 'Worktree folder prefix'
gtr.defaultBranch 'Default branch'
gtr.provider 'Hosting provider (github, gitlab)'
gtr.ui.color 'Color output mode (auto, always, never)'
gtr.ui.color 'gtr.ui.color'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
"

# Helper function to get branch names and special '1' for main repo
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