2023-09-27 09:03:24

by Justin Stitt

[permalink] [raw]
Subject: [PATCH 0/3] get_maintainer: add patch-only keyword matching

This series aims to add "D:" which behaves exactly the same as "K:" but
works only on patch files.

The goal of this is to reduce noise when folks use get_maintainer on
tree files as opposed to patches. This use case should be steered away
from [1] but "D:" should help maintainers reduce noise in their inboxes
regardless, especially when matching omnipresent keywords like [2]. In
the event of [2] Kees would be to/cc'd from folks running get_maintainer
on _any_ file containing "__counted_by". The number of these files is
rising and I fear for his inbox as his goal, as I understand it, is to
simply monitor the introduction of new __counted_by annotations to
ensure accurate semantics.

See [3/3] for an illustrative example.

This series also includes a formatting pass over get_maintainer because
I personally found it difficult to parse with the human eye.

[1]: https://lore.kernel.org/all/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/

Signed-off-by: Justin Stitt <[email protected]>
---
Justin Stitt (3):
MAINTAINERS: add documentation for D:
get_maintainer: run perltidy
get_maintainer: add patch-only pattern matching type

MAINTAINERS | 3 +
scripts/get_maintainer.pl | 3334 +++++++++++++++++++++++----------------------
2 files changed, 1718 insertions(+), 1619 deletions(-)
---
base-commit: 6465e260f48790807eef06b583b38ca9789b6072
change-id: 20230926-get_maintainer_add_d-07424a814e72

Best regards,
--
Justin Stitt <[email protected]>


2023-09-27 12:54:55

by Justin Stitt

[permalink] [raw]
Subject: [PATCH 2/3] get_maintainer: run perltidy

I'm a first time contributor to get_maintainer.pl and the formatting is
suspicious. I am not sure if there is a particular reason it is the way
it is but I let my editor format it and submitted the diff here in this
patch.

Note that my next patch [3/3] probably won't apply without this one. If
for some reason we don't want this file formatted I'll send a new patch
series with my changes diff'd against the non-formatted
get_maintainer.pl.

Note that I don't write perl very often and might not be aware of
particular styling decisions that were made. I just let perltidy do its
thing.

There's an online version of perltidy available here [1]

[1]: https://perltidy.com/
---
Note: I used these options (pretty sure these are default)
options="-l=478 -i=4 -ci=4 -vt=2 -cti=0 -pt=1 -bt=1 -sbt=1 -bbt=1 -nsfs -nolq -it=2 -wbb="% + - * / x != == >= <= =~ !~ < > | & = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x="

Note: I did not notice any regressions in my usage of get_maintainer
post-formatting. I'd be surprised if my formatter broke functionality
but you never know.
---
scripts/get_maintainer.pl | 3325 +++++++++++++++++++++++----------------------
1 file changed, 1706 insertions(+), 1619 deletions(-)

diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index ab123b498fd9..e679eac96793 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -21,58 +21,58 @@ use Cwd;
use File::Find;
use File::Spec::Functions;

-my $cur_path = fastgetcwd() . '/';
-my $lk_path = "./";
-my $email = 1;
-my $email_usename = 1;
-my $email_maintainer = 1;
-my $email_reviewer = 1;
-my $email_fixes = 1;
-my $email_list = 1;
-my $email_moderated_list = 1;
-my $email_subscriber_list = 0;
-my $email_git_penguin_chiefs = 0;
-my $email_git = 0;
+my $cur_path = fastgetcwd() . '/';
+my $lk_path = "./";
+my $email = 1;
+my $email_usename = 1;
+my $email_maintainer = 1;
+my $email_reviewer = 1;
+my $email_fixes = 1;
+my $email_list = 1;
+my $email_moderated_list = 1;
+my $email_subscriber_list = 0;
+my $email_git_penguin_chiefs = 0;
+my $email_git = 0;
my $email_git_all_signature_types = 0;
-my $email_git_blame = 0;
-my $email_git_blame_signatures = 1;
-my $email_git_fallback = 1;
-my $email_git_min_signatures = 1;
-my $email_git_max_maintainers = 5;
-my $email_git_min_percent = 5;
-my $email_git_since = "1-year-ago";
-my $email_hg_since = "-365";
-my $interactive = 0;
-my $email_remove_duplicates = 1;
-my $email_use_mailmap = 1;
-my $output_multiline = 1;
-my $output_separator = ", ";
-my $output_roles = 0;
-my $output_rolestats = 1;
-my $output_section_maxlen = 50;
-my $scm = 0;
-my $tree = 1;
-my $web = 0;
-my $subsystem = 0;
-my $status = 0;
-my $letters = "";
-my $keywords = 1;
-my $sections = 0;
-my $email_file_emails = 0;
-my $from_filename = 0;
-my $pattern_depth = 0;
-my $self_test = undef;
-my $version = 0;
-my $help = 0;
-my $find_maintainer_files = 0;
+my $email_git_blame = 0;
+my $email_git_blame_signatures = 1;
+my $email_git_fallback = 1;
+my $email_git_min_signatures = 1;
+my $email_git_max_maintainers = 5;
+my $email_git_min_percent = 5;
+my $email_git_since = "1-year-ago";
+my $email_hg_since = "-365";
+my $interactive = 0;
+my $email_remove_duplicates = 1;
+my $email_use_mailmap = 1;
+my $output_multiline = 1;
+my $output_separator = ", ";
+my $output_roles = 0;
+my $output_rolestats = 1;
+my $output_section_maxlen = 50;
+my $scm = 0;
+my $tree = 1;
+my $web = 0;
+my $subsystem = 0;
+my $status = 0;
+my $letters = "";
+my $keywords = 1;
+my $sections = 0;
+my $email_file_emails = 0;
+my $from_filename = 0;
+my $pattern_depth = 0;
+my $self_test = undef;
+my $version = 0;
+my $help = 0;
+my $find_maintainer_files = 0;
my $maintainer_path;
my $vcs_used = 0;

my $exit = 0;

-my @files = ();
-my @fixes = (); # If a patch description includes Fixes: lines
-my @range = ();
+my @files = ();
+my @fixes = (); # If a patch description includes Fixes: lines
+my @range = ();
my @keyword_tvi = ();
my @file_emails = ();

@@ -80,29 +80,30 @@ my %commit_author_hash;
my %commit_signer_hash;

