From 5734c66905d69410414b48d08e533268d2601cfc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 6 Jan 2013 22:30:04 -0800 Subject: [PATCH] Meta/GRADUATED: rewrite for simplicity and robustness --- GRADUATED | 196 +++++++++++++++++++++--------------------------------- 1 file changed, 75 insertions(+), 121 deletions(-) diff --git a/GRADUATED b/GRADUATED index aea874f5ac..89a8b84562 100755 --- a/GRADUATED +++ b/GRADUATED @@ -1,141 +1,95 @@ #!/bin/sh -# Older first! -old_maint=$( - git for-each-ref --format='%(refname)' 'refs/heads/maint-*' | - sed -e 's|^refs/heads/||' -) - -# Are older maint branches all included in newer ones? -and_or_thru=thru prev= -for m in $old_maint maint +base= +while : do - if test -n "$prev" - then - test "$(git rev-list $m..$prev | wc -l)" = 0 || { - and_or_thru=and - break - } - fi - prev=$m + case "$1" in + --base=*) + base=${1#*=} ;; + -*) + echo >&2 "Eh? $1" + exit 1 ;; + *) + break ;; + esac + shift done -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" +if test -z "$base" +then + describe=$(git describe "master") + base=$(expr "$describe" : '\(.*\)-\([0-9]*\)-g[0-9a-f]*$') || + base="$describe" + + git rev-parse --verify "$base^0" >/dev/null 2>/dev/null || { + echo >&2 "Eh? where is your base?" + exit 1 + } +fi + +topics= +leftover= +dothis= LF=' ' -# disable pager -GIT_PAGER=cat -export GIT_PAGER +defer () { + leftover="$leftover$1$LF" +} -find_last_tip () { - topic="$(git rev-parse --verify "$1")" integrate="$2" - git rev-list --first-parent --parents "$2" | - sed -n -e " - /^$_x40 $_x40 $topic$/{ - s/^\($_x40\) $_x40 $topic$/\1/p - q - } - " +dothis () { + dothis="$1$LF$LF$dothis" } +one_topic () { + topic="$1" tip="$2" date="$3" + case " $topics" in *" $topic "*) return ;; esac + topics="$topic$topic " -tmp=/tmp/GR.$$ + mergeable=no ready=no label= -trap 'rm -f "$tmp".*' 0 + master_count=$(git rev-list "$base..$tip" | wc -l) + maint_count=$(git rev-list "maint..$tip" | wc -l) -git branch --merged master | sed -n -e '/\//s/^. //p' | sort >"$tmp.master" + test $master_count = $maint_count && mergeable=yes ->"$tmp.known" -for m in $old_maint maint -do - git branch --merged $m | sed -n -e '/\//s/^. //p' | sort >"$tmp.$m" - comm -12 "$tmp.$m" "$tmp.master" >"$tmp.both0" - comm -23 "$tmp.both0" "$tmp.known" >"$tmp.both" - if test -s "$tmp.both" + if current=$(git rev-parse --verify -q "$topic^0") && + test "$current" = "$tip" then - echo "# Graduated to both $m $and_or_thru master" - while read branch - do - d=$(git describe --always $branch) - echo "$(git show -s --format='%ct' "$branch") $branch ;# $d" - done <"$tmp.both" | - sort -r -n | - sed -e 's/^[0-9]* //' \ - -e 's/^/git branch -d /' | - sort -V -k 6,6 - echo - cat "$tmp.known" "$tmp.both" | sort >"$tmp.next" - mv "$tmp.next" "$tmp.known" - fi -done - -comm -13 "$tmp.maint" "$tmp.master" | -{ - while read topic - do - t=$(find_last_tip $topic master) && - test -n "$t" && - m=$(git rev-parse --verify "$t^1") && - test -n "$m" || continue - - # NEEDSWORK: this misses repeated merges - # - # o---o---maint - # / - # .---o---o topic - # / \ \ - # ---o---o---*---*---master - - tsize=$(git rev-list "$m..$topic" | wc -l) - rsize=$(git rev-list "maint..$topic" | wc -l) - - if test $tsize -eq $rsize - then - s=$(git show -s --pretty="tformat:%ct %H" $t) - echo "$s $topic" - else - s=$(git show -s --pretty="tformat:%ct %H" $t) - echo >&3 "$s $topic" - fi - done 3>"$tmp.unmergeable" >"$tmp.mergeable" - - if test -s "$tmp.unmergeable" + ready=yes + label="$topic" + elif test -z "$current" then - echo ": # Graduated to master; unmergeable to maint" - sort -n "$tmp.unmergeable" | - while read timestamp merge topic - do - git show -s --pretty="format:: # %h %cd" $merge - echo "git branch -d $topic" - done - echo + ready=yes + label="$tip" fi - if test -s "$tmp.mergeable" - then - sort -n "$tmp.mergeable" | - while read timestamp merge topic - do - { - git show -s --pretty="format:%h %cd" $merge - git log --pretty=oneline --abbrev-commit maint..$topic - } | - sed -e 's/^/: # /' - maint=maint - these=$(git rev-list maint..$topic) - for m in $old_maint maint - do - those=$(git rev-list $m..$topic) - if test "z$these" = "z$those" - then - maint=$m - break - fi - done - echo "git checkout $maint && git merge $topic" - echo - done - fi + case "$mergeable,$ready" in + no,*) + defer "# $topic: not mergeable ($master_count vs $maint_count)" + ;; + yes,no) + topic_count=$(git rev-list "$base..$current" | wc -l) + defer "# $topic: not ready ($master_count vs $topic_count)" + ;; + yes,yes) + insn="$label # $master_count ($date)" + insn="$insn$LF$(git log --oneline "maint..$tip" | sed -e "s/^/# /")" + dothis "$insn" + ;; + esac +} + +git log --first-parent --min-parents=2 --max-parents=2 \ + --format='%ci %H %P %s' "$base..master" | { + while read date time zone commit parent tip subject + do + topic=$(expr "$subject" : "Merge branch '\(.*\)'$") || { + echo >&2 "Cannot parse $commit ($subject)" + continue + } + one_topic "$topic" "$tip" "$date" + done + echo "$leftover" + echo "$dothis" }