Browse Source

Meta/GRADUATED: rewrite for simplicity and robustness

todo
Junio C Hamano 12 years ago
parent
commit
5734c66905
  1. 196
      GRADUATED

196
GRADUATED

@ -1,141 +1,95 @@ @@ -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"
}

Loading…
Cancel
Save