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 scan_pm_files_in 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; } } =item scan_pm_files_in my @modules = scan_pm_files_in( "VCP::Filter" ); Returns a list of perl package names (like "VCP::Filter::Foo") corresponding to .pm files in the given namespace by scanning @INC. Does not recurse, does not return the parent .pm (VCP/Filter.pm in the example). =cut sub scan_pm_files_in { my ( $prefix ) = @_ ; my $dirname = $prefix . '::' ; $dirname =~ s{(::)+}{/}g ; my %seen ; require File::Spec; for ( @INC ) { my $dir = File::Spec->catdir( $_, $dirname ) ; opendir( D, $dir ) or next ; my @files = grep $_ !~ /^\.\.?$/ && s/\.pm$//i, readdir D ; closedir D ; $seen{$_} = 1 for @files ; } return map "${prefix}::$_", keys %seen; } =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 ;
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#35 | 4143 | Barrie Slaymaker | - Further adaptation to vcp.exe packaging format | ||
#34 | 4141 | Barrie Slaymaker | - Adapt online help and html generation to vcp.exe environment | ||
#33 | 3714 | Barrie Slaymaker | - Minor import cleanup | ||
#32 | 3642 | Barrie Slaymaker | - First cut at PAR based script to build vcp.exe | ||
#31 | 3569 | Barrie Slaymaker |
- Work around bug caused by p4's using the long pathname when $ENV{PWD} is not set. |
||
#30 | 3532 | John Fetkovich |
changed File::Spec->rel2abs( blah, start_dir ) to start_dir_rel2abs blah everywhere. which does the same thing and is defined in VCP::Utils |
||
#29 | 3496 | Barrie Slaymaker | - VSS branching | ||
#28 | 3464 | Barrie Slaymaker |
- Create VCP::ConfigFileUtils and move bin/vcp::parse_config_file in to it. - Add VCP::ConfigFileUtils::write_config_file() - Add --output-vcp-file to bin/vcp. - Add VCP::Driver::repo_spec_as_string() - Add VCP::Driver::config_file_section_as_string() - VCP::Driver::parse_repo_spec() now clears any settings that are not set by a given spec string (so old values don't remain after a call to it). |
||
#27 | 3412 | Barrie Slaymaker | - Add VCP::Utils::is_win32() | ||
#26 | 3167 | Barrie Slaymaker |
Add profiling report that details various chunks of time taken. |
||
#25 | 3162 | Barrie Slaymaker | Fix suprise interpolation in shell quoting RE | ||
#24 | 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. |
||
#23 | 3105 | Barrie Slaymaker | Tweak to profiling code | ||
#22 | 3008 | John Fetkovich |
make state database files go under vcp_state in the program start directory (start_dir) instead of start_dir itself. Also escape periods (.) from the database directory as well as the characters already escaped. |
||
#21 | 2972 | Barrie Slaymaker | Interim checkin | ||
#20 | 2941 | John Fetkovich | fix escape_filename | ||
#19 | 2936 | John Fetkovich | add empty() calls | ||
#18 | 2935 | John Fetkovich | added empty() calls | ||
#17 | 2928 | John Fetkovich |
Added empty sub to VCP::Utils.pm to check for empty or undefined strings. Added a couple of calls to it in Dest.pm. |
||
#16 | 2926 | John Fetkovich |
remove --state-location switch add --db-dir and --repo-id switches build state location from concatenation of those two. |
||
#15 | 2728 | John Fetkovich | oops, fix syntax error | ||
#14 | 2727 | John Fetkovich | more profiling capability added. | ||
#13 | 2701 | Barrie Slaymaker | Add support for start_dir | ||
#12 | 2683 | John Fetkovich |
VCPPROFILETIME environment var now controls if unix 'time' dumps elapsed times into profile log. |
||
#11 | 2679 | John Fetkovich | profiling fixes | ||
#10 | 2670 | John Fetkovich | get and use full path of time command when profiling | ||
#9 | 2669 | John Fetkovich | spelling fix | ||
#8 | 2668 | John Fetkovich | die if prepend_time_command called when profiling is off. | ||
#7 | 2661 | John Fetkovich | fix profiling so it determines absolute path of profiling log file | ||
#6 | 2655 | John Fetkovich |
Added usage of 'nix time command to run_safely in Utils.pm when profiling is turned on. |
||
#5 | 2654 | John Fetkovich | profiling tweaks. | ||
#4 | 2639 | John Fetkovich |
Added profiling to be made active when VCPPROFILE environment variable turned on. writes profile info to filename defined in VCPPROFILE. Put some profiling statements (activated at compile time) in vcp and p4.pm. |
||
#3 | 2300 | Barrie Slaymaker | improve shell quoting a bit | ||
#2 | 2293 | Barrie Slaymaker | Update CHANGES, TODO, improve .vcp files, add --init-cvs | ||
#1 | 2267 | Barrie Slaymaker | factor out cvs2revml, test both --use-cvs and direct modes, with times |