Merge branch 'cb/mergetool'
authorJunio C Hamano <gitster@pobox.com>
Thu, 1 Jan 2009 13:48:40 +0000 (05:48 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 1 Jan 2009 13:48:40 +0000 (05:48 -0800)
* cb/mergetool:
mergetool: Don't keep temporary merge files unless told to
mergetool: Add prompt to continue after failing to merge a file
Add -y/--no-prompt option to mergetool
Fix some tab/space inconsistencies in git-mergetool.sh

1  2 
Documentation/config.txt
Documentation/git-mergetool.txt
git-mergetool.sh
diff --combined Documentation/config.txt
index 52786c7df5eb902cf97fee165ceb25e3c4763e9e,3d5a8df0cf8e46256353b8884bc3c7a745560467..7408bb2d34441dede61718e5d77dd08e26de3731
@@@ -413,15 -413,6 +413,15 @@@ data writes properly, but can be usefu
  journalling (traditional UNIX filesystems) or that only journal metadata
  and not file contents (OS X's HFS+, or Linux ext3 with "data=writeback").
  
 +core.preloadindex::
 +      Enable parallel index preload for operations like 'git diff'
 ++
 +This can speed up operations like 'git diff' and 'git status' especially
 +on filesystems like NFS that have weak caching semantics and thus
 +relatively high IO latencies.  With this set to 'true', git will do the
 +index comparison to the filesystem data in parallel, allowing
 +overlapping IO's.
 +
  alias.*::
        Command aliases for the linkgit:git[1] command wrapper - e.g.
        after defining "alias.last = cat-file commit HEAD", the invocation
@@@ -581,6 -572,9 +581,6 @@@ color.status.<slot>:
        to red). The values of these variables may be specified as in
        color.branch.<slot>.
  
 -commit.template::
 -      Specify a file to use as the template for new commit messages.
 -
  color.ui::
        When set to `always`, always use colors in all git commands which
        are capable of colored output. When false (or `never`), never. When
        terminal. When more specific variables of color.* are set, they always
        take precedence over this setting. Defaults to false.
  
 +commit.template::
 +      Specify a file to use as the template for new commit messages.
 +
  diff.autorefreshindex::
        When using 'git-diff' to compare with work tree
        files, do not consider stat-only change as changed.
        affects only 'git-diff' Porcelain, and not lower level
        'diff' commands, such as 'git-diff-files'.
  
 -diff.suppress-blank-empty::
 -      A boolean to inhibit the standard behavior of printing a space
 -      before each empty output line. Defaults to false.
 -
  diff.external::
        If this config variable is set, diff generation is not
        performed using the internal diff machinery, but using the
@@@ -635,10 -630,6 +635,10 @@@ diff.renames:
        will enable basic rename detection.  If set to "copies" or
        "copy", it will detect copies, as well.
  
 +diff.suppress-blank-empty::
 +      A boolean to inhibit the standard behavior of printing a space
 +      before each empty output line. Defaults to false.
 +
  fetch.unpackLimit::
        If the number of objects fetched over the git native
        transfer is below this
@@@ -723,6 -714,18 +723,6 @@@ gc.rerereunresolved:
        kept for this many days when 'git-rerere gc' is run.
        The default is 15 days.  See linkgit:git-rerere[1].
  
 -rerere.autoupdate::
 -      When set to true, `git-rerere` updates the index with the
 -      resulting contents after it cleanly resolves conflicts using
 -      previously recorded resolution.  Defaults to false.
 -
 -rerere.enabled::
 -      Activate recording of resolved conflicts, so that identical
 -      conflict hunks can be resolved automatically, should they
 -      be encountered again.  linkgit:git-rerere[1] command is by
 -      default enabled if you create `rr-cache` directory under
 -      `$GIT_DIR`, but can be disabled by setting this option to false.
 -
  gitcvs.enabled::
        Whether the CVS server interface is enabled for this repository.
        See linkgit:git-cvsserver[1].
@@@ -793,14 -796,6 +793,14 @@@ gui.diffcontext:
        Specifies how many context lines should be used in calls to diff
        made by the linkgit:git-gui[1]. The default is "5".
  
 +gui.encoding::
 +      Specifies the default encoding to use for displaying of
 +      file contents in linkgit:git-gui[1] and linkgit:gitk[1].
 +      It can be overridden by setting the 'encoding' attribute
 +      for relevant files (see linkgit:gitattributes[5]).
 +      If this option is not set, the tools default to the
 +      locale encoding.
 +
  gui.matchtrackingbranch::
        Determines if new branches created with linkgit:git-gui[1] should
        default to tracking remote branches with matching names or
@@@ -823,73 -818,6 +823,73 @@@ gui.spellingdictionary:
        the linkgit:git-gui[1]. When set to "none" spell checking is turned
        off.
  
 +gui.fastcopyblame::
 +      If true, 'git gui blame' uses '-C' instead of '-C -C' for original
 +      location detection. It makes blame significantly faster on huge
 +      repositories at the expense of less thorough copy detection.
 +
 +gui.copyblamethreshold::
 +      Specifies the threshold to use in 'git gui blame' original location
 +      detection, measured in alphanumeric characters. See the
 +      linkgit:git-blame[1] manual for more information on copy detection.
 +
 +gui.blamehistoryctx::
 +      Specifies the radius of history context in days to show in
 +      linkgit:gitk[1] for the selected commit, when the `Show History
 +      Context` menu item is invoked from 'git gui blame'. If this
 +      variable is set to zero, the whole history is shown.
 +
 +guitool.<name>.cmd::
 +      Specifies the shell command line to execute when the corresponding item
 +      of the linkgit:git-gui[1] `Tools` menu is invoked. This option is
 +      mandatory for every tool. The command is executed from the root of
 +      the working directory, and in the environment it receives the name of
 +      the tool as 'GIT_GUITOOL', the name of the currently selected file as
 +      'FILENAME', and the name of the current branch as 'CUR_BRANCH' (if
 +      the head is detached, 'CUR_BRANCH' is empty).
 +
 +guitool.<name>.needsfile::
 +      Run the tool only if a diff is selected in the GUI. It guarantees
 +      that 'FILENAME' is not empty.
 +
 +guitool.<name>.noconsole::
 +      Run the command silently, without creating a window to display its
 +      output.
 +
 +guitool.<name>.norescan::
 +      Don't rescan the working directory for changes after the tool
 +      finishes execution.
 +
 +guitool.<name>.confirm::
 +      Show a confirmation dialog before actually running the tool.
 +
 +guitool.<name>.argprompt::
 +      Request a string argument from the user, and pass it to the tool
 +      through the 'ARGS' environment variable. Since requesting an
 +      argument implies confirmation, the 'confirm' option has no effect
 +      if this is enabled. If the option is set to 'true', 'yes', or '1',
 +      the dialog uses a built-in generic prompt; otherwise the exact
 +      value of the variable is used.
 +
 +guitool.<name>.revprompt::
 +      Request a single valid revision from the user, and set the
 +      'REVISION' environment variable. In other aspects this option
 +      is similar to 'argprompt', and can be used together with it.
 +
 +guitool.<name>.revunmerged::
 +      Show only unmerged branches in the 'revprompt' subdialog.
 +      This is useful for tools similar to merge or rebase, but not
 +      for things like checkout or reset.
 +
 +guitool.<name>.title::
 +      Specifies the title to use for the prompt dialog. The default
 +      is the tool name.
 +
 +guitool.<name>.prompt::
 +      Specifies the general prompt string to display at the top of
 +      the dialog, before subsections for 'argprompt' and 'revprompt'.
 +      The default value includes the actual command.
 +
  help.browser::
        Specify the browser that will be used to display help in the
        'web' format. See linkgit:git-help[1].
@@@ -965,10 -893,6 +965,10 @@@ i18n.logOutputEncoding:
        Character encoding the commit messages are converted to when
        running 'git-log' and friends.
  
 +imap::
 +      The configuration variables in the 'imap' section are described
 +      in linkgit:git-imap-send[1].
 +
  instaweb.browser::
        Specify the program that will be used to browse your working
        repository in gitweb. See linkgit:git-instaweb[1].
@@@ -1004,6 -928,8 +1004,6 @@@ man.viewer:
        Specify the programs that may be used to display help in the
        'man' format. See linkgit:git-help[1].
  
 -include::merge-config.txt[]
 -
  man.<tool>.cmd::
        Specify the command to invoke the specified man viewer. The
        specified command is evaluated in shell with the man page
@@@ -1013,7 -939,13 +1013,7 @@@ man.<tool>.path:
        Override the path for the given tool that may be used to
        display help in the 'man' format. See linkgit:git-help[1].
  
 -merge.conflictstyle::
 -      Specify the style in which conflicted hunks are written out to
 -      working tree files upon merge.  The default is "merge", which
 -      shows `<<<<<<<` conflict marker, change made by one side,
 -      `=======` marker, change made by the other side, and then
 -      `>>>>>>>` marker.  An alternate style, "diff3", adds `|||||||`
 -      marker and the original text before `=======` marker.
 +include::merge-config.txt[]
  
  mergetool.<tool>.path::
        Override the path for the given tool.  This is useful in case
@@@ -1044,6 -976,16 +1044,16 @@@ mergetool.keepBackup:
        is set to `false` then this file is not preserved.  Defaults to
        `true` (i.e. keep the backup files).
  
+ mergetool.keepTemporaries::
+       When invoking a custom merge tool, git uses a set of temporary
+       files to pass to the tool. If the tool returns an error and this
+       variable is set to `true`, then these temporary files will be
+       preserved, otherwise they will be removed after the tool has
+       exited. Defaults to `false`.
+ mergetool.prompt::
+       Prompt before each invocation of the merge resolution program.
  pack.window::
        The size of the window used by linkgit:git-pack-objects[1] when no
        window size is given on the command line. Defaults to 10.
@@@ -1123,41 -1065,6 +1133,41 @@@ pull.octopus:
  pull.twohead::
        The default merge strategy to use when pulling a single branch.
  
 +receive.fsckObjects::
 +      If it is set to true, git-receive-pack will check all received
 +      objects. It will abort in the case of a malformed object or a
 +      broken link. The result of an abort are only dangling objects.
 +      Defaults to false.
 +
 +receive.unpackLimit::
 +      If the number of objects received in a push is below this
 +      limit then the objects will be unpacked into loose object
 +      files. However if the number of received objects equals or
 +      exceeds this limit then the received pack will be stored as
 +      a pack, after adding any missing delta bases.  Storing the
 +      pack from a push can make the push operation complete faster,
 +      especially on slow filesystems.  If not set, the value of
 +      `transfer.unpackLimit` is used instead.
 +
 +receive.denyDeletes::
 +      If set to true, git-receive-pack will deny a ref update that deletes
 +      the ref. Use this to prevent such a ref deletion via a push.
 +
 +receive.denyCurrentBranch::
 +      If set to true or "refuse", receive-pack will deny a ref update
 +      to the currently checked out branch of a non-bare repository.
 +      Such a push is potentially dangerous because it brings the HEAD
 +      out of sync with the index and working tree. If set to "warn",
 +      print a warning of such a push to stderr, but allow the push to
 +      proceed. If set to false or "ignore", allow such pushes with no
 +      message. Defaults to "warn".
 +
 +receive.denyNonFastForwards::
 +      If set to true, git-receive-pack will deny a ref update which is
 +      not a fast forward. Use this to prevent such an update via a push,
 +      even if that push is forced. This configuration variable is
 +      set when initializing a shared repository.
 +
  remote.<name>.url::
        The URL of a remote repository.  See linkgit:git-fetch[1] or
        linkgit:git-push[1].
@@@ -1207,18 -1114,6 +1217,18 @@@ repack.usedeltabaseoffset:
        "false" and repack. Access from old git versions over the
        native protocol are unaffected by this option.
  
 +rerere.autoupdate::
 +      When set to true, `git-rerere` updates the index with the
 +      resulting contents after it cleanly resolves conflicts using
 +      previously recorded resolution.  Defaults to false.
 +
 +rerere.enabled::
 +      Activate recording of resolved conflicts, so that identical
 +      conflict hunks can be resolved automatically, should they
 +      be encountered again.  linkgit:git-rerere[1] command is by
 +      default enabled if you create `rr-cache` directory under
 +      `$GIT_DIR`, but can be disabled by setting this option to false.
 +
  showbranch.default::
        The default set of branches for linkgit:git-show-branch[1].
        See linkgit:git-show-branch[1].
@@@ -1255,11 -1150,6 +1265,11 @@@ tar.umask:
        archiving user's umask will be used instead.  See umask(2) and
        linkgit:git-archive[1].
  
 +transfer.unpackLimit::
 +      When `fetch.unpackLimit` or `receive.unpackLimit` are
 +      not set, the value of this variable is used instead.
 +      The default value is 100.
 +
  url.<base>.insteadOf::
        Any URL that starts with this value will be rewritten to
        start, instead, with <base>. In cases where some site serves a
@@@ -1288,6 -1178,50 +1298,6 @@@ user.signingkey:
        unchanged to gpg's --local-user parameter, so you may specify a key
        using any method that gpg supports.
  
 -imap::
 -      The configuration variables in the 'imap' section are described
 -      in linkgit:git-imap-send[1].
 -
 -receive.fsckObjects::
 -      If it is set to true, git-receive-pack will check all received
 -      objects. It will abort in the case of a malformed object or a
 -      broken link. The result of an abort are only dangling objects.
 -      Defaults to false.
 -
 -receive.unpackLimit::
 -      If the number of objects received in a push is below this
 -      limit then the objects will be unpacked into loose object
 -      files. However if the number of received objects equals or
 -      exceeds this limit then the received pack will be stored as
 -      a pack, after adding any missing delta bases.  Storing the
 -      pack from a push can make the push operation complete faster,
 -      especially on slow filesystems.  If not set, the value of
 -      `transfer.unpackLimit` is used instead.
 -
 -receive.denyDeletes::
 -      If set to true, git-receive-pack will deny a ref update that deletes
 -      the ref. Use this to prevent such a ref deletion via a push.
 -
 -receive.denyNonFastForwards::
 -      If set to true, git-receive-pack will deny a ref update which is
 -      not a fast forward. Use this to prevent such an update via a push,
 -      even if that push is forced. This configuration variable is
 -      set when initializing a shared repository.
 -
 -receive.denyCurrentBranch::
 -      If set to true or "refuse", receive-pack will deny a ref update
 -      to the currently checked out branch of a non-bare repository.
 -      Such a push is potentially dangerous because it brings the HEAD
 -      out of sync with the index and working tree. If set to "warn",
 -      print a warning of such a push to stderr, but allow the push to
 -      proceed. If set to false or "ignore", allow such pushes with no
 -      message. Defaults to "warn".
 -
 -transfer.unpackLimit::
 -      When `fetch.unpackLimit` or `receive.unpackLimit` are
 -      not set, the value of this variable is used instead.
 -      The default value is 100.
 -
  web.browser::
        Specify a web browser that may be used by some commands.
        Currently only linkgit:git-instaweb[1] and linkgit:git-help[1]
index 602e7c6d3b497aa4f891915305d507ae88910a54,176483a1ae19fb39550d1c24edf444943c12c12e..4c0ffec507185dfe1e88683e1a23066089571d2c
@@@ -7,7 -7,7 +7,7 @@@ git-mergetool - Run merge conflict reso
  
  SYNOPSIS
  --------
- 'git mergetool' [--tool=<tool>] [<file>]...
+ 'git mergetool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<file>]...
  
  DESCRIPTION
  -----------
@@@ -38,7 -38,7 +38,7 @@@ can configure the absolute path to kdif
  `mergetool.kdiff3.path`. Otherwise, 'git-mergetool' assumes the
  tool is available in PATH.
  +
 -Instead of running one of the known merge tool programs
 +Instead of running one of the known merge tool programs,
  'git-mergetool' can be customized to run an alternative program
  by specifying the command line to invoke in a configuration
  variable `mergetool.<tool>.cmd`.
@@@ -55,11 -55,20 +55,20 @@@ of the file to which the merge tool sho
  merge resolution.
  +
  If the custom merge tool correctly indicates the success of a
 -merge resolution with its exit code then the configuration
 +merge resolution with its exit code, then the configuration
  variable `mergetool.<tool>.trustExitCode` can be set to `true`.
  Otherwise, 'git-mergetool' will prompt the user to indicate the
  success of the resolution after the custom tool has exited.
  
+ -y or --no-prompt::
+       Don't prompt before each invocation of the merge resolution
+       program.
+ --prompt::
+       Prompt before each invocation of the merge resolution program.
+       This is the default behaviour; the option is provided to
+       override any configuration settings.
  Author
  ------
  Written by Theodore Y Ts'o <tytso@mit.edu>
diff --combined git-mergetool.sh
index d4078a6affd9b4c1fa52e6dba0fe6c151fa452dc,f04240dacaba88bfdac49b0e6e14047b1008a956..b2d53752ae49ff2c8323836e2907de584cb1e979
@@@ -8,7 -8,7 +8,7 @@@
  # at the discretion of Junio C Hamano.
  #
  
- USAGE='[--tool=tool] [file to merge] ...'
+ USAGE='[--tool=tool] [-y|--no-prompt|--prompt] [file to merge] ...'
  SUBDIRECTORY_OK=Yes
  OPTIONS_SPEC=
  . git-sh-setup
@@@ -70,16 -70,16 +70,16 @@@ resolve_symlink_merge () 
                git checkout-index -f --stage=2 -- "$MERGED"
                git add -- "$MERGED"
                cleanup_temp_files --save-backup
-               return
+               return 0
                ;;
            [rR]*)
                git checkout-index -f --stage=3 -- "$MERGED"
                git add -- "$MERGED"
                cleanup_temp_files --save-backup
