Meta/worklog: new script
Junio C Hamano committed
Apr 28, 2011 at 16:48 UTC
d1d05d1d722a1317d1d5cabad30e98b56f92927a
1 file changed
+219
worklog
new
+219
@@ -0,0 +1,219 @@
1
+#!/usr/bin/perl
2
+
3
+use strict;
4
+use warnings;
5
+use Getopt::Long;
6
+use Time::Local;
7
+
8
+sub seconds_in_a_week () {
9
+ return 7 * 24 * 3600;
10
+}
11
+
12
+my $verbose = 0;
13
+my $week;
14
+my $cycles;
15
+my $bow = 0;
16
+
17
+sub bow {
18
+ my ($week) = @_;
19
+ my (@time, $time);
20
+
21
+ if (!defined $week) {
22
+ $time = time;
23
+ } elsif ($week =~ /^\d+$/) {
24
+ $time = time - seconds_in_a_week * $week;
25
+ } else {
26
+ my ($year, $mon, $mday) = ($week =~ /^(\d{4})-(\d{2})-(\d{2})$/);
27
+ unless (defined $year && defined $mon && defined $mday &&
28
+ 1 <= $mon && $mon <= 12 &&
29
+ 1 <= $mday && $mday <= 31) {
30
+ die "Bad week specification: $week";
31
+ }
32
+ $time = timelocal(0, 0, 0, $mday, $mon - 1, $year - 1900);
33
+ }
34
+
35
+ @time = localtime($time);
36
+ if ($time[6] <= $bow) {
37
+ $time -= seconds_in_a_week;
38
+ @time = localtime($time);
39
+ }
40
+ $time -= $time[0] + 60 * ($time[1] + 60 * ($time[2] + 24 * ($time[6] - $bow)));
41
+ return $time;
42
+}
43
+
44
+if (!GetOptions(
45
+ "verbose!" => \$verbose,
46
+ "week=s" => \$week,
47
+ "cycles=i" => \$cycles,
48
+ "bow=i" => \$bow,
49
+ )) {
50
+ print STDERR "$0 [-v]\n";
51
+ exit 1;
52
+}
53
+
54
+if (defined $cycles && !defined $week) {
55
+ $week = bow($week);
56
+ $week -= ($cycles - 1) * seconds_in_a_week;
57
+} else {
58
+ $week = bow($week);
59
+}
60
+if (!defined $cycles) {
61
+ my $ends = time();
62
+ my $clock = $week;
63
+ for ($cycles = 0; $clock < $ends; $cycles++) {
64
+ $clock += seconds_in_a_week;
65
+ }
66
+}
67
+
68
+my $cull_old = "--since=" . $week;
69
+
70
+sub plural {
71
+ my ($number, $singular, $plural) = @_;
72
+ return ($number == 1) ? "$number $singular": "$number $plural";
73
+}
74
+
75
+sub fmt_join {
76
+ my ($leader, $limit, $joiner, @ary) = @_;
77
+ my @result = ();
78
+ my $width = 0;
79
+ my $wj = length($joiner);
80
+ my $wl = length($leader);
81
+
82
+ for my $item (@ary) {
83
+ my $need_joiner;
84
+ if ($width == 0) {
85
+ $width += $wl;
86
+ push @result, $leader;
87
+ $need_joiner = 0;
88
+ } else {
89
+ $need_joiner = 1;
90
+ }
91
+ my $len = length($item);
92
+ if (($need_joiner ? $wj : 0) + $len + $width < $limit) {
93
+ if ($need_joiner) {
94
+ $width += $wj;
95
+ push @result, $joiner;
96
+ }
97
+ $width += $len;
98
+ push @result, $item;
99
+ } else {
100
+ if ($width) {
101
+ push @result, "\n";
102
+ $width = 0;
103
+ }
104
+ $width += $wl;
105
+ push @result, $leader;
106
+ $width += $len;
107
+ push @result, $item;
108
+ }
109
+ }
110
+ push @result, "\n" unless ($result[-1] eq "\n");
111
+ return join("", @result);
112
+}
113
+
114
+my %patch;
115
+my %dates;
116
+my %patch_by_date;
117
+my %merge_by_branch_date;
118
+my @integrate = (['master', ', to include in the next release'],
119
+ ['next', ' for public testing'],
120
+ ['maint', ', to include in the maintenance release'],
121
+);
122
+
123
+open I, "-|", ("git", "log", "--pretty=%ci %H %an <%ae>\001%s",
124
+ $cull_old, "--glob=refs/heads",
125
+ "--no-merges") or die;
126
+while (<I>) {
127
+ my ($date, $sha1, $rest) = /^([-0-9]+) [:0-9]+ [-+][0-9]{4} ([0-9a-f]+) (.*)$/;
128
+ $patch_by_date{$date} ||= [];
129
+ push @{$patch_by_date{$date}}, $sha1;
130
+ my ($name, $subject) = split(/\001/, $rest, 2);
131
+ $patch{$sha1} = [$sha1, $name, $subject];
132
+ $dates{$date}++;
133
+}
134
+close (I) or die;
135
+
136
+for my $branch (map { $_->[0] } @integrate) {
137
+ open I, "-|", ("git", "log", "--pretty=%ci %H %s",
138
+ $cull_old,
139
+ "--first-parent",
140
+ "--merges",
141
+ $branch) or die;
142
+ while (<I>) {
143
+ my ($date, $sha1, $rest) = /^([-0-9]+) [:0-9]+ [-+][0-9]{4} ([0-9a-f]+) (.*)$/;
144
+ my $msg = $rest;
145
+ $msg =~ s/^Merge branch //;
146
+ $msg =~ s/ into \Q$branch\E$//;
147
+ $msg =~ s/^'(.*)'$/$1/;
148
+
149
+ next if (grep { $_ eq $msg } map { $_->[0] } @integrate);
150
+
151
+ $merge_by_branch_date{$branch} ||= {};
152
+ $merge_by_branch_date{$branch}{$date} ||= [];
153
+ push @{$merge_by_branch_date{$branch}{$date}}, $sha1;
154
+ $patch{$sha1} = [$sha1, undef, $msg];
155
+ $dates{$date}++;
156
+ }
157
+ close (I) or die;
158
+}
159
+
160
+my $sep = "";
161
+my %total_names = ();
162
+my %total_merges = ();
163
+my $total_patch = 0;
164
+my @dates = sort keys %dates;
165
+
166
+for my $date (@dates) {
167
+ print "$sep$date\n";
168
+ if (exists $patch_by_date{$date}) {
169
+ my $count = scalar @{$patch_by_date{$date}};
170
+ my %names = ();
171
+ for my $patch (map { $patch{$_} } (@{$patch_by_date{$date}})) {
172
+ my $name = $patch->[1];
173
+ $names{$name}++;
174
+ $total_names{$name}++;
175
+ }
176
+ my $people = scalar @{[keys %names]};
177
+ $total_patch += $count;
178
+
179
+ $count = plural($count, "patch", "patches");
180
+ $people = plural($people, "person", "people");
181
+ print "Queued $count from $people.\n";
182
+ if ($verbose) {
183
+ for my $patch (map { $patch{$_} } @{$patch_by_date{$date}}) {
184
+ print " $patch->[2]\n";
185
+ }
186
+ }
187
+ }
188
+ for my $branch_data (@integrate) {
189
+ my ($branch, $purpose) = @{$branch_data};
190
+ next unless (exists $merge_by_branch_date{$branch}{$date});
191
+ my $merges = $merge_by_branch_date{$branch}{$date};
192
+ my $count = scalar @$merges;
193
+ next unless $count;
194
+
195
+ $total_merges{$branch} ||= 0;
196
+ $total_merges{$branch} += $count;
197
+ $count = plural($count, "topic", "topics");
198
+ print "Merged $count to '$branch' branch$purpose.\n";
199
+ if ($verbose) {
200
+ print fmt_join(" ", 72, " ", (map { $patch{$_}->[2] } @$merges));
201
+ }
202
+ }
203
+ $sep = "\n";
204
+}
205
+
206
+if (1 < @dates) {
207
+ print "${sep}Between $dates[0]..$dates[-1]\n";
208
+
209
+ my $people = plural(scalar @{[keys %total_names]}, "person", "people");
210
+ my $count = plural($total_patch, "patch", "patches");
211
+ print "Queued $count from $people.\n";
212
+
213
+ for my $branch_data (@integrate) {
214
+ my ($branch, $purpose) = @{$branch_data};
215
+ next unless $total_merges{$branch};
216
+ my $count = plural($total_merges{$branch}, "merge", "merges");
217
+ print "Made $count to '$branch' branch$purpose.\n";
218
+ }
219
+}