File: Utils.pm

package info (click to toggle)
libvcp-perl 0.9-20050110-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,608 kB
  • ctags: 827
  • sloc: perl: 18,194; makefile: 42; sh: 11
file content (190 lines) | stat: -rw-r--r-- 4,099 bytes parent folder | download | duplicates (2)
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 ;