| 1 | #!/bin/sh |
| 2 | |
| 3 | base= ignore_file= |
| 4 | while : |
| 5 | do |
| 6 | case "$1" in |
| 7 | --base=*) |
| 8 | base=${1#*=} ;; |
| 9 | --ignore=*) |
| 10 | ignore_file=${1#*=} ;; |
| 11 | -*) |
| 12 | echo >&2 "Eh? $1" |
| 13 | exit 1 ;; |
| 14 | *) |
| 15 | break ;; |
| 16 | esac |
| 17 | shift |
| 18 | done |
| 19 | |
| 20 | if test -z "$base" |
| 21 | then |
| 22 | describe=$(git describe "master") |
| 23 | base=$(expr "$describe" : '\(.*\)-\([0-9]*\)-g[0-9a-f]*$') || |
| 24 | base="$describe" |
| 25 | |
| 26 | git rev-parse --verify "$base^0" >/dev/null 2>/dev/null || { |
| 27 | echo >&2 "Eh? where is your base?" |
| 28 | exit 1 |
| 29 | } |
| 30 | fi |
| 31 | |
| 32 | topics= leftover= dothis= |
| 33 | LF=' |
| 34 | ' |
| 35 | |
| 36 | ignores= |
| 37 | if test -f "$ignore_file" |
| 38 | then |
| 39 | while read ignore rest |
| 40 | do |
| 41 | test -n "$ignore" && |
| 42 | if ignore=$(git rev-parse -q --verify $ignore) |
| 43 | then |
| 44 | : |
| 45 | elif ignore=$(expr "$rest" : '.* \([0-9a-f]\{40\}\)$') |
| 46 | then |
| 47 | : |
| 48 | else |
| 49 | continue |
| 50 | fi |
| 51 | ignores="$ignores$ignore " |
| 52 | done <"$ignore_file" |
| 53 | fi |
| 54 | |
| 55 | defer () { |
| 56 | leftover="$leftover$1$LF" |
| 57 | } |
| 58 | |
| 59 | dothis () { |
| 60 | dothis="$1$LF$LF$dothis" |
| 61 | } |
| 62 | |
| 63 | one_topic () { |
| 64 | topic="$2" tip="$3" date="$4" merged="$1" |
| 65 | case " $topics" in *" $topic "*) return ;; esac |
| 66 | topics="$topics$topic " |
| 67 | |
| 68 | contam_count=$(git rev-list "maint..$tip" | grep -F "$merges_to_master" | wc -l) |
| 69 | if test "$contam_count" != 0 |
| 70 | then |
| 71 | echo "**** forked from master $topic ****" |
| 72 | return |
| 73 | fi |
| 74 | |
| 75 | maint_count=$(git rev-list "maint..$tip" | wc -l) |
| 76 | if test "$maint_count" = 0 |
| 77 | then |
| 78 | echo "**** already merged $topic ****" |
| 79 | return ;# already merged |
| 80 | fi |
| 81 | |
| 82 | ready=no label= |
| 83 | |
| 84 | master_count=$(git rev-list "$base..$tip" | wc -l) |
| 85 | if test $maint_count -le $master_count |
| 86 | then |
| 87 | mergeable=yes |
| 88 | else |
| 89 | mergeable=no |
| 90 | fi |
| 91 | |
| 92 | if current=$(git rev-parse --verify -q "$topic^0") && |
| 93 | test "$current" = "$tip" |
| 94 | then |
| 95 | ready=yes |
| 96 | label="$topic" |
| 97 | elif test -z "$current" |
| 98 | then |
| 99 | ready=yes |
| 100 | label="$tip" |
| 101 | fi |
| 102 | |
| 103 | case "$mergeable,$ready" in |
| 104 | no,*) |
| 105 | comment="# $topic: not mergeable ($master_count vs $maint_count)" |
| 106 | comment="$comment$LF# $merged" |
| 107 | defer "$comment" |
| 108 | ;; |
| 109 | yes,no) |
| 110 | topic_count=$(git rev-list "$base..$current" | wc -l) |
| 111 | |
| 112 | comment="# $topic: not ready ($master_count vs $topic_count)" |
| 113 | comment="$comment$LF# $merged" |
| 114 | defer "$comment" |
| 115 | ;; |
| 116 | yes,yes) |
| 117 | insn="$label" |
| 118 | if test $maint_count = $master_count |
| 119 | then |
| 120 | insn="$insn # $master_count ($date) $merged" |
| 121 | else |
| 122 | insn="$insn # $maint_count/$master_count ($date) $merged" |
| 123 | fi |
| 124 | insn="$insn$LF$(git log --oneline "maint..$tip" | sed -e "s/^/# /")" |
| 125 | dothis "$insn" |
| 126 | ;; |
| 127 | esac |
| 128 | } |
| 129 | |
| 130 | merges_to_master="$(git rev-list --merges $base..master)" |
| 131 | |
| 132 | git log --first-parent --min-parents=2 --max-parents=2 \ |
| 133 | --format='%ci %H %P %s' "$base..master" | { |
| 134 | while read date time zone commit parent tip subject |
| 135 | do |
| 136 | case " $ignores" in *" $commit "*) continue ;; esac |
| 137 | topic=$(expr "$subject" : "Merge branch '\(.*\)'$") || { |
| 138 | defer "# ignoring $commit ($subject)" |
| 139 | continue |
| 140 | } |
| 141 | one_topic "$commit" "$topic" "$tip" "$date" |
| 142 | done |
| 143 | echo "$leftover" |
| 144 | echo "$dothis" |
| 145 | } |