From c381eb19db81a767e478018756bc89c51356e393 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 3 Nov 2024 14:48:15 -0500 Subject: [PATCH 01/14] feat: add interactive git worktree operations --- bin/git-forgit | 98 +++++++++++++++++++++++++++++++++++++++ conf.d/forgit.plugin.fish | 4 ++ forgit.plugin.zsh | 24 ++++++++++ 3 files changed, 126 insertions(+) diff --git a/bin/git-forgit b/bin/git-forgit index 4aac1fc0..2c12069d 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -51,6 +51,7 @@ $FORGIT_FZF_DEFAULT_OPTS _forgit_warn() { printf "%b[Warn]%b %s\n" '\e[0;33m' '\e[0m' "$@" >&2; } _forgit_info() { printf "%b[Info]%b %s\n" '\e[0;32m' '\e[0m' "$@" >&2; } +_forgit_inside_git_dir() { git rev-parse --is_inside-git-dir >/dev/null; } _forgit_inside_work_tree() { git rev-parse --is-inside-work-tree >/dev/null; } # tac is not available on OSX, tail -r is not available on Linux, so we use either of them _forgit_reverse_lines() { tac 2> /dev/null || tail -r; } @@ -1176,6 +1177,98 @@ _forgit_paths_list() { find "$path" -name "*$ext" -print |sed -e "s#$ext\$##" -e 's#.*/##' -e '/^$/d' | sort -fu } +_forgit_worktree_preview() { + local sha + # trailing space in grep to avoid matching worktrees with a common path + sha=$(git worktree list | grep "$1 " | awk '{print $2}') + # bare git-dir has no history + [[ "$sha" == "(bare)" ]] && return + _forgit_worktree_preview_git_opts=() + _forgit_parse_array _forgit_worktree_preview_git_opts "$FORGIT_WORKTREE_PREVIEW_GIT_OPTS" + # the trailing '--' ensures that this works for branches that have a name + # that is identical to a file + git log "$sha" "${_forgit_worktree_preview_git_opts[@]}" -- +} + +_forgit_worktree_jump() { + _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 + local count tree opts + count=$(git worktree list | wc -l) + + [[ $count -eq 1 ]] && return 1 + + opts=" + $FORGIT_FZF_DEFAULT_OPTS + +s +m --tiebreak=index + --preview=\"$FORGIT worktree_preview {1}\" + $FORGIT_WORKTREE_JUMP_FZF_OPTS + " + + tree=$(git worktree list | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) + [[ -z "$tree" ]] && return 1 + echo "$tree" +} + +_forgit_git_worktree_lock() { + _forgit_worktree_lock_git_opts=() + _forgit_parse_array _forgit_worktree_lock_git_opts "$FORGIT_WORKTREE_LOCK_GIT_OPTS" + git worktree lock "${_forgit_worktree_lock_git_opts[@]}" "$@" +} + +_forgit_worktree_lock() { + _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 + local tree opts + + opts=" + $FORGIT_FZF_DEFAULT_OPTS + +s -m --tiebreak=index + --preview=\"$FORGIT worktree_preview {1}\" + $FORGIT_WORKTREE_LOCK_FZF_OPTS + " + + tree=$(git worktree list | awk '{print $1}' | grep -v "(bare)" | FZF_DEFAULT_OPTS="$opts" fzf) + [[ -z "$tree" ]] && return 1 + _forgit_git_worktree_lock "$tree" +} + +_forgit_git_worktree_remove() { + _forgit_worktree_remove_git_opts=() + _forgit_parse_array _forgit_worktree_remove_git_opts "$FORGIT_WORKTREE_REMOVE_GIT_OPTS" + git worktree remove "${_forgit_worktree_remove_git_opts[@]}" "$@" +} + +_forgit_worktree_remove() { + _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 + local tree opts + + opts=" + $FORGIT_FZF_DEFAULT_OPTS + +s -m --tiebreak=index --header-lines=1 + --preview=\"$FORGIT worktree_preview {1}\" + $FORGIT_WORKTREE_REMOVE_FZF_OPTS + " + + tree=$(git worktree list | awk '{print $1}' | grep -v "(bare)" | FZF_DEFAULT_OPTS="$opts" fzf) + [[ -z "$tree" ]] && return 1 + _forgit_git_worktree_remove "$tree" +} + +_forgit_worktree_unlock() { + _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 + local tree opts + + opts=" + $FORGIT_FZF_DEFAULT_OPTS + +s -m --tiebreak=index --header-lines=1 + --preview=\"$FORGIT worktree_preview {1}\" + $FORGIT_WORKTREE_UNLOCK_FZF_OPTS + " + + tree=$(git worktree list | awk '{print $1}' | grep -v "(bare)" | FZF_DEFAULT_OPTS="$opts" fzf) + [[ -z "$tree" ]] && return 1 + git worktree unlock "$tree" +} + public_commands=( "add" "attributes" @@ -1201,12 +1294,17 @@ public_commands=( "show" "stash_show" "stash_push" + "worktree_jump" + "worktree_lock" + "worktree_remove" + "worktree_unlock" ) private_commands=( "add_preview" "blame_preview" "branch_preview" + "worktree_preview" "checkout_commit_preview" "checkout_file_preview" "cherry_pick_from_branch_preview" diff --git a/conf.d/forgit.plugin.fish b/conf.d/forgit.plugin.fish index 58bb18af..1b881a28 100644 --- a/conf.d/forgit.plugin.fish +++ b/conf.d/forgit.plugin.fish @@ -55,4 +55,8 @@ if test -z "$FORGIT_NO_ALIASES" abbr -a -- (string collect $forgit_revert_commit; or string collect "grc") git-forgit revert_commit abbr -a -- (string collect $forgit_blame; or string collect "gbl") git-forgit blame abbr -a -- (string collect $forgit_checkout_tag; or string collect "gct") git-forgit checkout_tag + abbr -a -- (string collect $forgit_worktree_jump; or string collect "gwj") 'set tree (git-forgit worktree_jump); test -n "$tree"; and cd "$tree"' + abbr -a -- (string collect $forgit_worktree_lock; or string collect "gwl") git-forgit worktree_lock + abbr -a -- (string collect $forgit_worktree_remove; or string collect "gwr") git-forgit worktree_remove + abbr -a -- (string collect $forgit_worktree_unlock; or string collect "gwu") git-forgit worktree_unlock end diff --git a/forgit.plugin.zsh b/forgit.plugin.zsh index 54a8f8bd..a244d112 100755 --- a/forgit.plugin.zsh +++ b/forgit.plugin.zsh @@ -156,6 +156,22 @@ forgit::attributes() { "$FORGIT" attributes "$@" } +forgit::worktree::jump() { + cd "$("$FORGIT" worktree_jump "$@")" || exit +} + +forgit::worktree::lock() { + "$FORGIT" worktree_lock "$@" +} + +forgit::worktree::remove() { + "$FORGIT" worktree_remove "$@" +} + +forgit::worktree::unlock() { + "$FORGIT" worktree_unlock "$@" +} + # register aliases # shellcheck disable=SC2139 if [[ -z "$FORGIT_NO_ALIASES" ]]; then @@ -183,6 +199,10 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then builtin export forgit_squash="${forgit_squash:-gsq}" builtin export forgit_reword="${forgit_reword:-grw}" builtin export forgit_blame="${forgit_blame:-gbl}" + builtin export forgit_worktree_jump="${forgit_worktree_jump:-gwj}" + builtin export forgit_worktree_lock="${forgit_worktree_lock:-gwl}" + builtin export forgit_worktree_remove="${forgit_worktree_remove:-gwr}" + builtin export forgit_worktree_unlock="${forgit_worktree_unlock:-gwu}" builtin alias "${forgit_add}"='forgit::add' builtin alias "${forgit_reset_head}"='forgit::reset::head' @@ -207,5 +227,9 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then builtin alias "${forgit_squash}"='forgit::squash' builtin alias "${forgit_reword}"='forgit::reword' builtin alias "${forgit_blame}"='forgit::blame' + builtin alias "${forgit_worktree_jump}"='forgit::worktree::jump' + builtin alias "${forgit_worktree_lock}"='forgit::worktree::lock' + builtin alias "${forgit_worktree_remove}"='forgit::worktree::remove' + builtin alias "${forgit_worktree_unlock}"='forgit::worktree::unlock' fi From caee5c787be1ae3a24308f0744a83db6f2824bc6 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 3 Nov 2024 14:38:52 -0500 Subject: [PATCH 02/14] docs: update README to include worktree operations --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 6db49409..f4f6dc3d 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,14 @@ If you're having issues after updating, and commands such as `forgit::add` or al - **Interactive `git commit --fixup=reword && git rebase -i --autosquash` selector** (`grw`) +- **Interactive `git worktree list` selector** (`gwj`) + +- **Interactive `git worktree lock ` selector** (`gwl`) + +- **Interactive `git worktree remove ` selector** (`gwr`) + +- **Interactive `git worktree unlock ` selector** (`gwu`) + # ⌨ Keybindings | Key | Action | @@ -237,6 +245,10 @@ forgit_blame=gbl forgit_fixup=gfu forgit_squash=gsq forgit_reword=grw +forgit_worktree_jump=gwj +forgit_worktree_lock=gwl +forgit_worktree_remove=gwr +forgit_worktree_unlock=gwu ``` ## git integration @@ -298,6 +310,10 @@ These are passed to the according `git` calls. | `gsq` | `FORGIT_SQUASH_GIT_OPTS` | | `grw` | `FORGIT_REWORD_GIT_OPTS` | | `gcp` | `FORGIT_CHERRY_PICK_GIT_OPTS` | +| `gwj` | `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| `gwl` | `FORGIT_WORKTREE_LOCK_GIT_OPTS`, `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| `gwr` | `FORGIT_WORKTREE_REMOVE_GIT_OPTS`, `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| `gwu` | `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | ## pagers @@ -357,6 +373,10 @@ Customizing fzf options for each command individually is also supported: | `gsq` | `FORGIT_SQUASH_FZF_OPTS` | | `grw` | `FORGIT_REWORD_FZF_OPTS` | | `gcp` | `FORGIT_CHERRY_PICK_FZF_OPTS` | +| `gwj` | `FORGIT_WORKTREE_JUMP_FZF_OPTS` | +| `gwl` | `FORGIT_WORKTREE_LOCK_FZF_OPTS` | +| `gwr` | `FORGIT_WORKTREE_REMOVE_FZF_OPTS` | +| `gwu` | `FORGIT_WORKTREE_UNLOCK_FZF_OPTS` | Complete loading order of fzf options is: From 949225788f4278e4aa074e0a642fb6bb56611ccf Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Wed, 13 Nov 2024 17:51:10 -0500 Subject: [PATCH 03/14] fix: typos --- bin/git-forgit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/git-forgit b/bin/git-forgit index 2c12069d..88d51580 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -51,7 +51,7 @@ $FORGIT_FZF_DEFAULT_OPTS _forgit_warn() { printf "%b[Warn]%b %s\n" '\e[0;33m' '\e[0m' "$@" >&2; } _forgit_info() { printf "%b[Info]%b %s\n" '\e[0;32m' '\e[0m' "$@" >&2; } -_forgit_inside_git_dir() { git rev-parse --is_inside-git-dir >/dev/null; } +_forgit_inside_git_dir() { git rev-parse --is-inside-git-dir >/dev/null; } _forgit_inside_work_tree() { git rev-parse --is-inside-work-tree >/dev/null; } # tac is not available on OSX, tail -r is not available on Linux, so we use either of them _forgit_reverse_lines() { tac 2> /dev/null || tail -r; } @@ -1179,7 +1179,7 @@ _forgit_paths_list() { _forgit_worktree_preview() { local sha - # trailing space in grep to avoid matching worktrees with a common path + # trailing space in grep to avoid matching worktrees with a common path sha=$(git worktree list | grep "$1 " | awk '{print $2}') # bare git-dir has no history [[ "$sha" == "(bare)" ]] && return From f126ad9b1ab6c4688d21f543ab0003d63f6a0310 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Wed, 13 Nov 2024 19:22:43 -0500 Subject: [PATCH 04/14] fix: address reviewer comments --- bin/git-forgit | 62 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/bin/git-forgit b/bin/git-forgit index 88d51580..d45f7fad 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -1177,24 +1177,31 @@ _forgit_paths_list() { find "$path" -name "*$ext" -print |sed -e "s#$ext\$##" -e 's#.*/##' -e '/^$/d' | sort -fu } +_forgit_filter_existing_paths() { + while read -r path; do + [[ -d "$path" ]] && echo "$path" + done +} + _forgit_worktree_preview() { local sha # trailing space in grep to avoid matching worktrees with a common path sha=$(git worktree list | grep "$1 " | awk '{print $2}') - # bare git-dir has no history - [[ "$sha" == "(bare)" ]] && return - _forgit_worktree_preview_git_opts=() - _forgit_parse_array _forgit_worktree_preview_git_opts "$FORGIT_WORKTREE_PREVIEW_GIT_OPTS" + if [[ "$sha" == "(bare)" ]]; then + printf "%b(bare)%b %s\n" '\e[0;33m' '\e[0m' 'No history for git dir' + return + fi # the trailing '--' ensures that this works for branches that have a name # that is identical to a file - git log "$sha" "${_forgit_worktree_preview_git_opts[@]}" -- + git log "$sha" "${_forgit_log_preview_options[@]}" -- } _forgit_worktree_jump() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 - local count tree opts - count=$(git worktree list | wc -l) + local worktree_list count tree opts + worktree_list=$(git worktree list | grep -vE "prunable$" | awk '{print $1}' | _forgit_filter_existing_paths) + count=$(echo "$worktree_list" | wc -l) [[ $count -eq 1 ]] && return 1 opts=" @@ -1204,7 +1211,7 @@ _forgit_worktree_jump() { $FORGIT_WORKTREE_JUMP_FZF_OPTS " - tree=$(git worktree list | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) + tree=$(echo "$worktree_list" | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 echo "$tree" } @@ -1217,16 +1224,21 @@ _forgit_git_worktree_lock() { _forgit_worktree_lock() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 + if [[ $# -ne 0 ]]; then + git worktree lock "$@" + worktree_lock_status=$? + return $worktree_lock_status + fi local tree opts opts=" $FORGIT_FZF_DEFAULT_OPTS - +s -m --tiebreak=index + +s +m --tiebreak=index --preview=\"$FORGIT worktree_preview {1}\" $FORGIT_WORKTREE_LOCK_FZF_OPTS " - tree=$(git worktree list | awk '{print $1}' | grep -v "(bare)" | FZF_DEFAULT_OPTS="$opts" fzf) + tree=$(git worktree list | grep -vE "\(bare\)|locked" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 _forgit_git_worktree_lock "$tree" } @@ -1239,32 +1251,50 @@ _forgit_git_worktree_remove() { _forgit_worktree_remove() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 - local tree opts + if [[ $# -ne 0 ]]; then + git worktree remove "$@" + worktree_remove_status=$? + return $worktree_remove_status + fi + local worktree_list tree opts + worktree_list=$(git worktree list | grep -v "(bare)") + + count=$(echo "$worktree_list" | wc -l) + [[ $count -eq 1 ]] && return 1 opts=" $FORGIT_FZF_DEFAULT_OPTS - +s -m --tiebreak=index --header-lines=1 + +s +m --tiebreak=index --preview=\"$FORGIT worktree_preview {1}\" $FORGIT_WORKTREE_REMOVE_FZF_OPTS " - tree=$(git worktree list | awk '{print $1}' | grep -v "(bare)" | FZF_DEFAULT_OPTS="$opts" fzf) + tree=$(echo "$worktree_list" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 _forgit_git_worktree_remove "$tree" } _forgit_worktree_unlock() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 - local tree opts + if [[ $# -ne 0 ]]; then + git worktree unlock "$@" + worktree_unlock_status=$? + return $worktree_unlock_status + fi + local worktree_list tree opts + + worktree_list=$(git worktree list | grep -v "(bare)" | grep -E "locked$") + count=$(echo "$worktree_list" | wc -l) + [[ $count -eq 0 ]] && return 1 opts=" $FORGIT_FZF_DEFAULT_OPTS - +s -m --tiebreak=index --header-lines=1 + +s +m --tiebreak=index --preview=\"$FORGIT worktree_preview {1}\" $FORGIT_WORKTREE_UNLOCK_FZF_OPTS " - tree=$(git worktree list | awk '{print $1}' | grep -v "(bare)" | FZF_DEFAULT_OPTS="$opts" fzf) + tree=$(echo "$worktree_list" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 git worktree unlock "$tree" } From a168b750c1867f28a76f699bef2f4ae370cd11b1 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 17 Nov 2024 16:31:42 -0500 Subject: [PATCH 05/14] refactor: rename worktree_jump to worktree_select --- README.md | 4 ++-- bin/git-forgit | 6 +++--- conf.d/forgit.plugin.fish | 3 ++- forgit.plugin.zsh | 8 +++++++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f4f6dc3d..d2dff5b5 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,7 @@ forgit_blame=gbl forgit_fixup=gfu forgit_squash=gsq forgit_reword=grw -forgit_worktree_jump=gwj +forgit_worktree_select=gws forgit_worktree_lock=gwl forgit_worktree_remove=gwr forgit_worktree_unlock=gwu @@ -373,7 +373,7 @@ Customizing fzf options for each command individually is also supported: | `gsq` | `FORGIT_SQUASH_FZF_OPTS` | | `grw` | `FORGIT_REWORD_FZF_OPTS` | | `gcp` | `FORGIT_CHERRY_PICK_FZF_OPTS` | -| `gwj` | `FORGIT_WORKTREE_JUMP_FZF_OPTS` | +| `gws` | `FORGIT_WORKTREE_SELECT_FZF_OPTS` | | `gwl` | `FORGIT_WORKTREE_LOCK_FZF_OPTS` | | `gwr` | `FORGIT_WORKTREE_REMOVE_FZF_OPTS` | | `gwu` | `FORGIT_WORKTREE_UNLOCK_FZF_OPTS` | diff --git a/bin/git-forgit b/bin/git-forgit index d45f7fad..5cfa8504 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -1196,7 +1196,7 @@ _forgit_worktree_preview() { git log "$sha" "${_forgit_log_preview_options[@]}" -- } -_forgit_worktree_jump() { +_forgit_worktree_select() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 local worktree_list count tree opts worktree_list=$(git worktree list | grep -vE "prunable$" | awk '{print $1}' | _forgit_filter_existing_paths) @@ -1208,7 +1208,7 @@ _forgit_worktree_jump() { $FORGIT_FZF_DEFAULT_OPTS +s +m --tiebreak=index --preview=\"$FORGIT worktree_preview {1}\" - $FORGIT_WORKTREE_JUMP_FZF_OPTS + $FORGIT_WORKTREE_SELECT_FZF_OPTS " tree=$(echo "$worktree_list" | FZF_DEFAULT_OPTS="$opts" fzf) @@ -1324,7 +1324,7 @@ public_commands=( "show" "stash_show" "stash_push" - "worktree_jump" + "worktree_select" "worktree_lock" "worktree_remove" "worktree_unlock" diff --git a/conf.d/forgit.plugin.fish b/conf.d/forgit.plugin.fish index 1b881a28..9fcde26d 100644 --- a/conf.d/forgit.plugin.fish +++ b/conf.d/forgit.plugin.fish @@ -55,7 +55,8 @@ if test -z "$FORGIT_NO_ALIASES" abbr -a -- (string collect $forgit_revert_commit; or string collect "grc") git-forgit revert_commit abbr -a -- (string collect $forgit_blame; or string collect "gbl") git-forgit blame abbr -a -- (string collect $forgit_checkout_tag; or string collect "gct") git-forgit checkout_tag - abbr -a -- (string collect $forgit_worktree_jump; or string collect "gwj") 'set tree (git-forgit worktree_jump); test -n "$tree"; and cd "$tree"' + abbr -a -- (string collect $forgit_worktree_select; or string collect "gwj") git-forgit worktree_select + abbr -a -- (string collect $forgit_worktree_jump; or string collect "gwj") 'set tree (git-forgit worktree_select); test -n "$tree"; and cd "$tree"' abbr -a -- (string collect $forgit_worktree_lock; or string collect "gwl") git-forgit worktree_lock abbr -a -- (string collect $forgit_worktree_remove; or string collect "gwr") git-forgit worktree_remove abbr -a -- (string collect $forgit_worktree_unlock; or string collect "gwu") git-forgit worktree_unlock diff --git a/forgit.plugin.zsh b/forgit.plugin.zsh index a244d112..03473f47 100755 --- a/forgit.plugin.zsh +++ b/forgit.plugin.zsh @@ -156,8 +156,12 @@ forgit::attributes() { "$FORGIT" attributes "$@" } +forgit::worktree::select() { + "$FORGIT" worktree_select "$@" +} + forgit::worktree::jump() { - cd "$("$FORGIT" worktree_jump "$@")" || exit + cd "$(forgit::worktree::select "$@")" || exit } forgit::worktree::lock() { @@ -199,6 +203,7 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then builtin export forgit_squash="${forgit_squash:-gsq}" builtin export forgit_reword="${forgit_reword:-grw}" builtin export forgit_blame="${forgit_blame:-gbl}" + builtin export forgit_worktree_select="${forgit_worktree_select:-gws}" builtin export forgit_worktree_jump="${forgit_worktree_jump:-gwj}" builtin export forgit_worktree_lock="${forgit_worktree_lock:-gwl}" builtin export forgit_worktree_remove="${forgit_worktree_remove:-gwr}" @@ -227,6 +232,7 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then builtin alias "${forgit_squash}"='forgit::squash' builtin alias "${forgit_reword}"='forgit::reword' builtin alias "${forgit_blame}"='forgit::blame' + builtin alias "${forgit_worktree_select}"='forgit::worktree::select' builtin alias "${forgit_worktree_jump}"='forgit::worktree::jump' builtin alias "${forgit_worktree_lock}"='forgit::worktree::lock' builtin alias "${forgit_worktree_remove}"='forgit::worktree::remove' From a7cec92f16ef317e84857aa587889d32bb13daca Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sat, 23 Nov 2024 11:37:45 -0500 Subject: [PATCH 06/14] feat: add fish shell completions --- completions/git-forgit.fish | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/completions/git-forgit.fish b/completions/git-forgit.fish index 7876e888..87106ac1 100644 --- a/completions/git-forgit.fish +++ b/completions/git-forgit.fish @@ -8,7 +8,8 @@ function __fish_forgit_needs_subcommand for subcmd in add blame branch_delete checkout_branch checkout_commit checkout_file checkout_tag \ cherry_pick cherry_pick_from_branch clean diff fixup ignore log reflog rebase reset_head \ - revert_commit reword squash stash_show stash_push + revert_commit reword squash stash_show stash_push worktree_select worktree_lock \ + worktree_remove worktree_unlock if contains -- $subcmd (commandline -opc) return 1 end @@ -45,6 +46,10 @@ complete -c git-forgit -n __fish_forgit_needs_subcommand -a show -d 'git show vi complete -c git-forgit -n __fish_forgit_needs_subcommand -a squash -d 'git squash' complete -c git-forgit -n __fish_forgit_needs_subcommand -a stash_show -d 'git stash viewer' complete -c git-forgit -n __fish_forgit_needs_subcommand -a stash_push -d 'git stash push selector' +complete -c git-forgit -n __fish_forgit_needs_subcommand -a worktree_select -d 'git worktree selector' +complete -c git-forgit -n __fish_forgit_needs_subcommand -a worktree_lock -d 'git worktree lock selector' +complete -c git-forgit -n __fish_forgit_needs_subcommand -a worktree_remove -d 'git worktree remove selector' +complete -c git-forgit -n __fish_forgit_needs_subcommand -a worktree_unlock -d 'git worktree unlock selector' complete -c git-forgit -n '__fish_seen_subcommand_from add' -a "(complete -C 'git add ')" complete -c git-forgit -n '__fish_seen_subcommand_from branch_delete' -a "(__fish_git_local_branches)" @@ -66,3 +71,7 @@ complete -c git-forgit -n '__fish_seen_subcommand_from show' -a "(complete -C 'g complete -c git-forgit -n '__fish_seen_subcommand_from squash' -a "(__fish_git_local_branches)" complete -c git-forgit -n '__fish_seen_subcommand_from stash_show' -a "(__fish_git_complete_stashes)" complete -c git-forgit -n '__fish_seen_subcommand_from stash_push' -a "(__fish_git_files modified deleted modified-staged-deleted)" +complete -c git-forgit -n '__fish_seen_subcommand_from worktree_select' -a "(__fish_git_complete_worktrees)" +complete -c git-forgit -n '__fish_seen_subcommand_from worktree_lock' -a "(complete -C 'git worktree lock ')" +complete -c git-forgit -n '__fish_seen_subcommand_from worktree_remove' -a "(complete -C 'git worktree remove ')" +complete -c git-forgit -n '__fish_seen_subcommand_from worktree_unlock' -a "(complete -C 'git worktree unlock ')" From 7f62969c62d6859176c4a5c6ad1ed82d19e341f4 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 1 Dec 2024 12:32:13 -0500 Subject: [PATCH 07/14] feat: add zsh shell completions --- completions/_git-forgit | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/completions/_git-forgit b/completions/_git-forgit index 434c1611..8581eb6f 100644 --- a/completions/_git-forgit +++ b/completions/_git-forgit @@ -18,6 +18,10 @@ _git-stash-show() { _alternative "files:filename:($(git stash list | sed -n -e 's/:.*//p'))" } +_git-worktrees() { + _alternative "worktrees:worktree:($(git worktree list --porcelain | awk '/worktree/ {print $2}'))" +} + # The completions for git already define a _git-diff completion function, but # it provides the wrong results when called from _git-forgit because it heavily # depends on the context it's been called from (usage of $curcontext and @@ -79,6 +83,10 @@ _git-forgit() { 'squash:git squash' 'stash_show:git stash viewer' 'stash_push:git stash push selector' + 'worktree_select:git worktree selector' + 'worktree_lock:git worktree lock selector' + 'worktree_remove:git worktree remove selector' + 'worktree_unlock:git worktree unlock selector' ) _describe -t commands 'git forgit' subcommands ;; @@ -102,6 +110,10 @@ _git-forgit() { squash) __git_branch_names ;; stash_show) _git-stash-show ;; show) _git-show ;; + worktree_select) _git-worktrees ;; + worktree_lock) _git-worktrees ;; + worktree_remove) _git-worktrees ;; + worktree_unlock) _git-worktrees ;; esac } @@ -130,6 +142,10 @@ compdef __git_branch_names forgit::reword compdef __git_branch_names forgit::squash compdef _git-stash-show forgit::stash::show compdef _git-show forgit::show +compdef _git-worktrees forgit::worktree::select +compdef _git-worktrees forgit::worktree::lock +compdef _git-worktrees forgit::worktree::remove +compdef _git-worktrees forgit::worktree::unlock # this is the case of calling the command and pressing tab # the very first time of a shell session, we have to manually From edec0c17eab6860adede5fd70be179abbb0b9b71 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 1 Dec 2024 12:40:30 -0500 Subject: [PATCH 08/14] feat: add bash shell completions --- completions/git-forgit.bash | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/completions/git-forgit.bash b/completions/git-forgit.bash index 0d186006..75c584f4 100755 --- a/completions/git-forgit.bash +++ b/completions/git-forgit.bash @@ -35,6 +35,11 @@ _git_stash_show() __gitcomp_nl "$(__git stash list | sed -n -e 's/:.*//p')" } +_git_worktrees() +{ + __gitcomp_nl "$(git worktree list --porcelain | awk '/worktree/ {print $2}')" +} + # Completion for git-forgit # This includes git aliases, e.g. "alias.cb=forgit checkout_branch" will # correctly complete available branches on "git cb". @@ -80,6 +85,10 @@ _git_forgit() squash stash_show stash_push + worktree_select + worktree_lock + worktree_remove + worktree_unlock " case ${cword} in @@ -108,6 +117,10 @@ _git_forgit() show) _git_show ;; squash) _git_branch ;; stash_show) _git_stash_show ;; + worktree_select) _git_worktrees ;; + worktree_lock) _git_worktrees ;; + worktree_remove) _git_worktrees ;; + worktree_unlock) _git_worktrees ;; esac ;; *) @@ -145,6 +158,10 @@ then __git_complete forgit::show _git_show __git_complete forgit::squash _git_branch __git_complete forgit::stash::show _git_stash_show + __git_complete forgit::worktree::select _git_worktrees + __git_complete forgit::worktree::lock _git_worktrees + __git_complete forgit::worktree::remove _git_worktrees + __git_complete forgit::worktree::unlock _git_worktrees # Completion for forgit plugin shell aliases if [[ -z "$FORGIT_NO_ALIASES" ]]; then @@ -167,5 +184,9 @@ then __git_complete "${forgit_show}" _git_show __git_complete "${forgit_squash}" _git_branch __git_complete "${forgit_stash_show}" _git_stash_show + __git_complete "${forgit_worktree_select}" _git_worktrees + __git_complete "${forgit_worktree_lock}" _git_worktrees + __git_complete "${forgit_worktree_remove}" _git_worktrees + __git_complete "${forgit_worktree_unlock}" _git_worktrees fi fi From 00f3dadf97470f463d57adc5fa3120c1dc05c9e2 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Wed, 18 Dec 2024 11:30:54 -0500 Subject: [PATCH 09/14] feat: add flag parsing for git worktree lock --- bin/git-forgit | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/bin/git-forgit b/bin/git-forgit index 5cfa8504..2ea0777e 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -1224,12 +1224,23 @@ _forgit_git_worktree_lock() { _forgit_worktree_lock() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 + + local tree opts reason if [[ $# -ne 0 ]]; then - git worktree lock "$@" - worktree_lock_status=$? - return $worktree_lock_status + if [[ "$1" == "--reason" ]]; then + if [[ -z "$2" ]]; then + _forgit_warn "Option \`--reason' requires a value" + return 1 + fi + reason="$2" + shift 2 + fi + + if [[ $# -eq 0 ]] || _forgit_contains_non_flags "$@"; then + git worktree lock "$@" --reason "$reason" + return $? + fi fi - local tree opts opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1240,7 +1251,12 @@ _forgit_worktree_lock() { tree=$(git worktree list | grep -vE "\(bare\)|locked" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 - _forgit_git_worktree_lock "$tree" + + if [[ -z "$reason" ]]; then + _forgit_git_worktree_lock "$tree" + else + _forgit_git_worktree_lock "$tree" --reason "$reason" + fi } _forgit_git_worktree_remove() { From f5d88f6e432009cb5db9d9932a95a32cb91ad7cb Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Wed, 18 Dec 2024 12:08:37 -0500 Subject: [PATCH 10/14] feat: add flag parsing for git worktree remove --- bin/git-forgit | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/bin/git-forgit b/bin/git-forgit index 2ea0777e..ea4df262 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -1267,12 +1267,30 @@ _forgit_git_worktree_remove() { _forgit_worktree_remove() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 - if [[ $# -ne 0 ]]; then - git worktree remove "$@" + local worktree_list tree opts force_flags + + force_flags=() + + while (("$#")); do + case "$1" in + -f | --force) + force_flags+=("$1") + shift + ;; + -*) shift ;; + *) + tree="$1" + shift + ;; + esac + done + + if [[ -n "$tree" ]]; then + _forgit_git_worktree_remove "${force_flags[@]}" "$tree" worktree_remove_status=$? return $worktree_remove_status fi - local worktree_list tree opts + worktree_list=$(git worktree list | grep -v "(bare)") count=$(echo "$worktree_list" | wc -l) @@ -1287,7 +1305,7 @@ _forgit_worktree_remove() { tree=$(echo "$worktree_list" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 - _forgit_git_worktree_remove "$tree" + _forgit_git_worktree_remove "${force_flags[@]}" "$tree" } _forgit_worktree_unlock() { From 5f8e53a0b6c3726e1f5bbbafa49908c7eeb5d43f Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Tue, 24 Dec 2024 15:44:05 -0500 Subject: [PATCH 11/14] docs: include gws and gwj aliases together --- README.md | 122 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index d2dff5b5..d6c3bf69 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,13 @@ If you're having issues after updating, and commands such as `forgit::add` or al - **Interactive `git commit --fixup=reword && git rebase -i --autosquash` selector** (`grw`) -- **Interactive `git worktree list` selector** (`gwj`) +- **Interactive `git commit --squash && git rebase -i --autosquash` selector** (`gsq`) + +- **Interactive `git commit --fixup=reword && git rebase -i --autosquash` selector** (`grw`) + +- **Interactive `git worktree list` selector** (`gws`/`gwj`) + + + `gwj` jumps to the worktree using `cd` and can only be used via the alias, no equivalent behavior using forgit as a git subcommand - **Interactive `git worktree lock ` selector** (`gwl`) @@ -245,7 +251,7 @@ forgit_blame=gbl forgit_fixup=gfu forgit_squash=gsq forgit_reword=grw -forgit_worktree_select=gws +forgit_worktree_select=gws/gwj forgit_worktree_lock=gwl forgit_worktree_remove=gwr forgit_worktree_unlock=gwu @@ -287,33 +293,33 @@ git cf If you want to customize `git`'s behavior within forgit there is a dedicated variable for each forgit command. These are passed to the according `git` calls. -| Command | Option | -| -------- | --------------------------------------------------------------------------- | -| `ga` | `FORGIT_ADD_GIT_OPTS` | -| `glo` | `FORGIT_LOG_GIT_OPTS` | -| `grl` | `FORGIT_REFLOG_GIT_OPTS` | -| `gd` | `FORGIT_DIFF_GIT_OPTS` | -| `gso` | `FORGIT_SHOW_GIT_OPTS` | -| `grh` | `FORGIT_RESET_HEAD_GIT_OPTS` | -| `gcf` | `FORGIT_CHECKOUT_FILE_GIT_OPTS` | -| `gcb` | `FORGIT_CHECKOUT_BRANCH_GIT_OPTS`, `FORGIT_CHECKOUT_BRANCH_BRANCH_GIT_OPTS` | -| `gbd` | `FORGIT_BRANCH_DELETE_GIT_OPTS` | -| `gct` | `FORGIT_CHECKOUT_TAG_GIT_OPTS` | -| `gco` | `FORGIT_CHECKOUT_COMMIT_GIT_OPTS` | -| `grc` | `FORGIT_REVERT_COMMIT_GIT_OPTS` | -| `gss` | `FORGIT_STASH_SHOW_GIT_OPTS` | -| `gsp` | `FORGIT_STASH_PUSH_GIT_OPTS` | -| `gclean` | `FORGIT_CLEAN_GIT_OPTS` | -| `grb` | `FORGIT_REBASE_GIT_OPTS` | -| `gbl` | `FORGIT_BLAME_GIT_OPTS` | -| `gfu` | `FORGIT_FIXUP_GIT_OPTS` | -| `gsq` | `FORGIT_SQUASH_GIT_OPTS` | -| `grw` | `FORGIT_REWORD_GIT_OPTS` | -| `gcp` | `FORGIT_CHERRY_PICK_GIT_OPTS` | -| `gwj` | `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | -| `gwl` | `FORGIT_WORKTREE_LOCK_GIT_OPTS`, `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | -| `gwr` | `FORGIT_WORKTREE_REMOVE_GIT_OPTS`, `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | -| `gwu` | `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| Command | Option | +| ----------- | --------------------------------------------------------------------------- | +| `ga` | `FORGIT_ADD_GIT_OPTS` | +| `glo` | `FORGIT_LOG_GIT_OPTS` | +| `grl` | `FORGIT_REFLOG_GIT_OPTS` | +| `gd` | `FORGIT_DIFF_GIT_OPTS` | +| `gso` | `FORGIT_SHOW_GIT_OPTS` | +| `grh` | `FORGIT_RESET_HEAD_GIT_OPTS` | +| `gcf` | `FORGIT_CHECKOUT_FILE_GIT_OPTS` | +| `gcb` | `FORGIT_CHECKOUT_BRANCH_GIT_OPTS`, `FORGIT_CHECKOUT_BRANCH_BRANCH_GIT_OPTS` | +| `gbd` | `FORGIT_BRANCH_DELETE_GIT_OPTS` | +| `gct` | `FORGIT_CHECKOUT_TAG_GIT_OPTS` | +| `gco` | `FORGIT_CHECKOUT_COMMIT_GIT_OPTS` | +| `grc` | `FORGIT_REVERT_COMMIT_GIT_OPTS` | +| `gss` | `FORGIT_STASH_SHOW_GIT_OPTS` | +| `gsp` | `FORGIT_STASH_PUSH_GIT_OPTS` | +| `gclean` | `FORGIT_CLEAN_GIT_OPTS` | +| `grb` | `FORGIT_REBASE_GIT_OPTS` | +| `gbl` | `FORGIT_BLAME_GIT_OPTS` | +| `gfu` | `FORGIT_FIXUP_GIT_OPTS` | +| `gsq` | `FORGIT_SQUASH_GIT_OPTS` | +| `grw` | `FORGIT_REWORD_GIT_OPTS` | +| `gcp` | `FORGIT_CHERRY_PICK_GIT_OPTS` | +| `gws`/`gwj` | `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| `gwl` | `FORGIT_WORKTREE_LOCK_GIT_OPTS`, `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| `gwr` | `FORGIT_WORKTREE_REMOVE_GIT_OPTS`, `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | +| `gwu` | `FORGIT_WORKTREE_PREVIEW_GIT_OPTS` | ## pagers @@ -348,35 +354,35 @@ export FORGIT_FZF_DEFAULT_OPTS=" Customizing fzf options for each command individually is also supported: -| Command | Option | -|----------|-----------------------------------| -| `ga` | `FORGIT_ADD_FZF_OPTS` | -| `glo` | `FORGIT_LOG_FZF_OPTS` | -| `grl` | `FORGIT_REFLOG_FZF_OPTS` | -| `gi` | `FORGIT_IGNORE_FZF_OPTS` | -| `gat` | `FORGIT_ATTRIBUTES_FZF_OPTS` | -| `gd` | `FORGIT_DIFF_FZF_OPTS` | -| `gso` | `FORGIT_SHOW_FZF_OPTS` | -| `grh` | `FORGIT_RESET_HEAD_FZF_OPTS` | -| `gcf` | `FORGIT_CHECKOUT_FILE_FZF_OPTS` | -| `gcb` | `FORGIT_CHECKOUT_BRANCH_FZF_OPTS` | -| `gbd` | `FORGIT_BRANCH_DELETE_FZF_OPTS` | -| `gct` | `FORGIT_CHECKOUT_TAG_FZF_OPTS` | -| `gco` | `FORGIT_CHECKOUT_COMMIT_FZF_OPTS` | -| `grc` | `FORGIT_REVERT_COMMIT_FZF_OPTS` | -| `gss` | `FORGIT_STASH_FZF_OPTS` | -| `gsp` | `FORGIT_STASH_PUSH_FZF_OPTS` | -| `gclean` | `FORGIT_CLEAN_FZF_OPTS` | -| `grb` | `FORGIT_REBASE_FZF_OPTS` | -| `gbl` | `FORGIT_BLAME_FZF_OPTS` | -| `gfu` | `FORGIT_FIXUP_FZF_OPTS` | -| `gsq` | `FORGIT_SQUASH_FZF_OPTS` | -| `grw` | `FORGIT_REWORD_FZF_OPTS` | -| `gcp` | `FORGIT_CHERRY_PICK_FZF_OPTS` | -| `gws` | `FORGIT_WORKTREE_SELECT_FZF_OPTS` | -| `gwl` | `FORGIT_WORKTREE_LOCK_FZF_OPTS` | -| `gwr` | `FORGIT_WORKTREE_REMOVE_FZF_OPTS` | -| `gwu` | `FORGIT_WORKTREE_UNLOCK_FZF_OPTS` | +| Command | Option | +|-------------|-----------------------------------| +| `ga` | `FORGIT_ADD_FZF_OPTS` | +| `glo` | `FORGIT_LOG_FZF_OPTS` | +| `grl` | `FORGIT_REFLOG_FZF_OPTS` | +| `gi` | `FORGIT_IGNORE_FZF_OPTS` | +| `gat` | `FORGIT_ATTRIBUTES_FZF_OPTS` | +| `gd` | `FORGIT_DIFF_FZF_OPTS` | +| `gso` | `FORGIT_SHOW_FZF_OPTS` | +| `grh` | `FORGIT_RESET_HEAD_FZF_OPTS` | +| `gcf` | `FORGIT_CHECKOUT_FILE_FZF_OPTS` | +| `gcb` | `FORGIT_CHECKOUT_BRANCH_FZF_OPTS` | +| `gbd` | `FORGIT_BRANCH_DELETE_FZF_OPTS` | +| `gct` | `FORGIT_CHECKOUT_TAG_FZF_OPTS` | +| `gco` | `FORGIT_CHECKOUT_COMMIT_FZF_OPTS` | +| `grc` | `FORGIT_REVERT_COMMIT_FZF_OPTS` | +| `gss` | `FORGIT_STASH_FZF_OPTS` | +| `gsp` | `FORGIT_STASH_PUSH_FZF_OPTS` | +| `gclean` | `FORGIT_CLEAN_FZF_OPTS` | +| `grb` | `FORGIT_REBASE_FZF_OPTS` | +| `gbl` | `FORGIT_BLAME_FZF_OPTS` | +| `gfu` | `FORGIT_FIXUP_FZF_OPTS` | +| `gsq` | `FORGIT_SQUASH_FZF_OPTS` | +| `grw` | `FORGIT_REWORD_FZF_OPTS` | +| `gcp` | `FORGIT_CHERRY_PICK_FZF_OPTS` | +| `gws`/`gwj` | `FORGIT_WORKTREE_SELECT_FZF_OPTS` | +| `gwl` | `FORGIT_WORKTREE_LOCK_FZF_OPTS` | +| `gwr` | `FORGIT_WORKTREE_REMOVE_FZF_OPTS` | +| `gwu` | `FORGIT_WORKTREE_UNLOCK_FZF_OPTS` | Complete loading order of fzf options is: From 77ee1ca59c58385bcacaea201e6ceff0b68fd7d6 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 29 Jun 2025 22:24:32 -0400 Subject: [PATCH 12/14] fix: handle null byte output for worktree completion --- completions/_git-forgit | 1 + completions/git-forgit.bash | 1 + 2 files changed, 2 insertions(+) diff --git a/completions/_git-forgit b/completions/_git-forgit index 8581eb6f..9a741181 100644 --- a/completions/_git-forgit +++ b/completions/_git-forgit @@ -19,6 +19,7 @@ _git-stash-show() { } _git-worktrees() { + # --porcelain usually paired with -z but not needed since we use awk _alternative "worktrees:worktree:($(git worktree list --porcelain | awk '/worktree/ {print $2}'))" } diff --git a/completions/git-forgit.bash b/completions/git-forgit.bash index 75c584f4..fc4f0e55 100755 --- a/completions/git-forgit.bash +++ b/completions/git-forgit.bash @@ -37,6 +37,7 @@ _git_stash_show() _git_worktrees() { + # --porcelain usually paired with -z but not needed since we use awk __gitcomp_nl "$(git worktree list --porcelain | awk '/worktree/ {print $2}')" } From 3268f28f1d1653a981663ed019d79c033400fddc Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Sun, 29 Jun 2025 22:43:44 -0400 Subject: [PATCH 13/14] fix: simplify logic by propagating arg handling --- bin/git-forgit | 75 ++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/bin/git-forgit b/bin/git-forgit index ea4df262..1946884e 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -65,6 +65,18 @@ _forgit_previous_commit() { fi } +_forgit_all_non_flags() { + while (("$#")); do + case "$1" in + -*) + return 1 + ;; + esac + shift + done + return 0 +} + _forgit_contains_non_flags() { while (("$#")); do case "$1" in @@ -1216,6 +1228,16 @@ _forgit_worktree_select() { echo "$tree" } +_forgit_worktree_lock_max_args() { + local usage + usage=$(git worktree lock --help 2>/dev/null | grep -E 'usage: git worktree lock' | head -n1) + usage=${usage#*:} + rest=$(echo "$usage" | awk '{for(i=4;i<=NF;++i)printf "%s ",$i; print ""}') + # shellcheck disable=SC2206 + local args=($rest) + echo "${#args[@]}" +} + _forgit_git_worktree_lock() { _forgit_worktree_lock_git_opts=() _forgit_parse_array _forgit_worktree_lock_git_opts "$FORGIT_WORKTREE_LOCK_GIT_OPTS" @@ -1225,21 +1247,12 @@ _forgit_git_worktree_lock() { _forgit_worktree_lock() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 - local tree opts reason - if [[ $# -ne 0 ]]; then - if [[ "$1" == "--reason" ]]; then - if [[ -z "$2" ]]; then - _forgit_warn "Option \`--reason' requires a value" - return 1 - fi - reason="$2" - shift 2 - fi + local tree opts max_args + max_args=$(_forgit_worktree_lock_max_args) - if [[ $# -eq 0 ]] || _forgit_contains_non_flags "$@"; then - git worktree lock "$@" --reason "$reason" - return $? - fi + if [[ $# -ge "$max_args" ]] || { [[ $# -ne 0 ]] && _forgit_all_non_flags "$@"; }; then + git worktree lock "$@" + return $? fi opts=" @@ -1251,12 +1264,7 @@ _forgit_worktree_lock() { tree=$(git worktree list | grep -vE "\(bare\)|locked" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 - - if [[ -z "$reason" ]]; then - _forgit_git_worktree_lock "$tree" - else - _forgit_git_worktree_lock "$tree" --reason "$reason" - fi + _forgit_git_worktree_lock "$tree" "$@" } _forgit_git_worktree_remove() { @@ -1267,28 +1275,11 @@ _forgit_git_worktree_remove() { _forgit_worktree_remove() { _forgit_inside_work_tree || _forgit_inside_git_dir || return 1 - local worktree_list tree opts force_flags - - force_flags=() - - while (("$#")); do - case "$1" in - -f | --force) - force_flags+=("$1") - shift - ;; - -*) shift ;; - *) - tree="$1" - shift - ;; - esac - done + local worktree_list tree opts - if [[ -n "$tree" ]]; then - _forgit_git_worktree_remove "${force_flags[@]}" "$tree" - worktree_remove_status=$? - return $worktree_remove_status + if [[ $# -ne 0 ]] && _forgit_contains_non_flags "$@"; then + git worktree remove "$@" + return $? fi worktree_list=$(git worktree list | grep -v "(bare)") @@ -1305,7 +1296,7 @@ _forgit_worktree_remove() { tree=$(echo "$worktree_list" | awk '{print $1}' | FZF_DEFAULT_OPTS="$opts" fzf) [[ -z "$tree" ]] && return 1 - _forgit_git_worktree_remove "${force_flags[@]}" "$tree" + _forgit_git_worktree_remove "$tree" "$@" } _forgit_worktree_unlock() { From 785f1a9324acfd885686d170bf97f88135a16dd7 Mon Sep 17 00:00:00 2001 From: Sufien Tout Date: Tue, 1 Jul 2025 11:32:14 -0400 Subject: [PATCH 14/14] fix: remove trailing space --- bin/git-forgit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/git-forgit b/bin/git-forgit index 1946884e..bfe3950f 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -1119,7 +1119,7 @@ _forgit_ignore() { args=() while IFS='' read -r arg; do args+=("$arg") - done < <(_forgit_paths_list "$FORGIT_GI_TEMPLATES" .gitignore | + done < <(_forgit_paths_list "$FORGIT_GI_TEMPLATES" .gitignore | nl -w4 -s' ' | FZF_DEFAULT_OPTS="$opts" fzf | awk '{print $2}') fi