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
|
package VCP::Utils;
=head1 NAME
VCP::Utils - utilities used within VCP's modules.
=head1 SYNOPSIS
use VCP::Utils qw( shell_quote );
=head1 DESCRIPTION
A mix-in class providing methods shared by VCP::Source::cvs and VCP::Dest::cvs,
mostly wrappers for calling the cvs command.
=cut
@EXPORT_OK = qw(
empty
escape_filename
is_win32
program_name
start_dir_rel2abs
shell_quote
start_dir
xchdir
);
@ISA = qw( Exporter );
use Exporter;
use Cwd;
use strict;
use File::Spec;
use File::Basename qw( basename );
use VCP::Logger qw( lg program_name BUG );
use constant is_win32 => $^O =~ /Win32/;
my $start_dir;
BEGIN { $start_dir = cwd }
=head1 FUNCTIONS
=over
=item shell_quote
my $line = shell_quote \@command;
my $line = shell_quote @command;
print STDERR, $line, "\n";
Selectively quotes the command line to allow it to be printed in a non-vague
fashion and to be pastable in the local shell (sh/bash on Unix, COMMAND.COM,
etc. on Win32 and OS2).
NOTE: May not be perfect; errs on the side of safety and doesn't try to
escape things right on Win32 yet. Patches welcome.
=cut
{
my $q;
BEGIN { $q = is_win32 ? '"' : "'" };
sub shell_quote {
my @parms = ref $_[0] eq "ARRAY" ? @{$_[0]} : @_;
return join " ", map {
defined $_
? m{[^\w:/\\.,=\@-]}
? do {
( my $s = $_ ) =~ s/([\\$q])/\\$1/;
"$q$s$q";
}
: $_
: "(((undef)))";
} @parms;
}
}
=item empty
Determines if a scalar value is empty, that is
not defined or zero length.
=cut
sub empty($) {
return ! ( defined $_[0] && length $_[0] );
}
=item escape_filename
Escape a string so that it may be used as a filename. Converts
characters other than "-", "_", and alphanumerics to %NN% escape
sequences where NN is the ordinal value (usually the ASCII value or
UTF-8 codepoint) of the character.
=cut
sub escape_filename {
my ($s) = @_;
BUG "usage: escape_filename <filename-to-escape>"
if empty $s;
$s =~ s/([^0-9a-zA-Z\-_])/sprintf '%%%d%%', ord $1/eg ;
return $s;
}
=item start_dir_rel2abs
start_dir_rel2abs( $fn );
If $fn is a relative path (according to File::Spec), converts it to an
absolute path using start_dir() as the base directory.
=cut
sub start_dir_rel2abs {
BUG "start_dir_rel2abs() takes one and only one argument"
unless @_ == 1;
my $p = File::Spec->rel2abs( @_, $start_dir );
return $p unless is_win32;
$p =~ s{\\+}{/}g;
return $p;
}
=item start_dir
Returns the directory that was current when VCP::Utils was parsed.
=cut
sub start_dir { $start_dir }
=item xchdir
Changes to a directory (unless we're already in that directory) and logs
the change. Throws an exception on error. Sets $ENV{PWD}.
You should use minimal canonical paths where possible so that $ENV{PWD}
is a simple path. Some child processes might not like paths with
thisdir ("/./") or updir segments ("/../").
Relative paths are an error.
=cut
{
my %abs_cache;
my $cwd = start_dir;
sub xchdir($) {
my $to_dir = shift;
return if $cwd eq $to_dir;
BUG
"can't chdir() to relative path '$to_dir'"
unless $abs_cache{$to_dir}
||= File::Spec->file_name_is_absolute( $to_dir );
lg "\$ ", shell_quote "chdir", $to_dir;
chdir $to_dir or die "vcp: $!: $to_dir";
## Set $ENV{PWD} to tell the p4 command line where we are.
## Otherwise, on Win32, it (I guess) uses the OS to get the cwd
## and this causes it to get the *long* pathname, which is not under
## the client root if the long pathname differs from the tmpdir
## returned by File::Spec->tmpdir, which is the short pathname.
$ENV{PWD} = $cwd = $ENV{CWD} = $to_dir;
}
}
=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 ;
|