Code

difftool: remove the backup file feature
[git.git] / contrib / difftool / git-difftool-helper
1 #!/bin/sh
2 # git-difftool-helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
3 # It supports kdiff3, kompare, tkdiff, xxdiff, meld, opendiff,
4 # emerge, ecmerge, vimdiff, gvimdiff, and custom user-configurable tools.
5 # This script is typically launched by using the 'git difftool'
6 # convenience command.
7 #
8 # Copyright (c) 2009 David Aguilar
10 # Set GIT_DIFFTOOL_NO_PROMPT to bypass the per-file prompt.
11 should_prompt () {
12         test -z "$GIT_DIFFTOOL_NO_PROMPT"
13 }
15 # This function prepares temporary files and launches the appropriate
16 # merge tool.
17 launch_merge_tool () {
18         # Merged is the filename as it appears in the work tree
19         # Local is the contents of a/filename
20         # Remote is the contents of b/filename
21         # Custom merge tool commands might use $BASE so we provide it
22         MERGED="$1"
23         LOCAL="$2"
24         REMOTE="$3"
25         BASE="$1"
27         # $LOCAL and $REMOTE are temporary files so prompt
28         # the user with the real $MERGED name before launching $merge_tool.
29         if should_prompt; then
30                 printf "\nViewing: '$MERGED'\n"
31                 printf "Hit return to launch '%s': " "$merge_tool"
32                 read ans
33         fi
35         # Run the appropriate merge tool command
36         case "$merge_tool" in
37         kdiff3)
38                 basename=$(basename "$MERGED")
39                 "$merge_tool_path" --auto \
40                         --L1 "$basename (A)" \
41                         --L2 "$basename (B)" \
42                         "$LOCAL" "$REMOTE" \
43                         > /dev/null 2>&1
44                 ;;
46         kompare)
47                 "$merge_tool_path" "$LOCAL" "$REMOTE"
48                 ;;
50         tkdiff)
51                 "$merge_tool_path" "$LOCAL" "$REMOTE"
52                 ;;
54         meld)
55                 "$merge_tool_path" "$LOCAL" "$REMOTE"
56                 ;;
58         vimdiff)
59                 "$merge_tool_path" -d -c "wincmd l" "$LOCAL" "$REMOTE"
60                 ;;
62         gvimdiff)
63                 "$merge_tool_path" -d -c "wincmd l" -f "$LOCAL" "$REMOTE"
64                 ;;
66         xxdiff)
67                 "$merge_tool_path" \
68                         -R 'Accel.Search: "Ctrl+F"' \
69                         -R 'Accel.SearchForward: "Ctrl-G"' \
70                         "$LOCAL" "$REMOTE"
71                 ;;
73         opendiff)
74                 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
75                 ;;
77         ecmerge)
78                 "$merge_tool_path" "$LOCAL" "$REMOTE" \
79                         --default --mode=merge2 --to="$MERGED"
80                 ;;
82         emerge)
83                 "$merge_tool_path" -f emerge-files-command \
84                         "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
85                 ;;
87         *)
88                 if test -n "$merge_tool_cmd"; then
89                         ( eval $merge_tool_cmd )
90                 fi
91                 ;;
92         esac
93 }
95 # Verifies that (difftool|mergetool).<tool>.cmd exists
96 valid_custom_tool() {
97         merge_tool_cmd="$(git config difftool.$1.cmd)"
98         test -z "$merge_tool_cmd" &&
99         merge_tool_cmd="$(git config mergetool.$1.cmd)"
100         test -n "$merge_tool_cmd"
103 # Verifies that the chosen merge tool is properly setup.
104 # Built-in merge tools are always valid.
105 valid_tool() {
106         case "$1" in
107         kdiff3 | kompare | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
108                 ;; # happy
109         *)
110                 if ! valid_custom_tool "$1"
111                 then
112                         return 1
113                 fi
114                 ;;
115         esac
118 # Sets up the merge_tool_path variable.
119 # This handles the difftool.<tool>.path configuration.
120 # This also falls back to mergetool defaults.
121 init_merge_tool_path() {
122         merge_tool_path=$(git config difftool."$1".path)
123         test -z "$merge_tool_path" &&
124         merge_tool_path=$(git config mergetool."$1".path)
125         if test -z "$merge_tool_path"; then
126                 case "$1" in
127                 vimdiff)
128                         merge_tool_path=vim
129                         ;;
130                 gvimdiff)
131                         merge_tool_path=gvim
132                         ;;
133                 emerge)
134                         merge_tool_path=emacs
135                         ;;
136                 *)
137                         merge_tool_path="$1"
138                         ;;
139                 esac
140         fi
143 # Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
144 test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
145 test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
147 # If merge tool was not specified then use the diff.tool
148 # configuration variable.  If that's invalid then reset merge_tool.
149 # Fallback to merge.tool.
150 if test -z "$merge_tool"; then
151         merge_tool=$(git config diff.tool)
152         test -z "$merge_tool" &&
153         merge_tool=$(git config merge.tool)
154         if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
155                 echo >&2 "git config option diff.tool set to unknown tool: $merge_tool"
156                 echo >&2 "Resetting to default..."
157                 unset merge_tool
158         fi
159 fi
161 # Try to guess an appropriate merge tool if no tool has been set.
162 if test -z "$merge_tool"; then
163         # We have a $DISPLAY so try some common UNIX merge tools
164         if test -n "$DISPLAY"; then
165                 # If gnome then prefer meld, otherwise, prefer kdiff3 or kompare
166                 if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
167                         merge_tool_candidates="meld kdiff3 kompare tkdiff xxdiff gvimdiff"
168                 else
169                         merge_tool_candidates="kdiff3 kompare tkdiff xxdiff meld gvimdiff"
170                 fi
171         fi
172         if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
173                 # $EDITOR is emacs so add emerge as a candidate
174                 merge_tool_candidates="$merge_tool_candidates emerge opendiff vimdiff"
175         elif echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
176                 # $EDITOR is vim so add vimdiff as a candidate
177                 merge_tool_candidates="$merge_tool_candidates vimdiff opendiff emerge"
178         else
179                 merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
180         fi
181         echo "merge tool candidates: $merge_tool_candidates"
183         # Loop over each candidate and stop when a valid merge tool is found.
184         for i in $merge_tool_candidates
185         do
186                 init_merge_tool_path $i
187                 if type "$merge_tool_path" > /dev/null 2>&1; then
188                         merge_tool=$i
189                         break
190                 fi
191         done
193         if test -z "$merge_tool" ; then
194                 echo "No known merge resolution program available."
195                 exit 1
196         fi
198 else
199         # A merge tool has been set, so verify that it's valid.
200         if ! valid_tool "$merge_tool"; then
201                 echo >&2 "Unknown merge tool $merge_tool"
202                 exit 1
203         fi
205         init_merge_tool_path "$merge_tool"
207         if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
208                 echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
209                 exit 1
210         fi
211 fi
214 # Launch the merge tool on each path provided by 'git diff'
215 while test $# -gt 6
216 do
217         launch_merge_tool "$1" "$2" "$5"
218         shift 7
219 done