diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2022-07-14 16:31:03 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2022-07-14 19:37:44 +0200 |
commit | ccc7b5148bdd9deb33f3cfa5a872a74634105021 (patch) | |
tree | e9f0a5c16b0e6da1020cbfa515f4a4b83bd1d818 /mergetools/vimdiff | |
parent | mergetools: add description to all diff/merge tools (diff) | |
download | git-ccc7b5148bdd9deb33f3cfa5a872a74634105021.tar.xz git-ccc7b5148bdd9deb33f3cfa5a872a74634105021.zip |
mergetool(vimdiff): allow paths to contain spaces again
In 0041797449d (vimdiff: new implementation with layout support,
2022-03-30), we introduced a completely new implementation of the
`vimdiff` backend for `git mergetool`.
In this implementation, we no longer call `vim` directly but we
accumulate in the variable `FINAL_CMD` an arbitrary number of commands
for `vim` to execute, which necessitates the use of `eval` to split the
commands properly into multiple command-line arguments.
That same `eval` command also needs to pass the paths to `vim`, and
while it looks as if they are quoted correctly, that quoting only
reaches the `eval` instruction and is lost after that, therefore paths
that contain whitespace characters (or other characters that are
interpreted by the POSIX shell) are handled incorrectly.
This is a simple reproducer:
git init -b main bam-merge-fail
cd bam-merge-fail
echo a>"a file.txt"
git add "a file.txt"
git commit -m "added 'a file.txt'"
echo b>"a file.txt"
git add "a file.txt"
git commit -m "diverged b 'a file.txt'"
git checkout -b c HEAD~
echo c>"a file.txt"
git add "a file.txt"
git commit -m "diverged c 'a file.txt'"
git checkout main
git merge c
git mergetool --tool=vimdiff
With Git v2.37.0/v2.37.1, this will open 7 buffers, not four, and not
display the correct contents at all.
To fix this, let's not expand the variables containing the path
parameters before passing them to the `eval` command, but let that
command expand the variables instead.
This fixes https://github.com/git-for-windows/git/issues/3945
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to '')
-rw-r--r-- | mergetools/vimdiff | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/mergetools/vimdiff b/mergetools/vimdiff index 461a89b6f9..f7e7f27028 100644 --- a/mergetools/vimdiff +++ b/mergetools/vimdiff @@ -414,8 +414,8 @@ merge_cmd () { if $base_present then - eval "$merge_tool_path" \ - -f "$FINAL_CMD" "$LOCAL" "$BASE" "$REMOTE" "$MERGED" + eval '"$merge_tool_path"' \ + -f "$FINAL_CMD" '"$LOCAL"' '"$BASE"' '"$REMOTE"' '"$MERGED"' else # If there is no BASE (example: a merge conflict in a new file # with the same name created in both braches which didn't exist @@ -424,8 +424,8 @@ merge_cmd () { FINAL_CMD=$(echo "$FINAL_CMD" | \ sed -e 's:2b:quit:g' -e 's:3b:2b:g' -e 's:4b:3b:g') - eval "$merge_tool_path" \ - -f "$FINAL_CMD" "$LOCAL" "$REMOTE" "$MERGED" + eval '"$merge_tool_path"' \ + -f "$FINAL_CMD" '"$LOCAL"' '"$REMOTE"' '"$MERGED"' fi ret="$?" @@ -614,6 +614,37 @@ run_unit_tests () { fi done + # verify that `merge_cmd` handles paths with spaces + record_parameters () { + >actual + for arg + do + echo "$arg" >>actual + done + } + + base_present=false + LOCAL='lo cal' + BASE='ba se' + REMOTE="' '" + MERGED='mer ged' + merge_tool_path=record_parameters + + merge_cmd vimdiff || at_least_one_ko=true + + cat >expect <<-\EOF + -f + -c + echo | split | vertical split | 1b | wincmd l | vertical split | quit | wincmd l | 2b | wincmd j | 3b | tabdo windo diffthis + -c + tabfirst + lo cal + ' ' + mer ged + EOF + + diff -u expect actual || at_least_one_ko=true + if test "$at_least_one_ko" = "true" then return 255 |