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 @@
#!/bin/sh #!/bin/sh


# Older first! base=
old_maint=$( while :
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
do do
if test -n "$prev" case "$1" in
then --base=*)
test "$(git rev-list $m..$prev | wc -l)" = 0 || { base=${1#*=} ;;
and_or_thru=and -*)
break echo >&2 "Eh? $1"
} exit 1 ;;
fi *)
prev=$m break ;;
esac
shift
done done


_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' if test -z "$base"
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" 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=' LF='
' '


# disable pager defer () {
GIT_PAGER=cat leftover="$leftover$1$LF"
export GIT_PAGER }


find_last_tip () { dothis () {
topic="$(git rev-parse --verify "$1")" integrate="$2" dothis="$1$LF$LF$dothis"
git rev-list --first-parent --parents "$2" |
sed -n -e "
/^$_x40 $_x40 $topic$/{
s/^\($_x40\) $_x40 $topic$/\1/p
q
}
"
} }


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" if current=$(git rev-parse --verify -q "$topic^0") &&
for m in $old_maint maint test "$current" = "$tip"
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"
then then
echo "# Graduated to both $m $and_or_thru master" ready=yes
while read branch label="$topic"
do elif test -z "$current"
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"
then then
echo ": # Graduated to master; unmergeable to maint" ready=yes
sort -n "$tmp.unmergeable" | label="$tip"
while read timestamp merge topic
do
git show -s --pretty="format:: # %h %cd" $merge
echo "git branch -d $topic"
done
echo
fi 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" case "$mergeable,$ready" in
echo no,*)
done defer "# $topic: not mergeable ($master_count vs $maint_count)"
fi ;;
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