-               return
+               return 0
                ;;
            [aA]*)
-               exit 1
+               return 1
                ;;
            esac
        done
@@@ -97,15 -97,15 +97,15 @@@ resolve_deleted_merge () 
            [mMcC]*)
                git add -- "$MERGED"
                cleanup_temp_files --save-backup
-               return
+               return 0
                ;;
            [dD]*)
                git rm -- "$MERGED" > /dev/null
                cleanup_temp_files
-               return
+               return 0
                ;;
            [aA]*)
-               exit 1
+               return 1
                ;;
            esac
        done
@@@ -137,7 -137,7 +137,7 @@@ merge_file () 
        else
            echo "$MERGED: file does not need merging"
        fi
-       exit 1
+       return 1
      fi
  
      ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
      echo "Normal merge conflict for '$MERGED':"
      describe_file "$local_mode" "local" "$LOCAL"
      describe_file "$remote_mode" "remote" "$REMOTE"
-     printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
-     read ans
+     if "$prompt" = true; then
+       printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
+       read ans
+     fi
  
      case "$merge_tool" in
        kdiff3)
      if test "$status" -ne 0; then
        echo "merge of $MERGED failed" 1>&2
        mv -- "$BACKUP" "$MERGED"
-       exit 1
+       if test "$merge_keep_temporaries" = "false"; then
+           cleanup_temp_files
+       fi
+       return 1
      fi
  
      if test "$merge_keep_backup" = "true"; then
  
      git add -- "$MERGED"
      cleanup_temp_files
