What's cooking (2015/08 #03)
[git.git] / Reintegrate
blob8dee292051eb08bb01059b3913995d5aa3d25aaf
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 /^Can wait in / ||
33 /^Needs? / || /^Expecting / || /^May want to /) {
34 return 1;
36 return 0;
39 sub read_message {
40 my ($fh, $branch) = @_;
41 my ($in_section, $in_desc);
42 my @msg = ();
43 while (<$fh>) {
44 chomp;
45 if (/^\* $branch /) {
46 $in_section = 1;
47 next;
49 last if (/^[-*\[]/ && $in_section);
50 next unless $in_section;
51 s/^\s+//;
52 if (/^$/) {
53 $in_desc = 1;
55 next unless ($in_section && $in_desc);
56 next if (/Originally merged to '\''next'\'' on ([-0-9]+)/);
57 next if (wildo_match($_));
58 push @msg, "$_\n";
60 return ($in_section, @msg);
63 my ($branch) = $ARGV[0];
64 my ($fh, $in_section, @msg);
65 if (open $fh, "<", "Meta/whats-cooking.txt") {
66 ($in_section, @msg) = read_message($fh, $branch);
68 if (!@msg) {
69 open my $revs, "-|",
70 qw(git -C Meta rev-list -32 HEAD -- whats-cooking.txt);
71 while (my $rev = <$revs>) {
72 chomp($rev);
73 open $fh, "-|",
74 qw(git -C Meta cat-file blob), "$rev:whats-cooking.txt";
75 ($in_section, @msg) = read_message($fh, $branch);
76 last if (@msg);
79 if (@msg) {
80 open(my $fh, "-|", qw(git cat-file commit HEAD));
81 my @original = (<$fh>);
82 close $fh;
83 my @final;
84 $in_section = 0;
85 for (@original) {
86 if (!$in_section) {
87 $in_section = 1 if (/^$/);
88 next;
90 if (/^Conflicts:$/ && $in_section == 2) {
91 $in_section = 3;
94 if ($in_section == 3) {
95 $_ = "# $_";
97 push @final, $_;
98 if (/^$/ && $in_section == 1) {
99 push @final, @msg;
100 push @final, "\n";
101 $in_section = 2;
104 open($fh, "|-", qw(git commit --amend -F -));
105 print $fh @final;
106 close $fh;
108 ' "$1"
111 case "$generate" in
113 accept_rerere () {
114 if ! git write-tree 2>/dev/null >/dev/null
115 then
116 git rerere remaining
117 return 1
118 else
119 GIT_EDITOR=: git commit --no-verify
120 echo "Accepted previous resolution"
121 return 0
125 mark_cut () {
126 test -n "$stop_at_cut" && return
128 count_since_last_cut=$(( $count_since_last_cut + 1 ))
129 test -z "$prev_cut" && return
130 git commit --allow-empty -m "$prev_cut"
131 prev_cut=
134 cut_seen=0 prev_cut= count_since_last_cut=0
135 while read branch eh
137 case "$branch" in '###') cut_seen=$(( $cut_seen + 1 )) ;; esac
138 if test -n "$stop_at_cut" && test $stop_at_cut -le $cut_seen
139 then
140 continue ;# slurp the remainder and skip
143 case "$branch" in
144 '###')
145 if test "$count_since_last_cut" = 0
146 then
147 prev_cut=
148 else
149 echo >&2 "$branch $eh"
150 prev_cut="$branch $eh"
151 count_since_last_cut=0
153 continue ;;
154 '#'* | '')
155 continue ;;
156 esac
158 case "$eh" in
159 "" | "#"*)
160 echo >&2 "* $branch"
162 save=$(git rev-parse --verify HEAD) &&
163 tip=$(git rev-parse --verify "$branch^0") &&
164 mb=$(git merge-base "$tip" "$save") ||
165 exit
167 test "$mb" = "$tip" && continue
169 mark_cut
171 rebuild=$(git config "branch.$branch.rebuild" || :)
173 GIT_EDITOR=: git merge $rebuild $accept_rerere --edit "$branch" ||
174 accept_rerere ||
175 exit
177 annotate_merge "$branch" || exit
178 test -z "$edit" ||
179 git commit --amend || exit
181 this=$(git rev-parse --verify HEAD)
182 if test "$this" = "$save"
183 then
185 elif git show-ref -q --verify "refs/merge-fix/$branch"
186 then
187 echo >&2 "Fixing up the merge"
188 git cherry-pick --no-commit "refs/merge-fix/$branch" &&
189 git diff --stat HEAD &&
190 GIT_EDITOR=: git commit --amend -a || exit
193 pick" "*)
194 echo >&2 "* $eh"
196 mark_cut
198 git cherry-pick "$branch" || exit ;;
199 *) echo >&2 "Eh? $branch $eh"; exit ;;
200 esac
201 done
202 exit
203 esac
205 if test -n "$update" && test $# = 0
206 then
207 set x $(sed -n -e '2s/^# //p' <"$update") &&
208 shift
211 # Generation (or updating)
213 x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
214 x40="$x40$x40$x40$x40$x40$x40$x40$x40"
215 LF='
218 show_merge () {
219 case "$msg" in
220 "Merge branch '"*"'"*)
221 branch=$(expr "$msg" : "Merge branch '\(.*\)'")
222 merge_hier=heads/
224 "Merge remote branch '"*"'"*)
225 branch=$(expr "$msg" : "Merge remote branch '\(.*\)'")
226 merge_hier=
229 echo 2>&1 "Huh?: $msg"
230 return
232 esac &&
233 tip=$(git rev-parse --verify "refs/$merge_hier$branch" 2>/dev/null) &&
234 merged=$(git name-rev --refs="refs/$merge_hier$branch" "$other" 2>/dev/null) &&
235 merged=$(expr "$merged" : "$x40 \(.*\)") &&
236 test "$merged" != undefined || {
237 other=$(git log -1 --pretty='format:%s' $other) &&
238 merged="$branch :rebased? $other"
242 show_pick () {
243 case "$msg" in
244 "### "* | "###")
245 merged="$msg"
248 merged="$(git rev-parse --verify "$commit") pick $msg"
250 esac
254 generate () {
255 PROGRAM=$1
256 shift
257 echo '#!/bin/sh'
258 echo "# $1"
259 echo 'case "$#,$1" in'
260 echo '1,-u|1,-d)'
261 echo " exec $PROGRAM" '"$1" "$0"'
262 echo 'esac'
263 echo "$PROGRAM" '"$@" <<\EOF'
264 git log --no-decorate --pretty=oneline --first-parent "$1" |
266 series=
267 while read commit msg
269 if other=$(git rev-parse -q --verify "$commit^2")
270 then
271 show_merge
272 else
273 show_pick
276 if test -z "$series"
277 then
278 series="$merged"
279 else
280 series="$merged$LF$series"
282 done
283 echo "$series"
285 echo EOF
288 if test -z "$update"
289 then
290 generate "$0" "$@"
291 elif test -z "$diff"
292 then
293 generate "$0" "$@" | diff -w -u "$update" -
294 if test $? = 0
295 then
296 echo >&2 "No changes."
297 else
298 echo >&2 -n "Update [y/N]? "
299 read yesno
300 case "$yesno" in
301 [Yy]*)
302 generate "$0" "$@" |
303 sed -e 's/ :rebased?.*//' >"$update" ;;
305 echo >&2 "No update then." ;;
306 esac
308 else
309 generate "$0" "$@" | diff -w -u "$update" -