source: PSPA/madxPSPA/testing/MadWorkReport.pl @ 430

Last change on this file since 430 was 430, checked in by touze, 11 years ago

import madx-5.01.00

File size: 10.8 KB
Line 
1#!/usr/bin/perl
2
3# trigger build and test if the following condition is satisfied:
4# (1) find-out if the latest tag of the form 'madX_3_04_22'
5#     is located below the last 'madX_test' tag, which means
6#     some release occured after the last test of the code.
7# (2) tag the CVS with 'madX_test'.
8
9# ... then issue a trigger to the do following:
10# (3) do the build when extracting for the last release tag, ignoring
11#     all changes that occured in between.
12# (4) run the test suite
13
14use MIME::Lite; # to send e-mail
15
16use File::Path; # to remove directory trees
17
18
19my $trigger;
20
21$website = "/afs/cern.ch/user/n/nougaret/www/mad/";
22
23@extractedPackages = ('madX');
24
25$pwd = `pwd`;
26chop $pwd;
27$extractDir = $pwd . "/MadCvsExtract_testWorkReport" ;
28rmtree($extractDir);
29mkdir($extractDir, 0777);
30chdir($extractDir);
31
32
33$cvsDir = ":gserver:isscvs.cern.ch:/local/reps/madx" ;
34
35my $startTime = localtime;
36
37# Do we need to do the check-out or do we rely on FesaBuild.pl instead?
38foreach(@extractedPackages) {
39    my $pack = $_;
40    # print "Extract package $pack from CVS\n";
41    `cvs -d $cvsDir checkout $pack`;
42}
43
44# find-out the latest release
45chdir('./madX');
46my $representative = 'madxd.h';
47my @log = `cvs log $representative`;
48
49@releases = ();
50@tests = ();
51foreach $line (@log){
52    if ($line =~/^[\s\t]*madX-(\d+)_(\d+)_(\d+)[\s\t]*:[\s\t]*([\d\.]+)[\s\t]*$/){
53        my $release = "$1_$2_$3";
54        $release_revision{$release}=$4;
55        @releases = (@releases, $release);
56        # print "found release $1_$2_$3, with revision $4\n";
57    }
58    if ($line =~/^[\s\t]*test-(\d+)_(\d+)_(\d+)[\s\t]*:[\s\t]*([\d\.]+)[\s\t]*$/){
59        my $test = "$1_$2_$3";
60        $test_revision{$test}=$4;
61        @tests = (@tests, $test);
62        # print "found test $1_$2_$3, with revision $4\n";
63    }
64
65}
66
67my @sortedReleases = sort byDecreasingReleaseNumber @releases;
68my @sortedTests = sort byDecreasingReleaseNumber @tests;
69
70my $lastRelease = @sortedReleases[0];
71my $beforeLastRelease = @sortedReleases[1];
72my $lastTest = @sortedTests[0];
73
74       
75# now find-out all the work from the contributors
76# that went into the CVS in between the two last releases
77
78@authors = (); # global variable modified by recordWork
79recordWork("madX-$beforeLastRelease", "madX-$lastRelease");
80
81
82chdir($pwd); # back to the top menu
83rmtree($extractDir);
84
85exit 0;
86
87sub byDecreasingReleaseNumber {
88        # sort always assumes $a is to be compared with $b, such as '$f{$a} <=> f{$b}'
89        # here, all numbers are of the form x+_x+_x+
90        my @aNumbers = split /_/, $a;
91        my @bNumbers = split /_/, $b;
92        my $counter = 0;
93        my $result = 0; # default
94        foreach $aNumber (@aNumbers){
95                if ($aNumber<@bNumbers[$counter]){
96                        $result = 1;
97                        return $result;
98                }
99                if ($aNumber>@bNumbers[$counter]){
100                        $result = -1;
101                        return $result;
102                }
103                $counter++;
104        }
105        return $result;
106}
107
108sub recordWork { # should also pass the output file name
109    $rel1 = $_[0]; # first release
110    $rel2 = $_[1]; # second release
111
112    $rootDir = "$website"; 
113    chop $rootDir; # don't need the final "/"
114    $workReportFile = "workReport.html";
115    open WORKFILE, ">$rootDir/$workReportFile";
116    $workReportContent = "";
117
118    @files = `ls *.*`;
119    @makefiles = `ls Make*`;
120    @files = (@files, @makefiles);
121    # print "rel1 is $rel1, rel2 is $rel2\n";
122    FILE_LOOP: foreach $file (@files){
123        chop $file;
124        my @logs = `cvs log $file`;
125        # first look for the revisions associated to the first and second releases
126        foreach $log (@logs){
127           
128            my $pattern1 = "^[\\s\\t]*$rel1\[\\s\\t]*:[\\s\\t]*([\\d\\.]+)[\\s\\t]*\$";
129            # print "pattern is $pattern\n";
130            if ($log =~/$pattern1/){
131                $rev1 = $1;
132                # print "$file: $rel1 -> revision 1 is $rev1\n";
133            }
134            my $pattern2 = "^[\\s\\t]*$rel2\[\\s\\t]*:[\\s\\t]*([\\d\\.]+)[\\s\\t]*\$";
135            if ($log =~ /$pattern2/){
136                $rev2 = $1;
137                # print "$file: $rel2 -> revision 2 is $rev2\n";
138            }
139        }
140       
141        if ($rev1 eq $rev2){
142            # no work went into latest release, may skip
143            next FILE_LOOP;
144        }
145
146        # now look for the authors having modified the code between release 1 and 2
147        # (including the latter).
148        # to this end, check all revisions located between $rev1 and $rev2 for given file
149       
150        # re-scan log for this file in order to find-out revision work
151        # in a CVS log info looks like the following:
152        # revision: 1.2.3
153        # date: ... author: ...
154        my $parserState = "skipHeader" ; # some state-variable
155        my $nextParserState = ""; # default             
156        my @logsOfInterest = `cvs log -r$rev1:$rev2 $file`;
157
158#       print "cvs log -r$rev1:$rev2 $file\n";
159
160        foreach $log (@logsOfInterest){
161 
162#           print "Current Parser State = $parserState\n";
163   
164            if ($parserState eq "skipHeader"){
165                if ($log =~ /^description:[\s\t]*/){
166                    $nextParserState = "skipLine";
167                } else {
168                    $nextParserState = "skipHeader";
169                }
170            }
171
172            if ($parserState eq "skipLine"){
173                if ($log =~ /^\-\-\-(\-)+[\s\t]*/){
174                    $nextParserState = "readRev";
175                } else {
176                    if ($log =~ /^\=\=\=(\=)+[\s\t]*/){
177                        $nextParserState = "EOF";
178                    } else {
179                        print "line '-----' expected, but not found!\n";
180                        return; # leave function
181                        # should clean-up the HTML file containing the work-report first
182                    }
183                }
184            }
185           
186           
187            if ($parserState eq "readRevisionInfo"){
188                #print "Mode: retreive detailed work info\n";
189                #print "Process line $log\n";
190                if ($log =~ /author[\s\t]*:[\s\t]*(\w+);/){
191                    $author = $1;
192                    # print "found work-unit carried-out by $candidate\n";
193                    # make sure author is not already in the list
194                    my $alreadyRecorded = 0;
195                    foreach $auth (@authors){
196                        if ($auth eq $author) {
197                            $alreadyRecorded = 1;
198                        }
199                    }
200                   
201                    $log =~ /;[\s\t]+lines:[\s\t]+\+(\d+)[\s\t]+\-(\d+)[\s\t]*;/;
202                    # print "work is +$1 -$2 LOC\n";
203                    if ($alreadyRecorded == 0 ) {
204                        @authors = ( @authors, $author );
205                        $workByAuthor{$author}="";
206                        $linesAdded{$author} = $1;
207                        $linesDeleted{$author} = $2; 
208                    } else {
209                        $linesAdded{$author} += $1;
210                        $linesDeleted{$author} += $2;
211                       
212                    }
213                }
214                $nextParserState = "readComment" ;
215            }
216
217
218
219            if ($parserState eq "skipRevisionInfo"){
220                # in case the work has been registered for the previous release, we want to discard it here
221                # (a parallel sequential machine dedicated to rejecting work from previous release)
222                $nextParserState = "skipComment";
223            }
224            if ($parserState eq "skipComment"){ # also, just in case the work relates to the previous release
225                # (a parallel sequential machine dedicated to rejecting work from previous release)
226                if ($log =~ /\-\-\-\-(\-)+/){
227                    # actually we find-out we should actually be in "skipLine" state
228                    $nextParserState = "readRev";
229                } else {
230                    if ($log =~ /(========)+/){
231                        $nextParserState = "EOF";
232                    } else {
233                        $nextParserState = "skipComment"; # until encounter a '---' or '===' marker
234                    }
235                }
236            }
237
238
239           
240            if ($parserState eq "readComment"){
241               
242
243                if ($log =~ /\-\-\-\-(\-)+/){
244                    # actually we find-out we should actually be in "skipLine" state
245                    # mark the end of the comment with a specific beacon "EndOfComment"
246                    $workByAuthor{$author} .= "EndOfComment\n";
247                    $nextParserState = "readRev";
248                } else {
249                    if ($log =~ /(========)+/){
250                        # same as above
251                        $workByAuthor{$author} .= "EndOfComment\n";
252                        $nextParserState = "EOF";
253                    } else {
254                        # should concatenate the comment's string here...
255                        $workByAuthor{$author} .= "$log";
256                        $nextParserState = "readComment"; # until encounter a '---' or '===' marker
257                    }
258                }
259
260#               $nextParserState = "skipLine"; # unless the comment spreads over successive lines!
261               
262
263            }
264
265            if ($parserState eq "readRev"){
266                if ($log =~ /^[\s\t]*revision[\s\t]+([\d\.]+)[\s\t]*$/){
267                    # same number of dots?
268                    my $rev = $1;
269                   
270                    if ($rev eq $rev1){
271                        # print "revision $rev of $file belongs to last release => skip!\n";
272                        # don't want to register work that went in to the previous release: skip
273                        $nextParserState = "skipRevisionInfo";
274                    } else {
275                       
276                        # if we reach this point, the comparison was succesful
277                        # =>advance to the next log line contains the author
278                       
279                        $nextParserState = "readRevisionInfo";
280                        # print "$file: contribution found $rev1 < $rev <= $rev2\n";
281
282                    }
283                   
284                       
285                } else {
286                    print "Encountered error while parsing file\n";
287                    exit;
288                } # if ($log
289            } # if (parserState
290
291
292            $parserState = $nextParserState;
293           
294        } # foreach $log  line
295       
296
297    } # for each file
298
299    # sort list of authors in alphabetical order
300    @authors = sort (@authors);
301
302    foreach $author (@authors){
303        $workReportContent .= "<tr class=\"work-author\"><td>$author</td></tr>\n";
304        @workComments = split /EndOfComment\n/, $workByAuthor{$author}; # "EndOfComment" is our specific beacon
305
306        @cleanedWorkComments =();
307        # remove multiple entries, e.g. occuring when several files are commited at the same time
308        SCAN_COMMENTS: foreach $comment (@workComments){
309            foreach $registeredComment (@cleanedWorkComments){
310                if ($comment eq $registeredComment){
311                    next SCAN_COMMENTS;
312                }
313            }
314            @cleanedWorkComments = ( @cleanedWorkComments, $comment);
315        }
316
317       
318        # new HTML table line for each comment
319        $oddOrEven = "even";
320        foreach $comment (@cleanedWorkComments){
321
322            $workReportContent .= "<tr class=\"work-log-$oddOrEven\"><td>$comment</td></tr>\n";
323
324            if ($oddOrEven eq "even"){
325                $oddOrEven = "odd";
326            } else {
327                $oddOrEven = "even";
328            }
329
330        }
331    }
332
333    my $endTime = localtime; # note that startTime defined outside this subroutine
334
335    # create web page
336    my $html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">';
337    $html .= "<html>\n";
338    $html .= "<head>\n";
339    $html .= "<title>Work log between releases $rel1 and $rel2 </title>\n";
340    $html .= "<link rel=stylesheet href=\"./MadTestWebStyle.css\" type=\"text/css\">"; # CSS stylesheet at same level
341    $html .= "</head>\n";
342    $html .= "<!-- automatically generated by the MAD test script -->\n";
343    $html .= "<body>\n";
344    $html .= "<p>Work log between releases $rel1 and $rel2 </p>\n";   
345    $html .= "<p>Log report started $startTime, ended $endTime</p>\n";
346    $html .= "<table width=\"75%\" border=\"0\">\n";
347    $html .= $workReportContent;
348    $html .= "</table>\n";
349    $html .= "</body>\n";
350    $html .= "</html>\n";
351
352   
353    # also copy the work report into the MAD-X News html page
354    my $newsFile = "/afs/cern.ch/eng/sl/MAD-X/pro/docu/Introduction/news.html";
355    open NEWSFILE, "<$newsFile";
356    my $news = '';
357    while(<NEWSFILE>){
358        my $line = $_;
359        if ($line =~ /[\s\t]*<!\-\- do not remove \- START WORK LOG \- do not remove \-\->[\s\t]*/) { 
360            # insert contents of the work report here
361            $news .= "<!-- do not remove - START WORK LOG - do not remove -->\n";
362            $news .= "<p>Work log between releases $rel1 and $rel2 </p>\n";   
363            $news .= "<p>Log report started $startTime, ended $endTime</p>\n";
364            $news .= "<table width=\"75%\" border=\"0\">\n";
365            $news .= $workReportContent;
366            $news .= "</table>\n";
367        } else{
368            $news .= $line;
369        }
370    }
371    close NEWSFILE;
372    open NEWSFILE, ">$newsFile";
373    print NEWSFILE $news;
374    close NEWSFILE;
375
376    print WORKFILE $html;
377    close WORKFILE;
378
379} # sub
Note: See TracBrowser for help on using the repository browser.