What's cooking (2021/02 #04)
[git] / amlook
1 #!/bin/sh
2 # Usage:
3 # Meta/amlook <mbox (for single message from MUA) or
4 # Meta/amlook id1 id2... (from the command line)
5 # Meta/amlook --gc
6
7 MASTER=master
8
9 find_commit () {
10         in= commits=
11
12         if test -z "$commits"
13         then
14                 # I know I know there should be "notes grep" command...
15                 commits=$(
16                         git grep -l -e "$1" notes/amlog |
17                         sed -e 's|^notes/amlog:||' -e 's|/||g'
18                 )
19         fi
20
21         if test -z "$commits"
22         then
23                 commits=$(sed -ne "s|^\([0-9a-f]\{40\}\) $1|\1|p" .git/am.log)
24         fi
25
26         if test -z "$commits"
27         then
28                 echo "Never applied"
29                 return
30         fi
31
32         echo "$commits"
33
34         found=$(
35                 echo "$commits" |
36                 while read commit
37                 do
38                         git branch --with $commit
39                 done | sed -e 's|^..||' |
40                 sort -u |
41                 tr '\012' ' '
42         )
43         if test -z "$found"
44         then
45                 echo "Not merged ($commits)"
46                 return
47         fi
48         case " $found " in
49         *' maint '*) in=maint ;;
50         *" $MASTER "*) in=$MASTER ;;
51         *' next '*) in=next ;;
52         esac
53         if test -n "$in"
54         then
55                 echo "Found in $in"
56         else
57                 echo "Found in $found"
58         fi
59 }
60
61 garbage_collect () {
62         cutoff_days=${1-"180"} &&
63         git notes --ref amlog list |
64         sed -e 's/.* //' |
65         xargs -n 1 git show -s --format="%ci %H" 2>/dev/null |
66         perl -e '
67                 my @time = localtime(time() - $ARGV[0] * 24 * 3600);
68                 my $cutoff = sprintf("%04d-%02d-%02d 00:00:00",
69                                 $time[5]+1900, $time[4]+1, $time[3]);
70                 while (<STDIN>) {
71                         if ($_ le $cutoff) {
72                                 s/.* //;
73                                 print;
74                         }
75                 }
76         ' "$cutoff_days" >..gcinput
77
78 : <<\INVALID
79         : (
80                 GIT_INDEX_FILE=/tmp/amlook.$$.tmp &&
81                 export GIT_INDEX_FILE &&
82                 rm -f "$GIT_INDEX_FILE" &&
83                 git read-tree refs/notes/amlog &&
84                 xargs git rm -f &&
85                 T=$(git write-tree) &&
86                 C=$(echo Prune amlog | git commit-tree $T -p refs/notes/amlog) &&
87                 git update-ref -m "Prune amlog" refs/notes/amlog $C
88         )
89 INVALID
90 }
91
92 if test $# = 0
93 then
94         msg=$(sed -ne '
95                 /^[     ]/{
96                         # Append continuation line
97                         H
98                         x
99                         s/\n//
100                         x
101                         n
102                 }
103                 # Hold this new line, and look at what is in the hold space
104                 x
105                 # Is it the Message-ID line?  If so, spit out and finish.
106                 /^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:[       ]*/{
107                         s///p
108                         q
109                 }
110                 # Otherwise, check if this new line is empty
111                 x
112                 # Is it?  Then we are done with the header
113                 /^$/b end
114                 # Otherwise we need to hold onto this header line
115                 x
116                 # And start the next cycle
117                 b
118         : end
119                 q
120         ') &&
121         find_commit "$msg"
122 elif test "$1" = "--gc"
123 then
124         shift
125         garbage_collect "$@"
126 elif test "$1" == "--squash"
127 then
128         L=notes/amlog &&
129         git notes --ref=$L prune &&
130         C=$(echo amlog | git commit-tree refs/$L^{tree}) &&
131         git update-ref refs/$L $C
132 else
133         for msg
134         do
135                 find_commit "$msg"
136         done
137 fi