+     return 0
  }
  
+ prompt=$(git config --bool mergetool.prompt || echo true)
  while test $# != 0
  do
      case "$1" in
                    shift ;;
            esac
            ;;
+       -y|--no-prompt)
+           prompt=false
+           ;;
+       --prompt)
+           prompt=true
+           ;;
        --)
 +          shift
            break
            ;;
        -*)
@@@ -341,6 -356,22 +357,22 @@@ init_merge_tool_path() 
        fi
  }
  
+ prompt_after_failed_merge() {
+     while true; do
+       printf "Continue merging other unresolved paths (y/n) ? "
+       read ans
+       case "$ans" in
+           [yY]*)
+               return 0
+               ;;
+           [nN]*)
+               return 1
+               ;;
+       esac
+     done
+ }
  
  if test -z "$merge_tool"; then
      merge_tool=`git config merge.tool`
@@@ -389,6 -420,7 +421,7 @@@ els
      init_merge_tool_path "$merge_tool"
  
      merge_keep_backup="$(git config --bool merge.keepBackup || echo true)"
+     merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
  
      if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
          echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
      fi
  fi
  
+ last_status=0
+ rollup_status=0
  
  if test $# -eq 0 ; then
-       files=`git ls-files -u | sed -e 's/^[^  ]*      //' | sort -u`
-       if test -z "$files" ; then
-               echo "No files need merging"
-               exit 0
+     files=`git ls-files -u | sed -e 's/^[^    ]*      //' | sort -u`
+     if test -z "$files" ; then
+       echo "No files need merging"
+       exit 0
+     fi
+     echo Merging the files: "$files"
+     git ls-files -u |
+     sed -e 's/^[^     ]*      //' |
+     sort -u |
+     while IFS= read i
+     do
+       if test $last_status -ne 0; then
+           prompt_after_failed_merge < /dev/tty || exit 1
        fi
-       echo Merging the files: "$files"
-       git ls-files -u |
-       sed -e 's/^[^   ]*      //' |
-       sort -u |
-       while IFS= read i
-       do
-               printf "\n"
-               merge_file "$i" < /dev/tty > /dev/tty
-       done
+       printf "\n"
+       merge_file "$i" < /dev/tty > /dev/tty
+       last_status=$?
+       if test $last_status -ne 0; then
+           rollup_status=1
+       fi
+     done
  else
-       while test $# -gt 0; do
-               printf "\n"
-               merge_file "$1"
-               shift
-       done
+     while test $# -gt 0; do
+       if test $last_status -ne 0; then
+           prompt_after_failed_merge || exit 1
+       fi
+       printf "\n"
+       merge_file "$1"
+       last_status=$?
+       if test $last_status -ne 0; then
+           rollup_status=1
+       fi
+       shift
+     done
  fi
- exit 0
+ exit $rollup_status