From patchwork Wed Sep 27 03:19:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Justin Stitt X-Patchwork-Id: 145267 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp2486103vqu; Wed, 27 Sep 2023 01:59:46 -0700 (PDT) X-Google-Smtp-Source: AGHT+IF8Gkv8r1JK9V8xHdgTRLGxxubUAnPTfbLYfrREGkDOkQcy8qMJbEZkHlviqVeMwuQD/cln X-Received: by 2002:a17:90a:17a8:b0:26b:4ce1:9705 with SMTP id q37-20020a17090a17a800b0026b4ce19705mr970013pja.38.1695805185543; Wed, 27 Sep 2023 01:59:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695805185; cv=none; d=google.com; s=arc-20160816; b=hyor/3YJf6lUaensAoLVmdcLHajZtuozjt/fzNqdQuttWXgLHvRLPagsIZQwZAjYak /mv6nyXiVoWD59ELYvSgfupTdAfAwwbfSnBhFkjDlZGudXNtyIl8KpRDFrII0vvvSuo3 WpgSlujlPdjp5pHh08F/T7a4rC0SrbZn+YEzJgPGl+7jfY+Ei9rYS50K7o5ZrrP6cAdW MPXfhgc35jmcMmMbqnWLlDGJepPExoyCgO8qRZQuhDNL9RtqyVlY593u4LbF5zkMcBWx tR03sIs04PkvIh7DL2hFtmyZbSCO6Z2uaTa1JKURTdmSDfsxuR0zQopV40iy5y7w7T4v UGyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:from:subject :message-id:references:mime-version:in-reply-to:date:dkim-signature; bh=hfDWpIW/8CUzA5xcRwDkz4QJ+K8yTRgqRPHqwiaPezA=; fh=+nCTt54Nhk0ybOqE59EhWkLgCBS9Lm838M9BUp5KS3k=; b=v/emYrnGTJ+yxJtYjWA/SqQw3jcaOTO5UE7Bqbpw/dceHxRJ4pRL58G+1OXj1RTXPZ epT69G1SmGSkcSwIwNzs4H5epOswj+ZPHUxiT29cbUbd6ZiutnxK+/HM/pMj+fWMzoCN LfC215QZFyk/apSQg9iBVXfeSYQlsQ126UVHL1asi4kUmr0BLxJvdpgGVkQ1XDLjESLC 1EbcvwkQRETz4F8flkNi+/PQ6KBt+aoq/WHZNwZuAFcURWr8l8yFPXeHQuAO72rzXLEf r4gedfkWmc8Zy0GKAYowPBGwrVBFn6mMVtRHbOl1mJC4P0uCSo5vldOfV87FIUzd4sJX c3Vw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=j+UznnK3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id ot13-20020a17090b3b4d00b00263bfa6e205si19432351pjb.50.2023.09.27.01.59.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Sep 2023 01:59:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=j+UznnK3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 6416A81E9A5E; Tue, 26 Sep 2023 21:25:21 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229774AbjI0EZC (ORCPT + 26 others); Wed, 27 Sep 2023 00:25:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35918 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229500AbjI0EXm (ORCPT ); Wed, 27 Sep 2023 00:23:42 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 911AE1E97D for ; Tue, 26 Sep 2023 20:19:30 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-d81e9981ff4so14943754276.3 for ; Tue, 26 Sep 2023 20:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1695784770; x=1696389570; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=hfDWpIW/8CUzA5xcRwDkz4QJ+K8yTRgqRPHqwiaPezA=; b=j+UznnK3pIfZjulacSD2myHCBhnNku+hRXgBhw4OcPaLfZkMJ1woa5y6VWiqBJuj7t 1g63QsfHBWYNt7xX2OZmDnZsXH/J1WIkNXprNxJm8mfq3xsa4qNJlXFjrtZNrFc4s0Cv 1BD/X0jPkDMRnxP5QvmvlP7UCBxomHExdDRzWJ1NSIyOdJ68XFcPxfzgOWGy9PTFx0DF L5z1iY5cVNXiFsnJuHtjxxcoTIeSt/LCRpiH1xHMqaslnDqiZB9toYDF8L1J0LpqYeCs JeuOtuVwj+TgNOfEX3pQA/zqX7O3hfSv15W8Rq9yLHlp7LQwh6oIUriCnx0PjtfIPf/6 pX0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695784770; x=1696389570; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=hfDWpIW/8CUzA5xcRwDkz4QJ+K8yTRgqRPHqwiaPezA=; b=ge5Vjpxw1cSvsKW1wjGNlxXwVXJGoJk62Zihti3K7Wy+gyIwrkE4FV10nfaN3LoxFR WZpeQ/VDgf7q3Yxdzz9MnHhJyCnizuiS5zWCbsLXXxOzyUpuRHEs/Qktng1tM742lLvl 6l+Er+0afkQQcLQCtzgvHfIy64xyMlrgEmntOGOSBTJPDSPAG7wZwO8ssByRnbYxmKqu oCuItzBOa1RZvYapv2Ki+kSi46ZbOorTP8KGhXVpfJApkpYgFMuELAnqruuLei8SaZ6F YKiCSaJwUW3wjz23hOGaAuir1aD0nVC7RSU+CHq9gkwFpo7F/PljAuscL2EnNTukniAB ufjA== X-Gm-Message-State: AOJu0Yw/tTu6XTwlgC3QGSUiPGRglaqzXFKj+msCSkss+9NS+lmpmbGq HKVVEx7b029z6HTE66yJ/kzK4MvEl+Epnx7+tw== X-Received: from jstitt-linux1.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:23b5]) (user=justinstitt job=sendgmr) by 2002:a05:6902:1613:b0:d80:ff9:d19e with SMTP id bw19-20020a056902161300b00d800ff9d19emr8429ybb.9.1695784769795; Tue, 26 Sep 2023 20:19:29 -0700 (PDT) Date: Wed, 27 Sep 2023 03:19:15 +0000 In-Reply-To: <20230927-get_maintainer_add_d-v1-0-28c207229e72@google.com> Mime-Version: 1.0 References: <20230927-get_maintainer_add_d-v1-0-28c207229e72@google.com> X-Developer-Key: i=justinstitt@google.com; a=ed25519; pk=tC3hNkJQTpNX/gLKxTNQKDmiQl6QjBNCGKJINqAdJsE= X-Developer-Signature: v=1; a=ed25519-sha256; t=1695784766; l=137699; i=justinstitt@google.com; s=20230717; h=from:subject:message-id; bh=a5IMoV96NTdQdZo9TXRyC6eIeYI5zLVOlaygkttIAEg=; b=B4J9CoEMGjsEW10NeaG8Wco+w1j6Y3boxhiVQ86YnfOY9i4ykR5yyTe75JlV7+f2ewRy4YTVv QZD7s0cRyEBAUxtJRE+OA7adKKqwx51HnDShuNvrx8jiUTfvyRiGWCO X-Mailer: b4 0.12.3 Message-ID: <20230927-get_maintainer_add_d-v1-2-28c207229e72@google.com> Subject: [PATCH 2/3] get_maintainer: run perltidy From: Justin Stitt To: Joe Perches Cc: linux-kernel@vger.kernel.org, Kees Cook , Nick Desaulniers , Nathan Chancellor , Jakub Kicinski , Krzysztof Kozlowski , geert@linux-m68k.org, gregkh@linuxfoundation.org, workflows@vger.kernel.org, mario.limonciello@amd.com, Justin Stitt X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Tue, 26 Sep 2023 21:25:21 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778163499192626250 X-GMAIL-MSGID: 1778180618027394690 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 - # - # name1 - # name1 name2 - # (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 + # + # name1 + # name1 name2 + # (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/(?"; - } - } 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 <[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 <; - 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 <; + 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 <[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; }