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