Utils.pm #21

  • //
  • guest/
  • perforce_software/
  • revml/
  • lib/
  • VCP/
  • Utils.pm
  • View
  • Commits
  • Open Download .zip Download (5 KB)
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
   profile
   profiling
   profile_beg_interval
   profile_end_interval
   prepend_time_cmd
   shell_quote
   start_dir
);

@ISA = qw( Exporter );
use Exporter;

use Carp;
use strict ;
use File::Spec;
use IO::Handle ;
use Cwd;

my $start_dir;
BEGIN { $start_dir = cwd }

# disallow defined but not true logfiles.
# TODO: Tell the user that they used a bad profile file name or allow
# defined but false names.
#
use constant profiling => 
   defined $ENV{VCPPROFILE} && length $ENV{VCPPROFILE} ;
use constant profiling_with_time =>
   defined $ENV{VCPPROFILETIME} && length $ENV{VCPPROFILETIME} ;



my $profile_file_name;

BEGIN {
   if ( profiling ) {
      eval "use Time::HiRes qw(gettimeofday tv_interval); 1" or die $@;

      $profile_file_name = File::Spec->rel2abs( $ENV{VCPPROFILE} );
      
      open PROFILE_LOG, ">>$profile_file_name"
         or die "couldn't open log file '$profile_file_name' for append\n";
      autoflush PROFILE_LOG 1
         if profiling_with_time;
   }
}


=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 = $^O =~ /Win32|OS2/ ? '"' : "'";

    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.

=cut

sub escape_filename {
   my ($s) = @_;
   croak "usage: escape_filename <filename-to-escape>"
      if empty $s;

   $s =~ s/([^0-9a-zA-Z.\-_])/sprintf '%%%03d', ord $1/eg ;
   return $s;
}


=item start_dir

Returns the directory that was current when VCP::Utils was parsed.

=cut

sub start_dir { $start_dir }


=item profile

log high resolution time info to the PROFILE_LOG file.

=cut


sub profile {
   unless ( profiling ) {
      return;
   }

   die "usage: log_time <message>" unless @_ == 1;
   die "profile's log message must start with the string BEG or END"
      unless $_[0] =~ /^(BEG|END)/ ;
      
   my ($sec, $usec) = gettimeofday();
   seek PROFILE_LOG, 0, 2 or warn "$! seeking in PROFILE_LOG";
   printf PROFILE_LOG "%10d.%06d $_[0]\n", $sec, $usec;
}


=item profile_start_interval

takes no arguments.
returns a reference to array returned by gettimeofday.

=cut

sub profile_beg_interval {
   unless( profiling ) {
      return;
   }
   die "usage: profile_beg_interval" unless @_ == 0;

   my @timeofday = gettimeofday();
   return \@timeofday;
}


=item profile_end_interval

takes: 
1. a reference to array returned by gettimeofday (or profile_beg_interval)
2. a log message.

calculates interval between the given time and the current time.
logs that as 'ELA' (elapsed time) to the profile log.

=cut

sub profile_end_interval {
   unless( profiling ) {
      return;
   }
   die "usage: profile_end_interval <prev_time_ref>, <msg>" unless @_ == 2;

   my ($prev_time_ref, $msg) = @_;
   my $tv_interval = tv_interval $prev_time_ref;

   seek PROFILE_LOG, 0, 2 or warn "$! seeking in PROFILE_LOG";
   printf PROFILE_LOG "%s ELA $msg\n", $tv_interval;
}



=item prepend_time_cmd

Prepend unix time command to the given command and return it.
the command must be given as an array reference.

Only change code if VCPPROFILETIME is set.

=cut


my $time_full_path;

sub prepend_time_cmd {
   unless( profiling ) {
      die "prepend_time_cmd should only be called when profiling is turned on.";
   }
   
   die "usage: prepend_time_cmd <command-arg-array-ref>"
      unless @_ == 1 && ref $_[0] eq "ARRAY";
   my @cmd = @{$_[0]};

   if( profiling_with_time ) {
      my $cmdstr = join " ", @cmd;

      unless( $time_full_path ) {
         $time_full_path = `which time`;
         chomp $time_full_path;
      }
      my @time_cmd = ( $time_full_path, "-o", $profile_file_name, "-a", "-f", "%e ELA $cmdstr" );

      unshift @cmd, @time_cmd;
   }

   return \@cmd;
}


=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