What's cooking (2015/01 #05)
[git.git] / Reintegrate
blobf6d32b55eda4c83c9967ec865d62819168361868
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 my ($branch) = $ARGV[0];
40 my ($in_section, $in_desc);
41 my @msg = ();
42 while (<STDIN>) {
43 chomp;
44 if (/^\* $branch /) {
45 $in_section = 1;
46 next;
48 last if (/^[-*\[]/ && $in_section);
49 next unless $in_section;
50 s/^\s+//;
51 if (/^$/) {
52 $in_desc = 1;
54 next unless ($in_section && $in_desc);
55 next if (/Originally merged to '\''next'\'' on ([-0-9]+)/);
56 next if (wildo_match($_));
57 push @msg, "$_\n";
60 if ($in_section && @msg) {
61 open(my $fh, "-|", qw(git cat-file commit HEAD));
62 my @original = (<$fh>);
63 close $fh;
64 my @final;
65 $in_section = 0;
66 for (@original) {
67 if (!$in_section) {
68 $in_section = 1 if (/^$/);
69 next;
71 if (/^Conflicts:$/ && $in_section == 2) {
72 $in_section = 3;
75 if ($in_section == 3) {
76 $_ = "# $_";
78 push @final, $_;
79 if (/^$/ && $in_section == 1) {
80 push @final, @msg;
81 push @final, "\n";
82 $in_section = 2;
85 open($fh, "|-", qw(git commit --amend -F -));
86 print $fh @final;
87 close $fh;
89 ' <Meta/whats-cooking.txt "$1"
92 case "$generate" in
93 no)
94 accept_rerere () {
95 if ! git write-tree 2>/dev/null >/dev/null
96 then
97 git rerere remaining
98 return 1
99 else
100 EDITOR=: git commit --no-verify
101 echo "Accepted previous resolution"
102 return 0
106 mark_cut () {
107 test -n "$stop_at_cut" && return
109 count_since_last_cut=$(( $count_since_last_cut + 1 ))
110 test -z "$prev_cut" && return
111 git commit --allow-empty -m "$prev_cut"
112 prev_cut=
115 cut_seen=0 prev_cut= count_since_last_cut=0
116 while read branch eh
118 case "$branch" in '###') cut_seen=$(( $cut_seen + 1 )) ;; esac
119 if test -n "$stop_at_cut" && test $stop_at_cut -le $cut_seen
120 then
121 continue ;# slurp the remainder and skip
124 case "$branch" in
125 '###')
126 if test "$count_since_last_cut" = 0
127 then
128 prev_cut=
129 else
130 echo >&2 "$branch $eh"
131 prev_cut="$branch $eh"
132 count_since_last_cut=0
134 continue ;;
135 '#'* | '')
136 continue ;;
137 esac
139 case "$eh" in
140 "" | "#"*)
141 echo >&2 "* $branch"
143 save=$(git rev-parse --verify HEAD) &&
144 tip=$(git rev-parse --verify "$branch^0") &&
145 mb=$(git merge-base "$tip" "$save") ||
146 exit
148 test "$mb" = "$tip" && continue
150 mark_cut
152 rebuild=$(git config "branch.$branch.rebuild" || :)
154 EDITOR=: git merge $rebuild $accept_rerere --edit "$branch" ||
155 accept_rerere ||
156 exit
158 annotate_merge "$branch" || exit
159 test -z "$edit" ||
160 git commit --amend || exit
162 this=$(git rev-parse --verify HEAD)
163 if test "$this" = "$save"
164 then
166 elif git show-ref -q --verify "refs/merge-fix/$branch"
167 then
168 echo >&2 "Fixing up the merge"
169 git cherry-pick --no-commit "refs/merge-fix/$branch" &&
170 git diff --stat HEAD &&
171 EDITOR=: git commit --amend -a || exit
174 pick" "*)
175 echo >&2 "* $eh"
177 mark_cut
179 git cherry-pick "$branch" || exit ;;
180 *) echo >&2 "Eh? $branch $eh"; exit ;;
181 esac
182 done
183 exit
184 esac
186 if test -n "$update" && test $# = 0
187 then
188 set x $(sed -n -e '2s/^# //p' <"$update") &&
189 shift
192 # Generation (or updating)
194 x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
195 x40="$x40$x40$x40$x40$x40$x40$x40$x40"
196 LF='
199 show_merge () {
200 case "$msg" in
201 "Merge branch '"*"'"*)
202 branch=$(expr "$msg" : "Merge branch '\(.*\)'")
203 merge_hier=heads/
205 "Merge remote branch '"*"'"*)
206 branch=$(expr "$msg" : "Merge remote branch '\(.*\)'")
207 merge_hier=
210 echo 2>&1 "Huh?: $msg"
211 return
213 esac &&
214 tip=$(git rev-parse --verify "refs/$merge_hier$branch" 2>/dev/null) &&
215 merged=$(git name-rev --refs="refs/$merge_hier$branch" "$other" 2>/dev/null) &&
216 merged=$(expr "$merged" : "$x40 \(.*\)") &&
217 test "$merged" != undefined || {
218 other=$(git log -1 --pretty='format:%s' $other) &&
219 merged="$branch :rebased? $other"
223 show_pick () {
224 case "$msg" in
225 "### "* | "###")
226 merged="$msg"
229 merged="$(git rev-parse --verify "$commit") pick $msg"
231 esac
235 generate () {
236 PROGRAM=$1
237 shift
238 echo '#!/bin/sh'
239 echo "# $1"
240 echo 'case "$#,$1" in'
241 echo '1,-u|1,-d)'
242 echo " exec $PROGRAM" '"$1" "$0"'
243 echo 'esac'
244 echo "$PROGRAM" '"$@" <<\EOF'
245 git log --no-decorate --pretty=oneline --first-parent "$1" |
247 series=
248 while read commit msg
250 if other=$(git rev-parse -q --verify "$commit^2")
251 then
252 show_merge
253 else
254 show_pick
257 if test -z "$series"
258 then
259 series="$merged"
260 else
261 series="$merged$LF$series"
263 done
264 echo "$series"
266 echo EOF
269 if test -z "$update"
270 then
271 generate "$0" "$@"
272 elif test -z "$diff"
273 then
274 generate "$0" "$@" | diff -w -u "$update" -
275 if test $? = 0
276 then
277 echo >&2 "No changes."
278 else
279 echo >&2 -n "Update [y/N]? "
280 read yesno
281 case "$yesno" in
282 [Yy]*)
283 generate "$0" "$@" |
284 sed -e 's/ :rebased?.*//' >"$update" ;;
286 echo >&2 "No update then." ;;
287 esac
289 else
290 generate "$0" "$@" | diff -w -u "$update" -