3 # Extract information about recent CVS commits
5 # tridge@samba.org, April 2001
14 ####################################
24 if ($s =~ /(.*) (.*) ([0-9]+), ([0-9]+) @ ([0-9]+):([0-9]+)/) {
31 my (%months) = ('January' => 1, 'February' => 2, 'March' => 3, 'April' => 4,
32 'May' => 5, 'June' => 6, 'July' => 7, 'August' => 8, 'September' => 9,
33 'October' => 10, 'November' => 11, 'December' => 12);
34 my $t = mktime(0, $min, $hour, $mday, $months{$month}-1, $year-1900);
38 print "ERROR: bad date format $s\n";
43 ####################################
44 # push an entry onto the array
46 # FIXME: This incorrectly handles multiple commits with the same log
47 # message. The cvslog output only shows the revisions for the last
48 # commit, but actually we want to either not coalesce, or show the
58 my $lastentry = $log->[$#{$log}];
60 if ($lastentry->{DATE} && $lastentry->{AUTHOR} &&
61 ($lastentry->{DATE} > $entry->{DATE}-600) &&
62 ($lastentry->{AUTHOR} eq $entry->{AUTHOR}) &&
63 ((!$lastentry->{TAG} && !$entry->{TAG}) ||
64 ($lastentry->{TAG} eq $entry->{TAG})) &&
65 ((!$lastentry->{MESSAGE} && !$entry->{MESSAGE}) ||
66 ($lastentry->{MESSAGE} eq $entry->{MESSAGE}))) {
68 if (exists $lastentry->{FILES}) {
69 $lastentry->{FILES} .= " $entry->{FILES}";
71 $lastentry->{FILES} = $entry->{FILES};
74 if (exists $lastentry->{ADDED}) {
75 $lastentry->{ADDED} .= " $entry->{ADDED}";
77 $lastentry->{ADDED} = $entry->{ADDED};
80 if (exists $lastentry->{REMOVED}) {
81 $lastentry->{REMOVED} .= " $entry->{REMOVED}";
83 $lastentry->{REMOVED} = $entry->{REMOVED};
86 if (exists $lastentry->{REVISIONS}) {
87 $lastentry->{REVISIONS} = {%{$lastentry->{REVISIONS}},%{$entry->{REVISIONS}}};
89 $lastentry->{REVISIONS} = $entry->{REVISIONS};
92 if (($entry->{DATE} > time() - $days*24*60*60) &&
93 ((!$entry->{TAG} && !$tag) ||
94 ($entry->{TAG} eq $tag)) &&
95 ($entry->{TREE} eq $tree)) {
96 push(@{$log}, $entry);
102 ####################################
103 # return an array of logfile entries given a cvs log file.
104 # Only return entries newer than $days old
114 open(FILE, "< $file");
118 # ignore separator lines
119 if ($line =~ /^[*]+/) { next; }
121 if ($line =~ /^Date:\s*(.*)/) {
122 if ($entry->{DATE}) {
123 $log = push_entry($entry, $log, $days, $tree, $tag);
126 $entry->{DATE} = cvs_parse_date($1);
131 if ($line =~ /^Author:\s*(.*)/) {
132 $entry->{AUTHOR} = $1;
136 if ($line =~ /^Update of (.*)/) {
138 if ($entry->{TREE} =~ /\/(data|home)\/cvs\/([^\/]*)\/?(.*)/) {
141 if ($entry->{DIR}) { $entry->{DIR} .= "/"; }
142 } elsif ($entry->{TREE} =~ /\/home\/tridge\/cvstest\/([^\/]*)\/?(.*)/) {
145 if ($entry->{DIR}) { $entry->{DIR} .= "/"; }
147 print "badly formed tree $entry->{TREE}\n";
149 if (! $entry->{DIR}) { $entry->{DIR} = ""; }
153 if ($line =~ /^Modified Files:/) {
156 if ($line =~ /^[*A-Z]/) { last; }
158 if ($line =~ /^\s*Tag: (.*)/) {
163 while ($line =~ /\s*([^\s]+)(.*)/) {
164 if ($entry->{FILES}) {
165 $entry->{FILES} .= " $entry->{DIR}$1";
167 $entry->{FILES} = "$entry->{DIR}$1";
174 if ($line =~ /^Added Files:/) {
177 if ($line =~ /^[*A-Z]/) { last; }
179 if ($line =~ /^\s*Tag: (.*)/) {
184 while ($line =~ /\s*([^\s]+)(.*)/) {
185 if ($entry->{ADDED}) {
186 $entry->{ADDED} .= " $entry->{DIR}$1";
188 $entry->{ADDED} = "$entry->{DIR}$1";
195 if ($line =~ /^Removed Files:/) {
198 if ($line =~ /^[*A-Z]/) { last; }
200 if ($line =~ /^\s*Tag: (.*)/) {
205 while ($line =~ /\s*([^\s]+)(.*)/) {
206 if ($entry->{REMOVED}) {
207 $entry->{REMOVED} .= " $entry->{DIR}$1";
209 $entry->{REMOVED} = "$entry->{DIR}$1";
216 if ($line =~ /^Log Message:/) {
219 if ($line eq "****************************************\n") { last; }
220 if ($line =~ /^Revisions:/) { last; }
221 $entry->{MESSAGE} .= $line;
225 if ($line =~ /^Revisions:/) {
228 if ($line =~ /^[*]/) { last; }
229 if ($line =~ /^\s*http/) { next; }
230 if ($line =~ /^\s*(.*?)\s*(NONE|[0-9][0-9.]*) => (NONE|[0-9][0-9.]*)/) {
231 my $file = "$entry->{DIR}$1";
234 $entry->{REVISIONS}->{$file}->{REV1} = $rev1;
235 $entry->{REVISIONS}->{$file}->{REV2} = $rev2;
241 if ($entry->{DATE}) {
242 $log = push_entry($entry, $log, $days, $tree, $tag);
247 # cleanup the messages
248 for (my $line=0; $line <= $#{$log}; $line++) {
249 $entry = $log->[$line];
250 if ($entry->{MESSAGE}) {
251 while (chomp($entry->{MESSAGE})) { }
259 ######################################
263 Usage: cvslog.pl <FILE> <DAYS> <TREE> <TAG> <DEST>
265 Opens CVS log file \$FILE and extracts all commit info
266 from the last \$DAYS days for \$TREE with tag \$TAG. The result
267 is stored in \$DEST in a format that the build farm web scripts
268 can easily read, aggregating the messages from a
269 multiple-directory commit into a single entry.
280 my $log = cvs_parse($ARGV[0], $days, $tree, $tag);
282 util::SaveStructure($dest, $log);