1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
package VCP::ConfigFileUtils;
=head1 NAME
VCP::ConfigFileUtils - utilities used to parse or create vcp config files
=head1 SYNOPSIS
use VCP::ConfigFileUtils qw( parse_config_file write_config_file );
=head1 DESCRIPTION
=cut
@EXPORT_OK = qw(
config_file_quote
parse_config_file
write_config_file
);
@ISA = qw( Exporter );
use Exporter;
use strict;
use VCP::Debug qw( :debug );
use VCP::Logger qw( pr );
use VCP::Utils qw( start_dir_rel2abs );
=head1 FUNCTIONS
=over
=item config_file_quote
Adds quotation marks if a config file entry needs to be quoted.
LIMITATION: does not escape quotes in a string, can't figure out how to
do that for p4.
=cut
sub config_file_quote {
my @parms = ref $_[0] eq "ARRAY" ? @{$_[0]} : @_;
return join " ", map {
defined $_
? m{\s}
? qq{"$_"}
: $_
: "(((undef)))";
} @parms;
}
=item parse_config_file
parse_config_file( $fn );
parse_config_file( $fn, $may_not_be_a_config_file );
Reads a configuration file and returns a list of
(section name, \@section_tokens).
=cut
sub parse_config_file {
## NOTE: This should *not* be used to sniff files from STDIN because
## they can be huge and we don't have a mechanism that allows us to
## read a chunk, make a decision, then relace the chunk for the XML
## parser if it looks like revml. Thus, if it comes on STDIN, the
## config file must be specced with a "vcp:-" CLI param.
my ( $fn, $may_not_be_a_config_file ) = @_;
my $source_desc = $fn eq "-" ? "stdin" : $fn;
$fn = start_dir_rel2abs $fn unless $fn eq "-";
$may_not_be_a_config_file = 0 if $fn =~ /\.vcp\z/i;
if ( $fn eq "-" ) {
## Note: this can only occur if vcp:- was specified, not
## if "-" was specified (see the $arg ne "-" above).
*VCPSPECFILE = \*STDIN;
}
else {
open VCPSPECFILE, "<$fn" or die "$!: $fn\n";
}
my $vcp = "";
my $c;
do {
$c = read VCPSPECFILE, $vcp, 1_000_000, length $vcp;
die "$! while reading $fn\n"
unless defined $c;
} while ( $c );
close VCPSPECFILE;
die "IS REVML FILE\n"
if $may_not_be_a_config_file && $vcp =~ m{<revml[^>]*>.*</revml>}m;
require VCP::Utils::p4;
my @vcp_spec = VCP::Utils::p4->parse_p4_form( $vcp );
undef $vcp;
require Text::ParseWords;
my @out;
## The Options and Dest/Destination tags are special: Options must come
## first and Dest must come last.
my $options_value;
my $dest_value;
while ( @vcp_spec ) {
my ( $tag, $value ) = ( lc shift @vcp_spec, shift @vcp_spec );
for ( $value ) {
s/\A\s+//;
s/\s+\z//;
}
## use quotewords and tell it to keep the backslashes
## because backslashes are important on Win32.
$value = [ map {
s{^(['"]?)(.*)\1}{$2};
s{""}{"}; ## This is not p4-ish, don't think there's a p4-ish way
$_;
} Text::ParseWords::quotewords( '\s+', 1, $value )
];
if ( $tag eq "options" ) {
die "vcp: two Options entries found in config file\n"
if $options_value;
$options_value = $value;
}
elsif ( $tag eq "dest" || $tag eq "destination" ) {
die "vcp: two Destination entries found in config file\n"
if $dest_value;
$dest_value = $value;
}
elsif ( $tag eq "source" && @out ) {
die "vcp: Source must come before filter sections in config file\n";
}
else {
push @out, $tag, $value;
}
}
unshift @out, "options", $options_value if $options_value;
push @out, "dest", $dest_value if $dest_value;
if ( debugging ) {
require Data::Dumper;
debug( Data::Dumper->Dump( [ \@out ], [ $source_desc ] ) );
}
return \@out;
}
=item write_config_file
write_config_file( $filename, @plugins );
=cut
sub write_config_file {
my ( $fn, @plugins ) = @_;
$fn = start_dir_rel2abs $fn unless $fn eq "-";
pr "vcp: writing config file to $fn\n";
open CONFIG_FILE, ">$fn" or die "$!: $fn\n";
## Put dest after source.
if ( @plugins > 2 && $plugins[-1]->isa( "VCP::Dest" ) ) {
my $dest = pop @plugins;
splice @plugins, 1, 0, $dest;
}
for ( @plugins ) {
print CONFIG_FILE $_->config_file_section_as_string
or die "$!: $fn\n";
}
close CONFIG_FILE or die "$!: $fn\n";
}
=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>.
=cut
1 ;
|