Cope with unknown hosts in dead host list.
[amitay/build-farm.git] / svnlog.pl
1 #!/usr/bin/perl -w
2 #
3 # Extract information about recent SVN commits
4 #
5 # tridge@samba.org, April 2001
6 # vance@samba.org, August 2004
7
8 use strict;
9 use lib "web";
10 use util;
11 use POSIX;
12 use Data::Dumper;
13 use File::stat;
14 use Date::Parse;
15
16 ####################################
17 # push an entry onto the array
18
19 sub push_entry($$$$)
20 {
21         my $entry = shift;
22         my $log = shift;
23         my $days = shift;
24         my $tree = shift;
25
26         # we can assume that each entry is unique, due to the nature of svn
27         # so we don't need any of the magic required for cvs
28         if (($entry->{DATE} > time() - $days*24*60*60) &&
29             ($entry->{TREE} eq $tree)) {
30
31                 # we put these on in reverse order so that it's in order of
32                 # date.
33                 unshift(@{$log}, $entry);
34         }
35
36         return $log;
37 }
38
39 ####################################
40 # return an array of logfile entries given a svn log file. 
41 # Only return entries newer than $days old
42 sub svn_parse($$$$)
43 {
44         my $repo_url = shift;
45         my $tree_dir = shift;
46         my $days = shift;
47         my $tree = shift;
48         my $log;
49         my $entry = {};
50
51         # don't know what time zone this machine is, but given the granularity
52         # of days, (intended to be about 60 days), a few hours either way makes
53         # very little difference
54         my $start_date = POSIX::strftime("%Y-%m-%d", gmtime(time() - $days*60*60*24));
55
56         open(FILE, "svn log --verbose --non-interactive $repo_url/$tree_dir -r HEAD:'{$start_date}' |");
57         #open(FILE, "< log.txt") or die "Could not open log: $!";
58         while (defined (my $line = <FILE>)) {
59
60
61                 # separator line indicates new entry
62                 if ($line =~ /^\-{5,}$/) {
63                         # only add entry if one exists
64                         if ($entry->{DATE}) {
65                                 $log = push_entry($entry, $log, $days, $tree);
66                         }
67
68                         $entry = {};
69
70                         next;
71                 }
72
73                 # the first line after the separator (which sets entry to {})
74                 # looks like:
75                 # r15 | vance | 2004-07-31 22:24:55 -0700 (Sat, 31 Jul 2004) | 4 lines
76                 if (! defined $entry->{DATE}) {
77
78                         my ($rev, $author, $date, $lines) = split /\s+\|\s+/, $line;
79                         $entry->{DATE} = str2time($date);
80
81                         # kill the r in the revision
82                         $rev =~ s/^r//;
83                         $entry->{REVISION} = $rev;
84                         $entry->{AUTHOR} = $author;
85                         $entry->{TREE} = $tree;
86                         next;
87                 }
88
89
90                 # read the list of changed/added/removed files
91                 if ($line =~ /^Changed paths:/) {
92
93                         while (<FILE>) {
94
95                                 $line = $_;
96                                 if ($line =~ /^\s*$/) { last; }
97
98                                 elsif ($line =~ /\s+A (.*)/) {
99                                         my $file = $1;
100                                         $file =~ s#^/$tree_dir/##o;
101                                         if ($entry->{ADDED}) {
102                                                 $entry->{ADDED} .= " $file";
103                                         } else {
104                                                 $entry->{ADDED} = "$file";
105                                         }
106                                 }
107
108                                 elsif ($line =~ /\s+M (.*)/) {
109                                         my $file = $1;
110                                         $file =~ s#^/$tree_dir/##o;
111                                         if ($entry->{FILES}) {
112                                                 $entry->{FILES} .= " $file";
113                                         } else {
114                                                 $entry->{FILES} = "$file";
115                                         }
116                                 }
117
118                                 elsif ($line =~ /\s+R (.*)/ ||
119                                        $line =~ /\s+D (.*)/) {
120                                         my $file = $1;
121                                         $file =~ s#^/$tree_dir/##o;
122                                         if ($entry->{REMOVED}) {
123                                                 $entry->{REMOVED} .= " $file";
124                                         } else {
125                                                 $entry->{REMOVED} = "$file";
126                                         }
127                                 }
128                         }
129
130                         next;
131                 }
132
133                 # add the line to the message
134                 if (defined $entry->{MESSAGE}) {
135                         $entry->{MESSAGE} .= $line;
136                 }
137                 else {
138                         $entry->{MESSAGE} = $line;
139                 }
140         }
141
142         if ($entry->{DATE}) {
143                 $log = push_entry($entry, $log, $days, $tree);
144         }
145
146         close(FILE);
147
148         # cleanup the messages
149         for (my $line = $#{$log}; $line > 0; $line--) {
150                 $entry = $log->[$line];
151                 if ($entry->{MESSAGE}) {
152                         while (chomp($entry->{MESSAGE})) { }
153                 }
154         }
155
156         return $log;
157 }
158
159
160 ######################################
161 # main program
162 if ($#ARGV < 4 || $ARGV[0] eq '--help' || $ARGV[0] eq '-h') {
163         print "
164 Usage: svnlog.pl <REPOSITORY-URL> <TREE-DIR> <DAYS> <TREE> <DEST>
165
166 Extract all commits to REPOSITORY-URL/TREE-DIR in the last
167 DAYS days. Store the results in DEST, indexed under TREE,
168 in a format easily readable by the build farm web scripts.
169 ";
170         exit(1);
171 }
172
173 my $repo_url = $ARGV[0];
174 my $tree_dir = $ARGV[1];
175 my $days = $ARGV[2];
176 my $tree = $ARGV[3];
177 my $dest = $ARGV[4];
178
179
180 my $log = svn_parse($repo_url, $tree_dir, $days, $tree);
181
182 util::SaveStructure($dest, $log);