my @penguin_chief = ();
-push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
+push( @penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org" );
+
#Andrew wants in on most everything - 2009/01/14
#push(@penguin_chief, "Andrew Morton:akpm\@linux-foundation.org");

my @penguin_chief_names = ();
foreach my $chief (@penguin_chief) {
- if ($chief =~ m/^(.*):(.*)/) {
- my $chief_name = $1;
- my $chief_addr = $2;
- push(@penguin_chief_names, $chief_name);
+ if ( $chief =~ m/^(.*):(.*)/ ) {
+ my $chief_name = $1;
+ my $chief_addr = $2;
+ push( @penguin_chief_names, $chief_name );
}
}
-my $penguin_chiefs = "\(" . join("|", @penguin_chief_names) . "\)";
+my $penguin_chiefs = "\(" . join( "|", @penguin_chief_names ) . "\)";

# Signature types of people who are either
# a) responsible for the code in question, or
# b) familiar enough with it to give relevant feedback
my @signature_tags = ();
-push(@signature_tags, "Signed-off-by:");
-push(@signature_tags, "Reviewed-by:");
-push(@signature_tags, "Acked-by:");
+push( @signature_tags, "Signed-off-by:" );
+push( @signature_tags, "Reviewed-by:" );
+push( @signature_tags, "Acked-by:" );

-my $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+my $signature_pattern = "\(" . join( "|", @signature_tags ) . "\)";

# rfc822 email address - preloaded methods go here.
my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
@@ -113,282 +114,250 @@ my $rfc822_char = '[\\000-\\377]';
my %VCS_cmds;

my %VCS_cmds_git = (
- "execute_cmd" => \&git_execute_cmd,
- "available" => '(which("git") ne "") && (-e ".git")',
- "find_signers_cmd" =>
- "git log --no-color --follow --since=\$email_git_since " .
- '--numstat --no-merges ' .
- '--format="GitCommit: %H%n' .
- 'GitAuthor: %an <%ae>%n' .
- 'GitDate: %aD%n' .
- 'GitSubject: %s%n' .
- '%b%n"' .
- " -- \$file",
- "find_commit_signers_cmd" =>
- "git log --no-color " .
- '--numstat ' .
- '--format="GitCommit: %H%n' .
- 'GitAuthor: %an <%ae>%n' .
- 'GitDate: %aD%n' .
- 'GitSubject: %s%n' .
- '%b%n"' .
- " -1 \$commit",
- "find_commit_author_cmd" =>
- "git log --no-color " .
- '--numstat ' .
- '--format="GitCommit: %H%n' .
- 'GitAuthor: %an <%ae>%n' .
- 'GitDate: %aD%n' .
- 'GitSubject: %s%n"' .
- " -1 \$commit",
- "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
- "blame_file_cmd" => "git blame -l \$file",
- "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
- "blame_commit_pattern" => "^([0-9a-f]+) ",
- "author_pattern" => "^GitAuthor: (.*)",
- "subject_pattern" => "^GitSubject: (.*)",
- "stat_pattern" => "^(\\d+)\\t(\\d+)\\t\$file\$",
- "file_exists_cmd" => "git ls-files \$file",
- "list_files_cmd" => "git ls-files \$file",
+ "execute_cmd" => \&git_execute_cmd,
+ "available" => '(which("git") ne "") && (-e ".git")',
+ "find_signers_cmd" => "git log --no-color --follow --since=\$email_git_since " . '--numstat --no-merges ' . '--format="GitCommit: %H%n' . 'GitAuthor: %an <%ae>%n' . 'GitDate: %aD%n' . 'GitSubject: %s%n' . '%b%n"' . " -- \$file",
+ "find_commit_signers_cmd" => "git log --no-color " . '--numstat ' . '--format="GitCommit: %H%n' . 'GitAuthor: %an <%ae>%n' . 'GitDate: %aD%n' . 'GitSubject: %s%n' . '%b%n"' . " -1 \$commit",
+ "find_commit_author_cmd" => "git log --no-color " . '--numstat ' . '--format="GitCommit: %H%n' . 'GitAuthor: %an <%ae>%n' . 'GitDate: %aD%n' . 'GitSubject: %s%n"' . " -1 \$commit",
+ "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
+ "blame_file_cmd" => "git blame -l \$file",
+ "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
+ "blame_commit_pattern" => "^([0-9a-f]+) ",
+ "author_pattern" => "^GitAuthor: (.*)",
+ "subject_pattern" => "^GitSubject: (.*)",
+ "stat_pattern" => "^(\\d+)\\t(\\d+)\\t\$file\$",
+ "file_exists_cmd" => "git ls-files \$file",
+ "list_files_cmd" => "git ls-files \$file",
);

my %VCS_cmds_hg = (
- "execute_cmd" => \&hg_execute_cmd,
- "available" => '(which("hg") ne "") && (-d ".hg")',
- "find_signers_cmd" =>
- "hg log --date=\$email_hg_since " .
- "--template='HgCommit: {node}\\n" .
- "HgAuthor: {author}\\n" .
- "HgSubject: {desc}\\n'" .
- " -- \$file",
- "find_commit_signers_cmd" =>
- "hg log " .
- "--template='HgSubject: {desc}\\n'" .
- " -r \$commit",
- "find_commit_author_cmd" =>
- "hg log " .
- "--template='HgCommit: {node}\\n" .
- "HgAuthor: {author}\\n" .
- "HgSubject: {desc|firstline}\\n'" .
- " -r \$commit",
- "blame_range_cmd" => "", # not supported
- "blame_file_cmd" => "hg blame -n \$file",
- "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
- "blame_commit_pattern" => "^([ 0-9a-f]+):",
- "author_pattern" => "^HgAuthor: (.*)",
- "subject_pattern" => "^HgSubject: (.*)",
- "stat_pattern" => "^(\\d+)\t(\\d+)\t\$file\$",
- "file_exists_cmd" => "hg files \$file",
- "list_files_cmd" => "hg manifest -R \$file",
+ "execute_cmd" => \&hg_execute_cmd,
+ "available" => '(which("hg") ne "") && (-d ".hg")',
+ "find_signers_cmd" => "hg log --date=\$email_hg_since " . "--template='HgCommit: {node}\\n" . "HgAuthor: {author}\\n" . "HgSubject: {desc}\\n'" . " -- \$file",
+ "find_commit_signers_cmd" => "hg log " . "--template='HgSubject: {desc}\\n'" . " -r \$commit",
+ "find_commit_author_cmd" => "hg log " . "--template='HgCommit: {node}\\n" . "HgAuthor: {author}\\n" . "HgSubject: {desc|firstline}\\n'" . " -r \$commit",
+ "blame_range_cmd" => "", # not supported
+ "blame_file_cmd" => "hg blame -n \$file",
+ "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
+ "blame_commit_pattern" => "^([ 0-9a-f]+):",
+ "author_pattern" => "^HgAuthor: (.*)",
+ "subject_pattern" => "^HgSubject: (.*)",
+ "stat_pattern" => "^(\\d+)\t(\\d+)\t\$file\$",
+ "file_exists_cmd" => "hg files \$file",
+ "list_files_cmd" => "hg manifest -R \$file",
);

my $conf = which_conf(".get_maintainer.conf");
-if (-f $conf) {
+if ( -f $conf ) {
my @conf_args;
- open(my $conffile, '<', "$conf")
- or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
+ open( my $conffile, '<', "$conf" )
+ or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";

while (<$conffile>) {
- my $line = $_;
+ my $line = $_;

- $line =~ s/\s*\n?$//g;
- $line =~ s/^\s*//g;
- $line =~ s/\s+/ /g;
+ $line =~ s/\s*\n?$//g;
+ $line =~ s/^\s*//g;
+ $line =~ s/\s+/ /g;

- next if ($line =~ m/^\s*#/);
- next if ($line =~ m/^\s*$/);
+ next if ( $line =~ m/^\s*#/ );
+ next if ( $line =~ m/^\s*$/ );

- my @words = split(" ", $line);
- foreach my $word (@words) {
- last if ($word =~ m/^#/);
- push (@conf_args, $word);
- }
+ my @words = split( " ", $line );
+ foreach my $word (@words) {
+ last if ( $word =~ m/^#/ );
+ push( @conf_args, $word );
+ }
}
close($conffile);
- unshift(@ARGV, @conf_args) if @conf_args;
+ unshift( @ARGV, @conf_args ) if @conf_args;
}

my @ignore_emails = ();
-my $ignore_file = which_conf(".get_maintainer.ignore");
-if (-f $ignore_file) {
- open(my $ignore, '<', "$ignore_file")
- or warn "$P: Can't find a readable .get_maintainer.ignore file $!\n";
+my $ignore_file = which_conf(".get_maintainer.ignore");
+if ( -f $ignore_file ) {
+ open( my $ignore, '<', "$ignore_file" )
+ or warn "$P: Can't find a readable .get_maintainer.ignore file $!\n";
while (<$ignore>) {
- my $line = $_;
+ my $line = $_;

- $line =~ s/\s*\n?$//;
- $line =~ s/^\s*//;
- $line =~ s/\s+$//;
- $line =~ s/#.*$//;
+ $line =~ s/\s*\n?$//;
+ $line =~ s/^\s*//;
+ $line =~ s/\s+$//;
+ $line =~ s/#.*$//;

- next if ($line =~ m/^\s*$/);
- if (rfc822_valid($line)) {
- push(@ignore_emails, $line);
- }
+ next if ( $line =~ m/^\s*$/ );
+ if ( rfc822_valid($line) ) {
+ push( @ignore_emails, $line );
+ }
}
close($ignore);
}

-if ($#ARGV > 0) {
+if ( $#ARGV > 0 ) {
foreach (@ARGV) {
- if ($_ =~ /^-{1,2}self-test(?:=|$)/) {
+ if ( $_ =~ /^-{1,2}self-test(?:=|$)/ ) {
die "$P: using --self-test does not allow any other option or argument\n";
}
}
}

if (!GetOptions(
- 'email!' => \$email,
- 'git!' => \$email_git,
- 'git-all-signature-types!' => \$email_git_all_signature_types,
- 'git-blame!' => \$email_git_blame,
- 'git-blame-signatures!' => \$email_git_blame_signatures,
- 'git-fallback!' => \$email_git_fallback,
- 'git-chief-penguins!' => \$email_git_penguin_chiefs,
- 'git-min-signatures=i' => \$email_git_min_signatures,
- 'git-max-maintainers=i' => \$email_git_max_maintainers,
- 'git-min-percent=i' => \$email_git_min_percent,
- 'git-since=s' => \$email_git_since,
- 'hg-since=s' => \$email_hg_since,
- 'i|interactive!' => \$interactive,
- 'remove-duplicates!' => \$email_remove_duplicates,
- 'mailmap!' => \$email_use_mailmap,
- 'm!' => \$email_maintainer,
- 'r!' => \$email_reviewer,
- 'n!' => \$email_usename,
- 'l!' => \$email_list,
- 'fixes!' => \$email_fixes,
- 'moderated!' => \$email_moderated_list,
- 's!' => \$email_subscriber_list,
- 'multiline!' => \$output_multiline,
- 'roles!' => \$output_roles,
- 'rolestats!' => \$output_rolestats,
- 'separator=s' => \$output_separator,
- 'subsystem!' => \$subsystem,
- 'status!' => \$status,
- 'scm!' => \$scm,
- 'tree!' => \$tree,
- 'web!' => \$web,
- 'letters=s' => \$letters,
- 'pattern-depth=i' => \$pattern_depth,
- 'k|keywords!' => \$keywords,
- 'sections!' => \$sections,
- 'fe|file-emails!' => \$email_file_emails,
- 'f|file' => \$from_filename,
- 'find-maintainer-files' => \$find_maintainer_files,
- 'mpath|maintainer-path=s' => \$maintainer_path,
- 'self-test:s' => \$self_test,
- 'v|version' => \$version,
- 'h|help|usage' => \$help,
- )) {
+ 'email!' => \$email,
+ 'git!' => \$email_git,
+ 'git-all-signature-types!' => \$email_git_all_signature_types,
+ 'git-blame!' => \$email_git_blame,
+ 'git-blame-signatures!' => \$email_git_blame_signatures,
+ 'git-fallback!' => \$email_git_fallback,
+ 'git-chief-penguins!' => \$email_git_penguin_chiefs,
+ 'git-min-signatures=i' => \$email_git_min_signatures,
+ 'git-max-maintainers=i' => \$email_git_max_maintainers,
+ 'git-min-percent=i' => \$email_git_min_percent,
+ 'git-since=s' => \$email_git_since,
+ 'hg-since=s' => \$email_hg_since,
+ 'i|interactive!' => \$interactive,
+ 'remove-duplicates!' => \$email_remove_duplicates,
+ 'mailmap!' => \$email_use_mailmap,
+ 'm!' => \$email_maintainer,
+ 'r!' => \$email_reviewer,
+ 'n!' => \$email_usename,
+ 'l!' => \$email_list,
+ 'fixes!' => \$email_fixes,
+ 'moderated!' => \$email_moderated_list,
+ 's!' => \$email_subscriber_list,
+ 'multiline!' => \$output_multiline,
+ 'roles!' => \$output_roles,
+ 'rolestats!' => \$output_rolestats,
+ 'separator=s' => \$output_separator,
+ 'subsystem!' => \$subsystem,
+ 'status!' => \$status,
+ 'scm!' => \$scm,
+ 'tree!' => \$tree,
+ 'web!' => \$web,
+ 'letters=s' => \$letters,
+ 'pattern-depth=i' => \$pattern_depth,
+ 'k|keywords!' => \$keywords,
+ 'sections!' => \$sections,
+ 'fe|file-emails!' => \$email_file_emails,
+ 'f|file' => \$from_filename,
+ 'find-maintainer-files' => \$find_maintainer_files,
+ 'mpath|maintainer-path=s' => \$maintainer_path,
+ 'self-test:s' => \$self_test,
+ 'v|version' => \$version,
+ 'h|help|usage' => \$help,
+ )
+ )
+{
die "$P: invalid argument - use --help if necessary\n";
}

-if ($help != 0) {
+if ( $help != 0 ) {
usage();
exit 0;
}

-if ($version != 0) {
+if ( $version != 0 ) {
print("${P} ${V}\n");
exit 0;
}

-if (defined $self_test) {
+if ( defined $self_test ) {
read_all_maintainer_files();
self_test();
exit 0;
}

-if (-t STDIN && !@ARGV) {
+if ( -t STDIN && !@ARGV ) {
+
# We're talking to a terminal, but have no command line arguments.
die "$P: missing patchfile or -f file - use --help if necessary\n";
}

-$output_multiline = 0 if ($output_separator ne ", ");
+$output_multiline = 0 if ( $output_separator ne ", " );
$output_rolestats = 1 if ($interactive);
-$output_roles = 1 if ($output_rolestats);
-
-if ($sections || $letters ne "") {
- $sections = 1;
- $email = 0;
- $email_list = 0;
- $scm = 0;
- $status = 0;
- $subsystem = 0;
- $web = 0;
- $keywords = 0;
+$output_roles = 1 if ($output_rolestats);
+
+if ( $sections || $letters ne "" ) {
+ $sections = 1;
+ $email = 0;
+ $email_list = 0;
+ $scm = 0;
+ $status = 0;
+ $subsystem = 0;
+ $web = 0;
+ $keywords = 0;
$interactive = 0;
-} else {
+}
+else {
my $selections = $email + $scm + $status + $subsystem + $web;
- if ($selections == 0) {
- die "$P: Missing required option: email, scm, status, subsystem or web\n";
+ if ( $selections == 0 ) {
+ die "$P: Missing required option: email, scm, status, subsystem or web\n";
}
}

-if ($email &&
- ($email_maintainer + $email_reviewer +
- $email_list + $email_subscriber_list +
- $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
+if ( $email
+ && ( $email_maintainer + $email_reviewer + $email_list + $email_subscriber_list + $email_git + $email_git_penguin_chiefs + $email_git_blame ) == 0 )
+{
die "$P: Please select at least 1 email option\n";
}

-if ($tree && !top_of_kernel_tree($lk_path)) {
- die "$P: The current directory does not appear to be "
- . "a linux kernel source tree.\n";
+if ( $tree && !top_of_kernel_tree($lk_path) ) {
+ die "$P: The current directory does not appear to be " . "a linux kernel source tree.\n";
}

## Read MAINTAINERS for type/value pairs

my @typevalue = ();
my %keyword_hash;
-my @mfiles = ();
+my @mfiles = ();
my @self_test_info = ();

sub read_maintainer_file {
my ($file) = @_;

- open (my $maint, '<', "$file")
- or die "$P: Can't open MAINTAINERS file '$file': $!\n";
+ open( my $maint, '<', "$file" )
+ or die "$P: Can't open MAINTAINERS file '$file': $!\n";
my $i = 1;
while (<$maint>) {
- my $line = $_;
- chomp $line;
-
- if ($line =~ m/^([A-Z]):\s*(.*)/) {
- my $type = $1;
- my $value = $2;
-
- ##Filename pattern matching
- if ($type eq "F" || $type eq "X") {
- $value =~ s@\.@\\\.@g; ##Convert . to \.
- $value =~ s/\*/\.\*/g; ##Convert * to .*
- $value =~ s/\?/\./g; ##Convert ? to .
- ##if pattern is a directory and it lacks a trailing slash, add one
- if ((-d $value)) {
- $value =~ s@([^/])$@$1/@;
- }
- } elsif ($type eq "K") {
- $keyword_hash{@typevalue} = $value;
- }
- push(@typevalue, "$type:$value");
- } elsif (!(/^\s*$/ || /^\s*\#/)) {
- push(@typevalue, $line);
- }
- if (defined $self_test) {
- push(@self_test_info, {file=>$file, linenr=>$i, line=>$line});
- }
- $i++;
+ my $line = $_;
+ chomp $line;
+
+ if ( $line =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $type = $1;
+ my $value = $2;
+
+ ##Filename pattern matching
+ if ( $type eq "F" || $type eq "X" ) {
+ $value =~ s@\.@\\\.@g; ##Convert . to \.
+ $value =~ s/\*/\.\*/g; ##Convert * to .*
+ $value =~ s/\?/\./g; ##Convert ? to .
+ ##if pattern is a directory and it lacks a trailing slash, add one
+ if ( ( -d $value ) ) {
+ $value =~ s@([^/])$@$1/@;
+ }
+ }
+ elsif ( $type eq "K" ) {
+ $keyword_hash{@typevalue} = $value;
+ }
+ push( @typevalue, "$type:$value" );
+ }
+ elsif ( !( /^\s*$/ || /^\s*\#/ ) ) {
+ push( @typevalue, $line );
+ }
+ if ( defined $self_test ) {
+ push( @self_test_info, { file => $file, linenr => $i, line => $line } );
+ }
+ $i++;
}
close($maint);
}

sub find_is_maintainer_file {
my ($file) = $_;
- return if ($file !~ m@/MAINTAINERS$@);
+ return if ( $file !~ m@/MAINTAINERS$@ );
$file = $File::Find::name;
- return if (! -f $file);
- push(@mfiles, $file);
+ return if ( !-f $file );
+ push( @mfiles, $file );
}

sub find_ignore_git {
@@ -399,51 +368,58 @@ read_all_maintainer_files();

sub read_all_maintainer_files {
my $path = "${lk_path}MAINTAINERS";
- if (defined $maintainer_path) {
- $path = $maintainer_path;
- # Perl Cookbook tilde expansion if necessary
- $path =~ s@^~([^/]*)@ $1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($<))[7])@ex;
- }
-
- if (-d $path) {
- $path .= '/' if ($path !~ m@/$@);
- if ($find_maintainer_files) {
- find( { wanted => \&find_is_maintainer_file,
- preprocess => \&find_ignore_git,
- no_chdir => 1,
- }, "$path");
- } else {
- opendir(DIR, "$path") or die $!;
- my @files = readdir(DIR);
- closedir(DIR);
- foreach my $file (@files) {
- push(@mfiles, "$path$file") if ($file !~ /^\./);
- }
- }
- } elsif (-f "$path") {
- push(@mfiles, "$path");
- } else {
- die "$P: MAINTAINER file not found '$path'\n";
- }
- die "$P: No MAINTAINER files found in '$path'\n" if (scalar(@mfiles) == 0);
+ if ( defined $maintainer_path ) {
+ $path = $maintainer_path;
+
+ # Perl Cookbook tilde expansion if necessary
+ $path =~ s@^~([^/]*)@ $1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($<))[7])@ex;
+ }
+
+ if ( -d $path ) {
+ $path .= '/' if ( $path !~ m@/$@ );
+ if ($find_maintainer_files) {
+ find(
+ { wanted => \&find_is_maintainer_file,
+ preprocess => \&find_ignore_git,
+ no_chdir => 1,
+ },
+ "$path"
+ );
+ }
+ else {
+ opendir( DIR, "$path" ) or die $!;
+ my @files = readdir(DIR);
+ closedir(DIR);
+ foreach my $file (@files) {
+ push( @mfiles, "$path$file" ) if ( $file !~ /^\./ );
+ }
+ }
+ }
+ elsif ( -f "$path" ) {
+ push( @mfiles, "$path" );
+ }
+ else {
+ die "$P: MAINTAINER file not found '$path'\n";
+ }
+ die "$P: No MAINTAINER files found in '$path'\n" if ( scalar(@mfiles) == 0 );
foreach my $file (@mfiles) {
- read_maintainer_file("$file");
+ read_maintainer_file("$file");
}
}

sub maintainers_in_file {
my ($file) = @_;

- return if ($file =~ m@\bMAINTAINERS$@);
+ return if ( $file =~ m@\bMAINTAINERS$@ );

- if (-f $file && ($email_file_emails || $file =~ /\.yaml$/)) {
- open(my $f, '<', $file)
- or die "$P: Can't open $file: $!\n";
- my $text = do { local($/) ; <$f> };
- close($f);
+ if ( -f $file && ( $email_file_emails || $file =~ /\.yaml$/ ) ) {
+ open( my $f, '<', $file )
+ or die "$P: Can't open $file: $!\n";
+ my $text = do { local ($/); <$f> };
+ close($f);

- 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;
- push(@file_emails, clean_file_emails(@poss_addr));
+ 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;
+ push( @file_emails, clean_file_emails(@poss_addr) );
}
}

@@ -457,181 +433,188 @@ read_mailmap();

sub read_mailmap {
$mailmap = {
- names => {},
- addresses => {}
+ names => {},
+ addresses => {}
};

- return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
+ return if ( !$email_use_mailmap || !( -f "${lk_path}.mailmap" ) );

- open(my $mailmap_file, '<', "${lk_path}.mailmap")
- or warn "$P: Can't open .mailmap: $!\n";
+ open( my $mailmap_file, '<', "${lk_path}.mailmap" )
+ or warn "$P: Can't open .mailmap: $!\n";

while (<$mailmap_file>) {
- s/#.*$//; #strip comments
- s/^\s+|\s+$//g; #trim
-
- next if (/^\s*$/); #skip empty lines
- #entries have one of the following formats:
- # name1 <mail1>
- # <mail1> <mail2>
- # name1 <mail1> <mail2>
- # name1 <mail1> name2 <mail2>
- # (see man git-shortlog)
-
- if (/^([^<]+)<([^>]+)>$/) {
- my $real_name = $1;
- my $address = $2;
-
- $real_name =~ s/\s+$//;
- ($real_name, $address) = parse_email("$real_name <$address>");
- $mailmap->{names}->{$address} = $real_name;
-
- } elsif (/^<([^>]+)>\s*<([^>]+)>$/) {
- my $real_address = $1;
- my $wrong_address = $2;
-
- $mailmap->{addresses}->{$wrong_address} = $real_address;
-
- } elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) {
- my $real_name = $1;
- my $real_address = $2;
- my $wrong_address = $3;
-
- $real_name =~ s/\s+$//;
- ($real_name, $real_address) =
- parse_email("$real_name <$real_address>");
- $mailmap->{names}->{$wrong_address} = $real_name;
- $mailmap->{addresses}->{$wrong_address} = $real_address;
-
- } elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) {
- my $real_name = $1;
- my $real_address = $2;
- my $wrong_name = $3;
- my $wrong_address = $4;
-
- $real_name =~ s/\s+$//;
- ($real_name, $real_address) =
- parse_email("$real_name <$real_address>");
-
- $wrong_name =~ s/\s+$//;
- ($wrong_name, $wrong_address) =
- parse_email("$wrong_name <$wrong_address>");
-
- my $wrong_email = format_email($wrong_name, $wrong_address, 1);
- $mailmap->{names}->{$wrong_email} = $real_name;
- $mailmap->{addresses}->{$wrong_email} = $real_address;
- }
+ s/#.*$//; #strip comments
+ s/^\s+|\s+$//g; #trim
+
+ next if (/^\s*$/); #skip empty lines
+ #entries have one of the following formats:
+ # name1 <mail1>
+ # <mail1> <mail2>
+ # name1 <mail1> <mail2>
+ # name1 <mail1> name2 <mail2>
+ # (see man git-shortlog)
+
+ if (/^([^<]+)<([^>]+)>$/) {
+ my $real_name = $1;
+ my $address = $2;
+
+ $real_name =~ s/\s+$//;
+ ( $real_name, $address ) = parse_email("$real_name <$address>");
+ $mailmap->{names}->{$address} = $real_name;
+
+ }
+ elsif (/^<([^>]+)>\s*<([^>]+)>$/) {
+ my $real_address = $1;
+ my $wrong_address = $2;
+
+ $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+ }
+ elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) {
+ my $real_name = $1;
+ my $real_address = $2;
+ my $wrong_address = $3;
+
+ $real_name =~ s/\s+$//;
+ ( $real_name, $real_address ) = parse_email("$real_name <$real_address>");
+ $mailmap->{names}->{$wrong_address} = $real_name;
+ $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+ }
+ elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) {
+ my $real_name = $1;
+ my $real_address = $2;
+ my $wrong_name = $3;
+ my $wrong_address = $4;
+
+ $real_name =~ s/\s+$//;
+ ( $real_name, $real_address ) = parse_email("$real_name <$real_address>");
+
+ $wrong_name =~ s/\s+$//;
+ ( $wrong_name, $wrong_address ) = parse_email("$wrong_name <$wrong_address>");
+
+ my $wrong_email = format_email( $wrong_name, $wrong_address, 1 );
+ $mailmap->{names}->{$wrong_email} = $real_name;
+ $mailmap->{addresses}->{$wrong_email} = $real_address;
+ }
}
close($mailmap_file);
}

## use the filenames on the command line or find the filenames in the patchfiles

-if (!@ARGV) {
- push(@ARGV, "&STDIN");
+if ( !@ARGV ) {
+ push( @ARGV, "&STDIN" );
}

foreach my $file (@ARGV) {
- if ($file ne "&STDIN") {
- $file = canonpath($file);
- ##if $file is a directory and it lacks a trailing slash, add one
- if ((-d $file)) {
- $file =~ s@([^/])$@$1/@;
- } elsif (!(-f $file)) {
- die "$P: file '${file}' not found\n";
- }
- }
- if ($from_filename && (vcs_exists() && !vcs_file_exists($file))) {
- warn "$P: file '$file' not found in version control $!\n";
- }
- if ($from_filename || ($file ne "&STDIN" && vcs_file_exists($file))) {
- $file =~ s/^\Q${cur_path}\E//; #strip any absolute path
- $file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree
- push(@files, $file);
- if ($file ne "MAINTAINERS" && -f $file && $keywords) {
- open(my $f, '<', $file)
- or die "$P: Can't open $file: $!\n";
- my $text = do { local($/) ; <$f> };
- close($f);
- if ($keywords) {
- foreach my $line (keys %keyword_hash) {
- if ($text =~ m/$keyword_hash{$line}/x) {
- push(@keyword_tvi, $line);
- }
- }
- }
- }
- } else {
- my $file_cnt = @files;
- my $lastfile;
-
- open(my $patch, "< $file")
- or die "$P: Can't open $file: $!\n";
-
- # We can check arbitrary information before the patch
- # like the commit message, mail headers, etc...
- # This allows us to match arbitrary keywords against any part
- # of a git format-patch generated file (subject tags, etc...)
-
- my $patch_prefix = ""; #Parsing the intro
-
- while (<$patch>) {
- my $patch_line = $_;
- if (m/^ mode change [0-7]+ => [0-7]+ (\S+)\s*$/) {
- my $filename = $1;
- push(@files, $filename);
- } elsif (m/^rename (?:from|to) (\S+)\s*$/) {
- my $filename = $1;
- push(@files, $filename);
- } elsif (m/^diff --git a\/(\S+) b\/(\S+)\s*$/) {
- my $filename1 = $1;
- my $filename2 = $2;
- push(@files, $filename1);
- push(@files, $filename2);
- } elsif (m/^Fixes:\s+([0-9a-fA-F]{6,40})/) {
- push(@fixes, $1) if ($email_fixes);
- } elsif (m/^\+\+\+\s+(\S+)/ or m/^---\s+(\S+)/) {
- my $filename = $1;
- $filename =~ s@^[^/]*/@@;
- $filename =~ s@\n@@;
- $lastfile = $filename;
- push(@files, $filename);
- $patch_prefix = "^[+-].*"; #Now parsing the actual patch
- } elsif (m/^\@\@ -(\d+),(\d+)/) {
- if ($email_git_blame) {
- push(@range, "$lastfile:$1:$2");
- }
- } elsif ($keywords) {
- foreach my $line (keys %keyword_hash) {
- if ($patch_line =~ m/${patch_prefix}$keyword_hash{$line}/x) {
- push(@keyword_tvi, $line);
- }
- }
- }
- }
- close($patch);
-
- if ($file_cnt == @files) {
- warn "$P: file '${file}' doesn't appear to be a patch. "
- . "Add -f to options?\n";
- }
- @files = sort_and_uniq(@files);
+ if ( $file ne "&STDIN" ) {
+ $file = canonpath($file);
+ ##if $file is a directory and it lacks a trailing slash, add one
+ if ( ( -d $file ) ) {
+ $file =~ s@([^/])$@$1/@;
+ }
+ elsif ( !( -f $file ) ) {
+ die "$P: file '${file}' not found\n";
+ }
+ }
+ if ( $from_filename && ( vcs_exists() && !vcs_file_exists($file) ) ) {
+ warn "$P: file '$file' not found in version control $!\n";
+ }
+ if ( $from_filename || ( $file ne "&STDIN" && vcs_file_exists($file) ) ) {
+ $file =~ s/^\Q${cur_path}\E//; #strip any absolute path
+ $file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree
+ push( @files, $file );
+ if ( $file ne "MAINTAINERS" && -f $file && $keywords ) {
+ open( my $f, '<', $file )
+ or die "$P: Can't open $file: $!\n";
+ my $text = do { local ($/); <$f> };
+ close($f);
+ if ($keywords) {
+ foreach my $line ( keys %keyword_hash ) {
+ if ( $text =~ m/$keyword_hash{$line}/x ) {
+ push( @keyword_tvi, $line );
+ }
+ }
+ }
+ }
+ }
+ else {
+ my $file_cnt = @files;
+ my $lastfile;
+
+ open( my $patch, "< $file" )
+ or die "$P: Can't open $file: $!\n";
+
+ # We can check arbitrary information before the patch
+ # like the commit message, mail headers, etc...
+ # This allows us to match arbitrary keywords against any part
+ # of a git format-patch generated file (subject tags, etc...)
+
+ my $patch_prefix = ""; #Parsing the intro
+
+ while (<$patch>) {
+ my $patch_line = $_;
+ if (m/^ mode change [0-7]+ => [0-7]+ (\S+)\s*$/) {
+ my $filename = $1;
+ push( @files, $filename );
+ }
+ elsif (m/^rename (?:from|to) (\S+)\s*$/) {
+ my $filename = $1;
+ push( @files, $filename );
+ }
+ elsif (m/^diff --git a\/(\S+) b\/(\S+)\s*$/) {
+ my $filename1 = $1;
+ my $filename2 = $2;
+ push( @files, $filename1 );
+ push( @files, $filename2 );
+ }
+ elsif (m/^Fixes:\s+([0-9a-fA-F]{6,40})/) {
+ push( @fixes, $1 ) if ($email_fixes);
+ }
+ elsif ( m/^\+\+\+\s+(\S+)/ or m/^---\s+(\S+)/ ) {
+ my $filename = $1;
+ $filename =~ s@^[^/]*/@@;
+ $filename =~ s@\n@@;
+ $lastfile = $filename;
+ push( @files, $filename );
+ $patch_prefix = "^[+-].*"; #Now parsing the actual patch
+ }
+ elsif (m/^\@\@ -(\d+),(\d+)/) {
+ if ($email_git_blame) {
+ push( @range, "$lastfile:$1:$2" );
+ }
+ }
+ elsif ($keywords) {
+ foreach my $line ( keys %keyword_hash ) {
+ if ( $patch_line =~ m/${patch_prefix}$keyword_hash{$line}/x ) {
+ push( @keyword_tvi, $line );
+ }
+ }
+ }
+ }
+ close($patch);
+
+ if ( $file_cnt == @files ) {
+ warn "$P: file '${file}' doesn't appear to be a patch. " . "Add -f to options?\n";
+ }
+ @files = sort_and_uniq(@files);
}
}

@file_emails = uniq(@file_emails);
-@fixes = uniq(@fixes);
+@fixes = uniq(@fixes);

my %email_hash_name;
my %email_hash_address;
my @email_to = ();
my %hash_list_to;
-my @list_to = ();
-my @scm = ();
-my @web = ();
-my @subsystem = ();
-my @status = ();
-my %deduplicate_name_hash = ();
+my @list_to = ();
+my @scm = ();
+my @web = ();
+my @subsystem = ();
+my @status = ();
+my %deduplicate_name_hash = ();
my %deduplicate_address_hash = ();

my @maintainers = get_maintainers();
@@ -663,131 +646,148 @@ if ($web) {
exit($exit);

sub self_test {
- my @lsfiles = ();
- my @good_links = ();
- my @bad_links = ();
+ my @lsfiles = ();
+ my @good_links = ();
+ my @bad_links = ();
my @section_headers = ();
- my $index = 0;
+ my $index = 0;

@lsfiles = vcs_list_files($lk_path);

for my $x (@self_test_info) {
- $index++;
-
- ## Section header duplication and missing section content
- if (($self_test eq "" || $self_test =~ /\bsections\b/) &&
- $x->{line} =~ /^\S[^:]/ &&
- defined $self_test_info[$index] &&
- $self_test_info[$index]->{line} =~ /^([A-Z]):\s*\S/) {
- my $has_S = 0;
- my $has_F = 0;
- my $has_ML = 0;
- my $status = "";
- if (grep(m@^\Q$x->{line}\E@, @section_headers)) {
- print("$x->{file}:$x->{linenr}: warning: duplicate section header\t$x->{line}\n");
- } else {
- push(@section_headers, $x->{line});
- }
- my $nextline = $index;
- while (defined $self_test_info[$nextline] &&
- $self_test_info[$nextline]->{line} =~ /^([A-Z]):\s*(\S.*)/) {
- my $type = $1;
- my $value = $2;
- if ($type eq "S") {
- $has_S = 1;
- $status = $value;
- } elsif ($type eq "F" || $type eq "N") {
- $has_F = 1;
- } elsif ($type eq "M" || $type eq "R" || $type eq "L") {
- $has_ML = 1;
- }
- $nextline++;
- }
- if (!$has_ML && $status !~ /orphan|obsolete/i) {
- print("$x->{file}:$x->{linenr}: warning: section without email address\t$x->{line}\n");
- }
- if (!$has_S) {
- print("$x->{file}:$x->{linenr}: warning: section without status \t$x->{line}\n");
- }
- if (!$has_F) {
- print("$x->{file}:$x->{linenr}: warning: section without file pattern\t$x->{line}\n");
- }
- }
-
- next if ($x->{line} !~ /^([A-Z]):\s*(.*)/);
-
- my $type = $1;
- my $value = $2;
-
- ## Filename pattern matching
- if (($type eq "F" || $type eq "X") &&
- ($self_test eq "" || $self_test =~ /\bpatterns\b/)) {
- $value =~ s@\.@\\\.@g; ##Convert . to \.
- $value =~ s/\*/\.\*/g; ##Convert * to .*
- $value =~ s/\?/\./g; ##Convert ? to .
- ##if pattern is a directory and it lacks a trailing slash, add one
- if ((-d $value)) {
- $value =~ s@([^/])$@$1/@;
- }
- if (!grep(m@^$value@, @lsfiles)) {
- print("$x->{file}:$x->{linenr}: warning: no file matches\t$x->{line}\n");
- }
-
- ## Link reachability
- } elsif (($type eq "W" || $type eq "Q" || $type eq "B") &&
- $value =~ /^https?:/ &&
- ($self_test eq "" || $self_test =~ /\blinks\b/)) {
- next if (grep(m@^\Q$value\E$@, @good_links));
- my $isbad = 0;
- if (grep(m@^\Q$value\E$@, @bad_links)) {
- $isbad = 1;
- } else {
- my $output = `wget --spider -q --no-check-certificate --timeout 10 --tries 1 $value`;
- if ($? == 0) {
- push(@good_links, $value);
- } else {
- push(@bad_links, $value);
- $isbad = 1;
- }
- }
- if ($isbad) {
- print("$x->{file}:$x->{linenr}: warning: possible bad link\t$x->{line}\n");
- }
-
- ## SCM reachability
- } elsif ($type eq "T" &&
- ($self_test eq "" || $self_test =~ /\bscm\b/)) {
- next if (grep(m@^\Q$value\E$@, @good_links));
- my $isbad = 0;
- if (grep(m@^\Q$value\E$@, @bad_links)) {
- $isbad = 1;
- } elsif ($value !~ /^(?:git|quilt|hg)\s+\S/) {
- print("$x->{file}:$x->{linenr}: warning: malformed entry\t$x->{line}\n");
- } elsif ($value =~ /^git\s+(\S+)(\s+([^\(]+\S+))?/) {
- my $url = $1;
- my $branch = "";
- $branch = $3 if $3;
- my $output = `git ls-remote --exit-code -h "$url" $branch > /dev/null 2>&1`;
- if ($? == 0) {
- push(@good_links, $value);
- } else {
- push(@bad_links, $value);
- $isbad = 1;
- }
- } elsif ($value =~ /^(?:quilt|hg)\s+(https?:\S+)/) {
- my $url = $1;
- my $output = `wget --spider -q --no-check-certificate --timeout 10 --tries 1 $url`;
- if ($? == 0) {
- push(@good_links, $value);
- } else {
- push(@bad_links, $value);
- $isbad = 1;
- }
- }
- if ($isbad) {
- print("$x->{file}:$x->{linenr}: warning: possible bad link\t$x->{line}\n");
- }
- }
+ $index++;
+
+ ## Section header duplication and missing section content
+ if ( ( $self_test eq "" || $self_test =~ /\bsections\b/ )
+ && $x->{line} =~ /^\S[^:]/
+ && defined $self_test_info[$index]
+ && $self_test_info[$index]->{line} =~ /^([A-Z]):\s*\S/ )
+ {
+ my $has_S = 0;
+ my $has_F = 0;
+ my $has_ML = 0;
+ my $status = "";
+ if ( grep( m@^\Q$x->{line}\E@, @section_headers ) ) {
+ print("$x->{file}:$x->{linenr}: warning: duplicate section header\t$x->{line}\n");
+ }
+ else {
+ push( @section_headers, $x->{line} );
+ }
+ my $nextline = $index;
+ while ( defined $self_test_info[$nextline]
+ && $self_test_info[$nextline]->{line} =~ /^([A-Z]):\s*(\S.*)/ )
+ {
+ my $type = $1;
+ my $value = $2;
+ if ( $type eq "S" ) {
+ $has_S = 1;
+ $status = $value;
+ }
+ elsif ( $type eq "F" || $type eq "N" ) {
+ $has_F = 1;
+ }
+ elsif ( $type eq "M" || $type eq "R" || $type eq "L" ) {
+ $has_ML = 1;
+ }
+ $nextline++;
+ }
+ if ( !$has_ML && $status !~ /orphan|obsolete/i ) {
+ print("$x->{file}:$x->{linenr}: warning: section without email address\t$x->{line}\n");
+ }
+ if ( !$has_S ) {
+ print("$x->{file}:$x->{linenr}: warning: section without status \t$x->{line}\n");
+ }
+ if ( !$has_F ) {
+ print("$x->{file}:$x->{linenr}: warning: section without file pattern\t$x->{line}\n");
+ }
+ }
+
+ next if ( $x->{line} !~ /^([A-Z]):\s*(.*)/ );
+
+ my $type = $1;
+ my $value = $2;
+
+ ## Filename pattern matching
+ if ( ( $type eq "F" || $type eq "X" )
+ && ( $self_test eq "" || $self_test =~ /\bpatterns\b/ ) )
+ {
+ $value =~ s@\.@\\\.@g; ##Convert . to \.
+ $value =~ s/\*/\.\*/g; ##Convert * to .*
+ $value =~ s/\?/\./g; ##Convert ? to .
+ ##if pattern is a directory and it lacks a trailing slash, add one
+ if ( ( -d $value ) ) {
+ $value =~ s@([^/])$@$1/@;
+ }
+ if ( !grep( m@^$value@, @lsfiles ) ) {
+ print("$x->{file}:$x->{linenr}: warning: no file matches\t$x->{line}\n");
+ }
+
+ ## Link reachability
+ }
+ elsif (( $type eq "W" || $type eq "Q" || $type eq "B" )
+ && $value =~ /^https?:/
+ && ( $self_test eq "" || $self_test =~ /\blinks\b/ ) )
+ {
+ next if ( grep( m@^\Q$value\E$@, @good_links ) );
+ my $isbad = 0;
+ if ( grep( m@^\Q$value\E$@, @bad_links ) ) {
+ $isbad = 1;
+ }
+ else {
+ my $output = `wget --spider -q --no-check-certificate --timeout 10 --tries 1 $value`;
+ if ( $? == 0 ) {
+ push( @good_links, $value );
+ }
+ else {
+ push( @bad_links, $value );
+ $isbad = 1;
+ }
+ }
+ if ($isbad) {
+ print("$x->{file}:$x->{linenr}: warning: possible bad link\t$x->{line}\n");
+ }
+
+ ## SCM reachability
+ }
+ elsif ( $type eq "T"
+ && ( $self_test eq "" || $self_test =~ /\bscm\b/ ) )
+ {
+ next if ( grep( m@^\Q$value\E$@, @good_links ) );
+ my $isbad = 0;
+ if ( grep( m@^\Q$value\E$@, @bad_links ) ) {
+ $isbad = 1;
+ }
+ elsif ( $value !~ /^(?:git|quilt|hg)\s+\S/ ) {
+ print("$x->{file}:$x->{linenr}: warning: malformed entry\t$x->{line}\n");
+ }
+ elsif ( $value =~ /^git\s+(\S+)(\s+([^\(]+\S+))?/ ) {
+ my $url = $1;
+ my $branch = "";
+ $branch = $3 if $3;
+ my $output = `git ls-remote --exit-code -h "$url" $branch > /dev/null 2>&1`;
+ if ( $? == 0 ) {
+ push( @good_links, $value );
+ }
+ else {
+ push( @bad_links, $value );
+ $isbad = 1;
+ }
+ }
+ elsif ( $value =~ /^(?:quilt|hg)\s+(https?:\S+)/ ) {
+ my $url = $1;
+ my $output = `wget --spider -q --no-check-certificate --timeout 10 --tries 1 $url`;
+ if ( $? == 0 ) {
+ push( @good_links, $value );
+ }
+ else {
+ push( @bad_links, $value );
+ $isbad = 1;
+ }
+ }
+ if ($isbad) {
+ print("$x->{file}:$x->{linenr}: warning: possible bad link\t$x->{line}\n");
+ }
+ }
}
}

@@ -795,64 +795,66 @@ sub ignore_email_address {
my ($address) = @_;

foreach my $ignore (@ignore_emails) {
- return 1 if ($ignore eq $address);
+ return 1 if ( $ignore eq $address );
}

return 0;
}

sub range_is_maintained {
- my ($start, $end) = @_;
-
- for (my $i = $start; $i < $end; $i++) {
- my $line = $typevalue[$i];
- if ($line =~ m/^([A-Z]):\s*(.*)/) {
- my $type = $1;
- my $value = $2;
- if ($type eq 'S') {
- if ($value =~ /(maintain|support)/i) {
- return 1;
- }
- }
- }
+ my ( $start, $end ) = @_;
+
+ for ( my $i = $start; $i < $end; $i++ ) {
+ my $line = $typevalue[$i];
+ if ( $line =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $type = $1;
+ my $value = $2;
+ if ( $type eq 'S' ) {
+ if ( $value =~ /(maintain|support)/i ) {
+ return 1;
+ }
+ }
+ }
}
return 0;
}

sub range_has_maintainer {
- my ($start, $end) = @_;
-
- for (my $i = $start; $i < $end; $i++) {
- my $line = $typevalue[$i];
- if ($line =~ m/^([A-Z]):\s*(.*)/) {
- my $type = $1;
- my $value = $2;
- if ($type eq 'M') {
- return 1;
- }
- }
+ my ( $start, $end ) = @_;
+
+ for ( my $i = $start; $i < $end; $i++ ) {
+ my $line = $typevalue[$i];
+ if ( $line =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $type = $1;
+ my $value = $2;
+ if ( $type eq 'M' ) {
+ return 1;
+ }
+ }
}
return 0;
}

sub get_maintainers {
- %email_hash_name = ();
- %email_hash_address = ();
- %commit_author_hash = ();
- %commit_signer_hash = ();
- @email_to = ();
- %hash_list_to = ();
- @list_to = ();
- @scm = ();
- @web = ();
- @subsystem = ();
- @status = ();
- %deduplicate_name_hash = ();
+ %email_hash_name = ();
+ %email_hash_address = ();
+ %commit_author_hash = ();
+ %commit_signer_hash = ();
+ @email_to = ();
+ %hash_list_to = ();
+ @list_to = ();
+ @scm = ();
+ @web = ();
+ @subsystem = ();
+ @status = ();
+ %deduplicate_name_hash = ();
%deduplicate_address_hash = ();
+
if ($email_git_all_signature_types) {
- $signature_pattern = "(.+?)[Bb][Yy]:";
- } else {
- $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+ $signature_pattern = "(.+?)[Bb][Yy]:";
+ }
+ else {
+ $signature_pattern = "\(" . join( "|", @signature_tags ) . "\)";
}

# Find responsible parties
@@ -861,172 +863,180 @@ sub get_maintainers {

foreach my $file (@files) {

- my %hash;
- my $tvi = find_first_section();
- while ($tvi < @typevalue) {
- my $start = find_starting_index($tvi);
- my $end = find_ending_index($tvi);
- my $exclude = 0;
- my $i;
-
- #Do not match excluded file patterns
-
- for ($i = $start; $i < $end; $i++) {
- my $line = $typevalue[$i];
- if ($line =~ m/^([A-Z]):\s*(.*)/) {
- my $type = $1;
- my $value = $2;
- if ($type eq 'X') {
- if (file_match_pattern($file, $value)) {
- $exclude = 1;
- last;
- }
- }
- }
- }
-
- if (!$exclude) {
- for ($i = $start; $i < $end; $i++) {
- my $line = $typevalue[$i];
- if ($line =~ m/^([A-Z]):\s*(.*)/) {
- my $type = $1;
- my $value = $2;
- if ($type eq 'F') {
- if (file_match_pattern($file, $value)) {
- my $value_pd = ($value =~ tr@/@@);
- my $file_pd = ($file =~ tr@/@@);
- $value_pd++ if (substr($value,-1,1) ne "/");
- $value_pd = -1 if ($value =~ /^\.\*/);
- if ($value_pd >= $file_pd &&
- range_is_maintained($start, $end) &&
- range_has_maintainer($start, $end)) {
- $exact_pattern_match_hash{$file} = 1;
- }
- if ($pattern_depth == 0 ||
- (($file_pd - $value_pd) < $pattern_depth)) {
- $hash{$tvi} = $value_pd;
- }
- }
- } elsif ($type eq 'N') {
- if ($file =~ m/$value/x) {
- $hash{$tvi} = 0;
- }
- }
- }
- }
- }
- $tvi = $end + 1;
- }
-
- foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
- add_categories($line);
- if ($sections) {
- my $i;
- my $start = find_starting_index($line);
- my $end = find_ending_index($line);
- for ($i = $start; $i < $end; $i++) {
- my $line = $typevalue[$i];
- if ($line =~ /^[FX]:/) { ##Restore file patterns
- $line =~ s/([^\\])\.([^\*])/$1\?$2/g;
- $line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
- $line =~ s/\\\./\./g; ##Convert \. to .
- $line =~ s/\.\*/\*/g; ##Convert .* to *
- }
- my $count = $line =~ s/^([A-Z]):/$1:\t/g;
- if ($letters eq "" || (!$count || $letters =~ /$1/i)) {
- print("$line\n");
- }
- }
- print("\n");
- }
- }
-
- maintainers_in_file($file);
+ my %hash;
+ my $tvi = find_first_section();
+ while ( $tvi < @typevalue ) {
+ my $start = find_starting_index($tvi);
+ my $end = find_ending_index($tvi);
+ my $exclude = 0;
+ my $i;
+
+ #Do not match excluded file patterns
+
+ for ( $i = $start; $i < $end; $i++ ) {
+ my $line = $typevalue[$i];
+ if ( $line =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $type = $1;
+ my $value = $2;
+ if ( $type eq 'X' ) {
+ if ( file_match_pattern( $file, $value ) ) {
+ $exclude = 1;
+ last;
+ }
+ }
+ }
+ }
+
+ if ( !$exclude ) {
+ for ( $i = $start; $i < $end; $i++ ) {
+ my $line = $typevalue[$i];
+ if ( $line =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $type = $1;
+ my $value = $2;
+ if ( $type eq 'F' ) {
+ if ( file_match_pattern( $file, $value ) ) {
+ my $value_pd = ( $value =~ tr@/@@ );
+ my $file_pd = ( $file =~ tr@/@@ );
+ $value_pd++ if ( substr( $value, -1, 1 ) ne "/" );
+ $value_pd = -1 if ( $value =~ /^\.\*/ );
+ if ( $value_pd >= $file_pd
+ && range_is_maintained( $start, $end )
+ && range_has_maintainer( $start, $end ) )
+ {
+ $exact_pattern_match_hash{$file} = 1;
+ }
+ if ( $pattern_depth == 0
+ || ( ( $file_pd - $value_pd ) < $pattern_depth ) )
+ {
+ $hash{$tvi} = $value_pd;
+ }
+ }
+ }
+ elsif ( $type eq 'N' ) {
+ if ( $file =~ m/$value/x ) {
+ $hash{$tvi} = 0;
+ }
+ }
+ }
+ }
+ }
+ $tvi = $end + 1;
+ }
+
+ foreach my $line ( sort { $hash{$b} <=> $hash{$a} } keys %hash ) {
+ add_categories($line);
+ if ($sections) {
+ my $i;
+ my $start = find_starting_index($line);
+ my $end = find_ending_index($line);
+ for ( $i = $start; $i < $end; $i++ ) {
+ my $line = $typevalue[$i];
+ if ( $line =~ /^[FX]:/ ) { ##Restore file patterns
+ $line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+ $line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
+ $line =~ s/\\\./\./g; ##Convert \. to .
+ $line =~ s/\.\*/\*/g; ##Convert .* to *
+ }
+ my $count = $line =~ s/^([A-Z]):/$1:\t/g;
+ if ( $letters eq "" || ( !$count || $letters =~ /$1/i ) ) {
+ print("$line\n");
+ }
+ }
+ print("\n");
+ }
+ }
+
+ maintainers_in_file($file);
}

if ($keywords) {
- @keyword_tvi = sort_and_uniq(@keyword_tvi);
- foreach my $line (@keyword_tvi) {
- add_categories($line);
- }
+ @keyword_tvi = sort_and_uniq(@keyword_tvi);
+ foreach my $line (@keyword_tvi) {
+ add_categories($line);
+ }
}

- foreach my $email (@email_to, @list_to) {
- $email->[0] = deduplicate_email($email->[0]);
+ foreach my $email ( @email_to, @list_to ) {
+ $email->[0] = deduplicate_email( $email->[0] );
}

foreach my $file (@files) {
- if ($email &&
- ($email_git ||
- ($email_git_fallback &&
- $file !~ /MAINTAINERS$/ &&
- !$exact_pattern_match_hash{$file}))) {
- vcs_file_signoffs($file);
- }
- if ($email && $email_git_blame) {
- vcs_file_blame($file);
- }
+ if ($email
+ && ($email_git
+ || ( $email_git_fallback
+ && $file !~ /MAINTAINERS$/
+ && !$exact_pattern_match_hash{$file} )
+ )
+ )
+ {
+ vcs_file_signoffs($file);
+ }
+ if ( $email && $email_git_blame ) {
+ vcs_file_blame($file);
+ }
}

if ($email) {
- foreach my $chief (@penguin_chief) {
- if ($chief =~ m/^(.*):(.*)/) {
- my $email_address;
-
- $email_address = format_email($1, $2, $email_usename);
- if ($email_git_penguin_chiefs) {
- push(@email_to, [$email_address, 'chief penguin']);
- } else {
- @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
- }
- }
- }
+ foreach my $chief (@penguin_chief) {
+ if ( $chief =~ m/^(.*):(.*)/ ) {
+ my $email_address;
+
+ $email_address = format_email( $1, $2, $email_usename );
+ if ($email_git_penguin_chiefs) {
+ push( @email_to, [ $email_address, 'chief penguin' ] );
+ }
+ else {
+ @email_to = grep( $_->[0] !~ /${email_address}/, @email_to );
+ }
+ }
+ }

- foreach my $email (@file_emails) {
- $email = mailmap_email($email);
- my ($name, $address) = parse_email($email);
+ foreach my $email (@file_emails) {
+ $email = mailmap_email($email);
+ my ( $name, $address ) = parse_email($email);

- my $tmp_email = format_email($name, $address, $email_usename);
- push_email_address($tmp_email, '');
- add_role($tmp_email, 'in file');
- }
+ my $tmp_email = format_email( $name, $address, $email_usename );
+ push_email_address( $tmp_email, '' );
+ add_role( $tmp_email, 'in file' );
+ }
}

foreach my $fix (@fixes) {
- vcs_add_commit_signers($fix, "blamed_fixes");
+ vcs_add_commit_signers( $fix, "blamed_fixes" );
}

my @to = ();
- if ($email || $email_list) {
- if ($email) {
- @to = (@to, @email_to);
- }
- if ($email_list) {
- @to = (@to, @list_to);
- }
+ if ( $email || $email_list ) {
+ if ($email) {
+ @to = ( @to, @email_to );
+ }
+ if ($email_list) {
+ @to = ( @to, @list_to );
+ }
}

if ($interactive) {
- @to = interactive_get_maintainers(\@to);
+ @to = interactive_get_maintainers( \@to );
}

return @to;
}

sub file_match_pattern {
- my ($file, $pattern) = @_;
- if (substr($pattern, -1) eq "/") {
- if ($file =~ m@^$pattern@) {
- return 1;
- }
- } else {
- if ($file =~ m@^$pattern@) {
- my $s1 = ($file =~ tr@/@@);
- my $s2 = ($pattern =~ tr@/@@);
- if ($s1 == $s2) {
- return 1;
- }
- }
+ my ( $file, $pattern ) = @_;
+ if ( substr( $pattern, -1 ) eq "/" ) {
+ if ( $file =~ m@^$pattern@ ) {
+ return 1;
+ }
+ }
+ else {
+ if ( $file =~ m@^$pattern@ ) {
+ my $s1 = ( $file =~ tr@/@@ );
+ my $s2 = ( $pattern =~ tr@/@@ );
+ if ( $s1 == $s2 ) {
+ return 1;
+ }
+ }
}
return 0;
}
@@ -1126,26 +1136,27 @@ EOT
sub top_of_kernel_tree {
my ($lk_path) = @_;

- if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
- $lk_path .= "/";
- }
- if ( (-f "${lk_path}COPYING")
- && (-f "${lk_path}CREDITS")
- && (-f "${lk_path}Kbuild")
- && (-e "${lk_path}MAINTAINERS")
- && (-f "${lk_path}Makefile")
- && (-f "${lk_path}README")
- && (-d "${lk_path}Documentation")
- && (-d "${lk_path}arch")
- && (-d "${lk_path}include")
- && (-d "${lk_path}drivers")
- && (-d "${lk_path}fs")
- && (-d "${lk_path}init")
- && (-d "${lk_path}ipc")
- && (-d "${lk_path}kernel")
- && (-d "${lk_path}lib")
- && (-d "${lk_path}scripts")) {
- return 1;
+ if ( $lk_path ne "" && substr( $lk_path, length($lk_path) - 1, 1 ) ne "/" ) {
+ $lk_path .= "/";
+ }
+ if ( ( -f "${lk_path}COPYING" )
+ && ( -f "${lk_path}CREDITS" )
+ && ( -f "${lk_path}Kbuild" )
+ && ( -e "${lk_path}MAINTAINERS" )
+ && ( -f "${lk_path}Makefile" )
+ && ( -f "${lk_path}README" )
+ && ( -d "${lk_path}Documentation" )
+ && ( -d "${lk_path}arch" )
+ && ( -d "${lk_path}include" )
+ && ( -d "${lk_path}drivers" )
+ && ( -d "${lk_path}fs" )
+ && ( -d "${lk_path}init" )
+ && ( -d "${lk_path}ipc" )
+ && ( -d "${lk_path}kernel" )
+ && ( -d "${lk_path}lib" )
+ && ( -d "${lk_path}scripts" ) )
+ {
+ return 1;
}
return 0;
}
@@ -1153,52 +1164,56 @@ sub top_of_kernel_tree {
sub parse_email {
my ($formatted_email) = @_;

- my $name = "";
+ my $name = "";
my $address = "";

- if ($formatted_email =~ /^([^<]+)<(.+\@.*)>.*$/) {
- $name = $1;
- $address = $2;
- } elsif ($formatted_email =~ /^\s*<(.+\@\S*)>.*$/) {
- $address = $1;
- } elsif ($formatted_email =~ /^(.+\@\S*).*$/) {
- $address = $1;
+ if ( $formatted_email =~ /^([^<]+)<(.+\@.*)>.*$/ ) {
+ $name = $1;
+ $address = $2;
+ }
+ elsif ( $formatted_email =~ /^\s*<(.+\@\S*)>.*$/ ) {
+ $address = $1;
+ }
+ elsif ( $formatted_email =~ /^(.+\@\S*).*$/ ) {
+ $address = $1;
}

- $name =~ s/^\s+|\s+$//g;
- $name =~ s/^\"|\"$//g;
+ $name =~ s/^\s+|\s+$//g;
+ $name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;

- if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
- $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
- $name = "\"$name\"";
+ if ( $name =~ /[^\w \-]/i ) { ##has "must quote" chars
+ $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+ $name = "\"$name\"";
}

- return ($name, $address);
+ return ( $name, $address );
}

sub format_email {
- my ($name, $address, $usename) = @_;
+ my ( $name, $address, $usename ) = @_;

my $formatted_email;

- $name =~ s/^\s+|\s+$//g;
- $name =~ s/^\"|\"$//g;
+ $name =~ s/^\s+|\s+$//g;
+ $name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;

- if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
- $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
- $name = "\"$name\"";
+ if ( $name =~ /[^\w \-]/i ) { ##has "must quote" chars
+ $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+ $name = "\"$name\"";
}

if ($usename) {
- if ("$name" eq "") {
- $formatted_email = "$address";
- } else {
- $formatted_email = "$name <$address>";
- }
- } else {
- $formatted_email = $address;
+ if ( "$name" eq "" ) {
+ $formatted_email = "$address";
+ }
+ else {
+ $formatted_email = "$name <$address>";
+ }
+ }
+ else {
+ $formatted_email = $address;
}

return $formatted_email;
@@ -1207,12 +1222,12 @@ sub format_email {
sub find_first_section {
my $index = 0;

- while ($index < @typevalue) {
- my $tv = $typevalue[$index];
- if (($tv =~ m/^([A-Z]):\s*(.*)/)) {
- last;
- }
- $index++;
+ while ( $index < @typevalue ) {
+ my $tv = $typevalue[$index];
+ if ( ( $tv =~ m/^([A-Z]):\s*(.*)/ ) ) {
+ last;
+ }
+ $index++;
}

return $index;
@@ -1221,12 +1236,12 @@ sub find_first_section {
sub find_starting_index {
my ($index) = @_;

- while ($index > 0) {
- my $tv = $typevalue[$index];
- if (!($tv =~ m/^([A-Z]):\s*(.*)/)) {
- last;
- }
- $index--;
+ while ( $index > 0 ) {
+ my $tv = $typevalue[$index];
+ if ( !( $tv =~ m/^([A-Z]):\s*(.*)/ ) ) {
+ last;
+ }
+ $index--;
}

return $index;
@@ -1235,12 +1250,12 @@ sub find_starting_index {
sub find_ending_index {
my ($index) = @_;

- while ($index < @typevalue) {
- my $tv = $typevalue[$index];
- if (!($tv =~ m/^([A-Z]):\s*(.*)/)) {
- last;
- }
- $index++;
+ while ( $index < @typevalue ) {
+ my $tv = $typevalue[$index];
+ if ( !( $tv =~ m/^([A-Z]):\s*(.*)/ ) ) {
+ last;
+ }
+ $index++;
}

return $index;
@@ -1252,10 +1267,10 @@ sub get_subsystem_name {
my $start = find_starting_index($index);

my $subsystem = $typevalue[$start];
- if ($output_section_maxlen && length($subsystem) > $output_section_maxlen) {
- $subsystem = substr($subsystem, 0, $output_section_maxlen - 3);
- $subsystem =~ s/\s*$//;
- $subsystem = $subsystem . "...";
+ if ( $output_section_maxlen && length($subsystem) > $output_section_maxlen ) {
+ $subsystem = substr( $subsystem, 0, $output_section_maxlen - 3 );
+ $subsystem =~ s/\s*$//;
+ $subsystem = $subsystem . "...";
}
return $subsystem;
}
@@ -1265,35 +1280,40 @@ sub get_maintainer_role {

my $i;
my $start = find_starting_index($index);
- my $end = find_ending_index($index);
+ my $end = find_ending_index($index);

- my $role = "unknown";
+ my $role = "unknown";
my $subsystem = get_subsystem_name($index);

- for ($i = $start + 1; $i < $end; $i++) {
- my $tv = $typevalue[$i];
- if ($tv =~ m/^([A-Z]):\s*(.*)/) {
- my $ptype = $1;
- my $pvalue = $2;
- if ($ptype eq "S") {
- $role = $pvalue;
- }
- }
+ for ( $i = $start + 1; $i < $end; $i++ ) {
+ my $tv = $typevalue[$i];
+ if ( $tv =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $ptype = $1;
+ my $pvalue = $2;
+ if ( $ptype eq "S" ) {
+ $role = $pvalue;
+ }
+ }
}

$role = lc($role);
- if ($role eq "supported") {
- $role = "supporter";
- } elsif ($role eq "maintained") {
- $role = "maintainer";
- } elsif ($role eq "odd fixes") {
- $role = "odd fixer";
- } elsif ($role eq "orphan") {
- $role = "orphan minder";
- } elsif ($role eq "obsolete") {
- $role = "obsolete minder";
- } elsif ($role eq "buried alive in reporters") {
- $role = "chief penguin";
+ if ( $role eq "supported" ) {
+ $role = "supporter";
+ }
+ elsif ( $role eq "maintained" ) {
+ $role = "maintainer";
+ }
+ elsif ( $role eq "odd fixes" ) {
+ $role = "odd fixer";
+ }
+ elsif ( $role eq "orphan" ) {
+ $role = "orphan minder";
+ }
+ elsif ( $role eq "obsolete" ) {
+ $role = "obsolete minder";
+ }
+ elsif ( $role eq "buried alive in reporters" ) {
+ $role = "chief penguin";
}

return $role . ":" . $subsystem;
@@ -1304,8 +1324,8 @@ sub get_list_role {

my $subsystem = get_subsystem_name($index);

- if ($subsystem eq "THE REST") {
- $subsystem = "";
+ if ( $subsystem eq "THE REST" ) {
+ $subsystem = "";
}

return $subsystem;
@@ -1316,161 +1336,171 @@ sub add_categories {

my $i;
my $start = find_starting_index($index);
- my $end = find_ending_index($index);
-
- push(@subsystem, $typevalue[$start]);
-
- for ($i = $start + 1; $i < $end; $i++) {
- my $tv = $typevalue[$i];
- if ($tv =~ m/^([A-Z]):\s*(.*)/) {
- my $ptype = $1;
- my $pvalue = $2;
- if ($ptype eq "L") {
- my $list_address = $pvalue;
- my $list_additional = "";
- my $list_role = get_list_role($i);
-
- if ($list_role ne "") {
- $list_role = ":" . $list_role;
- }
- if ($list_address =~ m/([^\s]+)\s+(.*)$/) {
- $list_address = $1;
- $list_additional = $2;
- }
- if ($list_additional =~ m/subscribers-only/) {
- if ($email_subscriber_list) {
- if (!$hash_list_to{lc($list_address)}) {
- $hash_list_to{lc($list_address)} = 1;
- push(@list_to, [$list_address,
- "subscriber list${list_role}"]);
- }
- }
- } else {
- if ($email_list) {
- if (!$hash_list_to{lc($list_address)}) {
- if ($list_additional =~ m/moderated/) {
- if ($email_moderated_list) {
- $hash_list_to{lc($list_address)} = 1;
- push(@list_to, [$list_address,
- "moderated list${list_role}"]);
- }
- } else {
- $hash_list_to{lc($list_address)} = 1;
- push(@list_to, [$list_address,
- "open list${list_role}"]);
- }
- }
- }
- }
- } elsif ($ptype eq "M") {
- if ($email_maintainer) {
- my $role = get_maintainer_role($i);
- push_email_addresses($pvalue, $role);
- }
- } elsif ($ptype eq "R") {
- if ($email_reviewer) {
- my $subsystem = get_subsystem_name($i);
- push_email_addresses($pvalue, "reviewer:$subsystem");
- }
- } elsif ($ptype eq "T") {
- push(@scm, $pvalue);
- } elsif ($ptype eq "W") {
- push(@web, $pvalue);
- } elsif ($ptype eq "S") {
- push(@status, $pvalue);
- }
- }
+ my $end = find_ending_index($index);
+
+ push( @subsystem, $typevalue[$start] );
+
+ for ( $i = $start + 1; $i < $end; $i++ ) {
+ my $tv = $typevalue[$i];
+ if ( $tv =~ m/^([A-Z]):\s*(.*)/ ) {
+ my $ptype = $1;
+ my $pvalue = $2;
+ if ( $ptype eq "L" ) {
+ my $list_address = $pvalue;
+ my $list_additional = "";
+ my $list_role = get_list_role($i);
+
+ if ( $list_role ne "" ) {
+ $list_role = ":" . $list_role;
+ }
+ if ( $list_address =~ m/([^\s]+)\s+(.*)$/ ) {
+ $list_address = $1;
+ $list_additional = $2;
+ }
+ if ( $list_additional =~ m/subscribers-only/ ) {
+ if ($email_subscriber_list) {
+ if ( !$hash_list_to{ lc($list_address) } ) {
+ $hash_list_to{ lc($list_address) } = 1;
+ push( @list_to, [ $list_address, "subscriber list${list_role}" ] );
+ }
+ }
+ }
+ else {
+ if ($email_list) {
+ if ( !$hash_list_to{ lc($list_address) } ) {
+ if ( $list_additional =~ m/moderated/ ) {
+ if ($email_moderated_list) {
+ $hash_list_to{ lc($list_address) } = 1;
+ push( @list_to, [ $list_address, "moderated list${list_role}" ] );
+ }
+ }
+ else {
+ $hash_list_to{ lc($list_address) } = 1;
+ push( @list_to, [ $list_address, "open list${list_role}" ] );
+ }
+ }
+ }
+ }
+ }
+ elsif ( $ptype eq "M" ) {
+ if ($email_maintainer) {
+ my $role = get_maintainer_role($i);
+ push_email_addresses( $pvalue, $role );
+ }
+ }
+ elsif ( $ptype eq "R" ) {
+ if ($email_reviewer) {
+ my $subsystem = get_subsystem_name($i);
+ push_email_addresses( $pvalue, "reviewer:$subsystem" );
+ }
+ }
+ elsif ( $ptype eq "T" ) {
+ push( @scm, $pvalue );
+ }
+ elsif ( $ptype eq "W" ) {
+ push( @web, $pvalue );
+ }
+ elsif ( $ptype eq "S" ) {
+ push( @status, $pvalue );
+ }
+ }
}
}

sub email_inuse {
- my ($name, $address) = @_;
+ my ( $name, $address ) = @_;

- return 1 if (($name eq "") && ($address eq ""));
- return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
- return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
+ return 1 if ( ( $name eq "" ) && ( $address eq "" ) );
+ return 1 if ( ( $name ne "" ) && exists( $email_hash_name{ lc($name) } ) );
+ return 1 if ( ( $address ne "" ) && exists( $email_hash_address{ lc($address) } ) );

return 0;
}

sub push_email_address {
- my ($line, $role) = @_;
+ my ( $line, $role ) = @_;

- my ($name, $address) = parse_email($line);
+ my ( $name, $address ) = parse_email($line);

- if ($address eq "") {
- return 0;
+ if ( $address eq "" ) {
+ return 0;
}

- if (!$email_remove_duplicates) {
- push(@email_to, [format_email($name, $address, $email_usename), $role]);
- } elsif (!email_inuse($name, $address)) {
- push(@email_to, [format_email($name, $address, $email_usename), $role]);
- $email_hash_name{lc($name)}++ if ($name ne "");
- $email_hash_address{lc($address)}++;
+ if ( !$email_remove_duplicates ) {
+ push( @email_to, [ format_email( $name, $address, $email_usename ), $role ] );
+ }
+ elsif ( !email_inuse( $name, $address ) ) {
+ push( @email_to, [ format_email( $name, $address, $email_usename ), $role ] );
+ $email_hash_name{ lc($name) }++ if ( $name ne "" );
+ $email_hash_address{ lc($address) }++;
}

return 1;
}

sub push_email_addresses {
- my ($address, $role) = @_;
+ my ( $address, $role ) = @_;

my @address_list = ();

- if (rfc822_valid($address)) {
- push_email_address($address, $role);
- } elsif (@address_list = rfc822_validlist($address)) {
- my $array_count = shift(@address_list);
- while (my $entry = shift(@address_list)) {
- push_email_address($entry, $role);
- }
- } else {
- if (!push_email_address($address, $role)) {
- warn("Invalid MAINTAINERS address: '" . $address . "'\n");
- }
+ if ( rfc822_valid($address) ) {
+ push_email_address( $address, $role );
+ }
+ elsif ( @address_list = rfc822_validlist($address) ) {
+ my $array_count = shift(@address_list);
+ while ( my $entry = shift(@address_list) ) {
+ push_email_address( $entry, $role );
+ }
+ }
+ else {
+ if ( !push_email_address( $address, $role ) ) {
+ warn( "Invalid MAINTAINERS address: '" . $address . "'\n" );
+ }
}
}

sub add_role {
- my ($line, $role) = @_;
+ my ( $line, $role ) = @_;

- my ($name, $address) = parse_email($line);
- my $email = format_email($name, $address, $email_usename);
+ my ( $name, $address ) = parse_email($line);
+ my $email = format_email( $name, $address, $email_usename );

foreach my $entry (@email_to) {
- if ($email_remove_duplicates) {
- my ($entry_name, $entry_address) = parse_email($entry->[0]);
- if (($name eq $entry_name || $address eq $entry_address)
- && ($role eq "" || !($entry->[1] =~ m/$role/))
- ) {
- if ($entry->[1] eq "") {
- $entry->[1] = "$role";
- } else {
- $entry->[1] = "$entry->[1],$role";
- }
- }
- } else {
- if ($email eq $entry->[0]
- && ($role eq "" || !($entry->[1] =~ m/$role/))
- ) {
- if ($entry->[1] eq "") {
- $entry->[1] = "$role";
- } else {
- $entry->[1] = "$entry->[1],$role";
- }
- }
- }
+ if ($email_remove_duplicates) {
+ my ( $entry_name, $entry_address ) = parse_email( $entry->[0] );
+ if ( ( $name eq $entry_name || $address eq $entry_address )
+ && ( $role eq "" || !( $entry->[1] =~ m/$role/ ) ) )
+ {
+ if ( $entry->[1] eq "" ) {
+ $entry->[1] = "$role";
+ }
+ else {
+ $entry->[1] = "$entry->[1],$role";
+ }
+ }
+ }
+ else {
+ if ( $email eq $entry->[0]
+ && ( $role eq "" || !( $entry->[1] =~ m/$role/ ) ) )
+ {
+ if ( $entry->[1] eq "" ) {
+ $entry->[1] = "$role";
+ }
+ else {
+ $entry->[1] = "$entry->[1],$role";
+ }
+ }
+ }
}
}

sub which {
my ($bin) = @_;

- foreach my $path (split(/:/, $ENV{PATH})) {
- if (-e "$path/$bin") {
- return "$path/$bin";
- }
+ foreach my $path ( split( /:/, $ENV{PATH} ) ) {
+ if ( -e "$path/$bin" ) {
+ return "$path/$bin";
+ }
}

return "";
@@ -1479,10 +1509,10 @@ sub which {
sub which_conf {
my ($conf) = @_;

- foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
- if (-e "$path/$conf") {
- return "$path/$conf";
- }
+ foreach my $path ( split( /:/, ".:$ENV{HOME}:.scripts" ) ) {
+ if ( -e "$path/$conf" ) {
+ return "$path/$conf";
+ }
}

return "";
@@ -1491,28 +1521,30 @@ sub which_conf {
sub mailmap_email {
my ($line) = @_;

- my ($name, $address) = parse_email($line);
- my $email = format_email($name, $address, 1);
- my $real_name = $name;
+ my ( $name, $address ) = parse_email($line);
+ my $email = format_email( $name, $address, 1 );
+ my $real_name = $name;
my $real_address = $address;

- if (exists $mailmap->{names}->{$email} ||
- exists $mailmap->{addresses}->{$email}) {
- if (exists $mailmap->{names}->{$email}) {
- $real_name = $mailmap->{names}->{$email};
- }
- if (exists $mailmap->{addresses}->{$email}) {
- $real_address = $mailmap->{addresses}->{$email};
- }
- } else {
- if (exists $mailmap->{names}->{$address}) {
- $real_name = $mailmap->{names}->{$address};
- }
- if (exists $mailmap->{addresses}->{$address}) {
- $real_address = $mailmap->{addresses}->{$address};
- }
- }
- return format_email($real_name, $real_address, 1);
+ if ( exists $mailmap->{names}->{$email}
+ || exists $mailmap->{addresses}->{$email} )
+ {
+ if ( exists $mailmap->{names}->{$email} ) {
+ $real_name = $mailmap->{names}->{$email};
+ }
+ if ( exists $mailmap->{addresses}->{$email} ) {
+ $real_address = $mailmap->{addresses}->{$email};
+ }
+ }
+ else {
+ if ( exists $mailmap->{names}->{$address} ) {
+ $real_name = $mailmap->{names}->{$address};
+ }
+ if ( exists $mailmap->{addresses}->{$address} ) {
+ $real_address = $mailmap->{addresses}->{$address};
+ }
+ }
+ return format_email( $real_name, $real_address, 1 );
}

sub mailmap {
@@ -1520,7 +1552,7 @@ sub mailmap {

my @mapped_emails = ();
foreach my $line (@addresses) {
- push(@mapped_emails, mailmap_email($line));
+ push( @mapped_emails, mailmap_email($line) );
}
merge_by_realname(@mapped_emails) if ($email_use_mailmap);
return @mapped_emails;
@@ -1531,13 +1563,14 @@ sub merge_by_realname {
my (@emails) = @_;

foreach my $email (@emails) {
- my ($name, $address) = parse_email($email);
- if (exists $address_map{$name}) {
- $address = $address_map{$name};
- $email = format_email($name, $address, 1);
- } else {
- $address_map{$name} = $address;
- }
+ my ( $name, $address ) = parse_email($email);
+ if ( exists $address_map{$name} ) {
+ $address = $address_map{$name};
+ $email = format_email( $name, $address, 1 );
+ }
+ else {
+ $address_map{$name} = $address;
+ }
}
}

@@ -1547,7 +1580,7 @@ sub git_execute_cmd {

my $output = `$cmd`;
$output =~ s/^\s*//gm;
- @lines = split("\n", $output);
+ @lines = split( "\n", $output );

return @lines;
}
@@ -1557,7 +1590,7 @@ sub hg_execute_cmd {
my @lines = ();

my $output = `$cmd`;
- @lines = split("\n", $output);
+ @lines = split( "\n", $output );

return @lines;
}
@@ -1575,71 +1608,71 @@ sub extract_formatted_signatures {
## Reformat email addresses (with names) to avoid badly written signatures

foreach my $signer (@signature_lines) {
- $signer = deduplicate_email($signer);
+ $signer = deduplicate_email($signer);
}

- return (\@type, \@signature_lines);
+ return ( \@type, \@signature_lines );
}

sub vcs_find_signers {
- my ($cmd, $file) = @_;
+ my ( $cmd, $file ) = @_;
my $commits;
- my @lines = ();
+ my @lines = ();
my @signatures = ();
- my @authors = ();
- my @stats = ();
+ my @authors = ();
+ my @stats = ();

- @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+ @lines = &{ $VCS_cmds{"execute_cmd"} }($cmd);

- my $pattern = $VCS_cmds{"commit_pattern"};
+ my $pattern = $VCS_cmds{"commit_pattern"};
my $author_pattern = $VCS_cmds{"author_pattern"};
- my $stat_pattern = $VCS_cmds{"stat_pattern"};
+ my $stat_pattern = $VCS_cmds{"stat_pattern"};

- $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern
+ $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern

- $commits = grep(/$pattern/, @lines); # of commits
+ $commits = grep( /$pattern/, @lines ); # of commits

- @authors = grep(/$author_pattern/, @lines);
- @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
- @stats = grep(/$stat_pattern/, @lines);
+ @authors = grep( /$author_pattern/, @lines );
+ @signatures = grep( /^[ \t]*${signature_pattern}.*\@.*$/, @lines );
+ @stats = grep( /$stat_pattern/, @lines );

-# print("stats: <@stats>\n");
+ # print("stats: <@stats>\n");

- return (0, \@signatures, \@authors, \@stats) if !@signatures;
+ return ( 0, \@signatures, \@authors, \@stats ) if !@signatures;

save_commits_by_author(@lines) if ($interactive);
save_commits_by_signer(@lines) if ($interactive);

- if (!$email_git_penguin_chiefs) {
- @signatures = grep(!/${penguin_chiefs}/i, @signatures);
+ if ( !$email_git_penguin_chiefs ) {
+ @signatures = grep( !/${penguin_chiefs}/i, @signatures );
}

- my ($author_ref, $authors_ref) = extract_formatted_signatures(@authors);
- my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+ my ( $author_ref, $authors_ref ) = extract_formatted_signatures(@authors);
+ my ( $types_ref, $signers_ref ) = extract_formatted_signatures(@signatures);

- return ($commits, $signers_ref, $authors_ref, \@stats);
+ return ( $commits, $signers_ref, $authors_ref, \@stats );
}

sub vcs_find_author {
my ($cmd) = @_;
my @lines = ();

- @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+ @lines = &{ $VCS_cmds{"execute_cmd"} }($cmd);

- if (!$email_git_penguin_chiefs) {
- @lines = grep(!/${penguin_chiefs}/i, @lines);
+ if ( !$email_git_penguin_chiefs ) {
+ @lines = grep( !/${penguin_chiefs}/i, @lines );
}

return @lines if !@lines;

my @authors = ();
foreach my $line (@lines) {
- if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
- my $author = $1;
- my ($name, $address) = parse_email($author);
- $author = format_email($name, $address, 1);
- push(@authors, $author);
- }
+ if ( $line =~ m/$VCS_cmds{"author_pattern"}/ ) {
+ my $author = $1;
+ my ( $name, $address ) = parse_email($author);
+ $author = format_email( $name, $address, 1 );
+ push( @authors, $author );
+ }
}

save_commits_by_author(@lines) if ($interactive);
@@ -1649,16 +1682,16 @@ sub vcs_find_author {
}

sub vcs_save_commits {
- my ($cmd) = @_;
- my @lines = ();
+ my ($cmd) = @_;
+ my @lines = ();
my @commits = ();

- @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+ @lines = &{ $VCS_cmds{"execute_cmd"} }($cmd);

foreach my $line (@lines) {
- if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) {
- push(@commits, $1);
- }
+ if ( $line =~ m/$VCS_cmds{"blame_commit_pattern"}/ ) {
+ push( @commits, $1 );
+ }
}

return @commits;
@@ -1669,62 +1702,65 @@ sub vcs_blame {
my $cmd;
my @commits = ();

- return @commits if (!(-f $file));
-
- if (@range && $VCS_cmds{"blame_range_cmd"} eq "") {
- my @all_commits = ();
-
- $cmd = $VCS_cmds{"blame_file_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
- @all_commits = vcs_save_commits($cmd);
-
- foreach my $file_range_diff (@range) {
- next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
- my $diff_file = $1;
- my $diff_start = $2;
- my $diff_length = $3;
- next if ("$file" ne "$diff_file");
- for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) {
- push(@commits, $all_commits[$i]);
- }
- }
- } elsif (@range) {
- foreach my $file_range_diff (@range) {
- next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
- my $diff_file = $1;
- my $diff_start = $2;
- my $diff_length = $3;
- next if ("$file" ne "$diff_file");
- $cmd = $VCS_cmds{"blame_range_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
- push(@commits, vcs_save_commits($cmd));
- }
- } else {
- $cmd = $VCS_cmds{"blame_file_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
- @commits = vcs_save_commits($cmd);
+ return @commits if ( !( -f $file ) );
+
+ if ( @range && $VCS_cmds{"blame_range_cmd"} eq "" ) {
+ my @all_commits = ();
+
+ $cmd = $VCS_cmds{"blame_file_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ @all_commits = vcs_save_commits($cmd);
+
+ foreach my $file_range_diff (@range) {
+ next if ( !( $file_range_diff =~ m/(.+):(.+):(.+)/ ) );
+ my $diff_file = $1;
+ my $diff_start = $2;
+ my $diff_length = $3;
+ next if ( "$file" ne "$diff_file" );
+ for ( my $i = $diff_start; $i < $diff_start + $diff_length; $i++ ) {
+ push( @commits, $all_commits[$i] );
+ }
+ }
+ }
+ elsif (@range) {
+ foreach my $file_range_diff (@range) {
+ next if ( !( $file_range_diff =~ m/(.+):(.+):(.+)/ ) );
+ my $diff_file = $1;
+ my $diff_start = $2;
+ my $diff_length = $3;
+ next if ( "$file" ne "$diff_file" );
+ $cmd = $VCS_cmds{"blame_range_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ push( @commits, vcs_save_commits($cmd) );
+ }
+ }
+ else {
+ $cmd = $VCS_cmds{"blame_file_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ @commits = vcs_save_commits($cmd);
}

foreach my $commit (@commits) {
- $commit =~ s/^\^//g;
+ $commit =~ s/^\^//g;
}

return @commits;
}

my $printed_novcs = 0;
+
sub vcs_exists {
%VCS_cmds = %VCS_cmds_git;
return 1 if eval $VCS_cmds{"available"};
%VCS_cmds = %VCS_cmds_hg;
return 2 if eval $VCS_cmds{"available"};
%VCS_cmds = ();
- if (!$printed_novcs && $email_git) {
- warn("$P: No supported VCS found. Add --nogit to options?\n");
- warn("Using a git repository produces better results.\n");
- warn("Try Linus Torvalds' latest git repository using:\n");
- warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\n");
- $printed_novcs = 1;
+ if ( !$printed_novcs && $email_git ) {
+ warn("$P: No supported VCS found. Add --nogit to options?\n");
+ warn("Using a git repository produces better results.\n");
+ warn("Try Linus Torvalds' latest git repository using:\n");
+ warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\n");
+ $printed_novcs = 1;
}
return 0;
}
@@ -1739,9 +1775,9 @@ sub vcs_is_hg {
}

sub vcs_add_commit_signers {
- return if (!vcs_exists());
+ return if ( !vcs_exists() );

- my ($commit, $desc) = @_;
+ my ( $commit, $desc ) = @_;
my $commit_count = 0;
my $commit_authors_ref;
my $commit_signers_ref;
@@ -1751,17 +1787,17 @@ sub vcs_add_commit_signers {
my $cmd;

$cmd = $VCS_cmds{"find_commit_signers_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd

- ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, "");
+ ( $commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref ) = vcs_find_signers( $cmd, "" );
@commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
@commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;

foreach my $signer (@commit_signers) {
- $signer = deduplicate_email($signer);
+ $signer = deduplicate_email($signer);
}

- vcs_assign($desc, 1, @commit_signers);
+ vcs_assign( $desc, 1, @commit_signers );
}

sub interactive_get_maintainers {
@@ -1773,68 +1809,69 @@ sub interactive_get_maintainers {
my %selected;
my %authored;
my %signed;
- my $count = 0;
+ my $count = 0;
my $maintained = 0;
foreach my $entry (@list) {
- $maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
- $selected{$count} = 1;
- $authored{$count} = 0;
- $signed{$count} = 0;
- $count++;
+ $maintained = 1 if ( $entry->[1] =~ /^(maintainer|supporter)/i );
+ $selected{$count} = 1;
+ $authored{$count} = 0;
+ $signed{$count} = 0;
+ $count++;
}

#menu loop
- my $done = 0;
+ my $done = 0;
my $print_options = 0;
- my $redraw = 1;
- while (!$done) {
- $count = 0;
- if ($redraw) {
- printf STDERR "\n%1s %2s %-65s",
- "*", "#", "email/list and role:stats";
- if ($email_git ||
- ($email_git_fallback && !$maintained) ||
- $email_git_blame) {
- print STDERR "auth sign";
- }
- print STDERR "\n";
- foreach my $entry (@list) {
- my $email = $entry->[0];
- my $role = $entry->[1];
- my $sel = "";
- $sel = "*" if ($selected{$count});
- my $commit_author = $commit_author_hash{$email};
- my $commit_signer = $commit_signer_hash{$email};
- my $authored = 0;
- my $signed = 0;
- $authored++ for (@{$commit_author});
- $signed++ for (@{$commit_signer});
- printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
- printf STDERR "%4d %4d", $authored, $signed
- if ($authored > 0 || $signed > 0);
- printf STDERR "\n %s\n", $role;
- if ($authored{$count}) {
- my $commit_author = $commit_author_hash{$email};
- foreach my $ref (@{$commit_author}) {
- print STDERR " Author: @{$ref}[1]\n";
- }
- }
- if ($signed{$count}) {
- my $commit_signer = $commit_signer_hash{$email};
- foreach my $ref (@{$commit_signer}) {
- print STDERR " @{$ref}[2]: @{$ref}[1]\n";
- }
- }
-
- $count++;
- }
- }
- my $date_ref = \$email_git_since;
- $date_ref = \$email_hg_since if (vcs_is_hg());
- if ($print_options) {
- $print_options = 0;
- if (vcs_exists()) {
- print STDERR <<EOT
+ my $redraw = 1;
+ while ( !$done ) {
+ $count = 0;
+ if ($redraw) {
+ printf STDERR "\n%1s %2s %-65s", "*", "#", "email/list and role:stats";
+ if ( $email_git
+ || ( $email_git_fallback && !$maintained )
+ || $email_git_blame )
+ {
+ print STDERR "auth sign";
+ }
+ print STDERR "\n";
+ foreach my $entry (@list) {
+ my $email = $entry->[0];
+ my $role = $entry->[1];
+ my $sel = "";
+ $sel = "*" if ( $selected{$count} );
+ my $commit_author = $commit_author_hash{$email};
+ my $commit_signer = $commit_signer_hash{$email};
+ my $authored = 0;
+ my $signed = 0;
+ $authored++ for ( @{$commit_author} );
+ $signed++ for ( @{$commit_signer} );
+ printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
+ printf STDERR "%4d %4d", $authored, $signed
+ if ( $authored > 0 || $signed > 0 );
+ printf STDERR "\n %s\n", $role;
+
+ if ( $authored{$count} ) {
+ my $commit_author = $commit_author_hash{$email};
+ foreach my $ref ( @{$commit_author} ) {
+ print STDERR " Author: @{$ref}[1]\n";
+ }
+ }
+ if ( $signed{$count} ) {
+ my $commit_signer = $commit_signer_hash{$email};
+ foreach my $ref ( @{$commit_signer} ) {
+ print STDERR " @{$ref}[2]: @{$ref}[1]\n";
+ }
+ }
+
+ $count++;
+ }
+ }
+ my $date_ref = \$email_git_since;
+ $date_ref = \$email_hg_since if ( vcs_is_hg() );
+ if ($print_options) {
+ $print_options = 0;
+ if ( vcs_exists() ) {
+ print STDERR <<EOT;

Version Control options:
g use git history [$email_git]
@@ -1848,8 +1885,8 @@ x# max maintainers [$email_git_max_maintainers]
t all signature types [$email_git_all_signature_types]
m use .mailmap [$email_use_mailmap]
EOT
- }
- print STDERR <<EOT
+ }
+ print STDERR <<EOT;

Additional options:
0 toggle all
@@ -1862,145 +1899,172 @@ k keywords in file [$keywords]
r remove duplicates [$email_remove_duplicates]
p# pattern match depth [$pattern_depth]
EOT
- }
- print STDERR
-"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
-
- my $input = <STDIN>;
- chomp($input);
-
- $redraw = 1;
- my $rerun = 0;
- my @wish = split(/[, ]+/, $input);
- foreach my $nr (@wish) {
- $nr = lc($nr);
- my $sel = substr($nr, 0, 1);
- my $str = substr($nr, 1);
- my $val = 0;
- $val = $1 if $str =~ /^(\d+)$/;
-
- if ($sel eq "y") {
- $interactive = 0;
- $done = 1;
- $output_rolestats = 0;
- $output_roles = 0;
- last;
- } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
- $selected{$nr - 1} = !$selected{$nr - 1};
- } elsif ($sel eq "*" || $sel eq '^') {
- my $toggle = 0;
- $toggle = 1 if ($sel eq '*');
- for (my $i = 0; $i < $count; $i++) {
- $selected{$i} = $toggle;
- }
- } elsif ($sel eq "0") {
- for (my $i = 0; $i < $count; $i++) {
- $selected{$i} = !$selected{$i};
- }
- } elsif ($sel eq "t") {
- if (lc($str) eq "m") {
- for (my $i = 0; $i < $count; $i++) {
- $selected{$i} = !$selected{$i}
- if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
- }
- } elsif (lc($str) eq "g") {
- for (my $i = 0; $i < $count; $i++) {
- $selected{$i} = !$selected{$i}
- if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
- }
- } elsif (lc($str) eq "l") {
- for (my $i = 0; $i < $count; $i++) {
- $selected{$i} = !$selected{$i}
- if ($list[$i]->[1] =~ /^(open list)/i);
- }
- } elsif (lc($str) eq "s") {
- for (my $i = 0; $i < $count; $i++) {
- $selected{$i} = !$selected{$i}
- if ($list[$i]->[1] =~ /^(subscriber list)/i);
- }
- }
- } elsif ($sel eq "a") {
- if ($val > 0 && $val <= $count) {
- $authored{$val - 1} = !$authored{$val - 1};
- } elsif ($str eq '*' || $str eq '^') {
- my $toggle = 0;
- $toggle = 1 if ($str eq '*');
- for (my $i = 0; $i < $count; $i++) {
- $authored{$i} = $toggle;
- }
- }
- } elsif ($sel eq "s") {
- if ($val > 0 && $val <= $count) {
- $signed{$val - 1} = !$signed{$val - 1};
- } elsif ($str eq '*' || $str eq '^') {
- my $toggle = 0;
- $toggle = 1 if ($str eq '*');
- for (my $i = 0; $i < $count; $i++) {
- $signed{$i} = $toggle;
- }
- }
- } elsif ($sel eq "o") {
- $print_options = 1;
- $redraw = 1;
- } elsif ($sel eq "g") {
- if ($str eq "f") {
- bool_invert(\$email_git_fallback);
- } else {
- bool_invert(\$email_git);
- }
- $rerun = 1;
- } elsif ($sel eq "b") {
- if ($str eq "s") {
- bool_invert(\$email_git_blame_signatures);
- } else {
- bool_invert(\$email_git_blame);
- }
- $rerun = 1;
- } elsif ($sel eq "c") {
- if ($val > 0) {
- $email_git_min_signatures = $val;
- $rerun = 1;
- }
- } elsif ($sel eq "x") {
- if ($val > 0) {
- $email_git_max_maintainers = $val;
- $rerun = 1;
- }
- } elsif ($sel eq "%") {
- if ($str ne "" && $val >= 0) {
- $email_git_min_percent = $val;
- $rerun = 1;
- }
- } elsif ($sel eq "d") {
- if (vcs_is_git()) {
- $email_git_since = $str;
- } elsif (vcs_is_hg()) {
- $email_hg_since = $str;
- }
- $rerun = 1;
- } elsif ($sel eq "t") {
- bool_invert(\$email_git_all_signature_types);
- $rerun = 1;
- } elsif ($sel eq "f") {
- bool_invert(\$email_file_emails);
- $rerun = 1;
- } elsif ($sel eq "r") {
- bool_invert(\$email_remove_duplicates);
- $rerun = 1;
- } elsif ($sel eq "m") {
- bool_invert(\$email_use_mailmap);
- read_mailmap();
- $rerun = 1;
- } elsif ($sel eq "k") {
- bool_invert(\$keywords);
- $rerun = 1;
- } elsif ($sel eq "p") {
- if ($str ne "" && $val >= 0) {
- $pattern_depth = $val;
- $rerun = 1;
- }
- } elsif ($sel eq "h" || $sel eq "?") {
- print STDERR <<EOT
+ }
+ print STDERR "\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
+
+ my $input = <STDIN>;
+ chomp($input);
+
+ $redraw = 1;
+ my $rerun = 0;
+ my @wish = split( /[, ]+/, $input );
+ foreach my $nr (@wish) {
+ $nr = lc($nr);
+ my $sel = substr( $nr, 0, 1 );
+ my $str = substr( $nr, 1 );
+ my $val = 0;
+ $val = $1 if $str =~ /^(\d+)$/;
+
+ if ( $sel eq "y" ) {
+ $interactive = 0;
+ $done = 1;
+ $output_rolestats = 0;
+ $output_roles = 0;
+ last;
+ }
+ elsif ( $nr =~ /^\d+$/ && $nr > 0 && $nr <= $count ) {
+ $selected{ $nr - 1 } = !$selected{ $nr - 1 };
+ }
+ elsif ( $sel eq "*" || $sel eq '^' ) {
+ my $toggle = 0;
+ $toggle = 1 if ( $sel eq '*' );
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $selected{$i} = $toggle;
+ }
+ }
+ elsif ( $sel eq "0" ) {
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $selected{$i} = !$selected{$i};
+ }
+ }
+ elsif ( $sel eq "t" ) {
+ if ( lc($str) eq "m" ) {
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $selected{$i} = !$selected{$i}
+ if ( $list[$i]->[1] =~ /^(maintainer|supporter)/i );
+ }
+ }
+ elsif ( lc($str) eq "g" ) {
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $selected{$i} = !$selected{$i}
+ if ( $list[$i]->[1] =~ /^(author|commit|signer)/i );
+ }
+ }
+ elsif ( lc($str) eq "l" ) {
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $selected{$i} = !$selected{$i}
+ if ( $list[$i]->[1] =~ /^(open list)/i );
+ }
+ }
+ elsif ( lc($str) eq "s" ) {
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $selected{$i} = !$selected{$i}
+ if ( $list[$i]->[1] =~ /^(subscriber list)/i );
+ }
+ }
+ }
+ elsif ( $sel eq "a" ) {
+ if ( $val > 0 && $val <= $count ) {
+ $authored{ $val - 1 } = !$authored{ $val - 1 };
+ }
+ elsif ( $str eq '*' || $str eq '^' ) {
+ my $toggle = 0;
+ $toggle = 1 if ( $str eq '*' );
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $authored{$i} = $toggle;
+ }
+ }
+ }
+ elsif ( $sel eq "s" ) {
+ if ( $val > 0 && $val <= $count ) {
+ $signed{ $val - 1 } = !$signed{ $val - 1 };
+ }
+ elsif ( $str eq '*' || $str eq '^' ) {
+ my $toggle = 0;
+ $toggle = 1 if ( $str eq '*' );
+ for ( my $i = 0; $i < $count; $i++ ) {
+ $signed{$i} = $toggle;
+ }
+ }
+ }
+ elsif ( $sel eq "o" ) {
+ $print_options = 1;
+ $redraw = 1;
+ }
+ elsif ( $sel eq "g" ) {
+ if ( $str eq "f" ) {
+ bool_invert( \$email_git_fallback );
+ }
+ else {
+ bool_invert( \$email_git );
+ }
+ $rerun = 1;
+ }
+ elsif ( $sel eq "b" ) {
+ if ( $str eq "s" ) {
+ bool_invert( \$email_git_blame_signatures );
+ }
+ else {
+ bool_invert( \$email_git_blame );
+ }
+ $rerun = 1;
+ }
+ elsif ( $sel eq "c" ) {
+ if ( $val > 0 ) {
+ $email_git_min_signatures = $val;
+ $rerun = 1;
+ }
+ }
+ elsif ( $sel eq "x" ) {
+ if ( $val > 0 ) {
+ $email_git_max_maintainers = $val;
+ $rerun = 1;
+ }
+ }
+ elsif ( $sel eq "%" ) {
+ if ( $str ne "" && $val >= 0 ) {
+ $email_git_min_percent = $val;
+ $rerun = 1;
+ }
+ }
+ elsif ( $sel eq "d" ) {
+ if ( vcs_is_git() ) {
+ $email_git_since = $str;
+ }
+ elsif ( vcs_is_hg() ) {
+ $email_hg_since = $str;
+ }
+ $rerun = 1;
+ }
+ elsif ( $sel eq "t" ) {
+ bool_invert( \$email_git_all_signature_types );
+ $rerun = 1;
+ }
+ elsif ( $sel eq "f" ) {
+ bool_invert( \$email_file_emails );
+ $rerun = 1;
+ }
+ elsif ( $sel eq "r" ) {
+ bool_invert( \$email_remove_duplicates );
+ $rerun = 1;
+ }
+ elsif ( $sel eq "m" ) {
+ bool_invert( \$email_use_mailmap );
+ read_mailmap();
+ $rerun = 1;
+ }
+ elsif ( $sel eq "k" ) {
+ bool_invert( \$keywords );
+ $rerun = 1;
+ }
+ elsif ( $sel eq "p" ) {
+ if ( $str ne "" && $val >= 0 ) {
+ $pattern_depth = $val;
+ $rerun = 1;
+ }
+ }
+ elsif ( $sel eq "h" || $sel eq "?" ) {
+ print STDERR <<EOT;

Interactive mode allows you to select the various maintainers, submitters,
commit signers and mailing lists that could be CC'd on a patch.
@@ -2020,26 +2084,27 @@ maintainers are appropriate. You may enter multiple selections separated
by either commas or spaces.

EOT
- } else {
- print STDERR "invalid option: '$nr'\n";
- $redraw = 0;
- }
- }
- if ($rerun) {
- print STDERR "git-blame can be very slow, please have patience..."
- if ($email_git_blame);
- goto &get_maintainers;
- }
+ }
+ else {
+ print STDERR "invalid option: '$nr'\n";
+ $redraw = 0;
+ }
+ }
+ if ($rerun) {
+ print STDERR "git-blame can be very slow, please have patience..."
+ if ($email_git_blame);
+ goto &get_maintainers;
+ }
}

#drop not selected entries
$count = 0;
my @new_emailto = ();
foreach my $entry (@list) {
- if ($selected{$count}) {
- push(@new_emailto, $list[$count]);
- }
- $count++;
+ if ( $selected{$count} ) {
+ push( @new_emailto, $list[$count] );
+ }
+ $count++;
}
return @new_emailto;
}
@@ -2048,9 +2113,10 @@ sub bool_invert {
my ($bool_ref) = @_;

if ($$bool_ref) {
- $$bool_ref = 0;
- } else {
- $$bool_ref = 1;
+ $$bool_ref = 0;
+ }
+ else {
+ $$bool_ref = 1;
}
}

@@ -2058,28 +2124,29 @@ sub deduplicate_email {
my ($email) = @_;

my $matched = 0;
- my ($name, $address) = parse_email($email);
- $email = format_email($name, $address, 1);
+ my ( $name, $address ) = parse_email($email);
+ $email = format_email( $name, $address, 1 );
$email = mailmap_email($email);

- return $email if (!$email_remove_duplicates);
+ return $email if ( !$email_remove_duplicates );

- ($name, $address) = parse_email($email);
+ ( $name, $address ) = parse_email($email);

- if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
- $name = $deduplicate_name_hash{lc($name)}->[0];
- $address = $deduplicate_name_hash{lc($name)}->[1];
- $matched = 1;
- } elsif ($deduplicate_address_hash{lc($address)}) {
- $name = $deduplicate_address_hash{lc($address)}->[0];
- $address = $deduplicate_address_hash{lc($address)}->[1];
- $matched = 1;
+ if ( $name ne "" && $deduplicate_name_hash{ lc($name) } ) {
+ $name = $deduplicate_name_hash{ lc($name) }->[0];
+ $address = $deduplicate_name_hash{ lc($name) }->[1];
+ $matched = 1;
+ }
+ elsif ( $deduplicate_address_hash{ lc($address) } ) {
+ $name = $deduplicate_address_hash{ lc($address) }->[0];
+ $address = $deduplicate_address_hash{ lc($address) }->[1];
+ $matched = 1;
}
- if (!$matched) {
- $deduplicate_name_hash{lc($name)} = [ $name, $address ];
- $deduplicate_address_hash{lc($address)} = [ $name, $address ];
+ if ( !$matched ) {
+ $deduplicate_name_hash{ lc($name) } = [ $name, $address ];
+ $deduplicate_address_hash{ lc($address) } = [ $name, $address ];
}
- $email = format_email($name, $address, 1);
+ $email = format_email( $name, $address, 1 );
$email = mailmap_email($email);
return $email;
}
@@ -2087,89 +2154,89 @@ sub deduplicate_email {
sub save_commits_by_author {
my (@lines) = @_;

- my @authors = ();
- my @commits = ();
+ my @authors = ();
+ my @commits = ();
my @subjects = ();

foreach my $line (@lines) {
- if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
- my $author = $1;
- $author = deduplicate_email($author);
- push(@authors, $author);
- }
- push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
- push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
- }
-
- for (my $i = 0; $i < @authors; $i++) {
- my $exists = 0;
- foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
- if (@{$ref}[0] eq $commits[$i] &&
- @{$ref}[1] eq $subjects[$i]) {
- $exists = 1;
- last;
- }
- }
- if (!$exists) {
- push(@{$commit_author_hash{$authors[$i]}},
- [ ($commits[$i], $subjects[$i]) ]);
- }
+ if ( $line =~ m/$VCS_cmds{"author_pattern"}/ ) {
+ my $author = $1;
+ $author = deduplicate_email($author);
+ push( @authors, $author );
+ }
+ push( @commits, $1 ) if ( $line =~ m/$VCS_cmds{"commit_pattern"}/ );
+ push( @subjects, $1 ) if ( $line =~ m/$VCS_cmds{"subject_pattern"}/ );
+ }
+
+ for ( my $i = 0; $i < @authors; $i++ ) {
+ my $exists = 0;
+ foreach my $ref ( @{ $commit_author_hash{ $authors[$i] } } ) {
+ if ( @{$ref}[0] eq $commits[$i]
+ && @{$ref}[1] eq $subjects[$i] )
+ {
+ $exists = 1;
+ last;
+ }
+ }
+ if ( !$exists ) {
+ push( @{ $commit_author_hash{ $authors[$i] } }, [ ( $commits[$i], $subjects[$i] ) ] );
+ }
}
}

sub save_commits_by_signer {
my (@lines) = @_;

- my $commit = "";
+ my $commit = "";
my $subject = "";

foreach my $line (@lines) {
- $commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
- $subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
- if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
- my @signatures = ($line);
- my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
- my @types = @$types_ref;
- my @signers = @$signers_ref;
-
- my $type = $types[0];
- my $signer = $signers[0];
-
- $signer = deduplicate_email($signer);
-
- my $exists = 0;
- foreach my $ref(@{$commit_signer_hash{$signer}}) {
- if (@{$ref}[0] eq $commit &&
- @{$ref}[1] eq $subject &&
- @{$ref}[2] eq $type) {
- $exists = 1;
- last;
- }
- }
- if (!$exists) {
- push(@{$commit_signer_hash{$signer}},
- [ ($commit, $subject, $type) ]);
- }
- }
+ $commit = $1 if ( $line =~ m/$VCS_cmds{"commit_pattern"}/ );
+ $subject = $1 if ( $line =~ m/$VCS_cmds{"subject_pattern"}/ );
+ if ( $line =~ /^[ \t]*${signature_pattern}.*\@.*$/ ) {
+ my @signatures = ($line);
+ my ( $types_ref, $signers_ref ) = extract_formatted_signatures(@signatures);
+ my @types = @$types_ref;
+ my @signers = @$signers_ref;
+
+ my $type = $types[0];
+ my $signer = $signers[0];
+
+ $signer = deduplicate_email($signer);
+
+ my $exists = 0;
+ foreach my $ref ( @{ $commit_signer_hash{$signer} } ) {
+ if ( @{$ref}[0] eq $commit
+ && @{$ref}[1] eq $subject
+ && @{$ref}[2] eq $type )
+ {
+ $exists = 1;
+ last;
+ }
+ }
+ if ( !$exists ) {
+ push( @{ $commit_signer_hash{$signer} }, [ ( $commit, $subject, $type ) ] );
+ }
+ }
}
}

sub vcs_assign {
- my ($role, $divisor, @lines) = @_;
+ my ( $role, $divisor, @lines ) = @_;

my %hash;
my $count = 0;

- return if (@lines <= 0);
+ return if ( @lines <= 0 );

- if ($divisor <= 0) {
- warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n");
- $divisor = 1;
+ if ( $divisor <= 0 ) {
+ warn( "Bad divisor in " . ( caller(0) )[3] . ": $divisor\n" );
+ $divisor = 1;
}

@lines = mailmap(@lines);

- return if (@lines <= 0);
+ return if ( @lines <= 0 );

@lines = sort(@lines);

@@ -2177,23 +2244,24 @@ sub vcs_assign {
$hash{$_}++ for @lines;

# sort -rn
- foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
- my $sign_offs = $hash{$line};
- my $percent = $sign_offs * 100 / $divisor;
-
- $percent = 100 if ($percent > 100);
- next if (ignore_email_address($line));
- $count++;
- last if ($sign_offs < $email_git_min_signatures ||
- $count > $email_git_max_maintainers ||
- $percent < $email_git_min_percent);
- push_email_address($line, '');
- if ($output_rolestats) {
- my $fmt_percent = sprintf("%.0f", $percent);
- add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%");
- } else {
- add_role($line, $role);
- }
+ foreach my $line ( sort { $hash{$b} <=> $hash{$a} } keys %hash ) {
+ my $sign_offs = $hash{$line};
+ my $percent = $sign_offs * 100 / $divisor;
+
+ $percent = 100 if ( $percent > 100 );
+ next if ( ignore_email_address($line) );
+ $count++;
+ last if ( $sign_offs < $email_git_min_signatures
+ || $count > $email_git_max_maintainers
+ || $percent < $email_git_min_percent );
+ push_email_address( $line, '' );
+ if ($output_rolestats) {
+ my $fmt_percent = sprintf( "%.0f", $percent );
+ add_role( $line, "$role:$sign_offs/$divisor=$fmt_percent%" );
+ }
+ else {
+ add_role( $line, $role );
+ }
}
}

@@ -2205,195 +2273,200 @@ sub vcs_file_signoffs {
my $stats_ref;
my @authors = ();
my @signers = ();
- my @stats = ();
+ my @stats = ();
my $commits;

$vcs_used = vcs_exists();
- return if (!$vcs_used);
+ return if ( !$vcs_used );

my $cmd = $VCS_cmds{"find_signers_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
+ $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd

- ($commits, $signers_ref, $authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
+ ( $commits, $signers_ref, $authors_ref, $stats_ref ) = vcs_find_signers( $cmd, $file );

@signers = @{$signers_ref} if defined $signers_ref;
@authors = @{$authors_ref} if defined $authors_ref;
- @stats = @{$stats_ref} if defined $stats_ref;
+ @stats = @{$stats_ref} if defined $stats_ref;

-# print("commits: <$commits>\nsigners:<@signers>\nauthors: <@authors>\nstats: <@stats>\n");
+ # print("commits: <$commits>\nsigners:<@signers>\nauthors: <@authors>\nstats: <@stats>\n");

foreach my $signer (@signers) {
- $signer = deduplicate_email($signer);
- }
-
- vcs_assign("commit_signer", $commits, @signers);
- vcs_assign("authored", $commits, @authors);
- if ($#authors == $#stats) {
- my $stat_pattern = $VCS_cmds{"stat_pattern"};
- $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern
-
- my $added = 0;
- my $deleted = 0;
- for (my $i = 0; $i <= $#stats; $i++) {
- if ($stats[$i] =~ /$stat_pattern/) {
- $added += $1;
- $deleted += $2;
- }
- }
- my @tmp_authors = uniq(@authors);
- foreach my $author (@tmp_authors) {
- $author = deduplicate_email($author);
- }
- @tmp_authors = uniq(@tmp_authors);
- my @list_added = ();
- my @list_deleted = ();
- foreach my $author (@tmp_authors) {
- my $auth_added = 0;
- my $auth_deleted = 0;
- for (my $i = 0; $i <= $#stats; $i++) {
- if ($author eq deduplicate_email($authors[$i]) &&
- $stats[$i] =~ /$stat_pattern/) {
- $auth_added += $1;
- $auth_deleted += $2;
- }
- }
- for (my $i = 0; $i < $auth_added; $i++) {
- push(@list_added, $author);
- }
- for (my $i = 0; $i < $auth_deleted; $i++) {
- push(@list_deleted, $author);
- }
- }
- vcs_assign("added_lines", $added, @list_added);
- vcs_assign("removed_lines", $deleted, @list_deleted);
+ $signer = deduplicate_email($signer);
+ }
+
+ vcs_assign( "commit_signer", $commits, @signers );
+ vcs_assign( "authored", $commits, @authors );
+ if ( $#authors == $#stats ) {
+ my $stat_pattern = $VCS_cmds{"stat_pattern"};
+ $stat_pattern =~ s/(\$\w+)/$1/eeg; #interpolate $stat_pattern
+
+ my $added = 0;
+ my $deleted = 0;
+ for ( my $i = 0; $i <= $#stats; $i++ ) {
+ if ( $stats[$i] =~ /$stat_pattern/ ) {
+ $added += $1;
+ $deleted += $2;
+ }
+ }
+ my @tmp_authors = uniq(@authors);
+ foreach my $author (@tmp_authors) {
+ $author = deduplicate_email($author);
+ }
+ @tmp_authors = uniq(@tmp_authors);
+ my @list_added = ();
+ my @list_deleted = ();
+ foreach my $author (@tmp_authors) {
+ my $auth_added = 0;
+ my $auth_deleted = 0;
+ for ( my $i = 0; $i <= $#stats; $i++ ) {
+ if ( $author eq deduplicate_email( $authors[$i] )
+ && $stats[$i] =~ /$stat_pattern/ )
+ {
+ $auth_added += $1;
+ $auth_deleted += $2;
+ }
+ }
+ for ( my $i = 0; $i < $auth_added; $i++ ) {
+ push( @list_added, $author );
+ }
+ for ( my $i = 0; $i < $auth_deleted; $i++ ) {
+ push( @list_deleted, $author );
+ }
+ }
+ vcs_assign( "added_lines", $added, @list_added );
+ vcs_assign( "removed_lines", $deleted, @list_deleted );
}
}

sub vcs_file_blame {
my ($file) = @_;

- my @signers = ();
+ my @signers = ();
my @all_commits = ();
- my @commits = ();
+ my @commits = ();
my $total_commits;
my $total_lines;

$vcs_used = vcs_exists();
- return if (!$vcs_used);
+ return if ( !$vcs_used );

- @all_commits = vcs_blame($file);
- @commits = uniq(@all_commits);
+ @all_commits = vcs_blame($file);
+ @commits = uniq(@all_commits);
$total_commits = @commits;
- $total_lines = @all_commits;
+ $total_lines = @all_commits;

if ($email_git_blame_signatures) {
- if (vcs_is_hg()) {
- my $commit_count;
- my $commit_authors_ref;
- my $commit_signers_ref;
- my $stats_ref;
- my @commit_authors = ();
- my @commit_signers = ();
- my $commit = join(" -r ", @commits);
- my $cmd;
-
- $cmd = $VCS_cmds{"find_commit_signers_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
-
- ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
- @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
- @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
-
- push(@signers, @commit_signers);
- } else {
- foreach my $commit (@commits) {
- my $commit_count;
- my $commit_authors_ref;
- my $commit_signers_ref;
- my $stats_ref;
- my @commit_authors = ();
- my @commit_signers = ();
- my $cmd;
-
- $cmd = $VCS_cmds{"find_commit_signers_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
-
- ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
- @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
- @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
-
- push(@signers, @commit_signers);
- }
- }
+ if ( vcs_is_hg() ) {
+ my $commit_count;
+ my $commit_authors_ref;
+ my $commit_signers_ref;
+ my $stats_ref;
+ my @commit_authors = ();
+ my @commit_signers = ();
+ my $commit = join( " -r ", @commits );
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ ( $commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref ) = vcs_find_signers( $cmd, $file );
+ @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
+ @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
+
+ push( @signers, @commit_signers );
+ }
+ else {
+ foreach my $commit (@commits) {
+ my $commit_count;
+ my $commit_authors_ref;
+ my $commit_signers_ref;
+ my $stats_ref;
+ my @commit_authors = ();
+ my @commit_signers = ();
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ ( $commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref ) = vcs_find_signers( $cmd, $file );
+ @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
+ @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
+
+ push( @signers, @commit_signers );
+ }
+ }
}

if ($from_filename) {
- if ($output_rolestats) {
- my @blame_signers;
- if (vcs_is_hg()) {{ # Double brace for last exit
- my $commit_count;
- my @commit_signers = ();
- @commits = uniq(@commits);
- @commits = sort(@commits);
- my $commit = join(" -r ", @commits);
- my $cmd;
-
- $cmd = $VCS_cmds{"find_commit_author_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
-
- my @lines = ();
-
- @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
-
- if (!$email_git_penguin_chiefs) {
- @lines = grep(!/${penguin_chiefs}/i, @lines);
- }
-
- last if !@lines;
-
- my @authors = ();
- foreach my $line (@lines) {
- if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
- my $author = $1;
- $author = deduplicate_email($author);
- push(@authors, $author);
- }
- }
-
- save_commits_by_author(@lines) if ($interactive);
- save_commits_by_signer(@lines) if ($interactive);
-
- push(@signers, @authors);
- }}
- else {
- foreach my $commit (@commits) {
- my $i;
- my $cmd = $VCS_cmds{"find_commit_author_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
- my @author = vcs_find_author($cmd);
- next if !@author;
-
- my $formatted_author = deduplicate_email($author[0]);
-
- my $count = grep(/$commit/, @all_commits);
- for ($i = 0; $i < $count ; $i++) {
- push(@blame_signers, $formatted_author);
- }
- }
- }
- if (@blame_signers) {
- vcs_assign("authored lines", $total_lines, @blame_signers);
- }
- }
- foreach my $signer (@signers) {
- $signer = deduplicate_email($signer);
- }
- vcs_assign("commits", $total_commits, @signers);
- } else {
- foreach my $signer (@signers) {
- $signer = deduplicate_email($signer);
- }
- vcs_assign("modified commits", $total_commits, @signers);
+ if ($output_rolestats) {
+ my @blame_signers;
+ if ( vcs_is_hg() ) {
+ { # Double brace for last exit
+ my $commit_count;
+ my @commit_signers = ();
+ @commits = uniq(@commits);
+ @commits = sort(@commits);
+ my $commit = join( " -r ", @commits );
+ my $cmd;
+
+ $cmd = $VCS_cmds{"find_commit_author_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
+
+ my @lines = ();
+
+ @lines = &{ $VCS_cmds{"execute_cmd"} }($cmd);
+
+ if ( !$email_git_penguin_chiefs ) {
+ @lines = grep( !/${penguin_chiefs}/i, @lines );
+ }
+
+ last if !@lines;
+
+ my @authors = ();
+ foreach my $line (@lines) {
+ if ( $line =~ m/$VCS_cmds{"author_pattern"}/ ) {
+ my $author = $1;
+ $author = deduplicate_email($author);
+ push( @authors, $author );
+ }
+ }
+
+ save_commits_by_author(@lines) if ($interactive);
+ save_commits_by_signer(@lines) if ($interactive);
+
+ push( @signers, @authors );
+ }
+ }
+ else {
+ foreach my $commit (@commits) {
+ my $i;
+ my $cmd = $VCS_cmds{"find_commit_author_cmd"};
+ $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
+ my @author = vcs_find_author($cmd);
+ next if !@author;
+
+ my $formatted_author = deduplicate_email( $author[0] );
+
+ my $count = grep( /$commit/, @all_commits );
+ for ( $i = 0; $i < $count; $i++ ) {
+ push( @blame_signers, $formatted_author );
+ }
+ }
+ }
+ if (@blame_signers) {
+ vcs_assign( "authored lines", $total_lines, @blame_signers );
+ }
+ }
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
+ vcs_assign( "commits", $total_commits, @signers );
+ }
+ else {
+ foreach my $signer (@signers) {
+ $signer = deduplicate_email($signer);
+ }
+ vcs_assign( "modified commits", $total_commits, @signers );
}
}

@@ -2403,14 +2476,14 @@ sub vcs_file_exists {
my $exists;

my $vcs_used = vcs_exists();
- return 0 if (!$vcs_used);
+ return 0 if ( !$vcs_used );

my $cmd = $VCS_cmds{"file_exists_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
+ $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
$cmd .= " 2>&1";
- $exists = &{$VCS_cmds{"execute_cmd"}}($cmd);
+ $exists = &{ $VCS_cmds{"execute_cmd"} }($cmd);

- return 0 if ($? != 0);
+ return 0 if ( $? != 0 );

return $exists;
}
@@ -2421,13 +2494,13 @@ sub vcs_list_files {
my @lsfiles = ();

my $vcs_used = vcs_exists();
- return 0 if (!$vcs_used);
+ return 0 if ( !$vcs_used );

my $cmd = $VCS_cmds{"list_files_cmd"};
- $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
- @lsfiles = &{$VCS_cmds{"execute_cmd"}}($cmd);
+ $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
+ @lsfiles = &{ $VCS_cmds{"execute_cmd"} }($cmd);

- return () if ($? != 0);
+ return () if ( $? != 0 );

return @lsfiles;
}
@@ -2436,7 +2509,7 @@ sub uniq {
my (@parms) = @_;

my %saw;
- @parms = grep(!$saw{$_}++, @parms);
+ @parms = grep( !$saw{$_}++, @parms );
return @parms;
}

@@ -2445,7 +2518,7 @@ sub sort_and_uniq {

my %saw;
@parms = sort @parms;
- @parms = grep(!$saw{$_}++, @parms);
+ @parms = grep( !$saw{$_}++, @parms );
return @parms;
}

@@ -2454,42 +2527,46 @@ sub clean_file_emails {
my @fmt_emails = ();

foreach my $email (@file_emails) {
- $email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
- my ($name, $address) = parse_email($email);
- if ($name eq '"[,\.]"') {
- $name = "";
- }
-
- my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
- if (@nw > 2) {
- my $first = $nw[@nw - 3];
- my $middle = $nw[@nw - 2];
- my $last = $nw[@nw - 1];
-
- if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
- (length($first) == 2 && substr($first, -1) eq ".")) ||
- (length($middle) == 1 ||
- (length($middle) == 2 && substr($middle, -1) eq "."))) {
- $name = "$first $middle $last";
- } else {
- $name = "$middle $last";
- }
- }
-
- if (substr($name, -1) =~ /[,\.]/) {
- $name = substr($name, 0, length($name) - 1);
- } elsif (substr($name, -2) =~ /[,\.]"/) {
- $name = substr($name, 0, length($name) - 2) . '"';
- }
-
- if (substr($name, 0, 1) =~ /[,\.]/) {
- $name = substr($name, 1, length($name) - 1);
- } elsif (substr($name, 0, 2) =~ /"[,\.]/) {
- $name = '"' . substr($name, 2, length($name) - 2);
- }
-
- my $fmt_email = format_email($name, $address, $email_usename);
- push(@fmt_emails, $fmt_email);
+ $email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
+ my ( $name, $address ) = parse_email($email);
+ if ( $name eq '"[,\.]"' ) {
+ $name = "";
+ }
+
+ my @nw = split( /[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name );
+ if ( @nw > 2 ) {
+ my $first = $nw[ @nw - 3 ];
+ my $middle = $nw[ @nw - 2 ];
+ my $last = $nw[ @nw - 1 ];
+
+ if (( ( length($first) == 1 && $first =~ m/[A-Za-z]/ ) || ( length($first) == 2 && substr( $first, -1 ) eq "." ) )
+ || ( length($middle) == 1
+ || ( length($middle) == 2 && substr( $middle, -1 ) eq "." ) )
+ )
+ {
+ $name = "$first $middle $last";
+ }
+ else {
+ $name = "$middle $last";
+ }
+ }
+
+ if ( substr( $name, -1 ) =~ /[,\.]/ ) {
+ $name = substr( $name, 0, length($name) - 1 );
+ }
+ elsif ( substr( $name, -2 ) =~ /[,\.]"/ ) {
+ $name = substr( $name, 0, length($name) - 2 ) . '"';
+ }
+
+ if ( substr( $name, 0, 1 ) =~ /[,\.]/ ) {
+ $name = substr( $name, 1, length($name) - 1 );
+ }
+ elsif ( substr( $name, 0, 2 ) =~ /"[,\.]/ ) {
+ $name = '"' . substr( $name, 2, length($name) - 2 );
+ }
+
+ my $fmt_email = format_email( $name, $address, $email_usename );
+ push( @fmt_emails, $fmt_email );
}
return @fmt_emails;
}
@@ -2499,15 +2576,16 @@ sub merge_email {
my %saw;

for (@_) {
- my ($address, $role) = @$_;
- if (!$saw{$address}) {
- if ($output_roles) {
- push(@lines, "$address ($role)");
- } else {
- push(@lines, $address);
- }
- $saw{$address} = 1;
- }
+ my ( $address, $role ) = @$_;
+ if ( !$saw{$address} ) {
+ if ($output_roles) {
+ push( @lines, "$address ($role)" );
+ }
+ else {
+ push( @lines, $address );
+ }
+ $saw{$address} = 1;
+ }
}

return @lines;
@@ -2517,48 +2595,50 @@ sub output {
my (@parms) = @_;

if ($output_multiline) {
- foreach my $line (@parms) {
- print("${line}\n");
- }
- } else {
- print(join($output_separator, @parms));
- print("\n");
+ foreach my $line (@parms) {
+ print("${line}\n");
+ }
+ }
+ else {
+ print( join( $output_separator, @parms ) );
+ print("\n");
}
}

my $rfc822re;

sub make_rfc822re {
-# Basic lexical tokens are specials, domain_literal, quoted_string, atom, and
-# comment. We must allow for rfc822_lwsp (or comments) after each of these.
-# This regexp will only work on addresses which have had comments stripped
-# and replaced with rfc822_lwsp.
+
+ # Basic lexical tokens are specials, domain_literal, quoted_string, atom, and
+ # comment. We must allow for rfc822_lwsp (or comments) after each of these.
+ # This regexp will only work on addresses which have had comments stripped
+ # and replaced with rfc822_lwsp.

my $specials = '()<>@,;:\\\\".\\[\\]';
my $controls = '\\000-\\037\\177';

- my $dtext = "[^\\[\\]\\r\\\\]";
+ my $dtext = "[^\\[\\]\\r\\\\]";
my $domain_literal = "\\[(?:$dtext|\\\\.)*\\]$rfc822_lwsp*";

my $quoted_string = "\"(?:[^\\\"\\r\\\\]|\\\\.|$rfc822_lwsp)*\"$rfc822_lwsp*";

-# Use zero-width assertion to spot the limit of an atom. A simple
-# $rfc822_lwsp* causes the regexp engine to hang occasionally.
- my $atom = "[^$specials $controls]+(?:$rfc822_lwsp+|\\Z|(?=[\\[\"$specials]))";
- my $word = "(?:$atom|$quoted_string)";
+ # Use zero-width assertion to spot the limit of an atom. A simple
+ # $rfc822_lwsp* causes the regexp engine to hang occasionally.
+ my $atom = "[^$specials $controls]+(?:$rfc822_lwsp+|\\Z|(?=[\\[\"$specials]))";
+ my $word = "(?:$atom|$quoted_string)";
my $localpart = "$word(?:\\.$rfc822_lwsp*$word)*";

my $sub_domain = "(?:$atom|$domain_literal)";
- my $domain = "$sub_domain(?:\\.$rfc822_lwsp*$sub_domain)*";
+ my $domain = "$sub_domain(?:\\.$rfc822_lwsp*$sub_domain)*";

my $addr_spec = "$localpart\@$rfc822_lwsp*$domain";

- my $phrase = "$word*";
- my $route = "(?:\@$domain(?:,\@$rfc822_lwsp*$domain)*:$rfc822_lwsp*)";
+ my $phrase = "$word*";
+ my $route = "(?:\@$domain(?:,\@$rfc822_lwsp*$domain)*:$rfc822_lwsp*)";
my $route_addr = "\\<$rfc822_lwsp*$route?$addr_spec\\>$rfc822_lwsp*";
- my $mailbox = "(?:$addr_spec|$phrase$route_addr)";
+ my $mailbox = "(?:$addr_spec|$phrase$route_addr)";

- my $group = "$phrase:$rfc822_lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*";
+ my $group = "$phrase:$rfc822_lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*";
my $address = "(?:$mailbox|$group)";

return "$rfc822_lwsp*$address";
@@ -2566,13 +2646,18 @@ sub make_rfc822re {

sub rfc822_strip_comments {
my $s = shift;
-# Recursively remove comments, and replace with a single space. The simpler
-# regexps in the Email Addressing FAQ are imperfect - they will miss escaped
-# chars in atoms, for example.

- while ($s =~ s/^((?:[^"\\]|\\.)*
+ # Recursively remove comments, and replace with a single space. The simpler
+ # regexps in the Email Addressing FAQ are imperfect - they will miss escaped
+ # chars in atoms, for example.
+
+ while (
+ $s =~ s/^((?:[^"\\]|\\.)*
(?:"(?:[^"\\]|\\.)*"(?:[^"\\]|\\.)*)*)
- \((?:[^()\\]|\\.)*\)/$1 /osx) {}
+ \((?:[^()\\]|\\.)*\)/$1 /osx
+ )
+ {
+ }
return $s;
}

@@ -2581,7 +2666,7 @@ sub rfc822_strip_comments {
sub rfc822_valid {
my $s = rfc822_strip_comments(shift);

- if (!$rfc822re) {
+ if ( !$rfc822re ) {
$rfc822re = make_rfc822re();
}

@@ -2601,19 +2686,21 @@ sub rfc822_valid {
sub rfc822_validlist {
my $s = rfc822_strip_comments(shift);

- if (!$rfc822re) {
+ if ( !$rfc822re ) {
$rfc822re = make_rfc822re();
}
+
# * null list items are valid according to the RFC
# * the '1' business is to aid in distinguishing failure from no results

my @r;
- if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so &&
- $s =~ m/^$rfc822_char*$/) {
- while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) {
- push(@r, $1);
+ if ( $s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so
+ && $s =~ m/^$rfc822_char*$/ )
+ {
+ while ( $s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos ) {
+ push( @r, $1 );
}
- return wantarray ? (scalar(@r), @r) : 1;
+ return wantarray ? ( scalar(@r), @r ) : 1;
}
return wantarray ? () : 0;
}

--
2.42.0.582.g8ccd20d70d-goog

2023-09-27 18:21:50

by Nick Desaulniers

[permalink] [raw]
Subject: Re: [PATCH 0/3] get_maintainer: add patch-only keyword matching

On Tue, Sep 26, 2023 at 8:19 PM Justin Stitt <[email protected]> wrote:
>
> This series aims to add "D:" which behaves exactly the same as "K:" but
> works only on patch files.
>
> The goal of this is to reduce noise when folks use get_maintainer on
> tree files as opposed to patches. This use case should be steered away
> from [1] but "D:" should help maintainers reduce noise in their inboxes
> regardless, especially when matching omnipresent keywords like [2]. In
> the event of [2] Kees would be to/cc'd from folks running get_maintainer
> on _any_ file containing "__counted_by". The number of these files is
> rising and I fear for his inbox as his goal, as I understand it, is to
> simply monitor the introduction of new __counted_by annotations to
> ensure accurate semantics.

Something like this (whether this series or a different approach)
would be helpful to me as well; we use K: to get cc'ed on patches
mentioning clang or llvm, but our ML also then ends up getting cc'ed
on every follow up patch to most files.

This is causing excessive posts on our ML. As a result, it's a
struggle to get folks to cc themselves to the ML, which puts the code
review burden on fewer people.

Whether it's a new D: or refinement to the behavior of K:, I applaud
the effort. Hopefully we can find an approach that works for
everyone.

And may God have mercy on your soul for having to touch that much perl. :-P

>
> See [3/3] for an illustrative example.
>
> This series also includes a formatting pass over get_maintainer because
> I personally found it difficult to parse with the human eye.
>
> [1]: https://lore.kernel.org/all/[email protected]/
> [2]: https://lore.kernel.org/all/[email protected]/
>
> Signed-off-by: Justin Stitt <[email protected]>
> ---
> Justin Stitt (3):
> MAINTAINERS: add documentation for D:
> get_maintainer: run perltidy
> get_maintainer: add patch-only pattern matching type
>
> MAINTAINERS | 3 +
> scripts/get_maintainer.pl | 3334 +++++++++++++++++++++++----------------------
> 2 files changed, 1718 insertions(+), 1619 deletions(-)
> ---
> base-commit: 6465e260f48790807eef06b583b38ca9789b6072
> change-id: 20230926-get_maintainer_add_d-07424a814e72
>
> Best regards,
> --
> Justin Stitt <[email protected]>
>


--
Thanks,
~Nick Desaulniers

2023-09-27 21:44:10

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH 0/3] get_maintainer: add patch-only keyword matching

On Wed, Sep 27, 2023 at 08:24:58AM -0700, Nick Desaulniers wrote:
> On Tue, Sep 26, 2023 at 8:19 PM Justin Stitt <[email protected]> wrote:
> >
> > This series aims to add "D:" which behaves exactly the same as "K:" but
> > works only on patch files.
> >
> > The goal of this is to reduce noise when folks use get_maintainer on
> > tree files as opposed to patches. This use case should be steered away
> > from [1] but "D:" should help maintainers reduce noise in their inboxes
> > regardless, especially when matching omnipresent keywords like [2]. In
> > the event of [2] Kees would be to/cc'd from folks running get_maintainer
> > on _any_ file containing "__counted_by". The number of these files is
> > rising and I fear for his inbox as his goal, as I understand it, is to
> > simply monitor the introduction of new __counted_by annotations to
> > ensure accurate semantics.
>
> Something like this (whether this series or a different approach)
> would be helpful to me as well; we use K: to get cc'ed on patches
> mentioning clang or llvm, but our ML also then ends up getting cc'ed
> on every follow up patch to most files.
>
> This is causing excessive posts on our ML. As a result, it's a
> struggle to get folks to cc themselves to the ML, which puts the code
> review burden on fewer people.
>
> Whether it's a new D: or refinement to the behavior of K:, I applaud
> the effort. Hopefully we can find an approach that works for
> everyone.

Yes, please! I would use this immediately -- there are a bunch of places
where pstore, strings, hardening, etc all want review if certain
functions or structures are changed in a patch, but we're not
maintainers of the files they appear in.

> > Justin Stitt (3):
> > MAINTAINERS: add documentation for D:
> > get_maintainer: add patch-only pattern matching type

Can we squash these two changes together, and then likely add some
patches for moving things out of K: ?

--
Kees Cook