* subversion/svn/main.c
[svn.git] / contrib / client-side / search-svnlog.pl
blobd8bb331b04ba537826a4f0bfe7c621ac06751179
1 #!/usr/bin/perl -w
3 # ====================================================================
4 # Show log messages matching a certain pattern. Usage:
6 # search-svnlog.pl [-v] [-f LOGFILE] REGEXP
8 # See &usage() for details.
10 # ====================================================================
11 # Copyright (c) 2000-2004 CollabNet. All rights reserved.
13 # This software is licensed as described in the file COPYING, which
14 # you should have received as part of this distribution. The terms
15 # are also available at http://subversion.tigris.org/license-1.html.
16 # If newer versions of this license are posted there, you may use a
17 # newer version instead, at your option.
19 # This software consists of voluntary contributions made by many
20 # individuals. For exact contribution history, see the revision
21 # history and logs, available at http://subversion.tigris.org/.
22 # ====================================================================
24 use strict;
25 use Getopt::Long;
27 my $log_file;
28 my $invert = 0;
29 my $caseless = 0;
31 GetOptions('f|file=s' => \$log_file,
32 'v|invert' => \$invert,
33 'i|caseinsensitive' => \$caseless) or &usage;
35 &usage("$0: too few arguments") unless @ARGV;
36 &usage("$0: too many arguments") if @ARGV > 1;
38 my $filter = shift;
39 $filter = '(?i)' . $filter if $caseless;
41 my $log_cmd = "svn log";
43 my $log_separator = '-' x 72 . "\n";
45 my $open_string = defined $log_file ? $log_file : "$log_cmd |";
46 open(LOGDATA, $open_string) or
47 die "$0: cannot open `$open_string' for reading: $!\n";
49 my $this_entry_accum = "";
50 my $this_rev = -1;
51 my $this_lines = 0;
52 my $seen_blank_line; # A blank line separates headers from body.
54 while (<LOGDATA>)
56 if (/^r([0-9]+) \| [^\|]* \| [^\|]* \| ([0-9]+) (line|lines)$/)
58 $this_rev = $1;
59 $this_lines = $2 + 1; # Compensate for blank line preceding body.
61 $this_entry_accum .= $_;
63 elsif ($this_lines == 0) # Reached end of msg. Looking at log separator?
65 if (! ($_ eq $log_separator))
67 die "$0: wrong number of lines for log message!\n${this_entry_accum}\n";
70 if ($this_entry_accum =~ /$filter/og ^ $invert)
72 print "${this_entry_accum}${log_separator}";
75 # Reset accumulators.
76 $seen_blank_line = 0;
77 $this_entry_accum = "";
78 $this_rev = -1;
80 elsif ($this_lines < 0)
82 die "$0: line weirdness parsing log.\n";
84 else # Just continue accumulating.
86 $this_entry_accum .= $_;
88 if ($seen_blank_line)
90 $this_lines--;
92 elsif (/^$/)
94 $seen_blank_line = 1;
95 $this_lines--;
100 close(LOGDATA) or
101 die "$0: closing `$open_string' failed: $!\n";
103 exit 0;
105 sub usage {
106 warn "@_\n" if @_;
107 die "usage: $0: [-v] [-i] [-f LOGFILE] REGEXP\n",
108 "\n",
109 "Print only log messages matching REGEXP, either by running 'svn log'\n",
110 "in the current working directory, or if '-f LOGFILE' is passed, then\n",
111 "read the log data from LOGFILE (which should be in the same format\n",
112 "as the output of 'svn log').\n",
113 "\n",
114 "If '-v' is given, the matching is inverted (like 'grep -v').\n",
115 "\n",
116 "If '-i' is given, the matching is case-insensitive (like 'grep -i').\n";