From: Charles Bailey <charles@hashpling.org>
To: git@vger.kernel.org
Subject: [RFC/PATCH] Teach git mergetool to use custom commands defined at config time
Date: Sat, 16 Feb 2008 18:53:49 +0000 [thread overview]
Message-ID: <20080216185349.GA29177@hashpling.org> (raw)
Currently git mergetool is restricted to a set of commands defined
in the script. You can subvert the mergetool.<tool>.path to force
git mergetool to use a different command, but if you have a command
whose invocation syntax does not match one of the current tools then
you would have to write a wrapper script for it.
This patch adds three git config variable patterns which allow a more
flexible choice of merge tool.
If you run git mergetool with -t/--tool or the merge.tool config
variable set to an unrecognized tool then git mergetool will query the
mergetool.<tool>.cmd config variable. If this variable exists, then
git mergetool will treat the specified tool as a custom command and
will use a shell eval to run the command so that the appropriate shell
variables can be used to find the merge temporary files.
mergetool.<tool>.trustExitCode can be used to indicate that the exit
code of the custom command can be used to determine the success of the
merge. mergetool.<tool>.keepBackup can be used to specify whether the
original pre-merge file with conflict markers should be kept as a
'.orig' file after the merge tool completes.
---
This is a preliminary patch which aims to make it easier to use
a.n.other 3-way merge tool with git-mergetool without either hacking
the source or writing a wrapper script for the tool.
It follows filter-branch's 'eval a user shell snippet' philosophy to
provide the flexibility and here in lies an ugliness. It exposes
git-mergetool.sh's private variables to the user script. The variables
are BASE, REMOTE, LOCAL and path.
My feeling is that we should give this consistent and documented
names, perhaps GIT_BASE, GIT_REMOTE, GIT_LOCAL, GIT_MERGED or similar.
Also, does anyone know of any reason why the temporary files should
not be cleaned up after an unsuccessful merge? As it is, every time
you abort a mergetool run you end up with another set of .$$.BASE
.$$.REMOTE and .$$.LOCAL files.
A further enhancement that I have thought about is providing a config
option like mergetool.<tool>.cmdNoBase for the case where there is no
base file, as in many cases it might be easier for the user to provide
a second command than to have shell conditionals in their config.
Just for reference I've tried this patch in the windows world with
things like:
git config --global mergetool.tortoise.cmd 'TortoiseMerge.exe \
/base:"$BASE" /theirs:"$REMOTE" /mine:"$LOCAL" /merged:"$path"'
git config --global mergetool.p4.cmd 'p4merge.exe "$BASE" "$REMOTE" \
"$LOCAL" "$path"'
git config --global mergetool.p4win.cmd 'P4WinMrg "$BASE" "$REMOTE" \
"$LOCAL" "$path"'
Documentation/config.txt | 30 ++++++++++++++++++++++++++++--
git-mergetool.sh | 32 ++++++++++++++++++++++++++++++--
2 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index f9bdb16..e26c4b2 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -689,8 +689,10 @@ merge.summary::
merge.tool::
Controls which merge resolution program is used by
- linkgit:git-mergetool[1]. Valid values are: "kdiff3", "tkdiff",
- "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff", and "opendiff".
+ linkgit:git-mergetool[1]. Valid built-in values are: "kdiff3",
+ "tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff", and
+ "opendiff". Any other value is treated is custom merge tool
+ and there must be a corresponing mergetool.<tool>.cmd option.
merge.verbosity::
Controls the amount of output shown by the recursive merge
@@ -717,6 +719,30 @@ mergetool.<tool>.path::
Override the path for the given tool. This is useful in case
your tool is not in the PATH.
+mergetool.<tool>.cmd::
+ Specify the command to invoke the specified merge tool. The
+ specified command is evaluated in shell with the following
+ variables available: 'BASE' is the name of a temporary file
+ containing the common base of the files to be merged, if available;
+ 'LOCAL' is the name of a temporary file containing the contents of
+ the file on the current branch; 'REMOTE' is the name of a temporary
+ file containing the contents of the file from the branch being
+ merged; 'path' contains the name of the file to which the merge
+ tool should write the results of a successful merge.
+
+mergetool.<tool>.trustExitCode::
+ For a custom merge command, specify whether the exit code of
+ the merge command can be used to determine whether the merge was
+ successful. If this is not set to true then the merge target file
+ timestamp is checked and the merge assumed to have been successful
+ if the file has been updated, otherwise the user is prompted to
+ indicate the success of the merge.
+
+mergetool.<tool>.keepBackup::
+ After performing a merge, the original file with conflict markers
+ can be saved as a file with a `.orig` extension. If this variable
+ is set to `false` then this file is not preserved.
+
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.
diff --git a/git-mergetool.sh b/git-mergetool.sh
index cbbb707..78c73ca 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -271,6 +271,21 @@ merge_file () {
status=$?
save_backup
;;
+ *)
+ if test -n "$merge_tool_cmd"; then
+ touch "$BACKUP"
+ eval "$merge_tool_cmd"
+ status=$?
+ if test "$merge_tool_trust_exit_code" = "false"; then
+ check_unchanged
+ fi
+ if test "$merge_tool_keep_backup" = "true"; then
+ save_backup
+ else
+ remove_backup
+ fi
+ fi
+ ;;
esac
if test "$status" -ne 0; then
echo "merge of $path failed" 1>&2
@@ -309,12 +324,20 @@ do
shift
done
+valid_custom_tool()
+{
+ merge_tool_cmd="$(git config mergetool.$1.cmd)"
+ test -n "$merge_tool_cmd"
+}
+
valid_tool() {
case "$1" in
kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
;; # happy
*)
- return 1
+ if ! valid_custom_tool "$1"; then
+ return 1
+ fi
;;
esac
}
@@ -380,10 +403,15 @@ else
init_merge_tool_path "$merge_tool"
- if ! type "$merge_tool_path" > /dev/null 2>&1; then
+ 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'"
exit 1
fi
+
+ if ! test -z "$merge_tool_cmd"; then
+ merge_tool_trust_exit_code="$(git config --bool merge.$merge_tool.trustExitCode || echo false)"
+ merge_tool_keep_backup="$(git config --bool merge.$merge_tool.keepBackup || echo true)"
+ fi
fi
--
1.5.4.1.144.gb4758f
next reply other threads:[~2008-02-16 18:54 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-16 18:53 Charles Bailey [this message]
2008-02-16 20:04 ` [RFC/PATCH] Teach git mergetool to use custom commands defined at config time Junio C Hamano
2008-02-16 20:20 ` Charles Bailey
2008-02-16 21:11 ` Jakub Narebski
2008-02-16 22:37 ` Steffen Prohaska
2008-02-17 0:20 ` Charles Bailey
2008-02-17 0:46 ` Johannes Schindelin
2008-02-17 0:56 ` Charles Bailey
2008-02-17 1:15 ` Junio C Hamano
2008-02-17 7:59 ` Steffen Prohaska
2008-02-17 10:15 ` Charles Bailey
2008-02-17 21:49 ` Theodore Tso
2008-02-17 23:28 ` Charles Bailey
2008-02-17 23:41 ` Charles Bailey
2008-02-18 0:30 ` Junio C Hamano
2008-02-18 8:14 ` Charles Bailey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080216185349.GA29177@hashpling.org \
--to=charles@hashpling.org \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).