aboutsummaryrefslogtreecommitdiff
path: root/git-rebase--merge.sh
blob: 06a4723d4db3db74ea17ace60d824e83cdee25e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# This shell script fragment is sourced by git-rebase to implement
# its merge-based non-interactive mode that copes well with renamed
# files.
#
# Copyright (c) 2010 Junio C Hamano.
#

prec=4

read_state () {
	onto_name=$(cat "$state_dir"/onto_name) &&
	end=$(cat "$state_dir"/end) &&
	msgnum=$(cat "$state_dir"/msgnum)
}

continue_merge () {
	test -d "$state_dir" || die "$state_dir directory does not exist"

	unmerged=$(git ls-files -u)
	if test -n "$unmerged"
	then
		echo "You still have unmerged paths in your index"
		echo "did you forget to use git add?"
		die "$resolvemsg"
	fi

	cmt=$(cat "$state_dir/current")
	if ! git diff-index --quiet --ignore-submodules HEAD --
	then
		if ! git commit ${gpg_sign_opt:+"$gpg_sign_opt"} --no-verify -C "$cmt"
		then
			echo "Commit failed, please do not call \"git commit\""
			echo "directly, but instead do one of the following: "
			die "$resolvemsg"
		fi
		if test -z "$GIT_QUIET"
		then
			printf "Committed: %0${prec}d " $msgnum
		fi
		echo "$cmt $(git rev-parse HEAD^0)" >> "$state_dir/rewritten"
	else
		if test -z "$GIT_QUIET"
		then
			printf "Already applied: %0${prec}d " $msgnum
		fi
	fi
	test -z "$GIT_QUIET" &&
	GIT_PAGER='' git log --format=%s -1 "$cmt"

	# onto the next patch:
	msgnum=$(($msgnum + 1))
	echo "$msgnum" >"$state_dir/msgnum"
}

call_merge () {
	msgnum="$1"
	echo "$msgnum" >"$state_dir/msgnum"
	cmt="$(cat "$state_dir/cmt.$msgnum")"
	echo "$cmt" > "$state_dir/current"
	hd=$(git rev-parse --verify HEAD)
	cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
	eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
	eval GITHEAD_$hd='$onto_name'
	export GITHEAD_$cmt GITHEAD_$hd
	if test -n "$GIT_QUIET"
	then
		GIT_MERGE_VERBOSITY=1 && export GIT_MERGE_VERBOSITY
	fi
	test -z "$strategy" && strategy=recursive
	# If cmt doesn't have a parent, don't include it as a base
	base=$(git rev-parse --verify --quiet $cmt^)
	eval 'git-merge-$strategy' $strategy_opts $base ' -- "$hd" "$cmt"'
	rv=$?
	case "$rv" in
	0)
		unset GITHEAD_$cmt GITHEAD_$hd
		return
		;;
	1)
		git rerere $allow_rerere_autoupdate
		die "$resolvemsg"
		;;
	2)
		echo "Strategy: $strategy failed, try another" 1>&2
		die "$resolvemsg"
		;;
	*)
		die "Unknown exit code ($rv) from command:" \
			"git-merge-$strategy $cmt^ -- HEAD $cmt"
		;;
	esac
}

finish_rb_merge () {
	move_to_original_branch
	if test -s "$state_dir"/rewritten
	then
		git notes copy --for-rewrite=rebase <"$state_dir"/rewritten
		hook="$(git rev-parse --git-path hooks/post-rewrite)"
		test -x "$hook" && "$hook" rebase <"$state_dir"/rewritten
	fi
	say All done.
}

# The whole contents of this file is run by dot-sourcing it from
# inside a shell function.  It used to be that "return"s we see
# below were not inside any function, and expected to return
# to the function that dot-sourced us.
#
# However, older (9.x) versions of FreeBSD /bin/sh misbehave on such a
# construct and continue to run the statements that follow such a "return".
# As a work-around, we introduce an extra layer of a function
# here, and immediately call it after defining it.
git_rebase__merge () {

case "$action" in
continue)
	read_state
	continue_merge
	while test "$msgnum" -le "$end"
	do
		call_merge "$msgnum"
		continue_merge
	done
	finish_rb_merge
	return
	;;
skip)
	read_state
	git rerere clear
	msgnum=$(($msgnum + 1))
	while test "$msgnum" -le "$end"
	do
		call_merge "$msgnum"
		continue_merge
	done
	finish_rb_merge
	return
	;;
esac

mkdir -p "$state_dir"
echo "$onto_name" > "$state_dir/onto_name"
write_basic_state

msgnum=0
for cmt in $(git rev-list --reverse --no-merges "$revisions")
do
	msgnum=$(($msgnum + 1))
	echo "$cmt" > "$state_dir/cmt.$msgnum"
done

echo 1 >"$state_dir/msgnum"
echo $msgnum >"$state_dir/end"

end=$msgnum
msgnum=1

while test "$msgnum" -le "$end"
do
	call_merge "$msgnum"
	continue_merge
done

finish_rb_merge

}
# ... and then we call the whole thing.
git_rebase__merge