You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
9.5 KiB
449 lines
9.5 KiB
#!/bin/sh |
|
|
|
LANG=C LC_ALL=C GIT_PAGER=cat |
|
export LANG LC_ALL GIT_PAGER |
|
|
|
tmpdir=/var/tmp/cook.$$ |
|
mkdir "$tmpdir" || exit |
|
tmp="$tmpdir/t" |
|
trap 'rm -fr "$tmpdir"' 0 |
|
|
|
git branch --merged "master" | sed -n -e 's/^..//' -e '/\//p' >"$tmp.in.master" |
|
git branch --merged "pu" | sed -n -e 's/^..//' -e '/\//p' >"$tmp.in.pu" |
|
{ |
|
comm -13 "$tmp.in.master" "$tmp.in.pu" |
|
git branch --no-merged pu | |
|
sed -n -e 's/^..//' -e '/\//p' |
|
} >"$tmp.branches" |
|
|
|
git log --first-parent --format="%H %ci" master..next | |
|
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" |
|
git rev-list master..pu >"$tmp.commits.in.pu" |
|
|
|
format_branch () { |
|
# branch=$1 others=$2 |
|
git rev-list --no-merges --topo-order "master..$1" --not $2 >"$tmp.list" |
|
count=$(wc -l <"$tmp.list" | tr -d ' ') |
|
label="* $1 ($(git show -s --format="%ai" $1 | sed -e 's/ .*//')) $count commit" |
|
test "$count" = 1 || label="${label}s" |
|
|
|
echo "$label" |
|
lasttimelabel= |
|
lastfoundmerge= |
|
while read commit |
|
do |
|
merged= merged_with= |
|
while read merge at |
|
do |
|
if test -n "$lastfoundmerge" |
|
then |
|
if test "$lastfoundmerge" = "$merge" |
|
then |
|
lastfoundmerge= |
|
else |
|
continue |
|
fi |
|
fi |
|
mb=$(git merge-base $merge $commit) |
|
if test "$mb" = "$commit" |
|
then |
|
merged=$at merged_with=$merge |
|
else |
|
break |
|
fi |
|
done <"$tmp.next" |
|
|
|
lastfoundmerge=$merged_with |
|
thistimelabel= |
|
if test -n "$merged" |
|
then |
|
thistimelabel=$merged |
|
commitlabel="+" |
|
elif grep "$commit" "$tmp.commits.in.pu" >/dev/null |
|
then |
|
commitlabel="-" |
|
else |
|
commitlabel="." |
|
fi |
|
if test "$lasttimelabel" != "$thistimelabel" |
|
then |
|
with=$(git rev-parse --short $merged_with) |
|
echo " (merged to 'next' on $thistimelabel at $with)" |
|
lasttimelabel=$thistimelabel |
|
fi |
|
git show -s --format=" $commitlabel %s" $commit |
|
done <"$tmp.list" |
|
} |
|
|
|
add_desc () { |
|
kind=$1 |
|
shift |
|
test -z "$description" || description="$description;" |
|
others= |
|
while : |
|
do |
|
other=$1 |
|
case "$other" in |
|
"#EPO-"*) other="early parts of ${other#"#EPO-"}" |
|
esac |
|
shift |
|
case "$#,$others" in |
|
0,) |
|
others="$other" |
|
break ;; |
|
0,?*) |
|
others="$others and $other" |
|
break ;; |
|
*,) |
|
others="$other" |
|
;; |
|
*,?*) |
|
others="$others, $other" |
|
;; |
|
esac |
|
done |
|
description="$description $kind $others" |
|
} |
|
|
|
show_topic () { |
|
old=$1 new=$2 |
|
|
|
sed -n -e '/^ ..*/p' -e '/^\* /p' "$old" >"$tmp.old.nc" |
|
sed -n -e '/^ ..*/p' -e '/^\* /p' "$new" >"$tmp.new.nc" |
|
if cmp "$tmp.old.nc" "$tmp.new.nc" >/dev/null |
|
then |
|
cat "$old" |
|
else |
|
cat "$new" |
|
echo "<<" |
|
cat "$old" |
|
echo ">>" |
|
fi |
|
} |
|
|
|
compare_topic () { |
|
b=$1 r=$2 |
|
based=$(git rev-list --no-merges $b..$r | wc -l | tr -d ' ') |
|
bases=$(git rev-list --no-merges $r..$b | wc -l | tr -d ' ') |
|
case "$based,$bases" in |
|
0,0) echo same; exit ;; |
|
0,*) echo left; exit ;; |
|
*,0) echo right; exit ;; |
|
esac |
|
|
|
if test $based -lt $bases |
|
then |
|
echo left-p |
|
else |
|
echo fork |
|
fi |
|
} |
|
|
|
# List commits that are shared between more than one topic branches |
|
while read b |
|
do |
|
git rev-list --no-merges "master..$b" |
|
done <"$tmp.branches" | sort | uniq -d >"$tmp.shared" |
|
|
|
# Set of branches related to each other due to sharing the same commit |
|
while read shared |
|
do |
|
b=$(git branch --contains "$shared" | sed -n -e 's/^..//' -e '/\//p') |
|
echo "" $b "" |
|
done <"$tmp.shared" | sort -u >"$tmp.related" |
|
|
|
serial=1 |
|
while read b |
|
do |
|
related=$(grep " $b " "$tmp.related" | tr ' ' '\012' | sort -u | sed -e '/^$/d') |
|
|
|
based_on= based_on_msg= |
|
used_by= |
|
forks= |
|
same_as= |
|
if test -n "$related" |
|
then |
|
for r in $related |
|
do |
|
test "$b" = "$r" && continue |
|
case "$(compare_topic "$b" "$r")" in |
|
same) |
|
same_as="$same_as$r " |
|
;; |
|
left) |
|
based_on="$based_on$r " |
|
based_on_msg="$based_on_msg$r " |
|
;; |
|
left-p) |
|
based_on="$based_on$r " |
|
based_on_msg="${based_on_msg}#EPO-$r " |
|
;; |
|
right) |
|
used_by="$used_by$r " |
|
;; |
|
fork) |
|
forks="$forks$r " |
|
;; |
|
esac |
|
done |
|
fi |
|
|
|
{ |
|
format_branch "$b" "$based_on" |
|
|
|
description= |
|
test -z "$same_as" || add_desc 'is same as' $same_as |
|
test -z "$based_on" || add_desc 'uses' $based_on_msg |
|
test -z "$used_by" || add_desc 'is used by' $used_by |
|
test -z "$forks" || add_desc 'shares commits with' $forks |
|
|
|
test -z "$description" || |
|
echo " (this branch$description.)" |
|
} >"$tmp.output.$serial" |
|
echo "$b $serial" |
|
serial=$(( $serial + 1 )) |
|
done <"$tmp.branches" >"$tmp.output.toc" |
|
|
|
eval $(date +"monthname=%b month=%m year=%Y date=%d dow=%a") |
|
|
|
incremental=$( |
|
cd Meta && |
|
if git diff --quiet --no-ext-diff HEAD -- whats-cooking.txt >/dev/null |
|
then |
|
echo no |
|
else |
|
echo yes |
|
fi |
|
) |
|
|
|
# Find the current issue |
|
eval $(sed -ne '/^Subject: /{ |
|
s/^Subject: What.s cooking in git.git (\([A-Z][a-z][a-z]\) \([0-9][0-9][0-9][0-9]\), #\([0-9][0-9]*\); [A-Z][a-z][a-z], [0-9][0-9])$/lastmon=\1 lastyear=\2 lastissue=\3/p |
|
q |
|
}' Meta/whats-cooking.txt) |
|
if test "$monthname $year" = "$lastmon $lastyear" |
|
then |
|
while case "$lastissue" in 0?*) ;; *) break ;; esac |
|
do |
|
lastissue=${lastissue#0} |
|
done |
|
if test "$incremental" = no |
|
then |
|
issue=$(( $lastissue + 1 )) |
|
else |
|
issue=$(( $lastissue + 0 )) |
|
fi |
|
else |
|
issue=1 |
|
fi |
|
|
|
issue=$( printf "%02d" $issue ) |
|
last=whats-cooking.txt |
|
|
|
master_at=$(git rev-parse --verify refs/heads/master) |
|
next_at=$(git rev-parse --verify refs/heads/next) |
|
cat >"$tmp.output.blurb" <<EOF |
|
To: git@vger.kernel.org |
|
Subject: What's cooking in git.git ($monthname $year, #$issue; $dow, $date) |
|
X-master-at: $master_at |
|
X-next-at: $next_at |
|
|
|
What's cooking in git.git ($monthname $year, #$issue; $dow, $date) |
|
-------------------------------------------------- |
|
|
|
Here are the topics that have been cooking. Commits prefixed with '-' are |
|
only in 'pu' while commits prefixed with '+' are in 'next'. The ones |
|
marked with '.' do not appear in any of the branches, but I am still |
|
holding onto them. |
|
|
|
EOF |
|
|
|
if test -z "$NO_TEMPLATE" && test -f "Meta/$last" |
|
then |
|
template="Meta/$last" |
|
else |
|
template=/dev/null |
|
fi |
|
perl -w -e ' |
|
my $section = undef; |
|
my $serial = 1; |
|
my $blurb = "b..l..u..r..b"; |
|
my $branch = $blurb; |
|
my $tmp = $ARGV[0]; |
|
my $incremental = $ARGV[1] eq "yes"; |
|
my $last_empty = undef; |
|
my (@section, %section, @branch, %branch, %description, @leader); |
|
my $in_unedited_olde = 0; |
|
|
|
while (<STDIN>) { |
|
if ($in_unedited_olde) { |
|
if (/^>>$/) { |
|
$in_unedited_olde = 0; |
|
$_ = " | $_"; |
|
} |
|
} elsif (/^<<$/) { |
|
$in_unedited_olde = 1; |
|
} |
|
|
|
if ($in_unedited_olde) { |
|
$_ = " | $_"; |
|
} |
|
|
|
if (defined $section && /^-{20,}$/) { |
|
$_ = "\n"; |
|
} |
|
if (/^$/) { |
|
$last_empty = 1; |
|
next; |
|
} |
|
if (/^\[(.*)\]\s*$/) { |
|
$section = $1; |
|
$branch = undef; |
|
if ($section eq "New Topics" && !$incremental) { |
|
$section = "Old New Topics"; |
|
} |
|
if (!exists $section{$section}) { |
|
push @section, $section; |
|
$section{$section} = []; |
|
} |
|
next; |
|
} |
|
if (defined $section && /^\* (\S+) /) { |
|
$branch = $1; |
|
$last_empty = 0; |
|
if (!exists $branch{$branch}) { |
|
push @branch, [$branch, $section]; |
|
$branch{$branch} = 1; |
|
} |
|
push @{$section{$section}}, $branch; |
|
} |
|
if (defined $branch) { |
|
my $was_last_empty = $last_empty; |
|
$last_empty = 0; |
|
if (!exists $description{$branch}) { |
|
$description{$branch} = []; |
|
} |
|
if ($was_last_empty) { |
|
push @{$description{$branch}}, "\n"; |
|
} |
|
push @{$description{$branch}}, $_; |
|
} |
|
} |
|
|
|
if (open I, "<$tmp.output.toc") { |
|
$section = "New Topics"; |
|
while (<I>) { |
|
my ($branch, $oldserial) = /^(\S*) (\d+)$/; |
|
next if (exists $branch{$branch}); |
|
if (!exists $section{$section}) { |
|
# Have it at the beginning |
|
unshift @section, $section; |
|
$section{$section} = []; |
|
} |
|
push @{$section{$section}}, $branch; |
|
push @branch, [$branch, $section]; |
|
$branch{$branch} = 1; |
|
if (!exists $description{$branch}) { |
|
$description{$branch} = []; |
|
} |
|
open II, "<$tmp.output.$oldserial"; |
|
while (<II>) { |
|
push @{$description{$branch}}, $_; |
|
} |
|
close II; |
|
} |
|
close I; |
|
} |
|
|
|
while (0 <= @{$description{$blurb}}) { |
|
my $last = pop @{$description{$blurb}}; |
|
if ($last =~ /^$/ || $last =~ /^-{20,}$/) { |
|
next; |
|
} else { |
|
push @{$description{$blurb}}, $last; |
|
last; |
|
} |
|
} |
|
|
|
open O, ">$tmp.template.blurb"; |
|
for (@{$description{$blurb}}) { |
|
print O $_; |
|
} |
|
close O; |
|
|
|
open TOC, ">$tmp.template.toc"; |
|
$serial = 1; |
|
for my $section (@section) { |
|
for my $branch (@{$section{$section}}) { |
|
print TOC "$branch $serial $section\n"; |
|
open O, ">$tmp.template.$serial"; |
|
for (@{$description{$branch}}) { |
|
print O $_; |
|
} |
|
close O; |
|
$serial++; |
|
} |
|
} |
|
' <"$template" "$tmp" "$incremental" |
|
|
|
tmpserial=$( |
|
tail -n 1 "$tmp.template.toc" | |
|
read branch serial section && |
|
echo $serial |
|
) |
|
|
|
# Assemble them all |
|
|
|
if test -z "$TO_STDOUT" |
|
then |
|
exec >"Meta/whats-cooking.txt" |
|
fi |
|
|
|
if test -s "$tmp.template.blurb" |
|
then |
|
sed -e '/^---------------*$/q' <"$tmp.output.blurb" |
|
sed -e '1,/^---------------*$/d' <"$tmp.template.blurb" |
|
else |
|
cat "$tmp.output.blurb" |
|
fi |
|
|
|
current=' |
|
-------------------------------------------------- |
|
[Graduated to "master"] |
|
' |
|
while read branch oldserial section |
|
do |
|
test "$section" = 'Graduated to "master"' && |
|
test "$incremental" = no && continue |
|
|
|
tip=$(git rev-parse --quiet --verify "refs/heads/$branch") || continue |
|
mb=$(git merge-base master $tip) |
|
test "$mb" = "$tip" || continue |
|
if test -n "$current" |
|
then |
|
echo "$current" |
|
current= |
|
else |
|
echo |
|
fi |
|
cat "$tmp.template.$oldserial" |
|
done <"$tmp.template.toc" |
|
|
|
current= |
|
while read branch oldserial section |
|
do |
|
found=$(grep "^$branch " "$tmp.output.toc") || continue |
|
newserial=$(expr "$found" : '[^ ]* \(.*\)') |
|
if test "$current" != "$section" |
|
then |
|
current=$section |
|
echo " |
|
-------------------------------------------------- |
|
[$section] |
|
" |
|
else |
|
echo |
|
fi |
|
|
|
show_topic "$tmp.template.$oldserial" "$tmp.output.$newserial" |
|
done <"$tmp.template.toc"
|
|
|