New upstream version.

committer: mfx <mfx> 1049683526 +0000
This commit is contained in:
Markus F.X.J. Oberhumer 2003-04-07 02:45:26 +00:00
parent eeb1dfaf8f
commit 30915862cd

View File

@ -9,14 +9,15 @@ exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*-
### ###
##############################################################
## $Revision: 2.46 $
## $Date: 2003/01/18 13:14:52 $
## $Revision: 2.47 $
## $Date: 2003/03/10 16:08:30 $
## $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.
##
## (Extensively hacked on by Melissa O'Neill <oneill@cs.sfu.ca>.)
## (Gecos hacking by Robin Johnson <robbat2@orbis-terrarum.net>.)
##
## cvs2cl.pl is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@ -38,6 +39,7 @@ use strict;
use Text::Wrap;
use Time::Local;
use File::Basename;
use User::pwent;
# The Plan:
@ -78,7 +80,7 @@ use File::Basename;
my $Log_Source_Command = "cvs log";
# In case we have to print it out:
my $VERSION = '$Revision: 2.46 $';
my $VERSION = '$Revision: 2.47 $';
$VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/;
## Vars set by options:
@ -105,6 +107,15 @@ my $Cumulative = 0;
# Expand usernames to email addresses based on a map file?
my $User_Map_File = "";
# Output log in chronological order? [default is reverse chronological order]
my $Chronological_Order = 0;
# Grab user details via gecos
my $Gecos = 0;
# User domain for gecos email addresses
my $Domain = "";
# Output to a file or to stdout?
my $Output_To_Stdout = 0;
@ -112,7 +123,10 @@ my $Output_To_Stdout = 0;
my $Prune_Empty_Msgs = 0;
# Tags of which not to output
my @ignore_tags;
my %ignore_tags;
# Show only revisions with Tags
my %show_tags;
# Don't call Text::Wrap on the body of the message
my $No_Wrap = 0;
@ -178,6 +192,9 @@ my $Input_From_Stdin = 0;
# Don't show filenames in output.
my $Hide_Filenames = 0;
# Don't shorten directory names from filenames.
my $Common_Dir = 1;
# Max checkin duration. CVS checkin is not atomic, so we may have checkin
# times that span a range of time. We assume that checkins will last no
# longer than $Max_Checkin_Duration seconds, and that similarly, no
@ -477,6 +494,22 @@ sub derive_change_log ()
($time, $author) = &parse_date_and_author ($_);
if (defined ($usermap{$author}) and $usermap{$author}) {
$author = $usermap{$author};
} elsif($Domain ne "" or $Gecos == 1) {
my $email = $author;
if($Domain ne "") {
$email = $author."@".$Domain;
}
my $pw = getpwnam($author);
my $fullname;
my $office;
my $workphone;
my $homephone;
for (($fullname, $office, $workphone, $homephone) = split /\s*,\s*/, $pw->gecos) {
s/&/ucfirst(lc($pw->name))/ge;
}
if($fullname ne "") {
$author = $fullname . " <" . $email . ">";
}
}
}
else {
@ -769,7 +802,13 @@ sub derive_change_log ()
print LOG_OUT "$declaration\n\n$root\n\n";
}
foreach my $time (sort {$main::b <=> $main::a} (keys %changelog))
my @key_list = ();
if($Chronological_Order) {
@key_list = sort {$main::a <=> $main::b} (keys %changelog);
} else {
@key_list = sort {$main::b <=> $main::a} (keys %changelog);
}
foreach my $time (@key_list)
{
next if ($Delta_Mode &&
(($time <= $Delta_StartTime) ||
@ -832,17 +871,28 @@ sub derive_change_log ()
}
FOOBIE:
while (my ($msg,$qunklist) = each %$mesghash)
# We sort here to enable predictable ordering for the testing porpoises
for my $msg (sort keys %$mesghash)
{
my $qunklist = $mesghash->{$msg};
## MJP: 19.xii.01 : Exclude @ignore_tags
for my $ignore_tag (@ignore_tags) {
for my $ignore_tag (keys %ignore_tags) {
next FOOBIE
if grep $_ eq $ignore_tag, map(@{$_->{tags}},
if grep($_ eq $ignore_tag, map(@{$_->{tags}},
grep(defined $_->{tags},
@$qunklist));
@$qunklist)));
}
## MJP: 19.xii.01 : End exclude @ignore_tags
# show only files with tag --show-tag $show_tag
if ( keys %show_tags ) {
next FOOBIE
if !grep(exists $show_tags{$_}, map(@{$_->{tags}},
grep(defined $_->{tags},
@$qunklist)));
}
my $files = &pretty_file_list ($qunklist);
my $header_line; # date and author
my $body; # see below
@ -1017,7 +1067,15 @@ sub pretty_file_list ()
}
my $qunksref = shift;
my @qunkrefs = @$qunksref;
my @qunkrefs =
grep +((! exists $_->{'tags'} or
! grep exists $ignore_tags{$_}, @{$_->{'tags'}}) and
(! keys %show_tags or
(exists $_->{'tags'} and
grep exists $show_tags{$_}, @{$_->{'tags'}}))
),
@$qunksref;
my @filenames;
my $beauty = ""; # The accumulating header string for this entry.
my %non_unanimous_tags; # Tags found in a proper subset of qunks
@ -1032,17 +1090,10 @@ sub pretty_file_list ()
QUNKREF:
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
# same directory, and memorize it if so. We can make the output a
# little more compact by mentioning the directory only once.
if ((scalar (@qunkrefs)) > 1)
if ($Common_Dir && (scalar (@qunkrefs)) > 1)
{
if (! (defined ($common_dir)))
{
@ -1232,17 +1283,12 @@ sub pretty_file_list ()
# Okay; any qunks that were done according to branch are taken care
# of, and marked as printed. Now print everyone else.
my %fileinfo_printed;
foreach my $qunkref (@qunkrefs)
{
next if (defined ($$qunkref{'printed'})); # skip if already printed
if ($fbegun) {
$beauty .= ", ";
}
else {
$fbegun = 1;
}
$beauty .= substr ($$qunkref{'filename'}, length ($common_dir));
my $b = substr ($$qunkref{'filename'}, length ($common_dir));
# todo: Shlomo's change was this:
# $beauty .= substr ($$qunkref{'filename'},
# (($common_dir eq "./") ? "" : length ($common_dir)));
@ -1254,26 +1300,35 @@ sub pretty_file_list ()
if ($Show_Revisions) {
$started_addendum = 1;
$beauty .= " (";
$beauty .= "$$qunkref{'revision'}";
$b .= " (";
$b .= "$$qunkref{'revision'}";
}
if ($Show_Tags && (defined $$qunkref{'tags'})) {
my @tags = grep ($non_unanimous_tags{$_}, @{$$qunkref{'tags'}});
if ((scalar (@tags)) > 0) {
if ($started_addendum) {
$beauty .= ", ";
$b .= ", ";
}
else {
$beauty .= " (tags: ";
$b .= " (tags: ";
}
$beauty .= join (', ', @tags);
$b .= join (', ', @tags);
$started_addendum = 1;
}
}
if ($started_addendum) {
$beauty .= ")";
$b .= ")";
}
}
unless ( exists $fileinfo_printed{$b} ) {
if ($fbegun) {
$beauty .= ", ";
} else {
$fbegun = 1;
}
$beauty .= $b, $fileinfo_printed{$b} = 1;
}
}
# Unanimous tags always come last.
@ -1591,7 +1646,7 @@ sub maybe_read_user_map_file ()
else {
$expansions{$username} = $expansion;
}
}
} # fi ($User_Map_File)
close (MAPFILE);
}
@ -1648,14 +1703,28 @@ sub parse_options ()
elsif ($arg =~ /^--fsf$/) {
$FSF_Style = 1;
}
elsif ($arg =~ /^--FSF$/) {
$Show_Times = 0;
$Common_Dir = 0;
}
elsif ($arg =~ /^-U$|^--usermap$/) {
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
$User_Map_File = $narg;
}
elsif ($arg =~ /^--gecos$/) {
$Gecos = 1;
}
elsif ($arg =~ /^--domain$/) {
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
$Domain = $narg;
}
elsif ($arg =~ /^-W$|^--window$/) {
defined(my $narg = shift (@ARGV)) || die "$arg needs argument.\n";
$Max_Checkin_Duration = $narg;
}
elsif ($arg =~ /^--chrono$/) {
$Chronological_Order = 1;
}
elsif ($arg =~ /^-I$|^--ignore$/) {
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
push (@Ignore_Files, $narg);
@ -1731,10 +1800,18 @@ sub parse_options ()
$Hide_Filenames = 1;
$After_Header = "";
}
elsif ($arg =~ /^--no-common-dir$/) {
$Common_Dir = 0;
}
elsif ($arg =~ /^--ignore-tag$/ ) {
die "$arg needs argument.\n"
unless @ARGV;
push @ignore_tags, shift @ARGV;
$ignore_tags{shift @ARGV} = 1;
}
elsif ($arg =~ /^--show-tag$/ ) {
die "$arg needs argument.\n"
unless @ARGV;
$show_tags{shift @ARGV} = 1;
}
else {
# Just add a filename as argument to the log command
@ -1864,8 +1941,11 @@ Options/Arguments:
-d, --distributed Put ChangeLogs in subdirs
-f FILE, --file FILE Write to FILE instead of "ChangeLog"
--fsf Use this if log data is in FSF ChangeLog style
--FSF Attempt strict FSF-standard compatible output
-W SECS, --window SECS Window of time within which log entries unify
-U UFILE, --usermap UFILE Expand usernames to email addresses from UFILE
--domain DOMAIN Domain to build email addresses from
--gecos Get user information from GECOS data
-R REGEXP, --regexp REGEXP Include only entries that match REGEXP
-I REGEXP, --ignore REGEXP Ignore files whose names match REGEXP
-C, --case-insensitive Any regexp matching is done case-insensitively
@ -1880,7 +1960,20 @@ Options/Arguments:
--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)
--no-common-dir Don't shorten directory names from filenames.
-P, --prune Don't show empty log messages
--ignore-tag TAG Ignore individual changes that are associated
with a given tag. May be repeated, if so,
changes that are associated with any of the
given tags are ignored.
--show-tag TAG Log only individual changes that are associated
with a given tag. May be repeated, if so,
changes that are associated with any of the
given tags are logged.
--delta FROM_TAG:TO_TAG Attempt a delta between two tags (since FROM_TAG
up to & including TO_TAG). The algorithm is a
simple date-based one (this is a *hard* problem)
so results are imperfect
-g OPTS, --global-opts OPTS Invoke like this "cvs OPTS log ..."
-l OPTS, --log-opts OPTS Invoke like this "cvs ... log OPTS"
FILE1 [FILE2 ...] Show only log information for the named FILE(s)