New upstream version.

committer: mfx <mfx> 1042993977 +0000
This commit is contained in:
Markus F.X.J. Oberhumer 2003-01-19 16:32:57 +00:00
parent a38989dfbf
commit ff2c5300b8

View File

@ -2,16 +2,18 @@
exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*- exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*-
#!perl -w #!perl -w
############################################################## ##############################################################
### ### ### ###
### cvs2cl.pl: produce ChangeLog(s) from `cvs log` output. ### ### cvs2cl.pl: produce ChangeLog(s) from `cvs log` output. ###
### ### ### ###
############################################################## ##############################################################
## $Revision: 2.38 $ ## $Revision: 2.46 $
## $Date: 2001/02/12 19:54:35 $ ## $Date: 2003/01/18 13:14:52 $
## $Author: kfogel $ ## $Author: fluffy $
## ##
## (C) 2001,2002,2003 Martyn J. Pearce <fluffy@cpan.org>, under the GNU GPL.
## (C) 1999 Karl Fogel <kfogel@red-bean.com>, under the GNU GPL. ## (C) 1999 Karl Fogel <kfogel@red-bean.com>, under the GNU GPL.
## ##
## (Extensively hacked on by Melissa O'Neill <oneill@cs.sfu.ca>.) ## (Extensively hacked on by Melissa O'Neill <oneill@cs.sfu.ca>.)
@ -31,14 +33,13 @@ exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*-
## Free Software Foundation, Inc., 59 Temple Place - Suite 330, ## Free Software Foundation, Inc., 59 Temple Place - Suite 330,
## Boston, MA 02111-1307, USA. ## Boston, MA 02111-1307, USA.
use strict; use strict;
use Text::Wrap; use Text::Wrap;
use Time::Local; use Time::Local;
use File::Basename; use File::Basename;
# The Plan: # The Plan:
# #
# Read in the logs for multiple files, spit out a nice ChangeLog that # Read in the logs for multiple files, spit out a nice ChangeLog that
@ -70,15 +71,14 @@ use File::Basename;
# If we're not using the `--distributed' flag, the directory is always # If we're not using the `--distributed' flag, the directory is always
# considered to be `./', even as descend into subdirectories. # considered to be `./', even as descend into subdirectories.
############### Globals ################ ############### Globals ################
# What we run to generate it: # What we run to generate it:
my $Log_Source_Command = "cvs log"; my $Log_Source_Command = "cvs log";
# In case we have to print it out: # In case we have to print it out:
my $VERSION = '$Revision: 2.38 $'; my $VERSION = '$Revision: 2.46 $';
$VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/; $VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/;
## Vars set by options: ## Vars set by options:
@ -111,6 +111,9 @@ my $Output_To_Stdout = 0;
# Eliminate empty log messages? # Eliminate empty log messages?
my $Prune_Empty_Msgs = 0; my $Prune_Empty_Msgs = 0;
# Tags of which not to output
my @ignore_tags;
# Don't call Text::Wrap on the body of the message # Don't call Text::Wrap on the body of the message
my $No_Wrap = 0; my $No_Wrap = 0;
@ -119,6 +122,9 @@ my $No_Wrap = 0;
# make sure to go through all conditionals that use this var. # make sure to go through all conditionals that use this var.
my $After_Header = " "; my $After_Header = " ";
# XML Encoding
my $XML_Encoding = '';
# Format more for programs than for humans. # Format more for programs than for humans.
my $XML_Output = 0; my $XML_Output = 0;
@ -129,6 +135,9 @@ my $FSF_Style = 0;
# Show times in UTC instead of local time # Show times in UTC instead of local time
my $UTC_Times = 0; my $UTC_Times = 0;
# Show times in output?
my $Show_Times = 1;
# Show day of week in output? # Show day of week in output?
my $Show_Day_Of_Week = 0; my $Show_Day_Of_Week = 0;
@ -138,6 +147,9 @@ my $Show_Revisions = 0;
# Show tags (symbolic names) in output? # Show tags (symbolic names) in output?
my $Show_Tags = 0; my $Show_Tags = 0;
# Show tags separately in output?
my $Show_Tag_Dates = 0;
# Show branches by symbolic name in output? # Show branches by symbolic name in output?
my $Show_Branches = 0; my $Show_Branches = 0;
@ -176,8 +188,17 @@ my $Max_Checkin_Duration = 180;
# What to put at the front of [each] ChangeLog. # What to put at the front of [each] ChangeLog.
my $ChangeLog_Header = ""; my $ChangeLog_Header = "";
# Whether to enable 'delta' mode, and for what start/end tags.
my $Delta_Mode = 0;
my $Delta_From = "";
my $Delta_To = "";
## end vars set by options. ## end vars set by options.
# latest observed times for the start/end tags in delta mode
my $Delta_StartTime = 0;
my $Delta_EndTime = 0;
# In 'cvs log' output, one long unbroken line of equal signs separates # In 'cvs log' output, one long unbroken line of equal signs separates
# files: # files:
my $file_separator = "=======================================" my $file_separator = "======================================="
@ -187,17 +208,13 @@ my $file_separator = "======================================="
# within a file: # within a file:
my $logmsg_separator = "----------------------------"; my $logmsg_separator = "----------------------------";
############### End globals ############ ############### End globals ############
&parse_options (); &parse_options ();
&derive_change_log (); &derive_change_log ();
### Everything below is subroutine definitions. ### ### Everything below is subroutine definitions. ###
# If accumulating, grab the boundary date from pre-existing ChangeLog. # If accumulating, grab the boundary date from pre-existing ChangeLog.
@ -226,7 +243,6 @@ sub maybe_grab_accumulation_date ()
return $boundary_date; return $boundary_date;
} }
# Fills up a ChangeLog structure in the current directory. # Fills up a ChangeLog structure in the current directory.
sub derive_change_log () sub derive_change_log ()
{ {
@ -241,10 +257,15 @@ sub derive_change_log ()
my $msg_txt; my $msg_txt;
my $detected_file_separator; my $detected_file_separator;
my %tag_date_printed;
# Might be adding to an existing ChangeLog # Might be adding to an existing ChangeLog
my $accumulation_date = &maybe_grab_accumulation_date (); my $accumulation_date = &maybe_grab_accumulation_date ();
if ($accumulation_date) { if ($accumulation_date) {
$Log_Source_Command .= " -d\'>${accumulation_date}\'"; # Insert -d immediately after 'cvs log'
my $Log_Date_Command = "-d\'>${accumulation_date}\'";
$Log_Source_Command =~ s/(^.*log\S*)/$1 $Log_Date_Command/;
&debug ("(adding log msg starting from $accumulation_date)\n");
} }
# We might be expanding usernames # We might be expanding usernames
@ -267,6 +288,7 @@ sub derive_change_log ()
} }
if (! $Input_From_Stdin) { if (! $Input_From_Stdin) {
&debug ("(run \"${Log_Source_Command}\")\n");
open (LOG_SOURCE, "$Log_Source_Command |") open (LOG_SOURCE, "$Log_Source_Command |")
or die "unable to run \"${Log_Source_Command}\""; or die "unable to run \"${Log_Source_Command}\"";
} }
@ -274,10 +296,14 @@ sub derive_change_log ()
open (LOG_SOURCE, "-") or die "unable to open stdin for reading"; open (LOG_SOURCE, "-") or die "unable to open stdin for reading";
} }
binmode LOG_SOURCE;
%usermap = &maybe_read_user_map_file (); %usermap = &maybe_read_user_map_file ();
while (<LOG_SOURCE>) while (<LOG_SOURCE>)
{ {
# Canonicalize line endings
s/\r$//;
# If on a new file and don't see filename, skip until we find it, and # If on a new file and don't see filename, skip until we find it, and
# when we find it, grab it. # when we find it, grab it.
if ((! (defined $file_full_path)) and /^Working file: (.*)/) if ((! (defined $file_full_path)) and /^Working file: (.*)/)
@ -584,8 +610,9 @@ sub derive_change_log ()
# This may someday be used in a more sophisticated calculation # This may someday be used in a more sophisticated calculation
# of what other files are involved in this commit. For now, we # of what other files are involved in this commit. For now, we
# don't use it, because the common-commit-detection algorithm is # don't use it much except for delta mode, because the
# hypothesized to be "good enough" as it stands. # common-commit-detection algorithm is hypothesized to be
# "good enough" as it stands.
$qunk{'time'} = $time; $qunk{'time'} = $time;
# We might be including revision numbers and/or tags and/or # We might be including revision numbers and/or tags and/or
@ -615,6 +642,25 @@ sub derive_change_log ()
if (defined ($symbolic_names{$revision})) { if (defined ($symbolic_names{$revision})) {
$qunk{'tags'} = $symbolic_names{$revision}; $qunk{'tags'} = $symbolic_names{$revision};
delete $symbolic_names{$revision}; delete $symbolic_names{$revision};
# If we're in 'delta' mode, update the latest observed
# times for the beginning and ending tags, and
# when we get around to printing output, we will simply restrict
# ourselves to that timeframe...
if ($Delta_Mode) {
if (($time > $Delta_StartTime) &&
(grep { $_ eq $Delta_From } @{$qunk{'tags'}}))
{
$Delta_StartTime = $time;
}
if (($time > $Delta_EndTime) &&
(grep { $_ eq $Delta_To } @{$qunk{'tags'}}))
{
$Delta_EndTime = $time;
}
}
} }
# Add this file to the list # Add this file to the list
@ -713,13 +759,71 @@ sub derive_change_log ()
print LOG_OUT $ChangeLog_Header; print LOG_OUT $ChangeLog_Header;
if ($XML_Output) { if ($XML_Output) {
print LOG_OUT "<?xml version=\"1.0\"?>\n\n" my $encoding =
. "<changelog xmlns=\"http://www.red-bean.com/xmlns/cvs2cl/\">\n\n"; length $XML_Encoding ? qq'encoding="$XML_Encoding"' : '';
my $version = 'version="1.0"';
my $declaration =
sprintf '<?xml %s?>', join ' ', grep length, $version, $encoding;
my $root =
'<changelog xmlns="http://www.red-bean.com/xmlns/cvs2cl/">';
print LOG_OUT "$declaration\n\n$root\n\n";
} }
foreach my $time (sort {$main::b <=> $main::a} (keys %changelog)) foreach my $time (sort {$main::b <=> $main::a} (keys %changelog))
{ {
next if ($Delta_Mode &&
(($time <= $Delta_StartTime) ||
($time > $Delta_EndTime && $Delta_EndTime)));
# Set up the date/author line.
# kff todo: do some more XML munging here, on the header
# part of the entry:
my ($ignore,$min,$hour,$mday,$mon,$year,$wday)
= $UTC_Times ? gmtime($time) : localtime($time);
# XML output includes everything else, we might as well make
# it always include Day Of Week too, for consistency.
if ($Show_Day_Of_Week or $XML_Output) {
$wday = ("Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday")[$wday];
$wday = ($XML_Output) ? "<weekday>${wday}</weekday>\n" : " $wday";
}
else {
$wday = "";
}
my $authorhash = $changelog{$time}; my $authorhash = $changelog{$time};
if ($Show_Tag_Dates) {
my %tags;
while (my ($author,$mesghash) = each %$authorhash) {
while (my ($msg,$qunk) = each %$mesghash) {
foreach my $qunkref2 (@$qunk) {
if (defined ($$qunkref2{'tags'})) {
foreach my $tag (@{$$qunkref2{'tags'}}) {
$tags{$tag} = 1;
}
}
}
}
}
foreach my $tag (keys %tags) {
if (!defined $tag_date_printed{$tag}) {
$tag_date_printed{$tag} = $time;
if ($XML_Output) {
# NOT YET DONE
}
else {
if ($Show_Times) {
printf LOG_OUT ("%4u-%02u-%02u${wday} %02u:%02u tag %s\n\n",
$year+1900, $mon+1, $mday, $hour, $min, $tag);
} else {
printf LOG_OUT ("%4u-%02u-%02u${wday} tag %s\n\n",
$year+1900, $mon+1, $mday, $tag);
}
}
}
}
}
while (my ($author,$mesghash) = each %$authorhash) while (my ($author,$mesghash) = each %$authorhash)
{ {
# If XML, escape in outer loop to avoid compound quoting: # If XML, escape in outer loop to avoid compound quoting:
@ -727,30 +831,23 @@ sub derive_change_log ()
$author = &xml_escape ($author); $author = &xml_escape ($author);
} }
FOOBIE:
while (my ($msg,$qunklist) = each %$mesghash) while (my ($msg,$qunklist) = each %$mesghash)
{ {
## MJP: 19.xii.01 : Exclude @ignore_tags
for my $ignore_tag (@ignore_tags) {
next FOOBIE
if grep $_ eq $ignore_tag, map(@{$_->{tags}},
grep(defined $_->{tags},
@$qunklist));
}
## MJP: 19.xii.01 : End exclude @ignore_tags
my $files = &pretty_file_list ($qunklist); my $files = &pretty_file_list ($qunklist);
my $header_line; # date and author my $header_line; # date and author
my $body; # see below my $body; # see below
my $wholething; # $header_line + $body my $wholething; # $header_line + $body
# Set up the date/author line.
# kff todo: do some more XML munging here, on the header
# part of the entry:
my ($ignore,$min,$hour,$mday,$mon,$year,$wday)
= $UTC_Times ? gmtime($time) : localtime($time);
# XML output includes everything else, we might as well make
# it always include Day Of Week too, for consistency.
if ($Show_Day_Of_Week or $XML_Output) {
$wday = ("Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday")[$wday];
$wday = ($XML_Output) ? "<weekday>${wday}</weekday>\n" : " $wday";
}
else {
$wday = "";
}
if ($XML_Output) { if ($XML_Output) {
$header_line = $header_line =
sprintf ("<date>%4u-%02u-%02u</date>\n" sprintf ("<date>%4u-%02u-%02u</date>\n"
@ -760,11 +857,19 @@ sub derive_change_log ()
$year+1900, $mon+1, $mday, $hour, $min, $author); $year+1900, $mon+1, $mday, $hour, $min, $author);
} }
else { else {
if ($Show_Times) {
$header_line = $header_line =
sprintf ("%4u-%02u-%02u${wday} %02u:%02u %s\n\n", sprintf ("%4u-%02u-%02u${wday} %02u:%02u %s\n\n",
$year+1900, $mon+1, $mday, $hour, $min, $author); $year+1900, $mon+1, $mday, $hour, $min, $author);
} else {
$header_line =
sprintf ("%4u-%02u-%02u${wday} %s\n\n",
$year+1900, $mon+1, $mday, $author);
}
} }
$Text::Wrap::huge = 'overflow'
if $Text::Wrap::VERSION >= 2001.0130;
# Reshape the body according to user preferences. # Reshape the body according to user preferences.
if ($XML_Output) if ($XML_Output)
{ {
@ -885,7 +990,6 @@ sub derive_change_log ()
} }
} }
sub parse_date_and_author () sub parse_date_and_author ()
{ {
# Parses the date/time and author out of a line like: # Parses the date/time and author out of a line like:
@ -904,7 +1008,6 @@ sub parse_date_and_author ()
return ($time, $author); return ($time, $author);
} }
# Here we take a bunch of qunks and convert them into printed # Here we take a bunch of qunks and convert them into printed
# summary that will include all the information the user asked for. # summary that will include all the information the user asked for.
sub pretty_file_list () sub pretty_file_list ()
@ -926,8 +1029,16 @@ sub pretty_file_list ()
# First, loop over the qunks gathering all the tag/branch names. # First, loop over the qunks gathering all the tag/branch names.
# We'll put them all in non_unanimous_tags, and take out the # We'll put them all in non_unanimous_tags, and take out the
# unanimous ones later. # unanimous ones later.
QUNKREF:
foreach my $qunkref (@qunkrefs) foreach my $qunkref (@qunkrefs)
{ {
## MJP: 19.xii.01 : Exclude @ignore_tags
for my $ignore_tag (@ignore_tags) {
next QUNKREF
if grep $_ eq $ignore_tag, @{$$qunkref{'tags'}};
}
## MJP: 19.xii.01 : End exclude @ignore_tags
# Keep track of whether all the files in this commit were in the # Keep track of whether all the files in this commit were in the
# same directory, and memorize it if so. We can make the output a # same directory, and memorize it if so. We can make the output a
# little more compact by mentioning the directory only once. # little more compact by mentioning the directory only once.
@ -1079,6 +1190,7 @@ sub pretty_file_list ()
if ($Show_Tags && (defined @{$$qunkref{'tags'}})) { if ($Show_Tags && (defined @{$$qunkref{'tags'}})) {
my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}}); my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}});
if (@tags) { if (@tags) {
$beauty .= " (tags: "; $beauty .= " (tags: ";
$beauty .= join (', ', @tags); $beauty .= join (', ', @tags);
@ -1108,6 +1220,8 @@ sub pretty_file_list ()
$beauty .= "]"; $beauty .= "]";
} }
else { else {
# Square brackets are spurious here, since there's no range to
# encapsulate
$beauty .= ".$brevisions[0]"; $beauty .= ".$brevisions[0]";
} }
} }
@ -1166,7 +1280,7 @@ sub pretty_file_list ()
if ($Show_Tags && %unanimous_tags) if ($Show_Tags && %unanimous_tags)
{ {
$beauty .= " (utags: "; $beauty .= " (utags: ";
$beauty .= join (', ', keys (%unanimous_tags)); $beauty .= join (', ', sort keys (%unanimous_tags));
$beauty .= ")"; $beauty .= ")";
} }
@ -1177,7 +1291,6 @@ sub pretty_file_list ()
return $beauty; return $beauty;
} }
sub common_path_prefix () sub common_path_prefix ()
{ {
my $path1 = shift; my $path1 = shift;
@ -1204,14 +1317,13 @@ sub common_path_prefix ()
last if ($accum1 eq $dir1); last if ($accum1 eq $dir1);
my ($tmp1) = split (/\//, (substr ($dir1, length ($accum1)))); my ($tmp1) = split (/\//, (substr ($dir1, length ($accum1))));
my ($tmp2) = split (/\//, (substr ($dir2, length ($accum2)))); my ($tmp2) = split (/\//, (substr ($dir2, length ($accum2))));
$accum1 .= "$tmp1/" if ((defined ($tmp1)) and $tmp1); $accum1 .= "$tmp1/" if (defined $tmp1 and $tmp1 ne '');
$accum2 .= "$tmp2/" if ((defined ($tmp2)) and $tmp2); $accum2 .= "$tmp2/" if (defined $tmp2 and $tmp2 ne '');
} }
return $last_common_prefix; return $last_common_prefix;
} }
sub preprocess_msg_text () sub preprocess_msg_text ()
{ {
my $text = shift; my $text = shift;
@ -1244,7 +1356,6 @@ sub preprocess_msg_text ()
return $text; return $text;
} }
sub last_line_len () sub last_line_len ()
{ {
my $files_list = shift; my $files_list = shift;
@ -1253,7 +1364,6 @@ sub last_line_len ()
return length ($last_line); return length ($last_line);
} }
# A custom wrap function, sensitive to some common constructs used in # A custom wrap function, sensitive to some common constructs used in
# log entries. # log entries.
sub wrap_log_entry () sub wrap_log_entry ()
@ -1436,7 +1546,6 @@ sub wrap_log_entry ()
return $wrapped_text; return $wrapped_text;
} }
sub xml_escape () sub xml_escape ()
{ {
my $txt = shift; my $txt = shift;
@ -1446,7 +1555,6 @@ sub xml_escape ()
return $txt; return $txt;
} }
sub maybe_read_user_map_file () sub maybe_read_user_map_file ()
{ {
my %expansions; my %expansions;
@ -1491,7 +1599,6 @@ sub maybe_read_user_map_file ()
return %expansions; return %expansions;
} }
sub parse_options () sub parse_options ()
{ {
# Check this internally before setting the global variable. # Check this internally before setting the global variable.
@ -1506,6 +1613,16 @@ sub parse_options ()
if ($arg =~ /^-h$|^-help$|^--help$|^--usage$|^-?$/) { if ($arg =~ /^-h$|^-help$|^--help$|^--usage$|^-?$/) {
$Print_Usage = 1; $Print_Usage = 1;
} }
elsif ($arg =~ /^--delta$/) {
my $narg = shift(@ARGV) || die "$arg needs argument.\n";
if ($narg =~ /^([A-Za-z][A-Za-z0-9_\-]*):([A-Za-z][A-Za-z0-9_\-]*)$/) {
$Delta_From = $1;
$Delta_To = $2;
$Delta_Mode = 1;
} else {
die "--delta FROM_TAG:TO_TAG is what you meant to say.\n";
}
}
elsif ($arg =~ /^--debug$/) { # unadvertised option, heh elsif ($arg =~ /^--debug$/) { # unadvertised option, heh
$Debug = 1; $Debug = 1;
} }
@ -1536,7 +1653,7 @@ sub parse_options ()
$User_Map_File = $narg; $User_Map_File = $narg;
} }
elsif ($arg =~ /^-W$|^--window$/) { elsif ($arg =~ /^-W$|^--window$/) {
my $narg = shift (@ARGV) || die "$arg needs argument.\n"; defined(my $narg = shift (@ARGV)) || die "$arg needs argument.\n";
$Max_Checkin_Duration = $narg; $Max_Checkin_Duration = $narg;
} }
elsif ($arg =~ /^-I$|^--ignore$/) { elsif ($arg =~ /^-I$|^--ignore$/) {
@ -1574,12 +1691,18 @@ sub parse_options ()
elsif ($arg =~ /^-w$|^--day-of-week$/) { elsif ($arg =~ /^-w$|^--day-of-week$/) {
$Show_Day_Of_Week = 1; $Show_Day_Of_Week = 1;
} }
elsif ($arg =~ /^--no-times$/) {
$Show_Times = 0;
}
elsif ($arg =~ /^-r$|^--revisions$/) { elsif ($arg =~ /^-r$|^--revisions$/) {
$Show_Revisions = 1; $Show_Revisions = 1;
} }
elsif ($arg =~ /^-t$|^--tags$/) { elsif ($arg =~ /^-t$|^--tags$/) {
$Show_Tags = 1; $Show_Tags = 1;
} }
elsif ($arg =~ /^-T$|^--tagdates$/) {
$Show_Tag_Dates = 1;
}
elsif ($arg =~ /^-b$|^--branches$/) { elsif ($arg =~ /^-b$|^--branches$/) {
$Show_Branches = 1; $Show_Branches = 1;
} }
@ -1597,6 +1720,10 @@ sub parse_options ()
$ChangeLog_Header = ""; $ChangeLog_Header = "";
} }
} }
elsif ($arg =~ /^--xml-encoding$/) {
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
$XML_Encoding = $narg ;
}
elsif ($arg =~ /^--xml$/) { elsif ($arg =~ /^--xml$/) {
$XML_Output = 1; $XML_Output = 1;
} }
@ -1604,9 +1731,14 @@ sub parse_options ()
$Hide_Filenames = 1; $Hide_Filenames = 1;
$After_Header = ""; $After_Header = "";
} }
elsif ($arg =~ /^--ignore-tag$/ ) {
die "$arg needs argument.\n"
unless @ARGV;
push @ignore_tags, shift @ARGV;
}
else { else {
# Just add a filename as argument to the log command # Just add a filename as argument to the log command
$Log_Source_Command .= " $arg"; $Log_Source_Command .= " '$arg'";
} }
} }
@ -1649,7 +1781,6 @@ sub parse_options ()
} }
} }
sub slurp_file () sub slurp_file ()
{ {
my $filename = shift || die ("no filename passed to slurp_file()"); my $filename = shift || die ("no filename passed to slurp_file()");
@ -1664,7 +1795,6 @@ sub slurp_file ()
return $retstr; return $retstr;
} }
sub debug () sub debug ()
{ {
if ($Debug) { if ($Debug) {
@ -1673,13 +1803,11 @@ sub debug ()
} }
} }
sub version () sub version ()
{ {
print "cvs2cl.pl version ${VERSION}; distributed under the GNU GPL.\n"; print "cvs2cl.pl version ${VERSION}; distributed under the GNU GPL.\n";
} }
sub usage () sub usage ()
{ {
&version (); &version ();
@ -1730,6 +1858,7 @@ Options/Arguments:
-r, --revisions Show revision numbers in output -r, --revisions Show revision numbers in output
-b, --branches Show branch names in revisions when possible -b, --branches Show branch names in revisions when possible
-t, --tags Show tags (symbolic names) in output -t, --tags Show tags (symbolic names) in output
-T, --tagdates Show tags in output on their first occurance
--stdin Read from stdin, don't run cvs log --stdin Read from stdin, don't run cvs log
--stdout Output to stdout not to ChangeLog --stdout Output to stdout not to ChangeLog
-d, --distributed Put ChangeLogs in subdirs -d, --distributed Put ChangeLogs in subdirs
@ -1746,8 +1875,10 @@ Options/Arguments:
--gmt, --utc Show times in GMT/UTC instead of local time --gmt, --utc Show times in GMT/UTC instead of local time
--accum Add to an existing ChangeLog (incompat w/ --xml) --accum Add to an existing ChangeLog (incompat w/ --xml)
-w, --day-of-week Show day of week -w, --day-of-week Show day of week
--no-times Don't show times in output
--header FILE Get ChangeLog header from FILE ("-" means stdin) --header FILE Get ChangeLog header from FILE ("-" means stdin)
--xml Output XML instead of ChangeLog format --xml Output XML instead of ChangeLog format
--xml-encoding ENCODING Insert encoding clause in XML header
--hide-filenames Don't show filenames (ignored for XML output) --hide-filenames Don't show filenames (ignored for XML output)
-P, --prune Don't show empty log messages -P, --prune Don't show empty log messages
-g OPTS, --global-opts OPTS Invoke like this "cvs OPTS log ..." -g OPTS, --global-opts OPTS Invoke like this "cvs OPTS log ..."
@ -1808,7 +1939,6 @@ Version_Control/CVS
=cut =cut
-*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*- -*-
Note about a bug-slash-opportunity: Note about a bug-slash-opportunity:
@ -1831,7 +1961,6 @@ reveals it:
See? When the bug happens, we'll get the line of equal signs below See? When the bug happens, we'll get the line of equal signs below
this paragraph, even though it should be above."; this paragraph, even though it should be above.";
# Print out the test text with no wrapping: # Print out the test text with no wrapping:
print "$test_text"; print "$test_text";
print "\n"; print "\n";
@ -1863,3 +1992,4 @@ And how about:
Optionally, when encounter a line pre-indented by same as previous Optionally, when encounter a line pre-indented by same as previous
line, then strip the newline and refill, but indent by the same. line, then strip the newline and refill, but indent by the same.
Yeah... Yeah...