package VCP::Filter ;
=head1 NAME
VCP::Filter - A base class for filters
=head1 SYNOPSIS
use VCP::Filter;
@ISA = qw( VCP::Filter );
...
=head1 DESCRIPTION
A VPC::Filter is a VCP::Plugin that is placed between the source
and the destination and allows the stream of revisions to be altered.
For instance, the Map: option in vcp files is implemented by
VCP::Filter::Map
By default a filter is a pass-through.
=cut
$VERSION = 0.1 ;
use strict;
use Carp ();
use VCP::Debug qw( :debug );
use VCP::Logger qw( lg BUG );
use VCP::ConfigFileUtils qw( config_file_quote );
use base "VCP::Plugin";
use fields (
'PRETTY_PRINTED_RULES_LIST_LINES',
## The list of rules that was parsed so that it
## may be regurgitated in to a config file
'DEST', ## Points to the next filter.
);
sub dest {
my VCP::Filter $self = shift;
$self->{DEST} = shift if @_;
return $self->{DEST};
}
###############################################################################
=head1 SUBCLASSING
This class uses the fields pragma, so you'll need to use base and
possibly fields in any subclasses.
=over
=item parse_rules_list
Used in VCP::Filter::*map and VCP::Filter::*edit to parse lists of rules
where every rule is a set of N "words". The value of N is computed from
the number of labels passed in and the labels are used when printing an
error message:
@rules = $self->parse_rules( $options, "Pattern", "Replacement" );
=cut
sub parse_rules_list {
my $self = shift;
my $options = shift;
my $default = @_ && ref $_[-1] ? pop : [];
my @labels = @_;
my $expression_count = @labels;
BUG "No expression labels passed" unless $expression_count;
BUG "No options " unless $options;
my @rule;
my $rules;
while ( @$options ) {
my $v = shift @$options;
last if $v eq "--";
push @rule, $v;
push @$rules, [splice @rule] if @rule == $expression_count;
}
push @$rules, \@rule if @rule;
$rules = $default unless $rules || @rule;
## Format pretty rules for the log, error messages, or later output
## to config file.
my @out = map [
map config_file_quote( $_ ), @$_
], @$rules;
my @w;
for ( \@labels, @out ) {
for my $i (0..$#$_) {
$w[$i] = length $_->[$i]
if ! defined $w[$i] || length $_->[$i] > $w[$i];
}
}
( my $filter_type = ref $self ) =~ s/.*://;
my $format = join " ", map "%-${_}s", @w;
my @msg = (
sprintf( "## $format\n", @labels ),
sprintf( "## $format\n", map "=" x $_, @w ),
map(
sprintf( " $format\n", map defined $_ ? $_ : "", @$_ ),
@out
)
);
die "incomplete rule in $filter_type:\n\n", @msg, "\n" if @rule;
lg "$filter_type rules:\n", @msg;
## Take a copy in case the caller decides to alter the rules.
$self->{PRETTY_PRINTED_RULES_LIST_LINES} = \@msg;
return $rules;
}
=item filter_name
Returns the StudlyCaps version of the filter name. By default, assumes
a single work name and uses ucfirst on it. Filters like StringEdit should
overload this to be more creative and typgraphically appealing (heh).
=cut
sub filter_name {
my VCP::Filter $self = shift;
my ( $filtername ) = ( ref( $self ) =~ /\AVCP::Filter::(\w+)\z/ )
or BUG "Can't parse filter name from ", ref $self;
return ucfirst $filtername;
}
=item config_file_section_as_string
=cut
sub config_file_section_as_string {
my VCP::Filter $self = shift;
my $section_name = $self->filter_name;
my @body;
return join "",
"$section_name:\n",
$self->{PRETTY_PRINTED_RULES_LIST_LINES}
? map "\t$_", @{$self->{PRETTY_PRINTED_RULES_LIST_LINES}}
: (),
"\n";
}
=item last_rev_in_filebranch
(passthru; see L<VCP::Dest|VCP::Dest>)
=cut
sub last_rev_in_filebranch {
shift->dest->last_rev_in_filebranch( @_ );
}
=item backfill
(passthru; see L<VCP::Dest|VCP::Dest>)
=cut
sub backfill {
shift->dest->backfill( @_ );
}
=item is_sort_filter
Sort filters should return a 1 in this method, see L<VCP::Plugin> for details.
=cut
## inherited
=item handle_header
(passthru)
=cut
sub handle_header {
shift->dest->handle_header( @_ );
}
=item handle_rev
(passthru)
=cut
sub handle_rev {
shift->dest->handle_rev( @_ );
}
=item handle_footer
(passthru)
=cut
sub handle_footer {
shift->dest->handle_footer( @_ );
}
=back
=head1 COPYRIGHT
Copyright 2000, Perforce Software, Inc. All Rights Reserved.
This module and the VCP package are licensed according to the terms given in
the file LICENSE accompanying this distribution, a copy of which is included in
L<vcp>.
=head1 AUTHOR
Barrie Slaymaker <barries@slaysys.com>
=cut
1
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #18 | 4501 | Barrie Slaymaker | - improved config file formatting | ||
| #17 | 4483 | Barrie Slaymaker | - calls to skip_rev() are summarized to STDOUT | ||
| #16 | 4149 | Barrie Slaymaker | - VCP::Filters don't blow up when emitting docs any more | ||
| #15 | 4021 | Barrie Slaymaker |
- Remove all phashes and all base & fields pragmas - Work around SWASHGET error |
||
| #14 | 3855 | Barrie Slaymaker |
- vcp scan, filter, transfer basically functional - Need more work in re: storage format, etc, but functional |
||
| #13 | 3706 | Barrie Slaymaker | - VCP gives some indication of output progress (need more) | ||
| #12 | 3491 | Barrie Slaymaker | - All sections are now documented in generated config files | ||
| #11 | 3489 | Barrie Slaymaker | - Document options emitted to .vcp files. | ||
| #10 | 3467 | Barrie Slaymaker |
- Config file tokens are now quoted using (the new) VCP::ConfigFileUtils::config_file_quote(), which only quotes if whitespace is detected (for now). - t/61addlabels.t now tests config file section building a bit. |
||
| #9 | 3465 | Barrie Slaymaker | - VCP::Filters can now dump they're sections. | ||
| #8 | 3155 | Barrie Slaymaker |
Convert to logging using VCP::Logger to reduce stdout/err spew. Simplify & speed up debugging quite a bit. Provide more verbose information in logs. Print to STDERR progress reports to keep users from wondering what's going on. Breaks test; halfway through upgrading run3() to an inline function for speed and for VCP specific features. |
||
| #7 | 3133 | Barrie Slaymaker |
Make destinations call back to sources to check out files to simplify the architecture (is_metadata_only() no longer needed) and make it more optimizable (checkouts can be batched). |
||
| #6 | 3120 | Barrie Slaymaker | Move changeset aggregation in to its own filter. | ||
| #5 | 3100 | Barrie Slaymaker | Fix annoying debug-mode-only bug in VCP::Filter | ||
| #4 | 3091 | Barrie Slaymaker |
Factor out rules list parsing; it's useful elsewhere and should not have been copy & edited in to two files in the first place. |
||
| #3 | 2800 | Barrie Slaymaker | Get --continue working in cvs->foo transfers. | ||
| #2 | 2453 | John Fetkovich |
removed compilation of revml. will be making that a separate executable. |
||
| #1 | 2301 | Barrie Slaymaker | A chain of plugins instead of source & dest |