]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Meta/GRADUATED: rewrite for simplicity and robustness
authorJunio C Hamano <gitster@pobox.com>
Mon, 7 Jan 2013 06:30:04 +0000 (22:30 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Jan 2013 06:30:04 +0000 (22:30 -0800)
GRADUATED

index aea874f5ac77cff0baaced0595269bc3512c1120..89a8b845628c22249b9d03b2a176fdd61f999ce3 100755 (executable)
--- a/GRADUATED
+++ b/GRADUATED
 #!/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"
 }