Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix special characters in file names #388

Merged
merged 3 commits into from
May 12, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions bin/git-forgit
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,21 @@ _forgit_is_file_tracked() {
git ls-files "$1" --error-unmatch &> /dev/null
}

_forgit_list_files() {
local rootdir
rootdir=$(git rev-parse --show-toplevel)
# git escapes special characters in it's output when core.quotePath is
# true or unset. Git always expects unquoted file paths as input. This
# leads to issues when we consume output from git and use it to build
# input for other git commands. Use the -z flag to ensure file paths are
# unquoted.
# uniq is necessary because unmerged files are printed once for each
# merge conflict.
# With the -z flag, git also uses \0 line termination, so we
# have to replace the terminators.
git ls-files -z "$@" "$rootdir" | tr '\0' '\n' | uniq
}

_forgit_log_preview() {
local sha
sha=$(echo "$1" | _forgit_extract_sha)
Expand Down Expand Up @@ -329,13 +344,10 @@ _forgit_edit_add_file() {
# git add selector
_forgit_add() {
_forgit_inside_work_tree || return 1
local changed unmerged untracked files opts
local files opts
# Add files if passed as arguments
[[ $# -ne 0 ]] && { _forgit_git_add "$@" && git status -su; return $?; }

changed=$(git config --get-color color.status.changed red)
unmerged=$(git config --get-color color.status.unmerged red)
untracked=$(git config --get-color color.status.untracked red)
opts="
$FORGIT_FZF_DEFAULT_OPTS
-0 -m --nth 2..,..
Expand All @@ -346,8 +358,7 @@ _forgit_add() {
files=()
while IFS='' read -r file; do
files+=("$file")
done < <(git -c color.status=always -c status.relativePaths=true status -su |
grep -F -e "$changed" -e "$unmerged" -e "$untracked" |
done < <(_forgit_list_files --exclude-standard --modified --others |
sed -E 's/^(..[^[:space:]]*)[[:space:]]+(.*)$/[\1] \2/' |
FZF_DEFAULT_OPTS="$opts" fzf |
_forgit_get_single_file_from_add_line)
Expand Down Expand Up @@ -381,7 +392,7 @@ _forgit_reset_head() {
files=()
while IFS='' read -r file; do
files+=("$file")
done < <(git diff --staged --name-only | FZF_DEFAULT_OPTS="$opts" fzf)
done < <(git diff -z --staged --name-only | tr '\0' '\n' | FZF_DEFAULT_OPTS="$opts" fzf)
if [[ ${#files} -eq 0 ]]; then
echo 'Nothing to unstage.'
return 1
Expand Down Expand Up @@ -455,19 +466,18 @@ _forgit_stash_push() {
*) _forgit_git_stash_push "${args[@]}"; return $?
esac
done
local opts files rootdir
local opts files
opts="
$FORGIT_FZF_DEFAULT_OPTS
-m
--preview=\"$FORGIT stash_push_preview {}\"
$FORGIT_STASH_PUSH_FZF_OPTS
"
rootdir=$(git rev-parse --show-toplevel)
# Show both modified and untracked files
files=()
while IFS='' read -r file; do
files+=("$file")
done < <(git ls-files "$rootdir" --exclude-standard --modified --others |
done < <(_forgit_list_files --exclude-standard --modified --others |
FZF_DEFAULT_OPTS="$opts" fzf --exit-0)
[[ "${#files[@]}" -eq 0 ]] && echo "Nothing to stash" && return 1
_forgit_git_stash_push ${msg:+-m "$msg"} -u "${files[@]}"
Expand Down Expand Up @@ -497,7 +507,7 @@ _forgit_clean() {
$FORGIT_CLEAN_FZF_OPTS
"
# Note: Postfix '/' in directory path should be removed. Otherwise the directory itself will not be removed.
files=$(git clean -xdffn "$@"| sed 's/^Would remove //' | FZF_DEFAULT_OPTS="$opts" fzf |sed 's#/$##')
files=$(git -c core.quotePath=false clean -xdffn "$@"| sed 's/^Would remove //' | FZF_DEFAULT_OPTS="$opts" fzf |sed 's#/$##')
[[ -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.'
}
Expand Down Expand Up @@ -675,7 +685,7 @@ _forgit_checkout_file() {
files=()
while IFS='' read -r file; do
files+=("$file")
done < <(git ls-files --modified "$(git rev-parse --show-toplevel)" |
done < <(_forgit_list_files --modified |
FZF_DEFAULT_OPTS="$opts" fzf)
[[ "${#files[@]}" -gt 0 ]] && _forgit_git_checkout_file "${files[@]}"
}
Expand Down