git-mergetool--lib.sh 4.19 KB
Newer Older
1
#!/bin/sh
2 3 4 5 6 7 8 9 10 11
# git-mergetool--lib is a library for common merge tool functions
diff_mode() {
	test "$TOOL_MODE" = diff
}

merge_mode() {
	test "$TOOL_MODE" = merge
}

translate_merge_tool_path () {
12
	echo "$1"
13 14 15
}

check_unchanged () {
16 17
	if test "$MERGED" -nt "$BACKUP"
	then
18 19
		status=0
	else
20 21
		while true
		do
22 23
			echo "$MERGED seems unchanged."
			printf "Was the merge successful? [y/n] "
24
			read answer || return 1
25 26 27 28 29 30 31 32
			case "$answer" in
			y*|Y*) status=0; break ;;
			n*|N*) status=1; break ;;
			esac
		done
	fi
}

33 34 35 36 37 38 39 40 41
valid_tool_config () {
	if test -n "$(get_merge_tool_cmd "$1")"
	then
		return 0
	else
		return 1
	fi
}

42
valid_tool () {
43 44 45 46
	setup_tool "$1" || valid_tool_config "$1"
}

setup_tool () {
47
	case "$1" in
48 49
	vim*|gvim*)
		tool=vim
50 51
		;;
	*)
52
		tool="$1"
53 54
		;;
	esac
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
	mergetools="$(git --exec-path)/mergetools"

	# Load the default definitions
	. "$mergetools/defaults"
	if ! test -f "$mergetools/$tool"
	then
		return 1
	fi

	# Load the redefined functions
	. "$mergetools/$tool"

	if merge_mode && ! can_merge
	then
		echo "error: '$tool' can not be used to resolve merges" >&2
		exit 1
	elif diff_mode && ! can_diff
	then
		echo "error: '$tool' can only be used to resolve merges" >&2
		exit 1
	fi
	return 0
77 78 79
}

get_merge_tool_cmd () {
80
	# Prints the custom command for a merge tool
81
	merge_tool="$1"
82 83
	if diff_mode
	then
84
		echo "$(git config difftool.$merge_tool.cmd ||
85
			git config mergetool.$merge_tool.cmd)"
86 87 88
	else
		echo "$(git config mergetool.$merge_tool.cmd)"
	fi
89 90
}

91
# Entry point for running tools
92
run_merge_tool () {
93 94 95 96 97
	# If GIT_PREFIX is empty then we cannot use it in tools
	# that expect to be able to chdir() to its value.
	GIT_PREFIX=${GIT_PREFIX:-.}
	export GIT_PREFIX

98
	merge_tool_path="$(get_merge_tool_path "$1")" || exit
99 100 101
	base_present="$2"
	status=0

102 103 104 105 106 107 108 109 110
	# Bring tool-specific functions into scope
	setup_tool "$1"

	if merge_mode
	then
		merge_cmd "$1"
	else
		diff_cmd "$1"
	fi
111 112 113
	return $status
}

114
list_merge_tool_candidates () {
115 116
	if merge_mode
	then
117 118 119 120
		tools="tortoisemerge"
	else
		tools="kompare"
	fi
121 122 123 124
	if test -n "$DISPLAY"
	then
		if test -n "$GNOME_DESKTOP_SESSION_ID"
		then
125 126 127 128
			tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
		else
			tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
		fi
129
		tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3"
130
	fi
131 132
	case "${VISUAL:-$EDITOR}" in
	*vim*)
133
		tools="$tools vimdiff emerge"
134 135
		;;
	*)
136
		tools="$tools emerge vimdiff"
137 138
		;;
	esac
139 140 141 142
}

guess_merge_tool () {
	list_merge_tool_candidates
143 144 145 146 147 148
	echo >&2 "merge tool candidates: $tools"

	# Loop over each candidate and stop when a valid merge tool is found.
	for i in $tools
	do
		merge_tool_path="$(translate_merge_tool_path "$i")"
149 150
		if type "$merge_tool_path" >/dev/null 2>&1
		then
151 152
			echo "$i"
			return 0
153 154 155
		fi
	done

156 157
	echo >&2 "No known merge resolution program available."
	return 1
158 159 160 161 162
}

get_configured_merge_tool () {
	# Diff mode first tries diff.tool and falls back to merge.tool.
	# Merge mode only checks merge.tool
163 164
	if diff_mode
	then
165 166 167
		merge_tool=$(git config diff.tool || git config merge.tool)
	else
		merge_tool=$(git config merge.tool)
168
	fi
169 170
	if test -n "$merge_tool" && ! valid_tool "$merge_tool"
	then
171 172 173 174
		echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
		echo >&2 "Resetting to default..."
		return 1
	fi
175
	echo "$merge_tool"
176 177 178 179
}

get_merge_tool_path () {
	# A merge tool has been set, so verify that it's valid.
180
	merge_tool="$1"
181 182
	if ! valid_tool "$merge_tool"
	then
183 184 185
		echo >&2 "Unknown merge tool $merge_tool"
		exit 1
	fi
186 187
	if diff_mode
	then
188
		merge_tool_path=$(git config difftool."$merge_tool".path ||
189
				  git config mergetool."$merge_tool".path)
190 191
	else
		merge_tool_path=$(git config mergetool."$merge_tool".path)
192
	fi
193 194
	if test -z "$merge_tool_path"
	then
195
		merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
196
	fi
197
	if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
198 199
		! type "$merge_tool_path" >/dev/null 2>&1
	then
200
		echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
201
			 "'$merge_tool_path'"
202 203 204 205 206 207 208
		exit 1
	fi
	echo "$merge_tool_path"
}

get_merge_tool () {
	# Check if a merge tool has been configured
209
	merge_tool="$(get_configured_merge_tool)"
210
	# Try to guess an appropriate merge tool if no tool has been set.
211 212
	if test -z "$merge_tool"
	then
213
		merge_tool="$(guess_merge_tool)" || exit
214 215 216
	fi
	echo "$merge_tool"
}