diff --git a/.editorconfig b/.editorconfig index 2b44368..ebb4a06 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,4 +6,7 @@ end_of_line = lf indent_style = space insert_final_newline = true tab_width = 4 +indent_size = 4 +simplify = true +switch_case_indent = true trim_trailing_whitespace = true diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 719e9db..ae89b58 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -78,3 +78,13 @@ jobs: run: npm install -g @commitlint/cli @commitlint/config-conventional - name: Validate PR commits run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose + + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Check format + uses: mfinelli/setup-shfmt@v4 + with: + shfmt-version: 3.13.1 + - run: shfmt --diff . diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9257bf4..feff849 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,6 +62,7 @@ lib/bashunit . bash forgit.plugin.sh zsh forgit.plugin.zsh fish conf.d/forgit.plugin.fish +shfmt --write . ``` In your pull request, report which shells and operating systems you tested. diff --git a/bin/git-forgit b/bin/git-forgit index 55c8bca..a3a4c9c 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -39,8 +39,11 @@ _forgit_inside_work_tree() { git rev-parse --is-inside-work-tree >/dev/null 2>&1 _forgit_inside_git_dir() { git rev-parse --is-inside-git-dir >/dev/null 2>&1; } _forgit_inside_git_repo() { _forgit_inside_work_tree || _forgit_inside_git_dir; } # 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; } -_forgit_strip_ansi() { local ESC=$'\033'; sed "s/${ESC}\[[0-9;]*m//g"; } +_forgit_reverse_lines() { tac 2>/dev/null || tail -r; } +_forgit_strip_ansi() { + local ESC=$'\033' + sed "s/${ESC}\[[0-9;]*m//g" +} _forgit_previous_commit() { # "SHA~" is invalid when the commit is the first commit, but we can use "--root" instead @@ -54,10 +57,10 @@ _forgit_previous_commit() { _forgit_contains_non_flags() { while (("$#")); do case "$1" in - -*) shift ;; - *) - return 0 - ;; + -*) shift ;; + *) + return 0 + ;; esac done return 1 @@ -98,7 +101,7 @@ _forgit_parse_array() { ${IFS+"false"} && unset old_IFS || old_IFS="$IFS" # read the value of the second argument # into an array that has the name of the first argument - IFS=" " read -r -a "$1" <<< "$2" + IFS=" " read -r -a "$1" <<<"$2" ${old_IFS+"false"} && unset IFS || IFS="$old_IFS" } @@ -108,18 +111,18 @@ _forgit_quote_files() { local files add files=() add=false - while (( "$#" )); do + while (("$#")); do case "$1" in --) - add=true - shift - ;; + add=true + shift + ;; *) - if [ $add == true ]; then - files+=("'$1'") - fi - shift - ;; + if [ $add == true ]; then + files+=("'$1'") + fi + shift + ;; esac done echo "${files[*]}" @@ -130,19 +133,19 @@ _forgit_log_format=${FORGIT_LOG_FORMAT:-%C(auto)%h%d %s %C(black)%C(bold)%cr%Cre _forgit_log_preview_options=("--graph" "--pretty=format:$_forgit_log_format" "--color=always" "--abbrev-commit" "--date=relative") _forgit_fullscreen_context=${FORGIT_FULLSCREEN_CONTEXT:-10} _forgit_preview_context=${FORGIT_PREVIEW_CONTEXT:-3} -_forgit_dir_view=${FORGIT_DIR_VIEW:-$(hash tree &> /dev/null && echo 'tree' || echo 'find')} +_forgit_dir_view=${FORGIT_DIR_VIEW:-$(hash tree &>/dev/null && echo 'tree' || echo 'find')} _forgit_pager() { local pager # Preview mode must be marked explicitly by forgit. Inferred signals such # as FZF_PREVIEW_COLUMNS or a non-TTY stdout also show up in execute/fullscreen # paths, which would incorrectly route Enter actions to FORGIT_PREVIEW_PAGER. - if [[ -n "$FORGIT_IN_PREVIEW" ]] && [[ -n "$FORGIT_PREVIEW_PAGER" ]]; then + if [[ -n $FORGIT_IN_PREVIEW ]] && [[ -n $FORGIT_PREVIEW_PAGER ]]; then pager="$FORGIT_PREVIEW_PAGER" else pager=$(_forgit_get_pager "$1") fi - [[ -z "${pager}" ]] && exit 1 + [[ -z ${pager} ]] && exit 1 eval "${pager} ${*:2}" } @@ -171,7 +174,7 @@ _forgit_get_pager() { } _forgit_is_file_tracked() { - git ls-files "$1" --error-unmatch &> /dev/null + git ls-files "$1" --error-unmatch &>/dev/null } # List branches with current branch first (for use as fzf header) @@ -185,7 +188,7 @@ _forgit_is_file_tracked() { _forgit_branch_list() { local current current=$(git branch --show-current) - if [[ -n "$current" ]]; then + if [[ -n $current ]]; then _forgit_print_dim "* $current" else _forgit_print_dim "* (HEAD detached at $(git rev-parse --short HEAD))" @@ -361,7 +364,10 @@ _forgit_log() { # git reflog viewer _forgit_reflog() { _forgit_inside_work_tree || return 1 - _forgit_contains_non_flags "$@" && { git reflog "$@"; return $?; } + _forgit_contains_non_flags "$@" && { + git reflog "$@" + return $? + } local opts reflog_format opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -426,7 +432,7 @@ _forgit_diff_view() { repo=$(git rev-parse --show-toplevel) cd "$repo" || return 1 if [ $# -gt 2 ]; then - IFS=" " read -r -a commits <<< "${*:3}" + IFS=" " read -r -a commits <<<"${*:3}" fi echo "$input_line" | _forgit_get_files_from_diff_line | xargs -0 \ "$FORGIT" exec_diff "${commits[@]}" -U"$diff_context" -- | _forgit_pager diff @@ -453,7 +459,7 @@ _forgit_diff() { commits=() files=() [[ $# -ne 0 ]] && { - if git rev-parse "$1" -- &>/dev/null ; then + if git rev-parse "$1" -- &>/dev/null; then if [[ $# -gt 1 ]] && git rev-parse "$2" -- &>/dev/null; then commits=("$1" "$2") && files=("${@:3}") else @@ -511,7 +517,7 @@ _forgit_show_preview() { local input_line=$1 local diff_context=$2 local commit=$3 - if [[ "$FZF_PREVIEW_LABEL" =~ "Diff" ]]; then + if [[ $FZF_PREVIEW_LABEL =~ "Diff" ]]; then _forgit_show_view "${input_line}" "${diff_context}" "${commit}" else git show --quiet --color=always "${FZF_PROMPT%% *}" @@ -543,7 +549,7 @@ _forgit_show() { local files opts commit escaped_commit files=() if [[ $# -ne 0 ]]; then - if git rev-parse "$1" -- &>/dev/null ; then + if git rev-parse "$1" -- &>/dev/null; then commit="$1" && files=("${@:2}") else commit="HEAD" && files=("$@") @@ -577,11 +583,11 @@ _forgit_add_preview() { file=$1 # $file can be a directory when status.showUntrackedFiles is set to 'normal' # When this is the case and the directory is not a submodule show the content of the directory and return - if [[ -d "$file" ]] && ! _forgit_is_submodule "$file"; then + if [[ -d $file ]] && ! _forgit_is_submodule "$file"; then eval "$_forgit_dir_view \"$file\"" return 0 fi - if (git status -s -- "$file" | grep '^??') &>/dev/null; then # diff with /dev/null for untracked files + if (git status -s -- "$file" | grep '^??') &>/dev/null; then # diff with /dev/null for untracked files git diff --color=always --no-index -- /dev/null "$file" | _forgit_pager diff | sed '2 s/added:/untracked:/' else git diff --color=always -- "$file" | _forgit_pager diff @@ -605,7 +611,10 @@ _forgit_add() { _forgit_inside_work_tree || return 1 local files opts # Add files if passed as arguments - _forgit_contains_non_flags "$@" && { _forgit_git_add "$@" && git status -s; return $?; } + _forgit_contains_non_flags "$@" && { + _forgit_git_add "$@" && git status -s + return $? + } opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -621,7 +630,7 @@ _forgit_add() { while IFS='' read -r file; do files+=("$file") done < <(_forgit_worktree_changes | FZF_DEFAULT_OPTS="$opts" fzf) - [[ "${#files[@]}" -gt 0 ]] && _forgit_git_add "$@" "${files[@]}" && git status -s && return + [[ ${#files[@]} -gt 0 ]] && _forgit_git_add "$@" "${files[@]}" && git status -s && return echo 'Nothing to add.' } @@ -640,7 +649,10 @@ _forgit_git_reset_head() { _forgit_reset_head() { _forgit_inside_work_tree || return 1 local files opts rootdir - [[ $# -ne 0 ]] && { _forgit_git_reset_head "$@" && git status --short; return $?; } + [[ $# -ne 0 ]] && { + _forgit_git_reset_head "$@" && git status --short + return $? + } rootdir=$(git rev-parse --show-toplevel) opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -678,7 +690,10 @@ _forgit_stash_show_enter() { _forgit_stash_show() { _forgit_inside_work_tree || return 1 local opts - [[ $# -ne 0 ]] && { "${FORGIT}" show "$@"; return $?; } + [[ $# -ne 0 ]] && { + "${FORGIT}" show "$@" + return $? + } _forgit_stash_show_git_opts=() _forgit_parse_array _forgit_stash_show_git_opts "$FORGIT_STASH_SHOW_GIT_OPTS" opts=" @@ -713,18 +728,21 @@ _forgit_git_stash_push() { _forgit_stash_push() { _forgit_inside_work_tree || return 1 local msg args - args=( "$@" ) - while (( "$#" )); do + args=("$@") + while (("$#")); do case "$1" in # allow message as argument - -m|--message) - msg="$2" - shift 2 - ;; + -m | --message) + msg="$2" + shift 2 + ;; # ignore -u as it's used implicitly - -u|--include-untracked) shift ;; + -u | --include-untracked) shift ;; # pass to git directly when encountering anything else - *) _forgit_git_stash_push "${args[@]}"; return $? + *) + _forgit_git_stash_push "${args[@]}" + return $? + ;; esac done local opts files @@ -740,14 +758,14 @@ _forgit_stash_push() { files+=("$file") done < <(_forgit_list_files --exclude-standard --modified --others | FZF_DEFAULT_OPTS="$opts" fzf --exit-0) - [[ "${#files[@]}" -eq 0 ]] && echo "Nothing to stash" && return 1 + [[ ${#files[@]} -eq 0 ]] && echo "Nothing to stash" && return 1 _forgit_git_stash_push ${msg:+-m "$msg"} -u "${files[@]}" } _forgit_clean_preview() { local path path=$1 - if [[ -d "$path" ]]; then + if [[ -d $path ]]; then eval "$_forgit_dir_view \"$path\"" else git diff --color=always /dev/null "$path" | _forgit_pager diff @@ -771,12 +789,15 @@ _forgit_clean_select_files() { # git clean selector _forgit_clean() { _forgit_inside_work_tree || return 1 - _forgit_contains_non_flags "$@" && { git clean -q "$@"; return $?; } + _forgit_contains_non_flags "$@" && { + git clean -q "$@" + return $? + } local files _forgit_clean_git_opts=() _forgit_parse_array _forgit_clean_git_opts "$FORGIT_CLEAN_GIT_OPTS" files=$(_forgit_clean_select_files "$@") - [[ -n "$files" ]] && echo "$files" | tr '\n' '\0' | xargs -0 -I% git clean "${_forgit_clean_git_opts[@]}" -xdff '%' && git status --short && return + [[ -n $files ]] && echo "$files" | tr '\n' '\0' | xargs -0 -I% git clean "${_forgit_clean_git_opts[@]}" -xdff '%' && git status --short && return echo 'Nothing to clean.' } @@ -790,7 +811,7 @@ _forgit_cherry_pick() { local base target opts fzf_selection fzf_exitval base=$(git branch --show-current) - [[ -z "$base" ]] && echo "Current commit is not on a branch." && return 1 + [[ -z $base ]] && echo "Current commit is not on a branch." && return 1 [[ -z $1 ]] && echo "Please specify target branch" && return 1 target="$1" @@ -812,7 +833,7 @@ _forgit_cherry_pick() { FZF_DEFAULT_OPTS="$opts" fzf) fzf_exitval=$? [[ $fzf_exitval != 0 ]] && return $fzf_exitval - [[ -z "$fzf_selection" ]] && return $fzf_exitval + [[ -z $fzf_selection ]] && return $fzf_exitval commits=() while IFS='' read -r commit; do @@ -836,7 +857,7 @@ _forgit_cherry_pick_from_branch() { local opts branch exitval input_branch args base base=$(git branch --show-current) - [[ -z "$base" ]] && echo "Current commit is not on a branch." && return 1 + [[ -z $base ]] && echo "Current commit is not on a branch." && return 1 args=("$@") if [[ $# -ne 0 ]]; then @@ -850,8 +871,7 @@ _forgit_cherry_pick_from_branch() { " # loop until either the branch selector is closed or a commit to be cherry # picked has been selected from within a branch - while true - do + while true; do if [[ -z $input_branch ]]; then branch="$(_forgit_branch_list --all | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_branch_name)" else @@ -859,7 +879,7 @@ _forgit_cherry_pick_from_branch() { fi unset input_branch - [[ -z "$branch" ]] && return 1 + [[ -z $branch ]] && return 1 _forgit_cherry_pick "$branch" @@ -870,7 +890,10 @@ _forgit_cherry_pick_from_branch() { _forgit_rebase() { _forgit_inside_work_tree || return 1 - _forgit_contains_non_flags "$@" && { git rebase "$@"; return $?; } + _forgit_contains_non_flags "$@" && { + git rebase "$@" + return $? + } local opts graph target_commit prev_commit graph=() [[ $_forgit_log_graph_enable == true ]] && graph=(--graph) @@ -885,10 +908,11 @@ _forgit_rebase() { " target_commit=$( git log "${graph[@]}" --color=always --format="$_forgit_log_format" | - _forgit_emojify | - FZF_DEFAULT_OPTS="$opts" fzf | - _forgit_extract_sha) - if [[ -n "$target_commit" ]]; then + _forgit_emojify | + FZF_DEFAULT_OPTS="$opts" fzf | + _forgit_extract_sha + ) + if [[ -n $target_commit ]]; then prev_commit=$(_forgit_previous_commit "$target_commit") git rebase -i "${_forgit_rebase_git_opts[@]}" "$@" "$prev_commit" fi @@ -932,11 +956,12 @@ _forgit_edit_commit() { " target_commit=$( git log "${graph[@]}" --color=always --format="$_forgit_log_format" "$@" | - _forgit_emojify | - FZF_DEFAULT_OPTS="$opts" fzf | - _forgit_extract_sha) + _forgit_emojify | + FZF_DEFAULT_OPTS="$opts" fzf | + _forgit_extract_sha + ) # GIT_EDITOR=: is needed to skip the editor - if [[ -n "$target_commit" ]] && GIT_EDITOR=: git commit "${git_opts[@]}" "$action" "$target_commit"; then + if [[ -n $target_commit ]] && GIT_EDITOR=: git commit "${git_opts[@]}" "$action" "$target_commit"; then prev_commit=$(_forgit_previous_commit "$target_commit") # rebase will fail if there are unstaged changes so --autostash is needed to temporarily stash them # GIT_SEQUENCE_EDITOR=: is needed to skip the editor @@ -961,10 +986,11 @@ _forgit_reword() { " target_commit=$( git log "${graph[@]}" --color=always --format="$_forgit_log_format" "$@" | - _forgit_emojify | - FZF_DEFAULT_OPTS="$opts" fzf | - _forgit_extract_sha) - if [[ -n "$target_commit" ]] && git commit "${git_opts[@]}" --fixup=reword:"$target_commit"; then + _forgit_emojify | + FZF_DEFAULT_OPTS="$opts" fzf | + _forgit_extract_sha + ) + if [[ -n $target_commit ]] && git commit "${git_opts[@]}" --fixup=reword:"$target_commit"; then prev_commit=$(_forgit_previous_commit "$target_commit") # rebase will fail if there are unstaged changes so --autostash is needed to temporarily stash them # GIT_SEQUENCE_EDITOR=: is needed to skip the editor @@ -986,7 +1012,10 @@ _forgit_git_checkout_file() { _forgit_checkout_file() { _forgit_inside_work_tree || return 1 local files opts - _forgit_contains_non_flags "$@" && { _forgit_git_checkout_file "$@"; return $?; } + _forgit_contains_non_flags "$@" && { + _forgit_git_checkout_file "$@" + return $? + } [[ $(_forgit_list_files --modified | wc -l) -eq 0 ]] && echo 'Nothing to checkout.' && return 1 opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -999,7 +1028,7 @@ _forgit_checkout_file() { files+=("$file") done < <(_forgit_list_files --modified | FZF_DEFAULT_OPTS="$opts" fzf) - [[ "${#files[@]}" -gt 0 ]] && _forgit_git_checkout_file "$@" "${files[@]}" + [[ ${#files[@]} -gt 0 ]] && _forgit_git_checkout_file "$@" "${files[@]}" } # git checkout-file from commit selector @@ -1025,7 +1054,7 @@ _forgit_checkout_file_from_commit() { commit=$(_forgit_git_log "$_forgit_log_format" "$branch" "$@" | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_sha) - [[ -n "$commit" ]] || return 0 + [[ -n $commit ]] || return 0 # select the file interactively opts=" @@ -1040,11 +1069,11 @@ _forgit_checkout_file_from_commit() { --prompt=\"${commit} > \" " file=$(_forgit_git_show "$commit" | FZF_DEFAULT_OPTS="$opts" fzf) - [[ -n "$file" ]] || return 0 + [[ -n $file ]] || return 0 # special case: when the file was deleted in the commit # check out the file from the previous commit. - [[ "$file" =~ ^\[D\] ]] && commit="$commit~" + [[ $file =~ ^\[D\] ]] && commit="$commit~" file=$(echo "$file" | _forgit_get_single_file_from_diff_line) _forgit_git_checkout_file "$commit" -- "$file" @@ -1061,7 +1090,7 @@ _forgit_checkout_branch() { _forgit_inside_work_tree || return 1 # if called with arguments, check if branch exists, else create a new one if [[ $# -ne 0 ]]; then - if [[ "$*" == "-" ]] || git show-branch "$@" &>/dev/null; then + if [[ $* == "-" ]] || git show-branch "$@" &>/dev/null; then git switch "$@" else git switch -c "$@" @@ -1082,10 +1111,10 @@ _forgit_checkout_branch() { _forgit_parse_array _forgit_checkout_branch_branch_git_opts "$FORGIT_CHECKOUT_BRANCH_BRANCH_GIT_OPTS" branch="$(_forgit_branch_list "${_forgit_checkout_branch_branch_git_opts[@]:---all}" | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_branch_name)" - [[ -z "$branch" ]] && return 1 + [[ -z $branch ]] && return 1 # track the remote branch if possible - if [[ "$branch" == "remotes/"* ]]; then + if [[ $branch == "remotes/"* ]]; then if git branch | grep -qw "${branch#remotes/*/}"; then # hack to force creating a new branch which tracks the remote if a local branch already exists _forgit_git_checkout_branch -b "track/${branch#remotes/*/}" --track "$branch" @@ -1107,7 +1136,7 @@ _forgit_switch_branch() { _forgit_inside_work_tree || return 1 # if called with arguments, check if branch exists, else create a new one if [[ $# -ne 0 ]]; then - if [[ "$*" == "-" ]] || git show-branch "$@" &>/dev/null; then + if [[ $* == "-" ]] || git show-branch "$@" &>/dev/null; then git switch "$@" else git switch -c "$@" @@ -1128,10 +1157,10 @@ _forgit_switch_branch() { _forgit_parse_array _forgit_switch_branch_branch_git_opts "$FORGIT_SWITCH_BRANCH_BRANCH_GIT_OPTS" branch="$(_forgit_branch_list "${_forgit_switch_branch_branch_git_opts[@]:---all}" | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_branch_name)" - [[ -z "$branch" ]] && return 1 + [[ -z $branch ]] && return 1 # track the remote branch if possible - if [[ "$branch" == "remotes/"* ]]; then + if [[ $branch == "remotes/"* ]]; then if git branch | grep -qw "${branch#remotes/*/}"; then # hack to force creating a new branch which tracks the remote if a local branch already exists _forgit_git_switch_branch --create "track/${branch#remotes/*/}" --track "$branch" @@ -1153,7 +1182,10 @@ _forgit_git_checkout_tag() { _forgit_checkout_tag() { _forgit_inside_work_tree || return 1 local opts tag - [[ $# -ne 0 ]] && { _forgit_git_checkout_tag "$@"; return $?; } + [[ $# -ne 0 ]] && { + _forgit_git_checkout_tag "$@" + return $? + } [[ $(git tag -l | wc -l) -eq 0 ]] && echo 'Nothing to checkout: there are no tags.' && return 1 opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1162,7 +1194,7 @@ _forgit_checkout_tag() { $FORGIT_CHECKOUT_TAG_FZF_OPTS " tag="$(git tag -l --sort=-v:refname | FZF_DEFAULT_OPTS="$opts" fzf)" - [[ -z "$tag" ]] && return 1 + [[ -z $tag ]] && return 1 _forgit_git_checkout_tag "$tag" } @@ -1182,7 +1214,10 @@ _forgit_git_checkout_commit() { _forgit_checkout_commit() { _forgit_inside_work_tree || return 1 local opts graph commit - [[ $# -ne 0 ]] && { _forgit_git_checkout_commit "$@"; return $?; } + [[ $# -ne 0 ]] && { + _forgit_git_checkout_commit "$@" + return $? + } opts=" $FORGIT_FZF_DEFAULT_OPTS +s +m --tiebreak=index @@ -1215,7 +1250,10 @@ _forgit_git_branch_delete() { _forgit_branch_delete() { _forgit_inside_work_tree || return 1 local opts - [[ $# -ne 0 ]] && { _forgit_git_branch_delete "$@"; return $?; } + [[ $# -ne 0 ]] && { + _forgit_git_branch_delete "$@" + return $? + } opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1223,8 +1261,7 @@ _forgit_branch_delete() { --preview=\"$FORGIT preview branch_preview {}\" $FORGIT_BRANCH_DELETE_FZF_OPTS " - for branch in $(_forgit_branch_list | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_branch_name) - do + for branch in $(_forgit_branch_list | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_branch_name); do _forgit_git_branch_delete "$branch" done } @@ -1245,7 +1282,10 @@ _forgit_git_revert() { _forgit_revert_commit() { _forgit_inside_work_tree || return 1 local opts commits IFS - [[ $# -ne 0 ]] && { _forgit_git_revert "$@"; return $?; } + [[ $# -ne 0 ]] && { + _forgit_git_revert "$@" + return $? + } opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1267,12 +1307,13 @@ _forgit_revert_commit() { commits+=("$commit") done < <( git log "${graph[@]}" --color=always --format="$_forgit_log_format" | - _forgit_emojify | - nl | - FZF_DEFAULT_OPTS="$opts" fzf | - sort -n -k 1 | - cut -f2- | - sed 's/^[^a-f^0-9]*\([a-f0-9]*\).*/\1/') + _forgit_emojify | + nl | + FZF_DEFAULT_OPTS="$opts" fzf | + sort -n -k 1 | + cut -f2- | + sed 's/^[^a-f^0-9]*\([a-f0-9]*\).*/\1/' + ) [ ${#commits[@]} -eq 0 ] && return 1 @@ -1299,7 +1340,10 @@ _forgit_git_blame() { _forgit_blame() { _forgit_inside_work_tree || return 1 local opts flags file - _forgit_contains_non_flags "$@" && { _forgit_git_blame "$@"; return $?; } + _forgit_contains_non_flags "$@" && { + _forgit_git_blame "$@" + return $? + } flags=() while IFS='' read -r flag; do flags+=("$flag") @@ -1312,7 +1356,7 @@ _forgit_blame() { # flags is not quoted here, which is fine given that they are retrieved # with git rev-parse and can only contain flags file=$(FZF_DEFAULT_OPTS="$opts" fzf) - [[ -z "$file" ]] && return 1 + [[ -z $file ]] && return 1 _forgit_git_blame "$file" "${flags[@]}" } @@ -1335,8 +1379,8 @@ _forgit_path_preview() { } _forgit_ignore() { - [ -d "$FORGIT_GI_REPO_LOCAL" ] \ - || _forgit_repo_update "$FORGIT_GI_REPO_REMOTE" "$FORGIT_GI_REPO_LOCAL" + [ -d "$FORGIT_GI_REPO_LOCAL" ] || + _forgit_repo_update "$FORGIT_GI_REPO_REMOTE" "$FORGIT_GI_REPO_LOCAL" local IFS args opts opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1363,8 +1407,8 @@ export FORGIT_ATTR_REPO_LOCAL=${FORGIT_ATTR_REPO_LOCAL:-${XDG_CACHE_HOME:-$HOME/ export FORGIT_ATTR_TEMPLATES=${FORGIT_ATTR_TEMPLATES:-$FORGIT_ATTR_REPO_LOCAL} _forgit_attributes() { - [ -d "$FORGIT_ATTR_REPO_LOCAL" ] \ - || _forgit_repo_update "$FORGIT_ATTR_REPO_REMOTE" "$FORGIT_ATTR_REPO_LOCAL" + [ -d "$FORGIT_ATTR_REPO_LOCAL" ] || + _forgit_repo_update "$FORGIT_ATTR_REPO_REMOTE" "$FORGIT_ATTR_REPO_LOCAL" local IFS args opts opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1389,7 +1433,7 @@ _forgit_repo_update() { local remote path remote=$1 path=$2 - if [[ -d "$path" ]]; then + if [[ -d $path ]]; then _forgit_info 'Updating repo...' (cd "$path" && git pull --no-rebase --ff) || return 1 else @@ -1405,7 +1449,7 @@ _forgit_path_get() { shift 2 for item in "$@"; do if filename=$(find -L "$path" -type f \( -iname "${item}$ext" -o -iname "${item}" \) -print -quit); then - [[ -z "$filename" ]] && _forgit_warn "No template found for '$item'." && continue + [[ -z $filename ]] && _forgit_warn "No template found for '$item'." && continue header="${filename##*/}" && header="${header%"$ext"}" echo "### $header" && cat "$filename" && echo fi @@ -1416,7 +1460,7 @@ _forgit_paths_list() { local path ext path=$1 ext=$2 - find "$path" -name "*$ext" -print |sed -e "s#$ext\$##" -e 's#.*/##' -e '/^$/d' | sort -fu + find "$path" -name "*$ext" -print | sed -e "s#$ext\$##" -e 's#.*/##' -e '/^$/d' | sort -fu } # Get the root path of the main worktree (not the current worktree) @@ -1458,9 +1502,9 @@ _forgit_worktree_list() { "") relative_date=$(git log -1 --format='%cr' "$head" 2>/dev/null) local current_marker=" " lock_marker=" " - [[ "$worktree" == "$current_worktree" ]] && current_marker="*" - [[ -n "$prunable" ]] && lock_marker="$prunable" - [[ -n "$locked" ]] && lock_marker="$locked" + [[ $worktree == "$current_worktree" ]] && current_marker="*" + [[ -n $prunable ]] && lock_marker="$prunable" + [[ -n $locked ]] && lock_marker="$locked" printf "[%s%s] %s ${_cyan}(%s)${_reset} ${_gray}%s${_reset}\n" \ "$current_marker" "$lock_marker" "$worktree" "${branch:-HEAD}" "$relative_date" ;; @@ -1491,7 +1535,7 @@ _forgit_worktree_toggle_lock() { local line="$1" worktree stripped worktree=$(echo "$line" | _forgit_extract_worktree_path) stripped=$(echo "$line" | _forgit_strip_ansi) - if [[ "${stripped:2:1}" == "L" ]]; then + if [[ ${stripped:2:1} == "L" ]]; then git worktree unlock "$worktree" else git worktree lock "$worktree" @@ -1502,11 +1546,11 @@ _forgit_worktree_toggle_lock() { _forgit_worktree_preview() { local worktree worktree=$(echo "$1" | _forgit_extract_worktree_path) - [[ ! -d "$worktree" ]] && echo "Worktree directory not found: $worktree" && return 1 + [[ ! -d $worktree ]] && echo "Worktree directory not found: $worktree" && return 1 local status_output status_output=$(git -c color.status=always -C "$worktree" status -s 2>/dev/null) - [[ -n "$status_output" ]] && echo "$status_output" && echo "" + [[ -n $status_output ]] && echo "$status_output" && echo "" git -C "$worktree" log --oneline -n 200 --color=always 2>/dev/null } @@ -1523,7 +1567,10 @@ _forgit_git_worktree_delete() { _forgit_worktree() { _forgit_inside_git_repo || return 1 local opts worktree - [[ $# -ne 0 ]] && { git worktree "$@"; return $?; } + [[ $# -ne 0 ]] && { + git worktree "$@" + return $? + } opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1534,7 +1581,7 @@ _forgit_worktree() { $FORGIT_WORKTREE_FZF_OPTS " worktree=$(_forgit_worktree_list | FZF_DEFAULT_OPTS="$opts" fzf) - [[ -z "$worktree" ]] && return 1 + [[ -z $worktree ]] && return 1 echo "$worktree" | _forgit_extract_worktree_path } @@ -1542,11 +1589,14 @@ _forgit_worktree() { _forgit_worktree_delete() { _forgit_inside_git_repo || return 1 local opts worktrees - [[ $# -ne 0 ]] && { _forgit_git_worktree_delete "$@"; return $?; } + [[ $# -ne 0 ]] && { + _forgit_git_worktree_delete "$@" + return $? + } local candidates candidates=$(_forgit_worktree_list_deletable) - if [[ -z "$candidates" ]]; then + if [[ -z $candidates ]]; then echo "Nothing to delete." return 1 fi @@ -1562,7 +1612,7 @@ _forgit_worktree_delete() { worktrees=() while IFS='' read -r line; do - [[ -n "$line" ]] && worktrees+=("$(echo "$line" | _forgit_extract_worktree_path)") + [[ -n $line ]] && worktrees+=("$(echo "$line" | _forgit_extract_worktree_path)") done < <(echo "$candidates" | FZF_DEFAULT_OPTS="$opts" fzf) [[ ${#worktrees[@]} -eq 0 ]] && return 1 @@ -1591,7 +1641,7 @@ _forgit_worktree_add() { _forgit_parse_array _forgit_worktree_add_branch_git_opts "$FORGIT_WORKTREE_ADD_BRANCH_GIT_OPTS" local header_opt="" - [[ -z "$new_branch" ]] && header_opt="--header-lines=1" + [[ -z $new_branch ]] && header_opt="--header-lines=1" opts=" $FORGIT_FZF_DEFAULT_OPTS @@ -1601,12 +1651,12 @@ _forgit_worktree_add() { " branch=$(_forgit_branch_list "${_forgit_worktree_add_branch_git_opts[@]:---all}" | FZF_DEFAULT_OPTS="$opts" fzf | _forgit_extract_branch_name) - [[ -z "$branch" ]] && return 1 + [[ -z $branch ]] && return 1 # Strip remotes// prefix for remote branches local local_branch="${branch#remotes/*/}" - if [[ -n "$new_branch" ]]; then + if [[ -n $new_branch ]]; then # gwa : create new branch from selected base local target="$wt_dir/$new_branch" git worktree add -b "$new_branch" "$target" "$branch" >&2 && echo "$target" @@ -1623,14 +1673,14 @@ check_prequisites() { # Check if fzf is installed installed_fzf_version=$(fzf --version 2>/dev/null | awk '{print $1}') - if [[ -z "$installed_fzf_version" ]]; then + if [[ -z $installed_fzf_version ]]; then echo "fzf is not installed. Please install fzf first." exit 1 fi # Check fzf version higher_fzf_version=$(printf '%s\n' "$REQUIRED_FZF_VERSION" "$installed_fzf_version" | sort -V | tail -n1) - if [[ "$higher_fzf_version" != "$installed_fzf_version" ]]; then + if [[ $higher_fzf_version != "$installed_fzf_version" ]]; then echo "fzf version $REQUIRED_FZF_VERSION or higher is required. You have $installed_fzf_version." exit 1 fi @@ -1651,7 +1701,7 @@ main() { # shellcheck disable=SC2076 if [[ ! " ${PUBLIC_COMMANDS[*]} " =~ " ${cmd} " ]] && [[ ! " ${PRIVATE_COMMANDS[*]} " =~ " ${cmd} " ]]; then - if [[ -z "$cmd" ]]; then + if [[ -z $cmd ]]; then printf "forgit: missing command\n\n" else printf "forgit: '%s' is not a valid forgit command.\n\n" "$cmd" @@ -1718,7 +1768,7 @@ PRIVATE_COMMANDS=( # Check if the script is being sourced. This is necessary for unit tests where # we do not want to execute the main function. -if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then +if [[ ${BASH_SOURCE[0]} != "$0" ]]; then return 0 fi diff --git a/completions/git-forgit.bash b/completions/git-forgit.bash index ef467bc..ff1a3ef 100755 --- a/completions/git-forgit.bash +++ b/completions/git-forgit.bash @@ -10,36 +10,30 @@ # When using forgit via the shell plugin, source this file explicitly after # forgit.plugin.zsh to enable tab completion for shell functions and aliases. -_git_branch_delete() -{ +_git_branch_delete() { __gitcomp_nl "$(__git_heads)" } -_git_checkout_branch() -{ +_git_checkout_branch() { __gitcomp_nl "$(__git branch -a --format '%(refname:short)')" } -_git_checkout_file() -{ +_git_checkout_file() { __gitcomp_nl "$(__git ls-files --modified)" } -_git_checkout_tag() -{ +_git_checkout_tag() { __gitcomp_nl "$(__git_tags)" } -_git_stash_show() -{ +_git_stash_show() { __gitcomp_nl "$(__git stash list | sed -n -e 's/:.*//p')" } -_git_worktrees() -{ +_git_worktrees() { local wt_list="" field while IFS= read -r -d '' field; do - [[ "$field" == worktree\ * ]] && wt_list+="${field#worktree }"$'\n' + [[ $field == worktree\ * ]] && wt_list+="${field#worktree }"$'\n' done < <(__git worktree list --porcelain -z 2>/dev/null) __gitcomp_nl "$wt_list" } @@ -47,20 +41,18 @@ _git_worktrees() # Completion for git-forgit # This includes git aliases, e.g. "alias.cb=forgit checkout_branch" will # correctly complete available branches on "git cb". -_git_forgit() -{ +_git_forgit() { local subcommand cword cur prev cmds subcommand="${COMP_WORDS[1]}" - if [[ "$subcommand" != "forgit" ]] - then + if [[ $subcommand != "forgit" ]]; then # Forgit is obviously called via a git alias. Get the original # aliased subcommand and proceed as if it was the previous word. prev=$(git config --get "alias.$subcommand" | cut -d' ' -f 2) - cword=$((${COMP_CWORD} + 1)) + cword=$((COMP_CWORD + 1)) else cword=${COMP_CWORD} - prev=${COMP_WORDS[COMP_CWORD-1]} + prev=${COMP_WORDS[COMP_CWORD - 1]} fi cur=${COMP_WORDS[COMP_CWORD]} @@ -140,8 +132,7 @@ _git_forgit() } # Check if forgit plugin is loaded -if [[ $(type -t forgit::add) == function ]] -then +if [[ $(type -t forgit::add) == function ]]; then # We're reusing existing git completion functions, so load those first # and check if completion function exists afterwards. _completion_loader git @@ -175,7 +166,7 @@ then __git_complete forgit::worktree::delete _git_worktrees # Completion for forgit plugin shell aliases - if [[ -z "$FORGIT_NO_ALIASES" ]]; then + if [[ -z $FORGIT_NO_ALIASES ]]; then __git_complete "${forgit_add}" _git_add __git_complete "${forgit_branch_delete}" _git_branch_delete __git_complete "${forgit_checkout_branch}" _git_checkout_branch diff --git a/forgit.plugin.zsh b/forgit.plugin.zsh index 962efa9..a8675f9 100755 --- a/forgit.plugin.zsh +++ b/forgit.plugin.zsh @@ -5,17 +5,20 @@ # These shell built-ins prevent the wrong commands getting executed in case a # user added a shell alias with the same name. -forgit::error() { command printf "%b[Error]%b %s\n" '\e[0;31m' '\e[0m' "$@" >&2; builtin return 1; } +forgit::error() { + command printf "%b[Error]%b %s\n" '\e[0;31m' '\e[0m' "$@" >&2 + builtin return 1 +} forgit::warn() { command printf "%b[Warn]%b %s\n" '\e[0;33m' '\e[0m' "$@" >&2; } # determine installation path -if [[ -n "$ZSH_VERSION" ]]; then +if [[ -n $ZSH_VERSION ]]; then # shellcheck disable=2277,2296,2299 0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}" # shellcheck disable=2277,2296,2298 0="${${(M)0:#/*}:-$PWD/$0}" FORGIT_INSTALL_DIR="${0:h}" -elif [[ -n "$BASH_VERSION" ]]; then +elif [[ -n $BASH_VERSION ]]; then FORGIT_INSTALL_DIR="$(command dirname -- "${BASH_SOURCE[0]}")" else forgit::error "Only zsh and bash are supported" @@ -28,9 +31,10 @@ FORGIT="$FORGIT_INSTALL_DIR/bin/git-forgit" # export all user-defined FORGIT variables to make them available in git-forgit unexported_vars=0 # Set posix mode in bash to only get variables, see #256. -[[ -n "$BASH_VERSION" ]] && builtin set -o posix +[[ -n $BASH_VERSION ]] && builtin set -o posix builtin set | command awk -F '=' '{ print $1 }' | command grep FORGIT_ | while builtin read -r var; do - if ! builtin export | command grep -q "\(^$var=\|^export $var=\)"; then if [[ $unexported_vars == 0 ]]; then + if ! builtin export | command grep -q "\(^$var=\|^export $var=\)"; then + if [[ $unexported_vars == 0 ]]; then forgit::warn "Config options have to be exported in future versions of forgit." forgit::warn "Please update your config accordingly:" fi @@ -41,7 +45,7 @@ builtin set | command awk -F '=' '{ print $1 }' | command grep FORGIT_ | while b fi done builtin unset unexported_vars -[[ -n "$BASH_VERSION" ]] && builtin set +o posix +[[ -n $BASH_VERSION ]] && builtin set +o posix # register shell functions forgit::log() { @@ -165,16 +169,19 @@ forgit::attributes() { } forgit::worktree() { - if [[ $# -ne 0 ]]; then "$FORGIT" worktree "$@"; return $?; fi + if [[ $# -ne 0 ]]; then + "$FORGIT" worktree "$@" + return $? + fi local tree tree=$("$FORGIT" worktree) || return $? - [[ -d "$tree" ]] && builtin cd "$tree" || return 1 + [[ -d $tree ]] && builtin cd "$tree" || return 1 } forgit::worktree::add() { local tree tree=$("$FORGIT" worktree_add "$@") || return $? - [[ -d "$tree" ]] || return 0 + [[ -d $tree ]] || return 0 builtin cd "$tree" || return 1 } @@ -184,7 +191,7 @@ forgit::worktree::delete() { # register aliases # shellcheck disable=SC2139 -if [[ -z "$FORGIT_NO_ALIASES" ]]; then +if [[ -z $FORGIT_NO_ALIASES ]]; then builtin export forgit_add="${forgit_add:-ga}" builtin export forgit_reset_head="${forgit_reset_head:-grh}" diff --git a/tests/clean-select-files.test.sh b/tests/clean-select-files.test.sh index 8faaddd..ff6ae47 100644 --- a/tests/clean-select-files.test.sh +++ b/tests/clean-select-files.test.sh @@ -24,9 +24,9 @@ function test_forgit_clean_select_files_preview() { assert_file_exists "$file" } - function provider_clean_select_files() { - bashunit::data_set 1 - bashunit::data_set 2 - bashunit::data_set 3 - bashunit::data_set 4 - } +function provider_clean_select_files() { + bashunit::data_set 1 + bashunit::data_set 2 + bashunit::data_set 3 + bashunit::data_set 4 +} diff --git a/tests/empty-state.test.sh b/tests/empty-state.test.sh index d13fff8..bfc8d23 100644 --- a/tests/empty-state.test.sh +++ b/tests/empty-state.test.sh @@ -13,7 +13,7 @@ function set_up_before_script() { git config user.email "test@example.com" git config user.name "Test User" # Create an initial commit so we have a valid repo - echo "initial" > README.md + echo "initial" >README.md git add README.md git commit -q -m "Initial commit" } diff --git a/tests/helper-functions.test.sh b/tests/helper-functions.test.sh index 0cc0eab..cf11364 100644 --- a/tests/helper-functions.test.sh +++ b/tests/helper-functions.test.sh @@ -13,8 +13,8 @@ function test_forgit_get_files_from_diff_line() { local i while IFS= read -r line; do - actual+=( "$line" ) - done < <( echo -n "$input" | _forgit_get_files_from_diff_line | xargs -0 -n 1 echo ) + actual+=("$line") + done < <(echo -n "$input" | _forgit_get_files_from_diff_line | xargs -0 -n 1 echo) # Compare array sizes assert_same "${#expected[@]}" "${#actual[@]}" diff --git a/tests/preview-context.test.sh b/tests/preview-context.test.sh index a439a3d..816bff4 100644 --- a/tests/preview-context.test.sh +++ b/tests/preview-context.test.sh @@ -22,15 +22,15 @@ function test_forgit_pager_uses_preview_pager_only_in_explicit_preview_context() without_marker=$( FORGIT_DIFF_PAGER="printf diff" \ - FORGIT_PREVIEW_PAGER="printf preview" \ - FZF_PREVIEW_COLUMNS=80 \ - _forgit_pager diff + FORGIT_PREVIEW_PAGER="printf preview" \ + FZF_PREVIEW_COLUMNS=80 \ + _forgit_pager diff ) with_marker=$( FORGIT_DIFF_PAGER="printf diff" \ - FORGIT_PREVIEW_PAGER="printf preview" \ - FORGIT_IN_PREVIEW=1 \ - _forgit_pager diff + FORGIT_PREVIEW_PAGER="printf preview" \ + FORGIT_IN_PREVIEW=1 \ + _forgit_pager diff ) assert_same "diff" "$without_marker" diff --git a/tests/working-tree-changes.test.sh b/tests/working-tree-changes.test.sh index 20519c2..6e77433 100644 --- a/tests/working-tree-changes.test.sh +++ b/tests/working-tree-changes.test.sh @@ -2,7 +2,7 @@ FORGIT_REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) - function set_up_before_script() { +function set_up_before_script() { source bin/git-forgit # Ignore global git config files @@ -19,123 +19,122 @@ FORGIT_REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) git add . git commit -m "init" --quiet - echo modified > "modified file.txt" + echo modified >"modified file.txt" touch "staged file.txt" git add "staged file.txt" touch "untracked_file.txt" touch 'untracked_with_\backslash' - } +} - function test_forgit_worktree_changes_contains_modified() { - local output +function test_forgit_worktree_changes_contains_modified() { + local output - output=$(_forgit_worktree_changes) + output=$(_forgit_worktree_changes) - assert_contains "modified file.txt" "$output" - } + assert_contains "modified file.txt" "$output" +} - function test_forgit_worktree_changes_contains_untracked() { - local output +function test_forgit_worktree_changes_contains_untracked() { + local output - output=$(_forgit_worktree_changes) + output=$(_forgit_worktree_changes) - assert_contains "untracked_file.txt" "$output" - } + assert_contains "untracked_file.txt" "$output" +} - function test_forgit_worktree_changes_excludes_staged() { - local output +function test_forgit_worktree_changes_excludes_staged() { + local output - output=$(_forgit_worktree_changes) - assert_not_contains "staged file.txt" "$output" - } + output=$(_forgit_worktree_changes) + assert_not_contains "staged file.txt" "$output" +} +function test_forgit_worktree_changes_excludes_tracked() { + local output - function test_forgit_worktree_changes_excludes_tracked() { - local output + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_not_contains "tracked file.txt" "$output" +} - assert_not_contains "tracked file.txt" "$output" - } +function test_forgit_worktree_changes_supports_backslashes() { + local output - function test_forgit_worktree_changes_supports_backslashes() { - local output + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_contains 'untracked_with_\backslash' "$output" +} - assert_contains 'untracked_with_\backslash' "$output" - } +function test_forgit_build_status_entries_uses_cwd_relative_display_paths_within_subdirectories() { + local output - function test_forgit_build_status_entries_uses_cwd_relative_display_paths_within_subdirectories() { - local output + mkdir -p dir + touch dir/file.txt + cd dir || return 1 - mkdir -p dir - touch dir/file.txt - cd dir || return 1 + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_contains "file.txt" "$output" +} - assert_contains "file.txt" "$output" - } +function test_forgit_build_status_entries_prefixes_parent_paths_for_entries_outside_cwd() { + local output - function test_forgit_build_status_entries_prefixes_parent_paths_for_entries_outside_cwd() { - local output + mkdir -p dir other + touch other/file.txt + cd dir || return 1 - mkdir -p dir other - touch other/file.txt - cd dir || return 1 + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_contains "../other/file.txt" "$output" +} - assert_contains "../other/file.txt" "$output" - } +function test_forgit_build_status_entries_keeps_repo_relative_paths_at_repo_root() { + local output - function test_forgit_build_status_entries_keeps_repo_relative_paths_at_repo_root() { - local output + mkdir -p dir + touch dir/file.txt - mkdir -p dir - touch dir/file.txt + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_contains "dir/file.txt" "$output" +} - assert_contains "dir/file.txt" "$output" - } +function test_forgit_build_status_entries_uses_cwd_relative_display_paths_for_sibling_entries() { + local output - function test_forgit_build_status_entries_uses_cwd_relative_display_paths_for_sibling_entries() { - local output + mkdir -p dir1 dir2 + touch dir1/file.txt + cd dir2 || return 1 - mkdir -p dir1 dir2 - touch dir1/file.txt - cd dir2 || return 1 + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_contains "../dir1/file.txt" "$output" +} - assert_contains "../dir1/file.txt" "$output" - } +function test_forgit_build_status_entries_uses_cwd_relative_display_paths_from_logical_symlink_paths() { + local output sandbox - function test_forgit_build_status_entries_uses_cwd_relative_display_paths_from_logical_symlink_paths() { - local output sandbox + sandbox=$(bashunit::temp_dir) + mkdir -p "$sandbox/real/dir1" "$sandbox/real/dir2" + ( + cd "$sandbox/real" || exit 1 + git init --quiet + git config user.name "Test User" + git config user.email "test@example.com" + ) || return 1 + ln -s "$sandbox/real" "$sandbox/link" + cd "$sandbox/link/dir2" || return 1 + touch ../dir1/file.txt - sandbox=$(bashunit::temp_dir) - mkdir -p "$sandbox/real/dir1" "$sandbox/real/dir2" - ( - cd "$sandbox/real" || exit 1 - git init --quiet - git config user.name "Test User" - git config user.email "test@example.com" - ) || return 1 - ln -s "$sandbox/real" "$sandbox/link" - cd "$sandbox/link/dir2" || return 1 - touch ../dir1/file.txt + output=$(_forgit_worktree_changes) - output=$(_forgit_worktree_changes) + assert_contains "../dir1/file.txt" "$output" +} - assert_contains "../dir1/file.txt" "$output" - } - - function test_forgit_worktree_changes_emits_absolute_payloads_for_subdir_entries() { +function test_forgit_worktree_changes_emits_absolute_payloads_for_subdir_entries() { local output rootdir mkdir dir @@ -148,24 +147,24 @@ FORGIT_REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) assert_contains $'with_\\backslash'"$_ffsep""$rootdir/dir/with_\\backslash" "$output" } - function test_forgit_restore_untracked_color_colorizes_plain_untracked_lines() { - local output +function test_forgit_restore_untracked_color_colorizes_plain_untracked_lines() { + local output - output=$(printf '?? plain.txt\n' | _forgit_restore_untracked_color '' '') + output=$(printf '?? plain.txt\n' | _forgit_restore_untracked_color '' '') - assert_same '?? plain.txt' "$output" - } + assert_same '?? plain.txt' "$output" +} - function test_forgit_restore_untracked_color_leaves_colored_lines_unchanged() { - local colored output +function test_forgit_restore_untracked_color_leaves_colored_lines_unchanged() { + local colored output - colored=$'\033[33m??\033[m plain.txt' - output=$(printf '%s\n' "$colored" | _forgit_restore_untracked_color '' '') + colored=$'\033[33m??\033[m plain.txt' + output=$(printf '%s\n' "$colored" | _forgit_restore_untracked_color '' '') - assert_same "$colored" "$output" - } + assert_same "$colored" "$output" +} - function test_forgit_worktree_changes_preserves_special_characters_in_payload() { +function test_forgit_worktree_changes_preserves_special_characters_in_payload() { local output path rootdir path=$'tab\t space \\ name.txt' @@ -177,28 +176,28 @@ FORGIT_REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) assert_contains "${path}${_ffsep}${rootdir}/${path}" "$output" } - function test_forgit_fzf_separator_does_not_use_literal_tabs() { +function test_forgit_fzf_separator_does_not_use_literal_tabs() { local delimiter delimiter=$_ffsep assert_not_contains $'\t' "$delimiter" - } +} - function test_forgit_worktree_changes_works_in_zsh() { - local output +function test_forgit_worktree_changes_works_in_zsh() { + local output - output=$( - zsh -c ' + output=$( + zsh -c ' source "'"$FORGIT_REPO_ROOT"'/bin/git-forgit" cd "$(mktemp -d)" || exit 1 git init --quiet touch "space name.txt" "back\\slash.txt" $'"'"'tab\tname.txt'"'"' _forgit_worktree_changes ' - ) + ) - assert_contains 'space name.txt' "$output" - assert_contains 'back\slash.txt' "$output" - assert_contains 'tab' "$output" - } + assert_contains 'space name.txt' "$output" + assert_contains 'back\slash.txt' "$output" + assert_contains 'tab' "$output" +}