A new implementation of What's cooking script

Junio C Hamano committed Aug 20, 2009 at 18:21 UTC eac569bc59d3b39fffe4597ed8bfc3f9a1b37418
1 file changed +325
cook.sh new
+325
@@ -0,0 +1,325 @@
1 +#!/bin/sh
2 +
3 +LANG=C LC_ALL=C GIT_PAGER=cat
4 +export LANG LC_ALL GIT_PAGER
5 +
6 +tmp=/var/tmp/cook.$$
7 +trap 'rm -f "$tmp".*' 0
8 +
9 +git branch --merged "master" | sed -n -e 's/^..//' -e '/\//p' >"$tmp.in.master"
10 +git branch --merged "pu" | sed -n -e 's/^..//' -e '/\//p' >"$tmp.in.pu"
11 +{
12 + comm -13 "$tmp.in.master" "$tmp.in.pu"
13 + git branch --no-merged pu |
14 + sed -n -e 's/^..//' -e '/\//p'
15 +} >"$tmp.branches"
16 +
17 +git log --first-parent --format="%H %ci" master..next |
18 +sed -e 's/ [0-2][0-9]:[0-6][0-9]:[0-6][0-9] [-+][0-2][0-9][0-6][0-9]$//' >"$tmp.next"
19 +git rev-list master..pu >"$tmp.commits.in.pu"
20 +
21 +format_branch () {
22 + # branch=$1 others=$2
23 + git rev-list --no-merges --topo-order "master..$1" --not $2 >"$tmp.list"
24 + count=$(wc -l <"$tmp.list" | tr -d ' ')
25 + label="* $1 ($(git show -s --format="%ai" $1 | sed -e 's/ .*//')) $count commit"
26 + test "$count" = 1 || label="${label}s"
27 +
28 + count=$(git rev-list "master..$1" | wc -l)
29 + mcount=$(git rev-list "maint..$1" | wc -l)
30 + if test $mcount = $count
31 + then
32 + label="$label."
33 + fi
34 +
35 + echo "$label"
36 + lasttimelabel=
37 + lastfoundmerge=
38 + while read commit
39 + do
40 + merged= merged_with=
41 + while read merge at
42 + do
43 + if test -n "$lastfoundmerge"
44 + then
45 + if test "$lastfoundmerge" = "$merge"
46 + then
47 + lastfoundmerge=
48 + else
49 + continue
50 + fi
51 + fi
52 + mb=$(git merge-base $merge $commit)
53 + if test "$mb" = "$commit"
54 + then
55 + merged=$at merged_with=$merge
56 + else
57 + break
58 + fi
59 + done <"$tmp.next"
60 +
61 + lastfoundmerge=$merged_with
62 + thistimelabel=
63 + if test -n "$merged"
64 + then
65 + thistimelabel=$merged
66 + commitlabel="+"
67 + elif grep "$commit" "$tmp.commits.in.pu" >/dev/null
68 + then
69 + commitlabel="-"
70 + else
71 + commitlabel="."
72 + fi
73 + if test "$lasttimelabel" != "$thistimelabel"
74 + then
75 + with=$(git rev-parse --short $merged_with)
76 + echo " (merged to 'next' on $thistimelabel at $with)"
77 + lasttimelabel=$thistimelabel
78 + fi
79 + git show -s --format=" $commitlabel %s" $commit
80 + done <"$tmp.list"
81 +}
82 +
83 +add_desc () {
84 + kind=$1
85 + shift
86 + test -z "$description" || description="$description;"
87 + others=
88 + while :
89 + do
90 + other=$1
91 + shift
92 + case "$#,$others" in
93 + 0,)
94 + others="$other"
95 + break ;;
96 + 0,?*)
97 + others="$others and $other"
98 + break ;;
99 + *,)
100 + others="$other"
101 + ;;
102 + *,?*)
103 + others="$others, $other"
104 + ;;
105 + esac
106 + done
107 + description="$description $kind $others"
108 +}
109 +
110 +while read b
111 +do
112 + git rev-list --no-merges "master..$b"
113 +done <"$tmp.branches" | sort | uniq -d >"$tmp.shared"
114 +
115 +while read shared
116 +do
117 + b=$(git branch --contains "$shared" | sed -n -e 's/^..//' -e '/\//p')
118 + echo "" $b ""
119 +done <"$tmp.shared" | sort -u >"$tmp.related"
120 +
121 +serial=1
122 +while read b
123 +do
124 + related=$(grep " $b " "$tmp.related" | tr ' ' '\012' | sort -u | sed -e '/^$/d')
125 +
126 + based_on=
127 + used_by=
128 + forks=
129 + same_as=
130 + if test -n "$related"
131 + then
132 + for r in $related
133 + do
134 + test "$b" = "$r" && continue
135 + based=$(git rev-list --no-merges $b..$r | wc -l | tr -d ' ')
136 + bases=$(git rev-list --no-merges $r..$b | wc -l | tr -d ' ')
137 + case "$based,$bases" in
138 + 0,0)
139 + same_as="$same_as$r "
140 + ;;
141 + 0,*)
142 + based_on="$based_on$r "
143 + ;;
144 + *,0)
145 + used_by="$used_by$r "
146 + ;;
147 + *,*)
148 + forks="$forks$r "
149 + ;;
150 + esac
151 + done
152 + fi
153 +
154 + {
155 + format_branch "$b" "$based_on"
156 +
157 + description=
158 + test -z "$same_as" || add_desc 'is same as' $same_as
159 + test -z "$based_on" || add_desc 'uses' $based_on
160 + test -z "$used_by" || add_desc 'is used by' $used_by
161 + test -z "$forks" || add_desc 'is related to' $forks
162 +
163 + test -z "$description" ||
164 + echo " (this branch$description.)"
165 + } >"$tmp.output.$serial"
166 + echo "$b $serial"
167 + serial=$(( $serial + 1 ))
168 +done <"$tmp.branches" >"$tmp.output.toc"
169 +
170 +eval $(date +"monthname=%b month=%m year=%Y date=%d dow=%a")
171 +lead="whats/cooking/$year/$month"
172 +issue=$(
173 + cd Meta &&
174 + git ls-tree -r --name-only HEAD "$lead" | tail -n 1
175 +)
176 +if test -n "$issue"
177 +then
178 + issue=$( expr "$issue" : '.*/0*\([1-9][0-9]*\)\.txt$' )
179 + issue=$(( $issue + 1 ))
180 +else
181 + issue=1
182 +fi
183 +issue=$( printf "%02d" $issue )
184 +mkdir -p "Meta/$lead"
185 +
186 +last=$(
187 + cd Meta &&
188 + git ls-tree -r --name-only HEAD "whats/cooking" | tail -n 1
189 +)
190 +
191 +master_at=$(git rev-parse --verify refs/heads/master)
192 +next_at=$(git rev-parse --verify refs/heads/next)
193 +cat >"$tmp.output.0" <<EOF
194 +To: git@vger.kernel.org
195 +Subject: What's cooking in git.git ($monthname $year, #$issue; $dow, $date)
196 +X-master-at: $master_at
197 +X-next-at: $next_at
198 +
199 +What's cooking in git.git ($monthname $year, #$issue; $dow, $date)
200 +--------------------------------------------------
201 +
202 +Here are the topics that have been cooking. Commits prefixed with '-' are
203 +only in 'pu' while commits prefixed with '+' are in 'next'. The ones
204 +marked with '.' do not appear in any of the branches, but I am still
205 +holding onto them.
206 +
207 +EOF
208 +
209 +if test -z "$NO_TEMPLATE" && test -f "Meta/$last"
210 +then
211 + template="Meta/$last"
212 +else
213 + template=/dev/null
214 +fi
215 +perl -w -e '
216 + my $section = undef;
217 + my $serial = 1;
218 + my $branch = "b:l:u:r:b";
219 + my $tmp = $ARGV[0];
220 + my $last_empty = undef;
221 +
222 + open TOC, ">$tmp.template.toc";
223 + open O, ">$tmp.template.0";
224 +
225 + while (<STDIN>) {
226 + if (defined $section && /^-{20,}/) {
227 + $_ = "\n";
228 + }
229 + if (/^$/) {
230 + $last_empty = 1;
231 + next;
232 + }
233 + if (/\[(.*)\]\s*$/) {
234 + $section = $1;
235 + $branch = undef;
236 + next;
237 + }
238 + if (defined $section && /^\* (\S+) /) {
239 + $branch = $1;
240 + $last_empty = 0;
241 + open O, ">$tmp.template.$serial";
242 + print TOC "$branch $serial $section\n";
243 + $serial++;
244 + }
245 + if (defined $branch) {
246 + print O "\n" if ($last_empty);
247 + $last_empty = 0;
248 + print O "$_";
249 + }
250 + }
251 +' <"$template" "$tmp"
252 +
253 +# Assemble them all
254 +
255 +if test -z "$TO_STDOUT"
256 +then
257 + exec >"Meta/$lead/$issue.txt"
258 +fi
259 +
260 +if test -s "$tmp.template.0"
261 +then
262 + sed -e '/^---------------*/q' <"$tmp.output.0"
263 + sed -e '1,/^---------------*/d' <"$tmp.template.0"
264 +else
265 + cat "$tmp.output.0"
266 +fi | sed -e '$d'
267 +
268 +current='--------------------------------------------------
269 +[New Topics]
270 +'
271 +while read branch serial
272 +do
273 + grep "^$branch " "$tmp.template.toc" >/dev/null && continue
274 + if test -n "$current"
275 + then
276 + echo "$current"
277 + current=
278 + else
279 + echo
280 + fi
281 + cat "$tmp.output.$serial"
282 +done <"$tmp.output.toc"
283 +
284 +current='--------------------------------------------------
285 +[Graduated to "master"]
286 +'
287 +while read branch oldserial section
288 +do
289 + test "$section" = 'Graduated to "master"' && continue
290 + tip=$(git rev-parse --quiet --verify "refs/heads/$branch")
291 + mb=$(git merge-base master $tip)
292 + test "$mb" = "$tip" || continue
293 + if test -n "$current"
294 + then
295 + echo "$current"
296 + current=
297 + else
298 + echo
299 + fi
300 + cat "$tmp.template.$oldserial"
301 +done <"$tmp.template.toc"
302 +
303 +current=
304 +while read branch oldserial section
305 +do
306 + found=$(grep "^$branch " "$tmp.output.toc") || continue
307 + newserial=$(expr "$found" : '[^ ]* \(.*\)')
308 + if test "$section" = "New Topics"
309 + then
310 + section="Old New Topics"
311 + fi
312 + if test "$current" != "$section"
313 + then
314 + current=$section
315 + echo "--------------------------------------------------
316 +[$section]
317 +"
318 + else
319 + echo
320 + fi
321 + cat "$tmp.output.$newserial"
322 + echo "<<"
323 + cat "$tmp.template.$oldserial"
324 + echo ">>"
325 +done <"$tmp.template.toc"