|
1 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 # This component and the accompanying materials are made available |
|
3 # under the terms of the License "Eclipse Public License v1.0" |
|
4 # which accompanies this distribution, and is available |
|
5 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
6 # |
|
7 # Initial Contributors: |
|
8 # Nokia Corporation - initial contribution |
|
9 # |
|
10 # Contributors |
|
11 # |
|
12 # Description: Post processes result CSV file generated by the SFCheckSource.pl |
|
13 # Version: 0.5 $optNoIgnore added |
|
14 # Version: 0.52 filenameOf added and applied to normalized file names |
|
15 # |
|
16 |
|
17 use strict; |
|
18 use Getopt::Long; |
|
19 use File::Basename; |
|
20 use IO::Handle; |
|
21 use FileHandle; |
|
22 |
|
23 # Constants |
|
24 use constant HEADER_LINE => 'Issue,Category,Comment,Distr. ID,Url,Line,Package,PO,Stamp=$build'; |
|
25 use constant LINE_WITH_LXR => '$issue,$category,$comment,"$distrid",=HYPERLINK("http://s60lxr/source/$filename?v=$lxrbuild#$linenum"),$linenum,$package,$PO'; |
|
26 use constant LINE_WITH_SOURCEPATH => '$issue,$category,$comment,"$distrid",=HYPERLINK("$sourcepath$filename"),$linenum,$package,$PO'; |
|
27 use constant LINE_WITHOUT_LXR => '$issue,$category,$comment,"$distrid",$filename,$linenum,$package,$PO'; |
|
28 use constant NON_NOKIA_FILE => 'Non-Nokia-file'; |
|
29 use constant SOURCE_ISSUE => 'source-issue'; |
|
30 my $IGNORE = 'Ignore'; |
|
31 my $IGNORE_MAN ='Ignore-manually'; |
|
32 my $IGNORE_PATTERN ='Ignore-by-filename'; # Default comments |
|
33 |
|
34 # Global variables |
|
35 # Tool version |
|
36 use constant VERSION => "0.52"; |
|
37 my $optNoIgnored = 0; |
|
38 my $optBuild = "Undefined"; |
|
39 my $optPackageOwnerFile; |
|
40 my $optManuallyCheckedFile; |
|
41 my $optConfigFile; |
|
42 my $optIgnorefilepattern; # File patterns to ignore |
|
43 my $optIgnorefilepatternComment = ""; # Comment value for file patterns to ignore |
|
44 my %packageOwnerHash; |
|
45 my %manuallyCheckedHash; # Hash of manually ignored cases |
|
46 my @sfDistributionIdArray = (); # Distr ID array |
|
47 |
|
48 ################################################## |
|
49 # Postprocess subroutine |
|
50 ################################################## |
|
51 |
|
52 sub doIt($) |
|
53 { |
|
54 my $sourcefile = shift; |
|
55 my $lxrbuild = shift; |
|
56 my $outputfile = shift; |
|
57 my $sourcepath = shift; |
|
58 |
|
59 open(IN,$sourcefile) || die "Unable to open file: $sourcefile\"\" for reading."; |
|
60 my $headerline = HEADER_LINE(); |
|
61 $headerline =~ s/\$build/$optBuild/; |
|
62 if ($outputfile) |
|
63 { |
|
64 print OUTPUT "$headerline\n"; |
|
65 } |
|
66 else |
|
67 { |
|
68 print "$headerline\n"; |
|
69 } |
|
70 |
|
71 # Collect all files marked as ignored here |
|
72 my %ignoreFilesHash; |
|
73 |
|
74 LINE: |
|
75 while(<IN>) |
|
76 { |
|
77 chomp; |
|
78 my $line = $_; |
|
79 my @items = parse_csv($line); |
|
80 my $issue = $items[0]; |
|
81 my $category = $items[1]; |
|
82 my $comment = $items[2]; |
|
83 my $distrid = $items[3]; |
|
84 my $filename = $items[4]; |
|
85 $filename =~ s/\\/\//g; # Standardize name |
|
86 $filename =~ s/[a-zA-Z]\:(\/)?//i; # Remove possible "drive:/" strings |
|
87 my $linenum = $items[5]; |
|
88 # Sometimes the tool produces bad data, ignore them |
|
89 next LINE if (!($issue =~ m/issue/)); # Not issue |
|
90 next LINE if ($optNoIgnored && ($comment =~ m/$IGNORE/i)); # Ignore |
|
91 next LINE if !$category; |
|
92 next LINE if ($optConfigFile && !isSFDistribution($distrid)); |
|
93 my $ignoreThis = $manuallyCheckedHash{$category . filenameOf($filename)}; |
|
94 if (defined $ignoreThis) |
|
95 { |
|
96 next if $optNoIgnored; |
|
97 $comment = $IGNORE_MAN; |
|
98 } |
|
99 elsif ($optIgnorefilepattern && filenameOf($filename) =~ m/$optIgnorefilepattern/i) |
|
100 { |
|
101 # Ignore by given pattern in file name |
|
102 $comment = $optIgnorefilepatternComment; |
|
103 } |
|
104 |
|
105 # Extract file parts |
|
106 # my ($fname, $filepath, $filext)=fileparse($filename, qr/\.[^.]*/); |
|
107 |
|
108 my $linePattern = LINE_WITH_LXR(); |
|
109 if ($lxrbuild eq "") |
|
110 { |
|
111 $linePattern = LINE_WITHOUT_LXR(); |
|
112 } |
|
113 if ($sourcepath ne "") |
|
114 { |
|
115 $linePattern = LINE_WITH_SOURCEPATH(); |
|
116 } |
|
117 |
|
118 # Create result line using the pattern |
|
119 $linePattern =~ s/\$issue/$issue/; |
|
120 $linePattern =~ s/\$category/$category/; |
|
121 $linePattern =~ s/\$comment/$comment/; |
|
122 $linePattern =~ s/\$distrid/$distrid/; |
|
123 $linePattern =~ s/\$sourcepath/$sourcepath/; |
|
124 $linePattern =~ s/\$filename/$filename/; |
|
125 my $p = packageOf($filename); |
|
126 my $po = packageOwnerOf($filename); |
|
127 $linePattern =~ s/\$package/$p/; |
|
128 $linePattern =~ s/\$PO/$po/; |
|
129 if ($lxrbuild ne "") |
|
130 { |
|
131 $linenum = sprintf("%03d", $linenum); # LXR requires 3 digits |
|
132 $linePattern =~ s/\$lxrbuild/$lxrbuild/; |
|
133 } |
|
134 $linePattern =~ s/\$linenum/$linenum/; |
|
135 |
|
136 if ($outputfile) |
|
137 { |
|
138 print OUTPUT "$linePattern\n"; |
|
139 } |
|
140 else |
|
141 { |
|
142 print ("$linePattern\n"); |
|
143 } |
|
144 } |
|
145 |
|
146 close (IN); |
|
147 |
|
148 } |
|
149 |
|
150 |
|
151 ################################################## |
|
152 # Show usage help |
|
153 ################################################## |
|
154 sub usage |
|
155 { |
|
156 print "SFPostProcessResults.pl by matti.parnanen\@nokia.com, version " . VERSION() . "\n"; |
|
157 print "Generates hyperlinks to filenames using LXR or plain filename links\n"; |
|
158 print "Usage:\n"; |
|
159 print " perl SFPostProcessResults.pl -input csv-file-from-sfchecksource -lxrbuild LXR-buildname [-outputfile different-csv-file-name]\n"; |
|
160 print " perl SFPostProcessResults.pl -input csv-file-from-sfchecksource -sourcepath source-path [-outputfile different-csv-file-name]\n"; |
|
161 } |
|
162 |
|
163 |
|
164 ################################################## |
|
165 # Parse command line and extract options |
|
166 ################################################## |
|
167 sub parseCmdLine |
|
168 { |
|
169 |
|
170 |
|
171 my $opt1; |
|
172 my $opt2; |
|
173 my $opt3; |
|
174 my $opt4; |
|
175 |
|
176 if( ! GetOptions( |
|
177 'inputfile=s' => \$opt1, |
|
178 'lxrbuild:s' => \$opt2, |
|
179 'output:s' => \$opt3, |
|
180 'pofile:s' => \$optPackageOwnerFile, |
|
181 'configfile:s' => \$optConfigFile, |
|
182 'oldoutput:s' => \$optManuallyCheckedFile, |
|
183 'sourcepath:s' => \$opt4, |
|
184 'help' => \&usage, |
|
185 'noignored' => \$optNoIgnored, # Do not included items marked as Ignore |
|
186 'build:s' => \$optBuild, |
|
187 'ignorefile:s' => \$optIgnorefilepattern, #Ignore file pattern |
|
188 'ignorecomment:s' => \$optIgnorefilepatternComment, #Comment used for these |
|
189 '<>' => \&usage)) |
|
190 { |
|
191 &usage; |
|
192 exit(1); |
|
193 } |
|
194 |
|
195 if (lc($opt1) eq lc($opt3)) |
|
196 { |
|
197 &usage; |
|
198 exit(1); |
|
199 } |
|
200 |
|
201 return ($opt1, $opt2, $opt3,$opt4); |
|
202 |
|
203 } |
|
204 |
|
205 # |
|
206 # Taken from Mastering Regular Expressions |
|
207 # |
|
208 sub parse_csv { |
|
209 my $text = shift; ## record containing comma-separated values |
|
210 my @new = (); |
|
211 push(@new, $+) while $text =~ m{ |
|
212 "([^\"\\]*(?:\\.[^\"\\]*)*)",? |
|
213 | ([^,]+),? |
|
214 | , |
|
215 }gx; |
|
216 push(@new, undef) if substr($text, -1,1) eq ','; |
|
217 return @new; ## list of values that were comma-spearated |
|
218 } |
|
219 |
|
220 |
|
221 ################################################## |
|
222 # Read the content of old output |
|
223 ################################################## |
|
224 sub readPackageOwnerFile |
|
225 { |
|
226 my($filename) = $optPackageOwnerFile; |
|
227 if (!$filename) |
|
228 { |
|
229 return; |
|
230 } |
|
231 |
|
232 my $fh = new FileHandle "<$filename"; |
|
233 if (!defined($fh)) |
|
234 { |
|
235 return; |
|
236 } |
|
237 |
|
238 my @lines = <$fh>; |
|
239 my $line; |
|
240 foreach $line (@lines) |
|
241 { |
|
242 # Example line |
|
243 #ui,mw,classicui,ari.t.valtaoja@nokia.com,Nokia/S60/A&F/UFO,Beijing,1279685+166558 |
|
244 |
|
245 $line = lc($line); |
|
246 my (@parts) = split(/\,/,$line); # Split line with "," separator |
|
247 # print ("DEBUG:readPackageOwnerFile::$parts[1]/$parts[2]=$parts[3]\n"); |
|
248 $packageOwnerHash{$parts[1] . "/" . $parts[2]} = $parts[3] ; |
|
249 } |
|
250 |
|
251 close ($fh); |
|
252 } |
|
253 |
|
254 ################################################## |
|
255 # Get normalized filename starting from "sf/layer/package" |
|
256 ################################################## |
|
257 sub filenameOf |
|
258 { |
|
259 my($filename) = shift; |
|
260 $filename =~ s/\\/\//g; # Standardize name |
|
261 $filename = lc($filename); |
|
262 |
|
263 # There might be some paths before /sf/layer/package if tool run manually in some local directory |
|
264 # structure |
|
265 my ($tmp1,$tmp2) = split(/sf\//,$filename); |
|
266 # print ("DEBUG:sf/" . $tmp2 . "\n"); |
|
267 return "sf/" . $tmp2; |
|
268 } |
|
269 |
|
270 |
|
271 ################################################## |
|
272 # Get package owner |
|
273 ################################################## |
|
274 sub packageOwnerOf |
|
275 { |
|
276 my($filename) = shift; |
|
277 $filename = filenameOf($filename); |
|
278 |
|
279 my (@parts) = split(/\//,$filename); # "sf/layer/package" |
|
280 my $owner = $packageOwnerHash{$parts[1] . "/" . $parts[2]}; |
|
281 if (defined $owner) |
|
282 { |
|
283 return $owner; |
|
284 } |
|
285 return ""; |
|
286 } |
|
287 |
|
288 ################################################## |
|
289 # Get package name |
|
290 ################################################## |
|
291 sub packageOf |
|
292 { |
|
293 my($filename) = shift; |
|
294 $filename = filenameOf($filename); |
|
295 my (@parts) = split(/\//,$filename); # "sf/layer/package" |
|
296 |
|
297 return $parts[2]; |
|
298 } |
|
299 |
|
300 |
|
301 ################################################## |
|
302 # Read the content of cleaned cases manually ignored |
|
303 # (these are tool reported case cleared manually= |
|
304 ################################################## |
|
305 sub readManuallyCheckedFile |
|
306 { |
|
307 my($filename) = $optManuallyCheckedFile; |
|
308 if (!$filename) |
|
309 { |
|
310 return; |
|
311 } |
|
312 |
|
313 my $fh = new FileHandle "<$filename"; |
|
314 if (!defined($fh)) |
|
315 { |
|
316 return; |
|
317 } |
|
318 |
|
319 my @lines = <$fh>; |
|
320 my $line; |
|
321 foreach $line (@lines) |
|
322 { |
|
323 my (@parts) = split(/\,/,$line); # Split line with "," separator |
|
324 if ($parts[2] =~ m/$IGNORE_MAN/i) |
|
325 { |
|
326 my $fullfilename = lc($parts[4]); |
|
327 my $category = $parts[1]; |
|
328 $fullfilename =~ s/\\/\//g; # Standardize name |
|
329 # print("\nDEBUG:Marked:$category,$fullfilename as ignored"); |
|
330 $manuallyCheckedHash{$category . $fullfilename} = "1" ; # Just some value |
|
331 } |
|
332 } |
|
333 |
|
334 close ($fh); |
|
335 } |
|
336 |
|
337 ################################################## |
|
338 # Test ID is under SF distribution |
|
339 ################################################## |
|
340 sub isSFDistribution |
|
341 { |
|
342 my $id = shift; |
|
343 use constant SFL_DISTRIBUTION_VALUE => "3"; |
|
344 use constant EPL_DISTRIBUTION_VALUE => "7"; |
|
345 |
|
346 if ($id == "") |
|
347 { |
|
348 return 0; |
|
349 } |
|
350 |
|
351 if (($id == SFL_DISTRIBUTION_VALUE) || ($id == EPL_DISTRIBUTION_VALUE)) |
|
352 { |
|
353 # Implicit case |
|
354 return 1; |
|
355 } |
|
356 |
|
357 my $otherOkId = grep { $_ eq $id } @sfDistributionIdArray; # Use exact match |
|
358 return $otherOkId; |
|
359 } |
|
360 |
|
361 |
|
362 ################################################## |
|
363 # Read configuation file of the |
|
364 # SFUpdateLicenceHeader.pl to get OK distribution IDs |
|
365 ################################################## |
|
366 sub readConfigFile |
|
367 { |
|
368 my ($filename) = $optConfigFile; |
|
369 if (!$filename) |
|
370 { |
|
371 return; |
|
372 } |
|
373 |
|
374 open(IN,$filename) || die "Unable to open file: \"$filename\" for reading."; |
|
375 LINE: |
|
376 while(<IN>) |
|
377 { |
|
378 chomp; |
|
379 # tr/A-Z/a-z/; # Do not lowercase pattern |
|
380 my $line = $_; |
|
381 $line =~ s/^\s+//; # trim left |
|
382 $line =~ s/\s+$//; # trim right |
|
383 |
|
384 next LINE if length($line) == 0; # # Skip empty lines |
|
385 next LINE if ($line =~ /^\#.*/); # Skip comments; |
|
386 |
|
387 if ($line =~ /^sf-update-licence-header-config.*/i) |
|
388 { |
|
389 my ($tmp1, $tmp2) = split(/sf-update-licence-header-config-/,$line); # Get version |
|
390 } |
|
391 elsif ($line =~ /^sf-distribution-id/i) |
|
392 { |
|
393 my ($tmp, @parts) = split(/[\s\t]+/,$line); # space as separator |
|
394 my $cnt = @parts; |
|
395 push(@sfDistributionIdArray, @parts); |
|
396 my $cnt = @sfDistributionIdArray; |
|
397 } |
|
398 } |
|
399 |
|
400 # Pre-compile here the source line pattern |
|
401 close (IN); |
|
402 } |
|
403 |
|
404 |
|
405 ################################################## |
|
406 # MAIN |
|
407 ################################################## |
|
408 |
|
409 # |
|
410 # Command line variables |
|
411 # |
|
412 my $inputfile = ""; |
|
413 my $outputfile = ""; |
|
414 my $lxrbuild = ""; |
|
415 my $sourcepath = ""; |
|
416 |
|
417 # Initialize |
|
418 ($inputfile,$lxrbuild,$outputfile,$sourcepath) = &parseCmdLine; |
|
419 |
|
420 &readPackageOwnerFile(); |
|
421 &readManuallyCheckedFile(); |
|
422 &readConfigFile(); |
|
423 |
|
424 if ($outputfile) |
|
425 { |
|
426 open (OUTPUT, ">$outputfile") || die "Couldn't open $outputfile\n"; |
|
427 OUTPUT->autoflush(1); # Force flush |
|
428 } |
|
429 |
|
430 &doIt($inputfile,$lxrbuild,$outputfile,$sourcepath); |
|
431 |
|
432 close OUTPUT; |
|
433 |