What's cooking (2020/07 #06)
[git] / GRADUATED
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 }