summaryrefslogtreecommitdiffstats
path: root/scripts/get_maintainer.pl
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2010-03-30 17:39:27 -0400
committerJames Morris <jmorris@namei.org>2010-03-30 17:39:27 -0400
commitd25d6fa1a95f465ff1ec4458ca15e30b2c8dffec (patch)
tree7362b182dedd825fc762ef7706830837e42943af /scripts/get_maintainer.pl
parent225a9be24d799aa16d543c31fb09f0c9ed1d9caa (diff)
parent2eaa9cfdf33b8d7fb7aff27792192e0019ae8fc6 (diff)
Merge branch 'master' into next
Diffstat (limited to 'scripts/get_maintainer.pl')
-rwxr-xr-xscripts/get_maintainer.pl185
1 files changed, 147 insertions, 38 deletions
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 2f3230db7ffb..6f97a13bcee4 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -41,6 +41,8 @@ my $web = 0;
41my $subsystem = 0; 41my $subsystem = 0;
42my $status = 0; 42my $status = 0;
43my $keywords = 1; 43my $keywords = 1;
44my $sections = 0;
45my $file_emails = 0;
44my $from_filename = 0; 46my $from_filename = 0;
45my $pattern_depth = 0; 47my $pattern_depth = 0;
46my $version = 0; 48my $version = 0;
@@ -120,9 +122,11 @@ if (!GetOptions(
120 'web!' => \$web, 122 'web!' => \$web,
121 'pattern-depth=i' => \$pattern_depth, 123 'pattern-depth=i' => \$pattern_depth,
122 'k|keywords!' => \$keywords, 124 'k|keywords!' => \$keywords,
125 'sections!' => \$sections,
126 'fe|file-emails!' => \$file_emails,
123 'f|file' => \$from_filename, 127 'f|file' => \$from_filename,
124 'v|version' => \$version, 128 'v|version' => \$version,
125 'h|help' => \$help, 129 'h|help|usage' => \$help,
126 )) { 130 )) {
127 die "$P: invalid argument - use --help if necessary\n"; 131 die "$P: invalid argument - use --help if necessary\n";
128} 132}
@@ -137,9 +141,9 @@ if ($version != 0) {
137 exit 0; 141 exit 0;
138} 142}
139 143
140if ($#ARGV < 0) { 144if (-t STDIN && !@ARGV) {
141 usage(); 145 # We're talking to a terminal, but have no command line arguments.
142 die "$P: argument missing: patchfile or -f file please\n"; 146 die "$P: missing patchfile or -f file - use --help if necessary\n";
143} 147}
144 148
145if ($output_separator ne ", ") { 149if ($output_separator ne ", ") {
@@ -150,16 +154,24 @@ if ($output_rolestats) {
150 $output_roles = 1; 154 $output_roles = 1;
151} 155}
152 156
153my $selections = $email + $scm + $status + $subsystem + $web; 157if ($sections) {
154if ($selections == 0) { 158 $email = 0;
155 usage(); 159 $email_list = 0;
156 die "$P: Missing required option: email, scm, status, subsystem or web\n"; 160 $scm = 0;
161 $status = 0;
162 $subsystem = 0;
163 $web = 0;
164 $keywords = 0;
165} else {
166 my $selections = $email + $scm + $status + $subsystem + $web;
167 if ($selections == 0) {
168 die "$P: Missing required option: email, scm, status, subsystem or web\n";
169 }
157} 170}
158 171
159if ($email && 172if ($email &&
160 ($email_maintainer + $email_list + $email_subscriber_list + 173 ($email_maintainer + $email_list + $email_subscriber_list +
161 $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) { 174 $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
162 usage();
163 die "$P: Please select at least 1 email option\n"; 175 die "$P: Please select at least 1 email option\n";
164} 176}
165 177
@@ -173,8 +185,9 @@ if (!top_of_kernel_tree($lk_path)) {
173my @typevalue = (); 185my @typevalue = ();
174my %keyword_hash; 186my %keyword_hash;
175 187
176open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n"; 188open (my $maint, '<', "${lk_path}MAINTAINERS")
177while (<MAINT>) { 189 or die "$P: Can't open MAINTAINERS: $!\n";
190while (<$maint>) {
178 my $line = $_; 191 my $line = $_;
179 192
180 if ($line =~ m/^(\C):\s*(.*)/) { 193 if ($line =~ m/^(\C):\s*(.*)/) {
@@ -199,13 +212,14 @@ while (<MAINT>) {
199 push(@typevalue, $line); 212 push(@typevalue, $line);
200 } 213 }
201} 214}
202close(MAINT); 215close($maint);
203 216
204my %mailmap; 217my %mailmap;
205 218
206if ($email_remove_duplicates) { 219if ($email_remove_duplicates) {
207 open(MAILMAP, "<${lk_path}.mailmap") || warn "$P: Can't open .mailmap\n"; 220 open(my $mailmap, '<', "${lk_path}.mailmap")
208 while (<MAILMAP>) { 221 or warn "$P: Can't open .mailmap: $!\n";
222 while (<$mailmap>) {
209 my $line = $_; 223 my $line = $_;
210 224
211 next if ($line =~ m/^\s*#/); 225 next if ($line =~ m/^\s*#/);
@@ -224,7 +238,7 @@ if ($email_remove_duplicates) {
224 $mailmap{$name} = \@arr; 238 $mailmap{$name} = \@arr;
225 } 239 }
226 } 240 }
227 close(MAILMAP); 241 close($mailmap);
228} 242}
229 243
230## use the filenames on the command line or find the filenames in the patchfiles 244## use the filenames on the command line or find the filenames in the patchfiles
@@ -232,31 +246,47 @@ if ($email_remove_duplicates) {
232my @files = (); 246my @files = ();
233my @range = (); 247my @range = ();
234my @keyword_tvi = (); 248my @keyword_tvi = ();
249my @file_emails = ();
250
251if (!@ARGV) {
252 push(@ARGV, "&STDIN");
253}
235 254
236foreach my $file (@ARGV) { 255foreach my $file (@ARGV) {
237 ##if $file is a directory and it lacks a trailing slash, add one 256 if ($file ne "&STDIN") {
238 if ((-d $file)) { 257 ##if $file is a directory and it lacks a trailing slash, add one
239 $file =~ s@([^/])$@$1/@; 258 if ((-d $file)) {
240 } elsif (!(-f $file)) { 259 $file =~ s@([^/])$@$1/@;
241 die "$P: file '${file}' not found\n"; 260 } elsif (!(-f $file)) {
261 die "$P: file '${file}' not found\n";
262 }
242 } 263 }
243 if ($from_filename) { 264 if ($from_filename) {
244 push(@files, $file); 265 push(@files, $file);
245 if (-f $file && $keywords) { 266 if (-f $file && ($keywords || $file_emails)) {
246 open(FILE, "<$file") or die "$P: Can't open ${file}\n"; 267 open(my $f, '<', $file)
247 my $text = do { local($/) ; <FILE> }; 268 or die "$P: Can't open $file: $!\n";
248 foreach my $line (keys %keyword_hash) { 269 my $text = do { local($/) ; <$f> };
249 if ($text =~ m/$keyword_hash{$line}/x) { 270 close($f);
250 push(@keyword_tvi, $line); 271 if ($keywords) {
272 foreach my $line (keys %keyword_hash) {
273 if ($text =~ m/$keyword_hash{$line}/x) {
274 push(@keyword_tvi, $line);
275 }
251 } 276 }
252 } 277 }
253 close(FILE); 278 if ($file_emails) {
279 my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
280 push(@file_emails, clean_file_emails(@poss_addr));
281 }
254 } 282 }
255 } else { 283 } else {
256 my $file_cnt = @files; 284 my $file_cnt = @files;
257 my $lastfile; 285 my $lastfile;
258 open(PATCH, "<$file") or die "$P: Can't open ${file}\n"; 286
259 while (<PATCH>) { 287 open(my $patch, "< $file")
288 or die "$P: Can't open $file: $!\n";
289 while (<$patch>) {
260 my $patch_line = $_; 290 my $patch_line = $_;
261 if (m/^\+\+\+\s+(\S+)/) { 291 if (m/^\+\+\+\s+(\S+)/) {
262 my $filename = $1; 292 my $filename = $1;
@@ -276,7 +306,8 @@ foreach my $file (@ARGV) {
276 } 306 }
277 } 307 }
278 } 308 }
279 close(PATCH); 309 close($patch);
310
280 if ($file_cnt == @files) { 311 if ($file_cnt == @files) {
281 warn "$P: file '${file}' doesn't appear to be a patch. " 312 warn "$P: file '${file}' doesn't appear to be a patch. "
282 . "Add -f to options?\n"; 313 . "Add -f to options?\n";
@@ -285,6 +316,8 @@ foreach my $file (@ARGV) {
285 } 316 }
286} 317}
287 318
319@file_emails = uniq(@file_emails);
320
288my @email_to = (); 321my @email_to = ();
289my @list_to = (); 322my @list_to = ();
290my @scm = (); 323my @scm = ();
@@ -314,6 +347,7 @@ foreach my $file (@files) {
314 if ($type eq 'X') { 347 if ($type eq 'X') {
315 if (file_match_pattern($file, $value)) { 348 if (file_match_pattern($file, $value)) {
316 $exclude = 1; 349 $exclude = 1;
350 last;
317 } 351 }
318 } 352 }
319 } 353 }
@@ -340,12 +374,28 @@ foreach my $file (@files) {
340 } 374 }
341 } 375 }
342 376
343 $tvi += ($end - $start); 377 $tvi = $end + 1;
344
345 } 378 }
346 379
347 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { 380 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
348 add_categories($line); 381 add_categories($line);
382 if ($sections) {
383 my $i;
384 my $start = find_starting_index($line);
385 my $end = find_ending_index($line);
386 for ($i = $start; $i < $end; $i++) {
387 my $line = $typevalue[$i];
388 if ($line =~ /^[FX]:/) { ##Restore file patterns
389 $line =~ s/([^\\])\.([^\*])/$1\?$2/g;
390 $line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
391 $line =~ s/\\\./\./g; ##Convert \. to .
392 $line =~ s/\.\*/\*/g; ##Convert .* to *
393 }
394 $line =~ s/^([A-Z]):/$1:\t/g;
395 print("$line\n");
396 }
397 print("\n");
398 }
349 } 399 }
350 400
351 if ($email && $email_git) { 401 if ($email && $email_git) {
@@ -377,6 +427,14 @@ if ($email) {
377 } 427 }
378 } 428 }
379 } 429 }
430
431 foreach my $email (@file_emails) {
432 my ($name, $address) = parse_email($email);
433
434 my $tmp_email = format_email($name, $address, $email_usename);
435 push_email_address($tmp_email, '');
436 add_role($tmp_email, 'in file');
437 }
380} 438}
381 439
382if ($email || $email_list) { 440if ($email || $email_list) {
@@ -453,6 +511,7 @@ MAINTAINER field selection options:
453 --remove-duplicates => minimize duplicate email names/addresses 511 --remove-duplicates => minimize duplicate email names/addresses
454 --roles => show roles (status:subsystem, git-signer, list, etc...) 512 --roles => show roles (status:subsystem, git-signer, list, etc...)
455 --rolestats => show roles and statistics (commits/total_commits, %) 513 --rolestats => show roles and statistics (commits/total_commits, %)
514 --file-emails => add email addresses found in -f file (default: 0 (off))
456 --scm => print SCM tree(s) if any 515 --scm => print SCM tree(s) if any
457 --status => print status if any 516 --status => print status if any
458 --subsystem => print subsystem name if any 517 --subsystem => print subsystem name if any
@@ -466,6 +525,7 @@ Output type options:
466Other options: 525Other options:
467 --pattern-depth => Number of pattern directory traversals (default: 0 (all)) 526 --pattern-depth => Number of pattern directory traversals (default: 0 (all))
468 --keywords => scan patch for keywords (default: 1 (on)) 527 --keywords => scan patch for keywords (default: 1 (on))
528 --sections => print the entire subsystem sections with pattern matches
469 --version => show version 529 --version => show version
470 --help => show this help information 530 --help => show this help information
471 531
@@ -545,7 +605,7 @@ sub parse_email {
545 $name =~ s/^\"|\"$//g; 605 $name =~ s/^\"|\"$//g;
546 $address =~ s/^\s+|\s+$//g; 606 $address =~ s/^\s+|\s+$//g;
547 607
548 if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars 608 if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
549 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes 609 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
550 $name = "\"$name\""; 610 $name = "\"$name\"";
551 } 611 }
@@ -562,7 +622,7 @@ sub format_email {
562 $name =~ s/^\"|\"$//g; 622 $name =~ s/^\"|\"$//g;
563 $address =~ s/^\s+|\s+$//g; 623 $address =~ s/^\s+|\s+$//g;
564 624
565 if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars 625 if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
566 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes 626 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
567 $name = "\"$name\""; 627 $name = "\"$name\"";
568 } 628 }
@@ -811,7 +871,9 @@ sub add_role {
811 foreach my $entry (@email_to) { 871 foreach my $entry (@email_to) {
812 if ($email_remove_duplicates) { 872 if ($email_remove_duplicates) {
813 my ($entry_name, $entry_address) = parse_email($entry->[0]); 873 my ($entry_name, $entry_address) = parse_email($entry->[0]);
814 if ($name eq $entry_name || $address eq $entry_address) { 874 if (($name eq $entry_name || $address eq $entry_address)
875 && ($role eq "" || !($entry->[1] =~ m/$role/))
876 ) {
815 if ($entry->[1] eq "") { 877 if ($entry->[1] eq "") {
816 $entry->[1] = "$role"; 878 $entry->[1] = "$role";
817 } else { 879 } else {
@@ -819,7 +881,9 @@ sub add_role {
819 } 881 }
820 } 882 }
821 } else { 883 } else {
822 if ($email eq $entry->[0]) { 884 if ($email eq $entry->[0]
885 && ($role eq "" || !($entry->[1] =~ m/$role/))
886 ) {
823 if ($entry->[1] eq "") { 887 if ($entry->[1] eq "") {
824 $entry->[1] = "$role"; 888 $entry->[1] = "$role";
825 } else { 889 } else {
@@ -1099,6 +1163,51 @@ sub sort_and_uniq {
1099 return @parms; 1163 return @parms;
1100} 1164}
1101 1165
1166sub clean_file_emails {
1167 my (@file_emails) = @_;
1168 my @fmt_emails = ();
1169
1170 foreach my $email (@file_emails) {
1171 $email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
1172 my ($name, $address) = parse_email($email);
1173 if ($name eq '"[,\.]"') {
1174 $name = "";
1175 }
1176
1177 my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
1178 if (@nw > 2) {
1179 my $first = $nw[@nw - 3];
1180 my $middle = $nw[@nw - 2];
1181 my $last = $nw[@nw - 1];
1182
1183 if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
1184 (length($first) == 2 && substr($first, -1) eq ".")) ||
1185 (length($middle) == 1 ||
1186 (length($middle) == 2 && substr($middle, -1) eq "."))) {
1187 $name = "$first $middle $last";
1188 } else {
1189 $name = "$middle $last";
1190 }
1191 }
1192
1193 if (substr($name, -1) =~ /[,\.]/) {
1194 $name = substr($name, 0, length($name) - 1);
1195 } elsif (substr($name, -2) =~ /[,\.]"/) {
1196 $name = substr($name, 0, length($name) - 2) . '"';
1197 }
1198
1199 if (substr($name, 0, 1) =~ /[,\.]/) {
1200 $name = substr($name, 1, length($name) - 1);
1201 } elsif (substr($name, 0, 2) =~ /"[,\.]/) {
1202 $name = '"' . substr($name, 2, length($name) - 2);
1203 }
1204
1205 my $fmt_email = format_email($name, $address, $email_usename);
1206 push(@fmt_emails, $fmt_email);
1207 }
1208 return @fmt_emails;
1209}
1210
1102sub merge_email { 1211sub merge_email {
1103 my @lines; 1212 my @lines;
1104 my %saw; 1213 my %saw;
@@ -1183,7 +1292,7 @@ sub rfc822_strip_comments {
1183 1292
1184# valid: returns true if the parameter is an RFC822 valid address 1293# valid: returns true if the parameter is an RFC822 valid address
1185# 1294#
1186sub rfc822_valid ($) { 1295sub rfc822_valid {
1187 my $s = rfc822_strip_comments(shift); 1296 my $s = rfc822_strip_comments(shift);
1188 1297
1189 if (!$rfc822re) { 1298 if (!$rfc822re) {
@@ -1203,7 +1312,7 @@ sub rfc822_valid ($) {
1203# from success with no addresses found, because an empty string is 1312# from success with no addresses found, because an empty string is
1204# a valid list. 1313# a valid list.
1205 1314
1206sub rfc822_validlist ($) { 1315sub rfc822_validlist {
1207 my $s = rfc822_strip_comments(shift); 1316 my $s = rfc822_strip_comments(shift);
1208 1317
1209 if (!$rfc822re) { 1318 if (!$rfc822re) {