Cope with files that already exist.
[amitay/build-farm.git] / gitlog.pl
1 #!/usr/bin/perl -w
2 #
3 # Extract information about recent git commits
4 #
5 # tridge@samba.org, November 2006
6 # bjacke@samba.org
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         unshift(@{$log}, $entry);
26 #       printf("Adding entry\n");
27 #       print Dumper $entry;
28         return $log;
29 }
30
31 ####################################
32 # return an array of logfile entries given a git log file. 
33 # Only return entries newer than $days old
34 sub git_parse($$$$)
35 {
36         my $git_path = shift;
37         my $days = shift;
38         my $tree = shift;
39         my $subdir = shift;
40         my $log;
41         my $entry = {};
42         my $addto = "";
43
44         $subdir = "" unless defined($subdir);
45
46         my $magicstart = "---GIT-COMMIT-MAGIC-START---";
47         my $magicmsg = "---GIT-COMMIT-MAGIC-MESSAGE---";
48         my $magicdiff = "---GIT-COMMIT-MAGIC-DIFF---";
49         my $magicbody = "---GIT-COMMIT-MAGIC-BODY---";
50         my $format = $magicstart."%n%H%n%ct%n%an%n".$magicmsg."%n%s%n".$magicbody."%b%n".$magicdiff;
51         my $sincedays;
52         $sincedays = "--since='$days days'" if defined($days);
53         # the number of entries is also being limited to a maximum number
54         # in the "git log" command. This is required because we
55         # checked in 11 years of samba development 1 days ago :-)
56
57         # git log --pretty=format:---GIT-COMMIT-MAGIC-START---%n%H%n%ct%n%an%n---GIT-COMMIT-MAGIC-MESSAGE---%n%s%b%n---GIT-COMMIT-MAGIC-DIFF--- --numstat --since='1 days'
58         open(FILE, "cd $git_path; git log --pretty=format:$format --numstat $sincedays -500 $tree -- $subdir |");
59         my $line_count;
60         while (defined (my $line = <FILE>)) {
61 #               printf("line=$line");
62                 # separator line indicates new entry
63                 if ($line =~ /^$magicstart$/ ) {
64                         # only add entry if one exists
65                         if ($entry->{DATE}) {
66                                 $log = push_entry($entry, $log, $days, $tree);
67                         }
68
69                         $entry = {};
70                         $line_count = 0;
71                         next;
72                 }
73                 $line_count++;
74                 
75                 if ($line_count == 1) {
76                         chomp $line;
77                         $entry->{REVISION} = $line;
78                         next;
79                 } elsif ($line_count == 2) {
80                         chomp $line;
81                         $entry->{DATE} = $line;
82                         next;
83                 } elsif ($line_count == 3) {
84                         chomp $line;
85                         $entry->{AUTHOR} = $line;
86                         next;
87                 }
88
89                 if ($line =~ /^$magicmsg$/) {
90                         $addto = "MESSAGE";
91                         next;
92                 }
93
94                 if ($line =~ /^$magicdiff$/) {
95                         $addto = "DIFF_STUFF";
96                         next;
97                 }
98                 
99                 chomp $line;
100                 if ($addto eq "MESSAGE") {
101                         if ($line =~ /^$magicbody(<unknown>$)?(.*)$/) {
102                                 $line = $2;
103                         }
104                         $entry->{MESSAGE} .= $line."\n";
105                         next;
106                 }
107
108                 if ($addto eq "DIFF_STUFF") {
109                         $line =~ m/^([0-9]*)[ \t]*([0-9]*)[ \t]*(.*)/;
110                         my $a = $1;
111                         my $b = $2;
112                         my $f = $3;
113                         $f =~ s/^$subdir\///;
114                         if (($b eq "0") and ($a ne "0")) {
115                                 $entry->{ADDED} .= "$f ";
116                         } elsif (($a eq "0") and ($b ne "0")) {
117                                 $entry->{REMOVED} .= "$f ";
118                         } else {
119                                 $entry->{FILES} .= "$f ";
120                         }
121                         next;
122                 }
123         }
124         # the last log entry should be caught here:
125         if ($entry->{DATE}) {
126                 $log = push_entry($entry, $log, $days, $tree);
127         }
128
129         close(FILE);
130
131         # cleanup the messages
132 #       for (my $line = $#{$log}; $line > 0; $line--) {
133 #               $entry = $log->[$line];
134 #               if ($entry->{MESSAGE}) {
135 #                       while (chomp($entry->{MESSAGE})) { }
136 #               }
137 #       }
138
139         return $log;
140 }
141
142
143 ######################################
144 # main program
145 if ($#ARGV < 2 || $ARGV[0] eq '--help' || $ARGV[0] eq '-h') {
146         print "
147 Usage: gitlog.pl <PATH> <DAYS> <DEST> [<subdir>]
148
149 Extract all commits git tree <PATH> in the last DAYS days. Store the
150 results in DEST in a format easily readable by the build farm web
151 scripts.  "; exit(1); }
152
153 my $git_path_arg = $ARGV[0];
154 my $days_arg = $ARGV[1];
155 my $tree_arg = $ARGV[2];
156 my $dest_arg = $ARGV[3];
157 my $subdir_arg = $ARGV[4];
158
159 my $log_data = git_parse($git_path_arg, $days_arg, $tree_arg, $subdir_arg);
160
161 util::SaveStructure($dest_arg, $log_data);