From 8827b3a8873ebfad79b324d6134c1ec4bbea5f06 Mon Sep 17 00:00:00 2001 From: David Aguilar Date: Fri, 7 Oct 2016 16:58:03 -0700 Subject: [PATCH 1/4] mergetool: add copyright Signed-off-by: David Aguilar Reviewed-by: Johannes Sixt Signed-off-by: Junio C Hamano --- git-mergetool.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/git-mergetool.sh b/git-mergetool.sh index bf862705d8..300ce7f675 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -3,6 +3,7 @@ # This program resolves merge conflicts in git # # Copyright (c) 2006 Theodore Y. Ts'o +# Copyright (c) 2009-2016 David Aguilar # # This file is licensed under the GPL v2, or a later version # at the discretion of Junio C Hamano. From 08221e3fa27396aca30cb539f006f78636782951 Mon Sep 17 00:00:00 2001 From: David Aguilar Date: Fri, 7 Oct 2016 16:58:04 -0700 Subject: [PATCH 2/4] mergetool: move main program flow into a main() function Make it easier to follow the program's flow by isolating all logic into functions. Isolate the main execution code path into a single unit instead of having prompt_after_failed_merge() interrupt it partyway through. The use of a main() function is borrowing a convention from C, Python, Perl, and many other languages. This helps readers more familiar with other languages understand the purpose of each function when diving into the codebase with fresh eyes. Signed-off-by: David Aguilar Reviewed-by: Johannes Sixt Signed-off-by: Junio C Hamano --- git-mergetool.sh | 178 ++++++++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 86 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 300ce7f675..b2cd0a497b 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -366,51 +366,6 @@ merge_file () { return 0 } -prompt=$(git config --bool mergetool.prompt) -guessed_merge_tool=false - -while test $# != 0 -do - case "$1" in - --tool-help=*) - TOOL_MODE=${1#--tool-help=} - show_tool_help - ;; - --tool-help) - show_tool_help - ;; - -t|--tool*) - case "$#,$1" in - *,*=*) - merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') - ;; - 1,*) - usage ;; - *) - merge_tool="$2" - shift ;; - esac - ;; - -y|--no-prompt) - prompt=false - ;; - --prompt) - prompt=true - ;; - --) - shift - break - ;; - -*) - usage - ;; - *) - break - ;; - esac - shift -done - prompt_after_failed_merge () { while true do @@ -427,57 +382,108 @@ prompt_after_failed_merge () { done } -git_dir_init -require_work_tree +main () { + prompt=$(git config --bool mergetool.prompt) + guessed_merge_tool=false + + while test $# != 0 + do + case "$1" in + --tool-help=*) + TOOL_MODE=${1#--tool-help=} + show_tool_help + ;; + --tool-help) + show_tool_help + ;; + -t|--tool*) + case "$#,$1" in + *,*=*) + merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') + ;; + 1,*) + usage ;; + *) + merge_tool="$2" + shift ;; + esac + ;; + -y|--no-prompt) + prompt=false + ;; + --prompt) + prompt=true + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + git_dir_init + require_work_tree -if test -z "$merge_tool" -then - # Check if a merge tool has been configured - merge_tool=$(get_configured_merge_tool) - # Try to guess an appropriate merge tool if no tool has been set. if test -z "$merge_tool" then - merge_tool=$(guess_merge_tool) || exit - guessed_merge_tool=true + # Check if a merge tool has been configured + merge_tool=$(get_configured_merge_tool) + # Try to guess an appropriate merge tool if no tool has been set. + if test -z "$merge_tool" + then + merge_tool=$(guess_merge_tool) || exit + guessed_merge_tool=true + fi fi -fi -merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" -merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" + merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" + merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" -files= + files= -if test $# -eq 0 -then - cd_to_toplevel - - if test -e "$GIT_DIR/MERGE_RR" + if test $# -eq 0 then - files=$(git rerere remaining) + cd_to_toplevel + + if test -e "$GIT_DIR/MERGE_RR" + then + files=$(git rerere remaining) + else + files=$(git ls-files -u | + sed -e 's/^[^ ]* //' | sort -u) + fi else - files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u) + files=$(git ls-files -u -- "$@" | + sed -e 's/^[^ ]* //' | sort -u) fi -else - files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u) -fi -if test -z "$files" -then - echo "No files need merging" - exit 0 -fi - -printf "Merging:\n" -printf "%s\n" "$files" - -rc=0 -for i in $files -do - printf "\n" - if ! merge_file "$i" + if test -z "$files" then - rc=1 - prompt_after_failed_merge || exit 1 + echo "No files need merging" + exit 0 fi -done -exit $rc + printf "Merging:\n" + printf "%s\n" "$files" + + rc=0 + for i in $files + do + printf "\n" + if ! merge_file "$i" + then + rc=1 + prompt_after_failed_merge || exit 1 + fi + done + + exit $rc +} + +main "$@" From 57937f70a09c12ef484c290865dac4066d207c9c Mon Sep 17 00:00:00 2001 From: David Aguilar Date: Fri, 7 Oct 2016 16:58:05 -0700 Subject: [PATCH 3/4] mergetool: honor diff.orderFile Teach mergetool to get the list of files to edit via `diff` so that we gain support for diff.orderFile. Suggested-by: Luis Gutierrez Helped-by: Johannes Sixt Signed-off-by: David Aguilar Reviewed-by: Johannes Sixt Signed-off-by: Junio C Hamano --- Documentation/git-mergetool.txt | 5 +++++ git-mergetool.sh | 30 +++++++++++++++--------------- t/t7610-mergetool.sh | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index e846c2ed7f..c4c1a9bde4 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -79,6 +79,11 @@ success of the resolution after the custom tool has exited. Prompt before each invocation of the merge resolution program to give the user a chance to skip the path. +DIFF ORDER FILES +---------------- +`git mergetool` honors the `diff.orderFile` configuration variable +used by `git diff`. See linkgit:git-config[1] for more details. + TEMPORARY FILES --------------- `git mergetool` creates `*.orig` backup files while resolving merges. diff --git a/git-mergetool.sh b/git-mergetool.sh index b2cd0a497b..65696d8382 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -382,6 +382,11 @@ prompt_after_failed_merge () { done } +print_noop_and_exit () { + echo "No files need merging" + exit 0 +} + main () { prompt=$(git config --bool mergetool.prompt) guessed_merge_tool=false @@ -445,28 +450,23 @@ main () { merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" - files= - - if test $# -eq 0 + if test $# -eq 0 && test -e "$GIT_DIR/MERGE_RR" then - cd_to_toplevel - - if test -e "$GIT_DIR/MERGE_RR" + set -- $(git rerere remaining) + if test $# -eq 0 then - files=$(git rerere remaining) - else - files=$(git ls-files -u | - sed -e 's/^[^ ]* //' | sort -u) + print_noop_and_exit fi - else - files=$(git ls-files -u -- "$@" | - sed -e 's/^[^ ]* //' | sort -u) fi + files=$(git -c core.quotePath=false \ + diff --name-only --diff-filter=U -- "$@") + + cd_to_toplevel + if test -z "$files" then - echo "No files need merging" - exit 0 + print_noop_and_exit fi printf "Merging:\n" diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 7217f3968d..38c1e4de71 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -606,4 +606,37 @@ test_expect_success MKTEMP 'temporary filenames are used with mergetool.writeToT git reset --hard master >/dev/null 2>&1 ' +test_expect_success 'diff.orderFile configuration is honored' ' + test_config diff.orderFile order-file && + test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" && + test_config mergetool.myecho.trustExitCode true && + echo b >order-file && + echo a >>order-file && + git checkout -b order-file-start master && + echo start >a && + echo start >b && + git add a b && + git commit -m start && + git checkout -b order-file-side1 order-file-start && + echo side1 >a && + echo side1 >b && + git add a b && + git commit -m side1 && + git checkout -b order-file-side2 order-file-start && + echo side2 >a && + echo side2 >b && + git add a b && + git commit -m side2 && + test_must_fail git merge order-file-side1 && + cat >expect <<-\EOF && + Merging: + b + a + EOF + git mergetool --no-prompt --tool myecho >output && + git grep --no-index -h -A2 Merging: output >actual && + test_cmp expect actual && + git reset --hard >/dev/null +' + test_done From 654311bf6ee0fbf530c088271c2c76d46f31f82d Mon Sep 17 00:00:00 2001 From: David Aguilar Date: Fri, 7 Oct 2016 17:01:30 -0700 Subject: [PATCH 4/4] mergetool: honor -O Teach mergetool to pass "-O" down to `git diff` when specified on the command-line. Helped-by: Johannes Sixt Signed-off-by: David Aguilar Reviewed-by: Johannes Sixt Signed-off-by: Junio C Hamano --- Documentation/git-mergetool.txt | 10 ++++++---- git-mergetool.sh | 9 +++++++-- t/t7610-mergetool.sh | 27 +++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index c4c1a9bde4..3622d66488 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -79,10 +79,12 @@ success of the resolution after the custom tool has exited. Prompt before each invocation of the merge resolution program to give the user a chance to skip the path. -DIFF ORDER FILES ----------------- -`git mergetool` honors the `diff.orderFile` configuration variable -used by `git diff`. See linkgit:git-config[1] for more details. +-O:: + Process files in the order specified in the + , which has one shell glob pattern per line. + This overrides the `diff.orderFile` configuration variable + (see linkgit:git-config[1]). To cancel `diff.orderFile`, + use `-O/dev/null`. TEMPORARY FILES --------------- diff --git a/git-mergetool.sh b/git-mergetool.sh index 65696d8382..e52b4e4f24 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -9,7 +9,7 @@ # at the discretion of Junio C Hamano. # -USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [file to merge] ...' +USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [-O] [file to merge] ...' SUBDIRECTORY_OK=Yes NONGIT_OK=Yes OPTIONS_SPEC= @@ -390,6 +390,7 @@ print_noop_and_exit () { main () { prompt=$(git config --bool mergetool.prompt) guessed_merge_tool=false + orderfile= while test $# != 0 do @@ -419,6 +420,9 @@ main () { --prompt) prompt=true ;; + -O*) + orderfile="$1" + ;; --) shift break @@ -460,7 +464,8 @@ main () { fi files=$(git -c core.quotePath=false \ - diff --name-only --diff-filter=U -- "$@") + diff --name-only --diff-filter=U \ + ${orderfile:+"$orderfile"} -- "$@") cd_to_toplevel diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 38c1e4de71..6d9f21511f 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -638,5 +638,32 @@ test_expect_success 'diff.orderFile configuration is honored' ' test_cmp expect actual && git reset --hard >/dev/null ' +test_expect_success 'mergetool -Oorder-file is honored' ' + test_config diff.orderFile order-file && + test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" && + test_config mergetool.myecho.trustExitCode true && + test_must_fail git merge order-file-side1 && + cat >expect <<-\EOF && + Merging: + a + b + EOF + git mergetool -O/dev/null --no-prompt --tool myecho >output && + git grep --no-index -h -A2 Merging: output >actual && + test_cmp expect actual && + git reset --hard >/dev/null 2>&1 && + + git config --unset diff.orderFile && + test_must_fail git merge order-file-side1 && + cat >expect <<-\EOF && + Merging: + b + a + EOF + git mergetool -Oorder-file --no-prompt --tool myecho >output && + git grep --no-index -h -A2 Merging: output >actual && + test_cmp expect actual && + git reset --hard >/dev/null 2>&1 +' test_done