All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joe Perches <joe@perches.com>
To: Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@kernel.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 01/10] Add scripts/get_maintainer.pl
Date: Tue,  7 Apr 2009 22:17:43 -0700	[thread overview]
Message-ID: <1239167872-8179-2-git-send-email-joe@perches.com> (raw)
In-Reply-To: <1239167872-8179-1-git-send-email-joe@perches.com>

A script to parse file pattern information in MAINTAINERS
and return selected information about a file or patch

usage: scripts/get_maintainer.pl [options] patchfile
       scripts/get_maintainer.pl [options] -f file
version: 0.14

MAINTAINERS field selection options:
  --email => print email address(es) if any
    --git => include git "*-by:" signers in commit count order
    --git-chief-penguins => include (Linus Torvalds)
    --git-min-signatures => number of signatures required (default: 1)
    --git-max-maintainers => maximum maintainers to add (default: 5)
    --git-since => git history to use (default: 1-year-ago)
    --m => include maintainer(s) if any
    --n => include name 'Full Name <addr@domain.tld>'
    --l => include list(s) if any
    --s => include subscriber only list(s) if any
  --scm => print SCM tree(s) if any
  --status => print status if any
  --subsystem => print subsystem name if any
  --web => print website(s) if any

Output type options:
  --separator [, ] => separator for multiple entries on 1 line
  --multiline => print 1 entry per line

Default options:
  [--email --git --m --n --l --multiline]

Other options:
  --version => show version
  --help => show this help information

Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
---
 scripts/get_maintainer.pl |  518 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 518 insertions(+), 0 deletions(-)
 create mode 100755 scripts/get_maintainer.pl

diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
new file mode 100755
index 0000000..0f3c0a5
--- /dev/null
+++ b/scripts/get_maintainer.pl
@@ -0,0 +1,518 @@
+#!/usr/bin/perl -w
+# (c) 2007, Joe Perches <joe@perches.com>
+#           created from checkpatch.pl
+#
+# Print selected MAINTAINERS information for
+# the files modified in a patch or for a file
+#
+# usage: perl scripts/get_maintainers.pl [OPTIONS] <patch>
+#        perl scripts/get_maintainers.pl [OPTIONS] -f <file>
+#
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+
+my $P = $0;
+my $V = '0.14';
+
+use Getopt::Long qw(:config no_auto_abbrev);
+
+my $lk_path = "./";
+my $email = 1;
+my $email_usename = 1;
+my $email_maintainer = 1;
+my $email_list = 1;
+my $email_subscriber_list = 0;
+my $email_git = 1;
+my $email_git_penguin_chiefs = 0;
+my $email_git_min_signatures = 1;
+my $email_git_max_maintainers = 5;
+my $email_git_since = "1-year-ago";
+my $output_multiline = 1;
+my $output_separator = ", ";
+my $scm = 0;
+my $web = 0;
+my $subsystem = 0;
+my $status = 0;
+my $onefile = 0;
+my $version = 0;
+my $help = 0;
+
+my $exit = 0;
+
+my @penguin_chief = ();
+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);
+    }
+}
+my $penguin_chiefs = "\(" . join("|",@penguin_chief_names) . "\)";
+
+if (!GetOptions(
+		'email!' => \$email,
+		'git!' => \$email_git,
+		'git-chief-penguins!' => \$email_git_penguin_chiefs,
+		'git-min-signatures=i' => \$email_git_min_signatures,
+		'git-max-maintainers=i' => \$email_git_max_maintainers,
+		'git-since=s' => \$email_git_since,
+		'm!' => \$email_maintainer,
+		'n!' => \$email_usename,
+		'l!' => \$email_list,
+		's!' => \$email_subscriber_list,
+		'multiline!' => \$output_multiline,
+		'separator=s' => \$output_separator,
+		'subsystem!' => \$subsystem,
+		'status!' => \$status,
+		'scm!' => \$scm,
+		'web!' => \$web,
+		'f|file' => \$onefile,
+		'v|version' => \$version,
+		'h|help' => \$help,
+		)) {
+    usage();
+    die "$P: invalid argument\n";
+}
+
+if ($help != 0) {
+    usage();
+    exit 0;
+}
+
+if ($version != 0) {
+    print("${P} ${V}\n");
+    exit 0;
+}
+
+my $infile = $ARGV[0];
+
+if ($#ARGV < 0) {
+    usage();
+    die "$P: argument missing: patchfile or -f file please\n";
+}
+
+my $selections = $email + $scm + $status + $subsystem + $web;
+if ($selections == 0) {
+    usage();
+    die "$P:  Missing required option: email, scm, status, subsystem or web\n";
+}
+
+if ($email && ($email_maintainer + $email_list + $email_subscriber_list
+	       + $email_git + $email_git_penguin_chiefs) == 0) {
+    usage();
+    die "$P: Please select at least 1 email option\n";
+}
+
+if (!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 = ();
+open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n";
+while (<MAINT>) {
+    my $line = $_;
+
+    if ($line =~ m/^(\C):\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 .
+	}
+	push(@typevalue, "$type:$value");
+    } elsif (!/^(\s)*$/) {
+	$line =~ s/\n$//g;
+	push(@typevalue, $line);
+    }
+}
+close(MAINT);
+
+## use the filename on the command line or find the filenames in the patchfile
+
+my @files = ();
+
+if ($onefile) {
+    if (!(-f $infile)) {
+	die "$P: file '${infile}' not found\n";
+    }
+    push(@files, $infile);
+} else {
+    open(PATCH, "<$infile") or die "$P: Can't open ${infile}\n";
+    while (<PATCH>) {
+	if (m/^\+\+\+\s+(\S+)/) {
+	    my $file = $1;
+	    $file =~ s@^[^/]*/@@;
+	    $file =~ s@\n@@;
+	    push(@files, $file);
+	}
+    }
+    close(PATCH);
+    my $file_cnt = @files;
+    if ($file_cnt == 0) {
+	print STDERR "$P: file '${infile}' doesn't appear to be a patch.  "
+	    . "Add -f to options?\n";
+    }
+    @files = sort_and_uniq(@files);
+}
+
+my @email_to = ();
+my @scm = ();
+my @web = ();
+my @subsystem = ();
+my @status = ();
+
+# Find responsible parties
+
+foreach my $file (@files) {
+
+#Do not match excluded file patterns
+
+    my $exclude = 0;
+    foreach my $line (@typevalue) {
+	if ($line =~ m/^(\C):(.*)/) {
+	    my $type = $1;
+	    my $value = $2;
+	    if ($type eq 'X') {
+		if (file_match_pattern($file, $value)) {
+		    $exclude = 1;
+		}
+	    }
+	}
+    }
+
+    if (!$exclude) {
+	my $tvi = 0;
+	foreach my $line (@typevalue) {
+	    if ($line =~ m/^(\C):(.*)/) {
+		my $type = $1;
+		my $value = $2;
+		if ($type eq 'F') {
+		    if (file_match_pattern($file, $value)) {
+			add_categories($tvi);
+		    }
+		}
+	    }
+	    $tvi++;
+	}
+    }
+
+    if ($email_git) {
+	recent_git_signoffs($file);
+    }
+
+}
+
+if ($email_git_penguin_chiefs) {
+    foreach my $chief (@penguin_chief) {
+	if ($chief =~ m/^(.*):(.*)/) {
+	    my $chief_name = $1;
+	    my $chief_addr = $2;
+	    if ($email_usename) {
+		push(@email_to, format_email($chief_name, $chief_addr));
+	    } else {
+		push(@email_to, $chief_addr);
+	    }
+	}
+    }
+}
+
+if ($email) {
+    my $address_cnt = @email_to;
+    if ($address_cnt == 0 && $email_list) {
+	push(@email_to, "linux-kernel\@vger.kernel.org");
+    }
+
+#Don't sort email address list, but do remove duplicates
+    @email_to = uniq(@email_to);
+    output(@email_to);
+}
+
+if ($scm) {
+    if (!$onefile) {
+	@scm = sort_and_uniq(@scm);
+    }
+    output(@scm);
+}
+
+if ($status) {
+    if (!$onefile) {
+	@status = sort_and_uniq(@status);
+    }
+    output(@status);
+}
+
+if ($subsystem) {
+    if (!$onefile) {
+	@subsystem = sort_and_uniq(@subsystem);
+    }
+    output(@subsystem);
+}
+
+if ($web) {
+    if (!$onefile) {
+	@web = sort_and_uniq(@web);
+    }
+    output(@web);
+}
+
+exit($exit);
+
+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;
+	    }
+	}
+    }
+    return 0;
+}
+
+sub usage {
+    print <<EOT;
+usage: $P [options] patchfile
+       $P [options] -f file
+version: $V
+
+MAINTAINER field selection options:
+  --email => print email address(es) if any
+    --git => include recent git \*-by: signers
+    --git-chief-penguins => include ${penguin_chiefs}
+    --git-min-signatures => number of signatures required (default: 1)
+    --git-max-maintainers => maximum maintainers to add (default: 5)
+    --git-since => git history to use (default: 1-year-ago)
+    --m => include maintainer(s) if any
+    --n => include name 'Full Name <addr\@domain.tld>'
+    --l => include list(s) if any
+    --s => include subscriber only list(s) if any
+  --scm => print SCM tree(s) if any
+  --status => print status if any
+  --subsystem => print subsystem name if any
+  --web => print website(s) if any
+
+Output type options:
+  --separator [, ] => separator for multiple entries on 1 line
+  --multiline => print 1 entry per line
+
+Default options:
+  [--email --git --m --l --multiline]
+
+Other options:
+  --version -> show version
+  --help => show this help information
+
+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")
+	    && (-f "${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;
+}
+
+sub format_email {
+    my ($name, $email) = @_;
+
+    $name =~ s/^\s+|\s+$//g;
+    $email =~ s/^\s+|\s+$//g;
+
+    my $formatted_email = "";
+
+    if ($name =~ /[^a-z0-9 \.\-]/i) {    ##has "must quote" chars
+	$name =~ s/(?<!\\)"/\\"/g;       ##escape quotes
+	$formatted_email = "\"${name}\"\ \<${email}\>";
+    } else {
+	$formatted_email = "${name} \<${email}\>";
+    }
+    return $formatted_email;
+}
+
+sub add_categories {
+    my ($index) = @_;
+
+    $index = $index - 1;
+    while ($index >= 0) {
+	my $tv = $typevalue[$index];
+	if ($tv =~ m/^(\C):(.*)/) {
+	    my $ptype = $1;
+	    my $pvalue = $2;
+	    if ($ptype eq "L") {
+		my $subscr = $pvalue;
+		if ($subscr =~ m/\s*\(subscribers-only\)/) {
+		    if ($email_subscriber_list) {
+			$subscr =~ s/\s*\(subscribers-only\)//g;
+			push(@email_to, $subscr);
+		    }
+		} else {
+		    if ($email_list) {
+			push(@email_to, $pvalue);
+		    }
+		}
+	    } elsif ($ptype eq "M") {
+		if ($email_maintainer) {
+		    if ($index >= 0) {
+			my $tv = $typevalue[$index - 1];
+			if ($tv =~ m/^(\C):(.*)/) {
+			    if ($1 eq "P" && $email_usename) {
+				push(@email_to, format_email($2, $pvalue));
+			    } else {
+				push(@email_to, $pvalue);
+			    }
+			}
+		    } else {
+			push(@email_to, $pvalue);
+		    }
+		}
+	    } elsif ($ptype eq "T") {
+		push(@scm, $pvalue);
+	    } elsif ($ptype eq "W") {
+		push(@web, $pvalue);
+	    } elsif ($ptype eq "S") {
+		push(@status, $pvalue);
+	    }
+
+	    $index--;
+	} else {
+	    push(@subsystem,$tv);
+	    $index = -1;
+	}
+    }
+}
+
+sub which {
+    my ($bin) = @_;
+
+    foreach my $path (split /:/, $ENV{PATH}) {
+	if (-e "$path/$bin") {
+	    return "$path/$bin";
+	}
+    }
+
+    return "";
+}
+
+sub recent_git_signoffs {
+    my ($file) = @_;
+
+    my $sign_offs = "";
+    my $cmd = "";
+    my $output = "";
+    my $count = 0;
+    my @lines = ();
+
+    if (which("git") eq "") {
+	die("$P: git not found.  Add --nogit to options?\n");
+    }
+
+    $cmd = "git log --since=${email_git_since} -- ${file}";
+    $cmd .= " | grep -P '^    [-A-Za-z]+by:.*\\\@'";
+    if (!$email_git_penguin_chiefs) {
+	$cmd .= " | grep -E -v \"${penguin_chiefs}\"";
+    }
+    $cmd .= " | sort | uniq -c | sort -rn";
+
+    $output = `${cmd}`;
+    $output =~ s/^\s*//gm;
+
+    @lines = split("\n", $output);
+    foreach my $line (@lines) {
+	if ($line =~ m/([0-9]+)\s+([-A-Za-z]+by:)\s+(.*)/) {
+	    my $sign_offs = $1;
+	    $line = $3;
+	    $count++;
+	    if ($sign_offs < $email_git_min_signatures ||
+	        $count > $email_git_max_maintainers) {
+		last;
+	    }
+	} else {
+	    die("$P: Unexpected git output: ${line}\n");
+	}
+	if ($line =~ m/(.*) <(.*)>/) {
+	    my $git_name = $1;
+	    my $git_addr = $2;
+	    $git_name =~ tr/^\"//;
+	    $git_name =~ tr/\"$//;
+	    if ($email_usename) {
+		push(@email_to, format_email($git_name, $git_addr));
+	    } else {
+		push(@email_to, $git_addr);
+	    }
+	} elsif ($line =~ m/<(.*)>/) {
+	    my $git_addr = $1;
+	    push(@email_to, $git_addr);
+	} else {
+	    push(@email_to, $line);
+	}
+    }
+    return $output;
+}
+
+sub uniq {
+    my @parms = @_;
+
+    my %saw;
+    @parms = grep(!$saw{$_}++, @parms);
+    return @parms;
+}
+
+sub sort_and_uniq {
+    my @parms = @_;
+
+    my %saw;
+    @parms = sort @parms;
+    @parms = grep(!$saw{$_}++, @parms);
+    return @parms;
+}
+
+sub output {
+    my @parms = @_;
+
+    if ($output_multiline) {
+	foreach my $line (@parms) {
+	    print("${line}\n");
+	}
+    } else {
+	print(join($output_separator, @parms));
+	print("\n");
+    }
+}
-- 
1.6.0.2


  reply	other threads:[~2009-04-08  5:21 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-08  5:17 [PATCH 0/10] MAINTAINERS - add script, patterns and misc updates Joe Perches
2009-04-08  5:17 ` Joe Perches [this message]
2009-04-08  5:17 ` [PATCH 02/10] MAINTAINERS - Add file patterns Joe Perches
2009-04-08  6:59   ` Geert Uytterhoeven
2009-04-08  6:59     ` Geert Uytterhoeven
2009-04-08 15:44     ` Joe Perches
2009-04-08 14:13   ` Mauro Carvalho Chehab
2009-04-08 15:35     ` Joe Perches
2009-04-17  4:45       ` Mauro Carvalho Chehab
2009-04-08 16:51   ` Greg KH
2009-04-08 17:07     ` Joe Perches
2009-04-08 17:11       ` Greg KH
2009-04-09 15:42   ` Timur Tabi
2009-04-09 17:42     ` Joe Perches
2009-04-09 17:44       ` Timur Tabi
2009-04-08  5:17 ` [PATCH 03/10] MAINTAINERS - Standardize style Joe Perches
2009-04-08  5:17 ` [PATCH 04/10] MAINTAINERS - Remove HP Fibre Channel HBA no longer in tree Joe Perches
2009-04-08  5:17 ` [PATCH 05/10] MAINTAINERS - standardize "T: git urls" Joe Perches
2009-04-08  5:17 ` [PATCH 06/10] MAINTAINERS - Add Linus Torvalds' git Joe Perches
2009-04-08  5:17 ` [PATCH 07/10] MAINTAINERS - i2c_tiny_usb T: should be W: Joe Perches
2009-04-08  5:17 ` [PATCH 08/10] MAINTAINERS - Update FPU Emulator contact address and web page Joe Perches
2009-04-08  5:17 ` [PATCH 09/10] MAINTAINERS - Remove x86/Voyager no longer in tree Joe Perches
2009-04-08  5:17 ` [PATCH 10/10] MAINTAINERS - Remove cyblafb frame buffer " Joe Perches
2009-04-17 20:47 ` [PATCH 0/10] MAINTAINERS - add script, patterns and misc updates Randy Dunlap
2009-04-17 21:27   ` Joe Perches
2009-04-07  8:13     ` Pavel Machek
2009-04-22 15:54       ` Joe Perches
2009-04-22 18:59         ` Sam Ravnborg
2009-04-22 19:05           ` Andrew Morton
2009-04-22 19:56             ` Joe Perches
2009-04-22 20:30               ` Pavel Machek
2009-04-22 20:34                 ` Joe Perches
2009-04-24  7:13                 ` Joe Perches
2009-05-10 20:26                   ` RFC: MAINTAINER email address style? Joe Perches
2009-05-10 20:53                     ` Sam Ravnborg
2009-05-10 21:00                       ` Joe Perches
2009-05-10 21:09                         ` Sam Ravnborg
2009-05-10 21:45                           ` Bartlomiej Zolnierkiewicz
2009-05-11  1:37                             ` KOSAKI Motohiro
2009-05-11  0:48                       ` Andrew Morton
2009-05-10 21:22                     ` Pavel Machek
2009-05-10 21:24                     ` Alan Cox
2009-05-10 21:36                       ` Pavel Machek
2009-05-10 22:46                         ` Alan Cox
2009-05-10 21:52                       ` Joe Perches
2009-05-10 22:04                         ` Alan Cox
2009-05-10 22:35                           ` Joe Perches
2009-05-13  0:03                     ` [GIT PULL] MAINTAINERS, scripts/get_maintainer.pl, and Documentation/SubmittingPatches Joe Perches
2009-04-17 21:30     ` [PATCH 0/10] MAINTAINERS - add script, patterns and misc updates Randy Dunlap
2009-04-17 21:41     ` Andrew Morton
2009-04-17 21:58       ` Linus Torvalds
2009-04-17 22:09       ` Joe Perches
2009-04-17 22:18         ` Andrew Morton
2009-04-17 22:53           ` Joe Perches
  -- strict thread matches above, loose matches on Subject: below --
2009-01-13 20:28 [PATCH 0/10] MAINTAINERS - script, patterns, and misc fixes Joe Perches
2009-01-13 20:28 ` [PATCH 01/10] Add scripts/get_maintainer.pl Joe Perches
2008-11-18 17:13 [PATCH 0/10] MAINTAINERS - add script and patterns Joe Perches
2008-11-18 17:13 ` [PATCH 01/10] Add scripts/get_maintainer.pl Joe Perches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1239167872-8179-2-git-send-email-joe@perches.com \
    --to=joe@perches.com \
    --cc=akpm@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.