summaryrefslogtreecommitdiff
path: root/mergetools
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2022-07-14 14:31:03 (GMT)
committerJunio C Hamano <gitster@pobox.com>2022-07-14 17:37:44 (GMT)
commitccc7b5148bdd9deb33f3cfa5a872a74634105021 (patch)
treee9f0a5c16b0e6da1020cbfa515f4a4b83bd1d818 /mergetools
parent980145f7470e20826ca22d7343494712eda9c81d (diff)
downloadgit-ccc7b5148bdd9deb33f3cfa5a872a74634105021.zip
git-ccc7b5148bdd9deb33f3cfa5a872a74634105021.tar.gz
git-ccc7b5148bdd9deb33f3cfa5a872a74634105021.tar.bz2
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 'mergetools')
-rw-r--r--mergetools/vimdiff39
1 files changed, 35 insertions, 4 deletions
diff --git a/mergetools/vimdiff b/mergetools/vimdiff
index 461a89b..f7e7f27 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