#!/bin/sh LANG=C LC_ALL=C GIT_PAGER=cat export LANG LC_ALL GIT_PAGER tmp=/var/tmp/cook.$$ trap 'rm -f "$tmp".*' 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" count=$(git rev-list "master..$1" | wc -l) mcount=$(git rev-list "maint..$1" | wc -l) if test $mcount = $count then label="$label." fi 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 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" } while read b do git rev-list --no-merges "master..$b" done <"$tmp.branches" | sort | uniq -d >"$tmp.shared" 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= used_by= forks= same_as= if test -n "$related" then for r in $related do test "$b" = "$r" && continue 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) same_as="$same_as$r " ;; 0,*) based_on="$based_on$r " ;; *,0) used_by="$used_by$r " ;; *,*) 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 test -z "$used_by" || add_desc 'is used by' $used_by test -z "$forks" || add_desc 'is related to' $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") lead="whats/cooking/$year/$month" issue=$( cd Meta && git ls-tree -r --name-only HEAD "$lead" | tail -n 1 ) if test -n "$issue" then issue=$( expr "$issue" : '.*/0*\([1-9][0-9]*\)\.txt$' ) issue=$(( $issue + 1 )) else issue=1 fi issue=$( printf "%02d" $issue ) mkdir -p "Meta/$lead" last=$( cd Meta && git ls-tree -r --name-only HEAD "whats/cooking" | tail -n 1 ) master_at=$(git rev-parse --verify refs/heads/master) next_at=$(git rev-parse --verify refs/heads/next) cat >"$tmp.output.0" <$tmp.template.toc"; open O, ">$tmp.template.0"; while () { if (defined $section && /^-{20,}/) { $_ = "\n"; } if (/^$/) { $last_empty = 1; next; } if (/\[(.*)\]\s*$/) { $section = $1; $branch = undef; next; } if (defined $section && /^\* (\S+) /) { $branch = $1; $last_empty = 0; open O, ">$tmp.template.$serial"; print TOC "$branch $serial $section\n"; $serial++; } if (defined $branch) { print O "\n" if ($last_empty); $last_empty = 0; print O "$_"; } } ' <"$template" "$tmp" # Assemble them all if test -z "$TO_STDOUT" then exec >"Meta/$lead/$issue.txt" fi if test -s "$tmp.template.0" then sed -e '/^---------------*/q' <"$tmp.output.0" sed -e '1,/^---------------*/d' <"$tmp.template.0" else cat "$tmp.output.0" fi | sed -e '$d' current='-------------------------------------------------- [New Topics] ' while read branch serial do grep "^$branch " "$tmp.template.toc" >/dev/null && continue if test -n "$current" then echo "$current" current= else echo fi cat "$tmp.output.$serial" done <"$tmp.output.toc" current='-------------------------------------------------- [Graduated to "master"] ' while read branch oldserial section do test "$section" = 'Graduated to "master"' && continue tip=$(git rev-parse --quiet --verify "refs/heads/$branch") 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 "$section" = "New Topics" then section="Old New Topics" fi if test "$current" != "$section" then current=$section echo "-------------------------------------------------- [$section] " else echo fi cat "$tmp.output.$newserial" echo "<<" cat "$tmp.template.$oldserial" echo ">>" done <"$tmp.template.toc"