standalone message retrieval unless - given
[git-grep-footer.git] / git-grep-footer
index 2e42b4a49f576614b139b2f6104028c5b2ae3c00..a868319653246030ea7f83e7540b0e78a7ee2e48 100755 (executable)
@@ -9,10 +9,12 @@ use Getopt::Long qw(:config bundling);
 
 GetOptions(\my %opt,
        'debug!',
 
 GetOptions(\my %opt,
        'debug!',
+       '',  # stdin
        'count|c!',
        'simplify|s:s',
        'ignore-case|i!',
        'fuzzy!',
        'count|c!',
        'simplify|s:s',
        'ignore-case|i!',
        'fuzzy!',
+       'grep|S=s',
        'min|min-count|unique|u:i',
        'max|max-count|show|n:i',
        'version|V'  => sub { Getopt::Long::VersionMessage() },
        'min|min-count|unique|u:i',
        'max|max-count|show|n:i',
        'version|V'  => sub { Getopt::Long::VersionMessage() },
@@ -20,6 +22,11 @@ GetOptions(\my %opt,
        'help|man|?' => sub { Getopt::Long::HelpMessage(-verbose => 2) },
 ) or exit 129;
 
        'help|man|?' => sub { Getopt::Long::HelpMessage(-verbose => 2) },
 ) or exit 129;
 
+my $inputstream = $opt{''} ? \*ARGV : eval {
+       require Git;
+       Git::command_output_pipe('log', '-z', '--pretty=format:%b', @ARGV);
+} || die "Automatic git log failed: $@";
+
 local $| = 1;
 local $/ = "\0";
 
 local $| = 1;
 local $/ = "\0";
 
@@ -27,7 +34,7 @@ my $HEADERMATCH = qr/ [a-z]+ (?: (?:-\w+)+ | \ by ) | cc | reference /ix;
 
 my (%headercount, @headercache);
 
 
 my (%headercount, @headercache);
 
-while (readline) {
+while (readline $inputstream) {
        s/^([0-9a-f]{4,40})\n//m and
        my $hash = $1;
 
        s/^([0-9a-f]{4,40})\n//m and
        my $hash = $1;
 
@@ -75,6 +82,10 @@ while (readline) {
                                }
                        }
 
                                }
                        }
 
+                       if (defined $opt{grep}) {
+                               $_ ~~ qr/$opt{grep}/i or next LINE;
+                       }
+
                        given ($opt{simplify} // 'none') {
                                when (['email', 'authors']) {
                                        $header[1] =~ s{
                        given ($opt{simplify} // 'none') {
                                when (['email', 'authors']) {
                                        $header[1] =~ s{
@@ -125,7 +136,7 @@ while (readline) {
                        my $line = $_->[2] // join(': ', @$_);
                        $line =~ s/^/$hash / if defined $hash;
 
                        my $line = $_->[2] // join(': ', @$_);
                        $line =~ s/^/$hash / if defined $hash;
 
-                       if (defined $opt{min} or $opt{max}) {
+                       if (defined $opt{min} or $opt{max} or $opt{count}) {
                                my $counter = \$headercount{ $_->[0] }->{ $_->[1] // '' };
                                my $excess = $$counter++ - ($opt{min} // 0);
                                next if $excess >= ($opt{max} || 1);
                                my $counter = \$headercount{ $_->[0] }->{ $_->[1] // '' };
                                my $excess = $$counter++ - ($opt{min} // 0);
                                next if $excess >= ($opt{max} || 1);
@@ -154,7 +165,9 @@ git-grep-footer - Find custom header lines in commit messages
 
 =head1 SYNOPSIS
 
 
 =head1 SYNOPSIS
 
-F<git> log --pretty=%b%x00 | F<git-grep-footer> [OPTIONS]
+F<git-grep-footer> [OPTIONS] [-- <git log options>]
+
+F<git> log -z --pretty=format:%b | F<git-grep-footer> [OPTIONS] -
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -200,6 +213,11 @@ Values will be hidden entirely, so only attribute names remain.
 
 =back
 
 
 =back
 
+=item --grep=<pattern>
+
+Only include lines matching the specified regular expression.
+Case insensitivity can be disabled by prepending C<(?-i)>.
+
 =item -u, --unique[=<threshold>]
 
 Each match is only shown once,
 =item -u, --unique[=<threshold>]
 
 Each match is only shown once,
@@ -211,6 +229,38 @@ The original line is given for each match,
 but simplifications still apply for duplicate determination.
 Additional samples are optionally given upto the given maximum.
 
 but simplifications still apply for duplicate determination.
 Additional samples are optionally given upto the given maximum.
 
+=item -c, --count
+
+Prefixes (unique) lines by the number of occurrences.
+Causes output to be buffered until all input has been read (obviously).
+
+=back
+
+=head1 EXAMPLES
+
+=over
+
+=item git-grep-footer --grep=^ack v2.6.32..v2.6.33
+
+Search for I<Acked-by> lines for version I<v2.6.33>.
+Append C<-uin> to skip reoccurrences.
+
+=item git-grep-footer -u --grep=junio
+
+Show distinct lines mentioning a specific author.
+
+=item git-grep-footer -c --simplify --grep=^si
+
+Compare various capitalisations and (mis)spellings of signoffs.
+
+=item git-grep-footer -c --simplify=all -i | sort -n -r | head -n10
+
+List the ten most frequently used attribute names.
+
+=item git-grep-footer -n2 -i -s -- --reverse
+
+The earliest two usages of each distinct identifier.
+
 =back
 
 =head1 AUTHOR
 =back
 
 =head1 AUTHOR
@@ -219,5 +269,7 @@ Mischa POSLAWSKY <perl@shiar.org>
 
 =head1 LICENSE
 
 
 =head1 LICENSE
 
-Copyright. All rights reserved.
+This software is free software;
+you can redistribute and/or modify it under the terms of the GNU GPL
+version 2 or later.