Merge branch 'da/mergetool-diff-order'
authorJunio C Hamano <gitster@pobox.com>
Mon, 17 Oct 2016 20:25:21 +0000 (13:25 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Oct 2016 20:25:21 +0000 (13:25 -0700)
"git mergetool" learned to honor "-O<orderfile>" to control the
order of paths to present to the end user.

* da/mergetool-diff-order:
mergetool: honor -O<orderfile>
mergetool: honor diff.orderFile
mergetool: move main program flow into a main() function
mergetool: add copyright

Documentation/git-mergetool.txt
git-mergetool.sh
t/t7610-mergetool.sh
index e846c2ed7f7f862f5324c0e95a2b17dabcaac58d..3622d66488c7de057d32e02cd4cfd21704500822 100644 (file)
@@ -79,6 +79,13 @@ 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.
 
+-O<orderfile>::
+       Process files in the order specified in the
+       <orderfile>, 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
 ---------------
 `git mergetool` creates `*.orig` backup files while resolving merges.
index bf862705d8c654a5dd58ec70d6781583b7dbefc3..e52b4e4f24088d7552d88aa5a3c9ffc308f6a4cf 100755 (executable)
@@ -3,12 +3,13 @@
 # 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.
 #
 
-USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [file to merge] ...'
+USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [-O<orderfile>] [file to merge] ...'
 SUBDIRECTORY_OK=Yes
 NONGIT_OK=Yes
 OPTIONS_SPEC=
@@ -365,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
@@ -426,57 +382,113 @@ prompt_after_failed_merge () {
        done
 }
 
-git_dir_init
-require_work_tree
+print_noop_and_exit () {
+       echo "No files need merging"
+       exit 0
+}
+
+main () {
+       prompt=$(git config --bool mergetool.prompt)
+       guessed_merge_tool=false
+       orderfile=
+
+       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
+                       ;;
+               -O*)
+                       orderfile="$1"
+                       ;;
+               --)
+                       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
+       merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
+       merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
+
+       if test $# -eq 0 && test -e "$GIT_DIR/MERGE_RR"
+       then
+               set -- $(git rerere remaining)
+               if test $# -eq 0
+               then
+                       print_noop_and_exit
+               fi
        fi
-fi
-merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
-merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
 
-files=
+       files=$(git -c core.quotePath=false \
+               diff --name-only --diff-filter=U \
+               ${orderfile:+"$orderfile"} -- "$@")
 
-if test $# -eq 0
-then
        cd_to_toplevel
 
-       if test -e "$GIT_DIR/MERGE_RR"
+       if test -z "$files"
        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
 
-if test -z "$files"
-then
-       echo "No files need merging"
-       exit 0
-fi
+       printf "Merging:\n"
+       printf "%s\n" "$files"
 
-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
 
-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
+}
 
-exit $rc
+main "$@"
index 7217f3968d51d9061b14bd46c473329b26bb087c..6d9f21511fe1062565d8d08f60c385cffd94cac6 100755 (executable)
@@ -606,4 +606,64 @@ 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_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