Remove RCS Id keyword.
[bpt/emacs.git] / lib-src / grep-changelog
CommitLineData
056565f7 1#! /usr/bin/perl
6dde7e38 2
41848daa 3# Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
6dde7e38
GM
4#
5# This file is part of GNU Emacs.
6#
7# GNU Emacs is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2, or (at your option)
10# any later version.
11#
12# GNU Emacs is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with GNU Emacs; see the file COPYING. If not, write to the
19# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20# Boston, MA 02111-1307, USA.
21
22
23# Extract entries from ChangeLogs matching specified criteria.
24# Optionally format the resulting output to a form suitable for RCS
25# logs, like they are used in Emacs, for example. In this format,
26# author lines leading spaces, and file names are removed.
27
28require 5;
db3cd0ae 29use strict;
6dde7e38
GM
30
31# Parse command line options.
32
db3cd0ae
GM
33use vars qw($author $regexp $exclude $from_date $to_date
34 $rcs_log $with_date $version $help);
35
6dde7e38 36use Getopt::Long;
db3cd0ae
GM
37my $result = GetOptions ("author=s" => \$author,
38 "text=s" => \$regexp,
39 "exclude=s" => \$exclude,
40 "from-date=s" => \$from_date,
41 "to-date=s" => \$to_date,
42 "rcs-log" => \$rcs_log,
43 "with-date" => \$with_date,
44 "version" => \$version,
45 "help" => \$help);
6dde7e38
GM
46
47# If date options are specified, check that they have the format
48# YYYY-MM-DD.
49
50$result = 0 if $from_date && $from_date !~ /^\d\d\d\d-\d\d-\d\d$/;
51$result = 0 if $to_date && $to_date !~ /^\d\d\d\d-\d\d-\d\d$/;
52
53# Print usage information and exit when necessary.
54
55if ($result == 0 || $help) {
56 print <<USAGE;
57Usage: $0 [options] [CHANGELOG...]
58Print entries in ChangeLogs matching various criteria. Valid options
59are
60
2ca8a587 61 --author=AUTHOR match entries whose author line matches
6dde7e38
GM
62 regular expression AUTHOR
63 --text=TEXT match entries whose text matches regular
64 expression TEXT.
65 --exclude=TEXT exclude entries matching TEXT.
66 --from-date=YYYY-MM-DD match entries not older than given date
67 --to-date=YYYY-MM-DD match entries not younger than given date
68 --rcs-log format output suitable for RCS log entries.
69 --with-date print short date line in RCS log
70 --version print version info
71 --help print this help
72
73If no CHANGELOG is specified scan the files "ChangeLog" and
2ca8a587 74"ChangeLog.[9-1]" in the current directory. Old-style dates in ChangeLogs
6dde7e38
GM
75are not recognized.
76USAGE
77 exit $help ? 0 : 1;
78}
79
80# Print version info and exit if `--version' was specified.
81
82if ($version) {
83 print "0.1\n";
84 exit 0;
85}
86
87
88# Value is non-zero if HEADER matches according to command line
89# options specified, i.e. it matches $author, and its date is in
90# the range $from_date <= date <= $to_date.
91
92sub header_match_p ($) {
93 my $header = shift;
94
b6a6731a
GM
95 return 0 unless $header;
96
6dde7e38
GM
97 # No match if AUTHOR-regexp specified and doesn't match.
98 return 0 if $author && $header !~ /$author/;
99
100 # Check that the date of the entry matches if date options
101 # `--from-date' and/or `--to-date' were specified . Old-style
102 # dates in ChangeLogs are not recognized, and never match.
103 if ($from_date || $to_date) {
104 if ($header =~ /^(\d\d\d\d-\d\d-\d\d)/) {
105 my $date = $1;
106 return 0 if $from_date && $date lt $from_date;
107 return 0 if $to_date && $date gt $to_date;
108 } else {
109 # Don't bother recognizing old-style dates.
110 return 0;
111 }
112 }
113
114 return 1;
115}
116
117
2ca8a587 118# Value is non-zero if ENTRY matches the criteria specified on the
6dde7e38
GM
119# command line, i.e. it matches $regexp, and it doesn't match
120# $exclude.
121
122sub entry_match_p ($) {
123 my $entry = shift;
124
b6a6731a
GM
125 return 0 unless $entry;
126
6dde7e38 127 if ($regexp) {
2ca8a587 128 return 1 if ($entry =~ /$regexp/
6dde7e38
GM
129 && (!$exclude || $entry !~ $exclude));
130 } else {
131 return 1 if !$exclude || $entry !~ $exclude;
132 }
133
134 return 0;
135}
136
137
138# Print HEADER and/or ENTRY in a format suitable for what was
139# specified on the command line. If $rcs_log is specified, author
140# lines are not printed, and leading spaces and file names are removed
141# from ChangeLog entries.
142
143sub print_log ($$) {
144 my ($header, $entry) = @_;
145
146 if ($rcs_log) {
147 # Remove leading whitespace from entry.
148 $entry =~ s/^\s+//mg;
149 # Remove file name parts.
150 $entry =~ s/^\*.*\(/(/mg;
151 # Remove file name parts, 2.
152 $entry =~ s/^\*.*://mg;
153 if ($with_date) {
154 $header =~ /(\d\d\d\d-\d\d-\d\d)/;
155 print "!changelog-date $1\n";
156 }
157 print $entry;
158 } else {
159 print $header, $entry;
160 }
161}
162
163# Scan LOG for matching entries, and print them to standard output.
164
165sub parse_changelog ($) {
166 my $log = shift;
db3cd0ae
GM
167 my $entry = undef;
168 my $header = undef;
6dde7e38
GM
169 my $match;
170
171 # Open the ChangeLog.
172 open (IN, "< $log") || die "Cannot open $log: $!";
173
db3cd0ae 174 while (defined(my $line = <IN>)) {
6dde7e38
GM
175 if ($line =~ /^\S/) {
176 # Line is an author-line. Print previous entry if
177 # it matches.
2ca8a587 178 print_log ($header, $entry)
6dde7e38
GM
179 if header_match_p ($header) && entry_match_p ($entry);
180
181 $entry = "";
182 $header = $line;
183
184 # Add empty lines below the header.
41848daa 185 while (defined($line = <IN>) && $line =~ /^\s*$/) {
6dde7e38
GM
186 $header = "$header$line";
187 }
2ca8a587 188 }
6dde7e38 189
3eb7ddf3
GM
190 last unless defined $line;
191
6dde7e38
GM
192 if ($line =~ /^\s*\*/) {
193 # LINE is the first line of a ChangeLog entry. Print
194 # previous entry if it matches.
2ca8a587 195 print_log ($header, $entry)
6dde7e38
GM
196 if header_match_p ($header) && entry_match_p ($entry);
197 $entry = $line;
198 } else {
199 # Add LINE to the current entry.
200 $entry = "$entry$line";
201 }
202 }
203
204 # Print last entry if it matches.
2ca8a587 205 print_log ($header, $entry)
6dde7e38
GM
206 if header_match_p ($header) && entry_match_p ($entry);
207
208 close IN;
209}
210
211
212# Main program. Process ChangeLogs.
213
214if (@ARGV > 0) {
215 # If files were specified on the command line, parse those files.
db3cd0ae 216 while (defined(my $log = shift @ARGV)) {
6dde7e38
GM
217 parse_changelog ($log);
218 }
219} else {
220 # Parse default files ChangeLog and ChangeLog.9...ChangeLog.1 in
221 # that order.
222 parse_changelog ("ChangeLog");
db3cd0ae 223 for (my $i = 9; $i >= 1; --$i) {
6dde7e38
GM
224 my $log = "ChangeLog.$i";
225 parse_changelog ($log) if -f $log;
226 }
227}
228
229
2ca8a587 230# grep-changelog ends here.