[p4] Find old dead code?
Peter Stephenson
pws at csr.com
Tue Oct 30 03:16:19 PDT 2007
Peter Stephenson wrote:
> The attached Perl script
Hmm. I specifically looked to see if my mailer had got the details in
the attachment correct and it still looks like it's decided not to send it.
It's not that long: here it is inline with some lines wrapped, although
some mailers aggresively wreck plain text anyway.
#!/usr/bin/perl -w -
=head1 NAME
p4annotate.pl - Front end to `p4 annotate' for customizing the annotation.
=head1 SYNOPSIS
p4annotate.pl -f "%r %c" file.c
=head1 DESCRIPTION
F<p4annotate.pl> I<file> has the same basic effect as C<p4 annotate> I<file>,
but you can customize the annotation using the option C<-f>. Note that
the global options to C<p4> are not currently handled, so that you
will need to set environment variables (C<P4CLIENT>, etc.) appropriately.
The options C<-a> and C<-q> work as expected, so the only
differences are the additional options:
=over
=item C<-f> I<fmt>
I<fmt> is a format string containing printf-style
escapes which will be replaced by information about each version.
The escapes are:
=over
=item C<%r>
The revision number.
=item C<%c>
The change which brought about the revision.
=item C<%T>
The type of the change --- edit, integrate, etc.
=item C<%d>
The date of the change.
=item C<%t>
The time of the change (not including the date).
=item C<%u>
The Perforce user who submitted the change.
=item C<%C>
The user's client which submitted the change.
=item C<%f>
The type of the file after the change.
=item C<%m>
The start of the change's description.
=back
Hence, for example, the annotation given by p4 annotate itself is
represented by "%r". The default is "%r %u", i.e. the revision augmented
by the user. This agrees with the research which led to the corresponding
command in Subversion being called `svn blame'.
=item C<-r>
Raw: don't put the colon and space after the annotation.
=back
=cut
use strict;
use vars qw($join $opt_a $opt_f $opt_q $opt_r $warn @p4_args);
$opt_f = "%c %u";
$opt_a = $opt_q = $opt_r = $warn = 0;
use Getopt::Std;
getopts('af:qr') or exit 1;
@p4_args = ('-a') if $opt_a;
$join = $opt_r ? "" : ": ";
# Do substitution on $opt_f using the hash ref passed.
sub subst ($) {
my $hashref = shift;
my $sofar = '';
my $fmt = $opt_f;
while ($fmt =~ /%(.)/) {
$sofar .= $`;
$fmt = $';
if ($1 eq '%') {
$sofar .= '%';
} else {
my $repl = $hashref->{$1};
$repl = "%$1" unless defined $repl;
$sofar .= $repl;
}
}
$sofar . $fmt;
}
sub get_filelog($$) {
# Get the filelog for the specified file/revision.
# Only remember changes from revision to revision, ignore
# integrations to other branches etc.
my $filespec = shift;
my $hashref = shift;
my $pid = open(PIPEINFO, "-|");
die "Failed to fork: $!\n" unless defined $pid;
exec "p4", "filelog", "-t", $filespec if $pid == 0;
# avoid long lines
my $pat = '^\.\.\. \#(\d+) change (\d+) (\S+)' .
' on (\S+) (\S+) by (\S+)\@(\S+) \((\S+)\) ' . "'(.*)'\$";
while (<PIPEINFO>) {
next unless /$pat/o;
$hashref->{$1} = subst(
{
r => $1,
c => $2,
T => $3,
d => $4,
t => $5,
u => $6,
C => $7,
f => $8,
"m" => $9
});
}
close PIPEINFO;
die "Subcommand failed" if $? >> 8;
}
while (@ARGV) {
my $spec = shift;
my $filespec;
my %versioninfo;
my $pid = open(PIPEIT, "-|");
my $curver;
my $curspec;
die "Failed to fork: $!\n" unless defined $pid;
exec "p4", "annotate", @p4_args, "$spec" if $pid == 0;
while (<PIPEIT>) {
if (m%^//.*\#\d+%) {
$filespec = $&;
%versioninfo = ();
$curver = undef;
print unless $opt_q;
} elsif (/^(\d+): /) {
# use cache if possible
if (defined($curver) && $curver == $1) {
print "$curspec$join$'";
} else {
$curver = $1;
my $line = $';
get_filelog($filespec, \%versioninfo) unless %versioninfo;
my $curinfo = $versioninfo{$curver};
if (defined $curinfo) {
$curspec = $curinfo;
} else {
$curspec = $curver;
}
print "$curspec$join$line";
}
} else {
$warn++;
print;
}
}
close PIPEIT;
die "Subcommand failed" if $? >> 8;
}
warn "Some lines could not be parsed properly.\n" if $warn;
exit 0;
# end
More information about the perforce-user
mailing list