What's cooking (2013/08 #06)
[git.git] / Reintegrate
blob45e384c0aab486e6a669ea215e1baa42d1e6af40
1 #!/bin/sh
3 accept_rerere="--rerere-autoupdate" generate=no update= diff= edit= stop_at_cut=
4 while case "$#,$1" in 0,*) break;; *,-*) ;; esac
5 do
6 case "$1" in
7 -n) accept_rerere= ;;
8 -e) edit=t ;;
9 -c) stop_at_cut=1 ;;
10 -c?*) stop_at_cut=${1#-c} ;;
11 -d) update=${2?"diff with what?"}
12 diff=yes
13 generate=yes
14 shift ;;
15 -u) update=${2?"update what?"}
16 generate=yes
17 shift ;;
18 *) generate=yes
19 break ;;
20 esac
21 shift
22 done
24 annotate_merge () {
25 test -f Meta/whats-cooking.txt || return 0
27 perl -e '
28 sub wildo_match {
29 s/^\s*//;
30 if (/^Will (?:\S+ ){0,2}(fast-track|keep|merge|drop|discard|cook|kick|defer|be re-?rolled)[,. ]/ ||
31 /^Not urgent/ || /^Not ready/ || /^Waiting for / ||
32 /^Needs? / || /^Expecting / || /^May want to /) {
33 return 1;
35 return 0;
38 my ($branch) = $ARGV[0];
39 my ($in_section, $in_desc);
40 my @msg = ();
41 while (<STDIN>) {
42 chomp;
43 if (/^\* $branch /) {
44 $in_section = 1;
45 next;
47 last if (/^[-*\[]/ && $in_section);
48 next unless $in_section;
49 s/^\s+//;
50 if (/^$/) {
51 $in_desc = 1;
53 next unless ($in_section && $in_desc);
54 next if (/Originally merged to '\''next'\'' on ([-0-9]+)/);
55 next if (wildo_match($_));
56 push @msg, "$_\n";
59 if ($in_section && @msg) {
60 open(my $fh, "-|", qw(git cat-file commit HEAD));
61 my @original = (<$fh>);
62 close $fh;
63 my @final;
64 $in_section = 0;
65 for (@original) {
66 if (!$in_section) {
67 $in_section = 1 if (/^$/);
68 next;
70 if (/^Conflicts:$/ && $in_section == 2) {
71 $in_section = 3;
74 if ($in_section == 3) {
75 $_ = "# $_";
77 push @final, $_;
78 if (/^$/ && $in_section == 1) {
79 push @final, @msg;
80 push @final, "\n";
81 $in_section = 2;
84 open($fh, "|-", qw(git commit --amend -F -));
85 print $fh @final;
86 close $fh;
88 ' <Meta/whats-cooking.txt "$1"
91 case "$generate" in
92 no)
93 accept_rerere () {
94 if ! git write-tree 2>/dev/null >/dev/null
95 then
96 git rerere remaining
97 return 1
98 else
99 EDITOR=: git commit --no-verify
100 echo "Accepted previous resolution"
101 return 0
105 mark_cut () {
106 test -n "$stop_at_cut" && return
108 count_since_last_cut=$(( $count_since_last_cut + 1 ))
109 test -z "$prev_cut" && return
110 git commit --allow-empty -m "$prev_cut"
111 prev_cut=
114 cut_seen=0 prev_cut= count_since_last_cut=0
115 while read branch eh
117 case "$branch" in '###') cut_seen=$(( $cut_seen + 1 )) ;; esac
118 if test -n "$stop_at_cut" && test $stop_at_cut -le $cut_seen
119 then
120 continue ;# slurp the remainder and skip
123 case "$branch" in
124 '###')
125 if test "$count_since_last_cut" = 0
126 then
127 prev_cut=
128 else
129 echo >&2 "$branch $eh"
130 prev_cut="$branch $eh"
131 count_since_last_cut=0
133 continue ;;
134 '#'* | '')
135 continue ;;
136 esac
138 case "$eh" in
139 "" | "#"*)
140 echo >&2 "* $branch"
142 save=$(git rev-parse --verify HEAD) &&
143 tip=$(git rev-parse --verify "$branch^0") &&
144 mb=$(git merge-base "$tip" "$save") ||
145 exit
147 test "$mb" = "$tip" && continue
149 mark_cut
151 EDITOR=: git merge $accept_rerere --edit "$branch" ||
152 accept_rerere ||
153 exit
155 annotate_merge "$branch" || exit
156 test -z "$edit" ||
157 git commit --amend || exit
159 this=$(git rev-parse --verify HEAD)
160 if test "$this" = "$save"
161 then
163 elif git show-ref -q --verify "refs/merge-fix/$branch"
164 then
165 echo >&2 "Fixing up the merge"
166 git cherry-pick --no-commit "refs/merge-fix/$branch" &&
167 EDITOR=: git commit --amend -a || exit
170 pick" "*)
171 echo >&2 "* $eh"
173 mark_cut
175 git cherry-pick "$branch" || exit ;;
176 *) echo >&2 "Eh? $branch $eh"; exit ;;
177 esac
178 done
179 exit
180 esac
182 if test -n "$update" && test $# = 0
183 then
184 set x $(sed -n -e '2s/^# //p' <"$update") &&
185 shift
188 # Generation (or updating)
190 x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
191 x40="$x40$x40$x40$x40$x40$x40$x40$x40"
192 LF='
195 show_merge () {
196 case "$msg" in
197 "Merge branch '"*"'"*)
198 branch=$(expr "$msg" : "Merge branch '\(.*\)'")
199 merge_hier=heads/
201 "Merge remote branch '"*"'"*)
202 branch=$(expr "$msg" : "Merge remote branch '\(.*\)'")
203 merge_hier=
206 echo 2>&1 "Huh?: $msg"
207 return
209 esac &&
210 tip=$(git rev-parse --verify "refs/$merge_hier$branch" 2>/dev/null) &&
211 merged=$(git name-rev --refs="refs/$merge_hier$branch" "$other" 2>/dev/null) &&
212 merged=$(expr "$merged" : "$x40 \(.*\)") &&
213 test "$merged" != undefined || {
214 other=$(git log -1 --pretty='format:%s' $other) &&
215 merged="$branch :rebased? $other"
219 show_pick () {
220 case "$msg" in
221 "### "* | "###")
222 merged="$msg"
225 merged="$(git rev-parse --verify "$commit") pick $msg"
227 esac
231 generate () {
232 PROGRAM=$1
233 shift
234 echo '#!/bin/sh'
235 echo "# $1"
236 echo 'case "$#,$1" in'
237 echo '1,-u|1,-d)'
238 echo " exec $PROGRAM" '"$1" "$0"'
239 echo 'esac'
240 echo "$PROGRAM" '"$@" <<\EOF'
241 git log --no-decorate --pretty=oneline --first-parent "$1" |
243 series=
244 while read commit msg
246 if other=$(git rev-parse -q --verify "$commit^2")
247 then
248 show_merge
249 else
250 show_pick
253 if test -z "$series"
254 then
255 series="$merged"
256 else
257 series="$merged$LF$series"
259 done
260 echo "$series"
262 echo EOF
265 if test -z "$update"
266 then
267 generate "$0" "$@"
268 elif test -z "$diff"
269 then
270 generate "$0" "$@" | diff -w -u "$update" -
271 if test $? = 0
272 then
273 echo >&2 "No changes."
274 else
275 echo >&2 -n "Update [y/N]? "
276 read yesno
277 case "$yesno" in
278 [Yy]*)
279 generate "$0" "$@" |
280 sed -e 's/ :rebased?.*//' >"$update" ;;
282 echo >&2 "No update then." ;;
283 esac
285 else
286 generate "$0" "$@" | diff -w -u "$update" -