line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package ClearCase::Wrapper; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
$VERSION = '1.19'; |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
require 5.006; |
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
4189
|
use AutoLoader 'AUTOLOAD'; |
|
1
|
|
|
|
|
4751
|
|
|
1
|
|
|
|
|
7
|
|
8
|
1
|
|
|
1
|
|
36
|
use B; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
70
|
|
9
|
1
|
|
|
1
|
|
10
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
30
|
|
10
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
39
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
6
|
use vars qw(%Packages %ExtMap $libdir $prog $dieexit $dieexec $diemexec); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
134
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# Inherit some symbols from the main package. We will later "donate" |
15
|
|
|
|
|
|
|
# these to all overlay packages as well. |
16
|
|
|
|
|
|
|
BEGIN { |
17
|
1
|
|
|
1
|
|
3
|
*prog = \$::prog; |
18
|
1
|
|
|
|
|
2
|
*dieexit = \$::dieexit; |
19
|
1
|
|
|
|
|
1
|
*dieexec = \$::dieexec; |
20
|
1
|
|
|
|
|
78
|
*diemexec = \$::diemexec; |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# For some reason this can't be handled the same as $prog above ... |
24
|
1
|
50
|
|
1
|
|
6
|
use constant MSWIN => $^O =~ /MSWin|Windows_NT/i ? 1 : 0; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
252
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# This is the list of functions we want to export to overlay pkgs. |
27
|
|
|
|
|
|
|
my @exports = qw(MSWIN GetOptions Assert Burrow Msg Pred ViewTag |
28
|
|
|
|
|
|
|
AutoCheckedOut AutoNotCheckedOut AutoViewPrivate); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# Hacks for portability with Windows env vars. |
31
|
|
|
|
|
|
|
BEGIN { |
32
|
1
|
|
33
|
1
|
|
16
|
$ENV{LOGNAME} ||= $ENV{USERNAME}; |
33
|
1
|
|
33
|
|
|
252
|
$ENV{HOME} ||= "$ENV{HOMEDRIVE}/$ENV{HOMEPATH}"; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# Unless the user has their own CLEARCASE_PROFILE, set it to the global one. |
37
|
|
|
|
|
|
|
BEGIN { |
38
|
|
|
|
|
|
|
# Learn where this module was found so we can look there for other files. |
39
|
1
|
|
|
1
|
|
7
|
($libdir = $INC{'ClearCase/Wrapper.pm'}) =~ s%\.pm$%%; |
40
|
|
|
|
|
|
|
|
41
|
1
|
50
|
|
|
|
23
|
if (defined $ENV{CLEARCASE_PROFILE}) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
42
|
0
|
|
|
|
|
0
|
$ENV{_CLEARCASE_WRAPPER_PROFILE} = $ENV{CLEARCASE_PROFILE}; |
43
|
|
|
|
|
|
|
} elsif ($ENV{_CLEARCASE_WRAPPER_PROFILE}) { |
44
|
0
|
|
|
|
|
0
|
$ENV{CLEARCASE_PROFILE} = $ENV{_CLEARCASE_WRAPPER_PROFILE}; |
45
|
|
|
|
|
|
|
} elsif (! -f "$ENV{HOME}/.clearcase_profile") { |
46
|
1
|
|
|
|
|
3
|
my $rc = join('/', $libdir, 'clearcase_profile'); |
47
|
1
|
50
|
|
|
|
386
|
$ENV{CLEARCASE_PROFILE} = $rc if -r $rc; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Skip the Getopt::Long->import(), we need our own GetOptions(). |
52
|
|
|
|
|
|
|
require Getopt::Long; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Getopt::Long::GetOptions() respects '--' but strips it, while |
55
|
|
|
|
|
|
|
# we want to respect '--' and leave it in. Thus this override. |
56
|
|
|
|
|
|
|
sub GetOptions { |
57
|
0
|
0
|
|
0
|
0
|
0
|
@ARGV = map {/^--$/ ? qw(=--= --) : $_} @ARGV; |
|
0
|
|
|
|
|
0
|
|
58
|
0
|
|
|
|
|
0
|
my $ret = Getopt::Long::GetOptions(@_); |
59
|
0
|
0
|
|
|
|
0
|
@ARGV = map {/^=--=$/ ? qw(--) : $_} @ARGV; |
|
0
|
|
|
|
|
0
|
|
60
|
0
|
|
|
|
|
0
|
return $ret; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# Technically we should use Getopt::Long::Configure() for these but |
64
|
|
|
|
|
|
|
# there's a tangled version history and this is faster anyway. |
65
|
|
|
|
|
|
|
$Getopt::Long::passthrough = 1; # required for wrapper programs |
66
|
|
|
|
|
|
|
$Getopt::Long::ignorecase = 0; # global override for dumb default |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Any subroutine declared in a module located via this code |
69
|
|
|
|
|
|
|
# will eclipse one of the same name declared above. |
70
|
|
|
|
|
|
|
## NOTE: functions defined in modules found here should not |
71
|
|
|
|
|
|
|
## be placed directly into ClearCase::Wrapper. They MUST be |
72
|
|
|
|
|
|
|
## placed in the standard package analogous to their pathname |
73
|
|
|
|
|
|
|
## (e.g. ClearCase::Wrapper::Foo). Magic occurs here to get |
74
|
|
|
|
|
|
|
## them into ClearCase::Wrapper where they belong. |
75
|
|
|
|
|
|
|
sub _FindAndLoadModules { |
76
|
22
|
|
|
22
|
|
36
|
my ($dir, $subdir) = @_; |
77
|
|
|
|
|
|
|
# Not sure how glob() sorts so force a standard order. |
78
|
22
|
|
|
|
|
1244
|
my @pms = sort glob("$dir/$subdir/*.pm"); |
79
|
22
|
|
|
|
|
62
|
for my $pm (@pms) { |
80
|
1
|
|
|
|
|
4
|
my $dirQuoted = quotemeta($dir); |
81
|
1
|
|
|
|
|
32
|
$pm =~ s%^$dirQuoted/(.*)\.pm$%$1%; |
82
|
1
|
|
|
|
|
7
|
(my $pkg = $pm) =~ s%[/\\]+%::%g; |
83
|
1
|
|
|
|
|
90
|
eval "*${pkg}::exit = \$dieexit"; |
84
|
1
|
|
|
|
|
61
|
eval "*${pkg}::exec = \$dieexec"; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# In this block we temporarily enter the overlay's package |
87
|
|
|
|
|
|
|
# just in case the overlay module forgot its package stmt. |
88
|
|
|
|
|
|
|
# We then require the overlay file and also, if it's |
89
|
|
|
|
|
|
|
# an autoloaded module (which is recommended), we drag |
90
|
|
|
|
|
|
|
# in the index file too. This is because we need to |
91
|
|
|
|
|
|
|
# derive a list of all functions defined in the overlay |
92
|
|
|
|
|
|
|
# in order to import them to our own namespace. |
93
|
|
|
|
|
|
|
{ |
94
|
1
|
|
|
|
|
3
|
eval qq(package $pkg); # default the pkg correctly |
|
1
|
|
|
|
|
27
|
|
95
|
1
|
|
|
1
|
|
7
|
no warnings qw(redefine); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
226
|
|
96
|
1
|
|
|
|
|
2
|
eval { |
97
|
1
|
|
|
|
|
48
|
eval "require $pkg"; |
98
|
1
|
50
|
|
|
|
1899
|
warn $@ if $@; |
99
|
|
|
|
|
|
|
}; |
100
|
1
|
50
|
|
|
|
4
|
next if $@; |
101
|
1
|
|
|
|
|
3
|
my $ix = "auto/$pm/autosplit.ix"; |
102
|
1
|
50
|
|
|
|
53
|
if (-e "$dir/$ix") { |
103
|
1
|
|
|
|
|
2
|
eval { require $ix }; |
|
1
|
|
|
|
|
12694
|
|
104
|
1
|
50
|
|
|
|
23
|
warn $@ if $@; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# Now the overlay module is read in. We need to examine its |
109
|
|
|
|
|
|
|
# newly-created symbol table, determine which functions |
110
|
|
|
|
|
|
|
# it defined, and import them here. The same basic thing is |
111
|
|
|
|
|
|
|
# done for the base package later. |
112
|
1
|
|
|
1
|
|
6
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1733
|
|
113
|
1
|
|
|
|
|
3
|
my %names = %{"${pkg}::"}; |
|
1
|
|
|
|
|
123
|
|
114
|
1
|
|
|
|
|
12
|
for (keys %names) { |
115
|
|
|
|
|
|
|
# Skip symbols that can't be names of valid cleartool ops. |
116
|
32
|
100
|
|
|
|
289
|
next if m%^(?:_?[A-Z]|__|[ab]$)%; |
117
|
29
|
|
|
|
|
62
|
my $tglob = "${pkg}::$_"; |
118
|
29
|
|
|
|
|
34
|
my $coderef = \&{$tglob}; |
|
29
|
|
|
|
|
98
|
|
119
|
29
|
50
|
|
|
|
77
|
next unless ref $coderef; |
120
|
29
|
|
|
|
|
106
|
my $cv = B::svref_2object($coderef); |
121
|
29
|
50
|
|
|
|
191
|
next unless $cv->isa('B::CV'); |
122
|
29
|
50
|
|
|
|
195
|
next if $cv->GV->isa('B::SPECIAL'); |
123
|
29
|
|
|
|
|
173
|
my $p = $cv->GV->STASH->NAME; |
124
|
29
|
50
|
|
|
|
105
|
next unless $p eq $pkg; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Take what survives the above tests and create a hash |
127
|
|
|
|
|
|
|
# mapping defined functions to the pkg that defines them. |
128
|
29
|
|
|
|
|
68
|
$ExtMap{$_} = $pkg; |
129
|
|
|
|
|
|
|
# We import the entire typeglob for 'foo' when we |
130
|
|
|
|
|
|
|
# find an extension func named foo(). This allows usage |
131
|
|
|
|
|
|
|
# msg extensions (in the form $foo) to come over too. |
132
|
29
|
|
|
|
|
1903
|
eval qq(*$_ = *$tglob); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# The base module defines a few functions which the |
136
|
|
|
|
|
|
|
# overlay's code might want to use. Make aliases |
137
|
|
|
|
|
|
|
# for those in the overlay's symbol table. |
138
|
1
|
|
|
|
|
7
|
for (@exports) { |
139
|
10
|
|
|
|
|
852
|
eval "*${pkg}::$_ = \\&$_"; |
140
|
|
|
|
|
|
|
} |
141
|
1
|
|
|
|
|
87
|
eval "*${pkg}::prog = \\\$prog"; |
142
|
|
|
|
|
|
|
|
143
|
1
|
|
|
|
|
25
|
$Packages{$pkg} = $INC{"$pm.pm"}; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
for my $subdir (qw(ClearCase/Wrapper ClearCase/Wrapper/Site)) { |
147
|
|
|
|
|
|
|
for my $dir (@INC) { |
148
|
|
|
|
|
|
|
_FindAndLoadModules($dir, $subdir); |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
$Packages{'ClearCase::Wrapper'} = __FILE__; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Piggyback on the -ver flag to show our version too. |
155
|
|
|
|
|
|
|
if (@ARGV && $ARGV[0] =~ /^-ver/i) { |
156
|
|
|
|
|
|
|
my $fmt = "*%-32s %s (%s)\n"; |
157
|
|
|
|
|
|
|
local $| = 1; |
158
|
|
|
|
|
|
|
for (sort keys %Packages) { |
159
|
|
|
|
|
|
|
my $ver = eval "\$$_\::VERSION" || '????'; |
160
|
|
|
|
|
|
|
my $mtime = localtime((stat $Packages{$_})[9]); |
161
|
|
|
|
|
|
|
printf $fmt, $_, $ver, $mtime || '----'; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
exit 0 if $ARGV[0] =~ /^-verw/i; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# Take a string and an array, return the index of the 1st occurrence |
167
|
|
|
|
|
|
|
# of the string in the array. |
168
|
|
|
|
|
|
|
sub _FirstIndex { |
169
|
3
|
|
|
3
|
|
5
|
my $flag = shift; |
170
|
3
|
|
|
|
|
7
|
for my $i (0..$#_) { |
171
|
0
|
0
|
|
|
|
0
|
return $i if $flag eq $_[$i]; |
172
|
|
|
|
|
|
|
} |
173
|
3
|
|
|
|
|
21
|
return undef; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# Implements the -me -tag convention (see POD). |
177
|
|
|
|
|
|
|
if (my $me = _FirstIndex('-me', @ARGV)) { |
178
|
|
|
|
|
|
|
if ($ARGV[0] =~ /^(?:set|start|end)view$|^rdl$|^work/) { |
179
|
|
|
|
|
|
|
my $delim = 0; |
180
|
|
|
|
|
|
|
for (@ARGV) { |
181
|
|
|
|
|
|
|
last if /^--$/; |
182
|
|
|
|
|
|
|
$delim++; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
for (reverse @ARGV[0..$delim-1]) { |
185
|
|
|
|
|
|
|
if (/^\w+$/) { |
186
|
|
|
|
|
|
|
$_ = join('_', $ENV{LOGNAME}, $_); |
187
|
|
|
|
|
|
|
last; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
splice(@ARGV, $me, 1); |
191
|
|
|
|
|
|
|
} elsif (my $tag = _FirstIndex('-tag', @ARGV)) { |
192
|
|
|
|
|
|
|
$ARGV[$tag+1] = join('_', $ENV{LOGNAME}, $ARGV[$tag+1]); |
193
|
|
|
|
|
|
|
splice(@ARGV, $me, 1); |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# Implements the -M flag (see POD). |
198
|
|
|
|
|
|
|
if (my $mflag = _FirstIndex('-M', @ARGV) || $ENV{CLEARCASE_WRAPPER_PAGER}) { |
199
|
|
|
|
|
|
|
splice(@ARGV, $mflag, 1) if $mflag && !$ENV{CLEARCASE_WRAPPER_PAGER}; |
200
|
|
|
|
|
|
|
pipe(READER, WRITER); |
201
|
|
|
|
|
|
|
my $pid; |
202
|
|
|
|
|
|
|
if ($pid = fork) { |
203
|
|
|
|
|
|
|
close WRITER; |
204
|
|
|
|
|
|
|
open(STDIN, ">&READER") || die Msg('E', "STDIN: $!"); |
205
|
|
|
|
|
|
|
my $pager = $ENV{CLEARCASE_WRAPPER_PAGER} || $ENV{PAGER}; |
206
|
|
|
|
|
|
|
if (!$pager) { |
207
|
|
|
|
|
|
|
require Config; |
208
|
|
|
|
|
|
|
$pager = $Config::Config{pager} || 'more'; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
exec $pager || warn Msg('W', "can't run $pager: $!"); |
211
|
|
|
|
|
|
|
} else { |
212
|
|
|
|
|
|
|
die Msg('E', "can't fork") if !defined($pid); |
213
|
|
|
|
|
|
|
close READER; |
214
|
|
|
|
|
|
|
open(STDOUT, ">&WRITER") || die Msg('E', "STDOUT: $!"); |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# Implements the -P flag to pause after a GUI operation. |
219
|
|
|
|
|
|
|
if (my $pflag = _FirstIndex('-P', @ARGV)) { |
220
|
|
|
|
|
|
|
splice(@ARGV, $pflag, 1); |
221
|
|
|
|
|
|
|
if (MSWIN) { |
222
|
|
|
|
|
|
|
eval "END { system qw(cmd /c pause) }"; |
223
|
|
|
|
|
|
|
} else { |
224
|
|
|
|
|
|
|
my $foo = ; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
############################################################################# |
229
|
|
|
|
|
|
|
# Usage Message Extensions |
230
|
|
|
|
|
|
|
############################################################################# |
231
|
|
|
|
|
|
|
{ |
232
|
1
|
|
|
1
|
|
9
|
no strict 'vars'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
528
|
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# Extended messages for actual cleartool commands that we extend. |
235
|
|
|
|
|
|
|
$checkin = "\n* [-dir|-rec|-all|-avobs] [-ok] [-diff [diff-opts]]" . |
236
|
|
|
|
|
|
|
"\n* [-revert [-mkhlink]]"; |
237
|
|
|
|
|
|
|
$checkout = "\n* [-dir|-rec] [-ok]"; |
238
|
|
|
|
|
|
|
$diff = "\n* [-] [-dir|-rec|-all|-avobs]"; |
239
|
|
|
|
|
|
|
$diffcr = "\n* [-data]"; |
240
|
|
|
|
|
|
|
$lsprivate = "\n* [-dir|-rec|-all] [-ecl/ipsed] [-type d|f]" . |
241
|
|
|
|
|
|
|
"\n* [-rel/ative] [-ext] [pname]"; |
242
|
|
|
|
|
|
|
$lsview = "\n* [-me]"; |
243
|
|
|
|
|
|
|
$mkelem = "\n* [-dir|-rec] [-do] [-ok]"; |
244
|
|
|
|
|
|
|
$uncheckout = " * [-nc]"; |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Extended messages for pseudo cleartool commands that we implement here. |
247
|
|
|
|
|
|
|
my $z = $ARGV[0] || ''; |
248
|
|
|
|
|
|
|
$edit = "$z [-ci] pname ..."; |
249
|
|
|
|
|
|
|
$extensions = "$z [-long]"; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
############################################################################# |
253
|
|
|
|
|
|
|
# Command Aliases |
254
|
|
|
|
|
|
|
############################################################################# |
255
|
|
|
|
|
|
|
*ci = *checkin; |
256
|
|
|
|
|
|
|
*co = *checkout; |
257
|
|
|
|
|
|
|
*lsp = *lsprivate; |
258
|
|
|
|
|
|
|
*lspriv = *lsprivate; |
259
|
|
|
|
|
|
|
*unco = *uncheckout; |
260
|
|
|
|
|
|
|
*vi = *edit; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
############################################################################# |
263
|
|
|
|
|
|
|
# Allow per-user configurability. Give the individual access to @ARGV just |
264
|
|
|
|
|
|
|
# before we hand it off to the local wrapper function and/or cleartool. |
265
|
|
|
|
|
|
|
# Access to this feature is suppressed if the 'NO_OVERRIDES' file exists. |
266
|
|
|
|
|
|
|
############################################################################# |
267
|
|
|
|
|
|
|
if (-r "$ENV{HOME}/.clearcase_profile.pl" && ! -e "$libdir/NO_OVERRIDES") { |
268
|
|
|
|
|
|
|
require "$ENV{HOME}/.clearcase_profile.pl"; |
269
|
1
|
|
|
1
|
|
7
|
no warnings qw(redefine); |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
1318
|
|
270
|
|
|
|
|
|
|
*Argv::exec = $diemexec; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Add to ExtMap the names of extensions defined in the base package. |
274
|
|
|
|
|
|
|
for (keys %ClearCase::Wrapper::) { |
275
|
|
|
|
|
|
|
# Skip functions that can't be names of valid cleartool ops. |
276
|
|
|
|
|
|
|
next if m%^(?:_?[A-Z]|__)%; |
277
|
|
|
|
|
|
|
# Skip typeglobs that don't involve functions. |
278
|
|
|
|
|
|
|
my $tglob = "ClearCase::Wrapper::$_"; |
279
|
|
|
|
|
|
|
next unless ref \&{$tglob}; |
280
|
|
|
|
|
|
|
# Take what survives the above tests and create a hash |
281
|
|
|
|
|
|
|
# mapping defined functions to the pkg that defines them. |
282
|
|
|
|
|
|
|
$ExtMap{$_} ||= __PACKAGE__; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# Returns undefined if is not being extended and returns the |
286
|
|
|
|
|
|
|
# package that extends it otherwise. Potentially useful for extension |
287
|
|
|
|
|
|
|
# writers. |
288
|
|
|
|
|
|
|
sub Extension { |
289
|
0
|
|
|
0
|
0
|
|
my $op = shift; |
290
|
0
|
|
|
|
|
|
return $ExtMap{$op}; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# Returns the full name of a command, whether native or not; unchanged in error |
294
|
|
|
|
|
|
|
sub Canonic { |
295
|
0
|
|
|
0
|
0
|
|
my $op = shift; |
296
|
0
|
|
|
|
|
|
my $tglob = $ExtMap{$op} . "::" . $op; |
297
|
0
|
|
|
|
|
|
my $coderef = \&{$tglob}; |
|
0
|
|
|
|
|
|
|
298
|
0
|
0
|
|
|
|
|
return $op unless ref $coderef; |
299
|
0
|
|
|
|
|
|
my $cv = B::svref_2object($coderef); |
300
|
0
|
|
|
|
|
|
return $cv->GV->NAME; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# Returns a boolean indicating whether the named cmd is native to |
304
|
|
|
|
|
|
|
# CC or not. Note: the first call to this func has a "cost" of one |
305
|
|
|
|
|
|
|
# "cleartool help" operation; subsequent calls are free. |
306
|
|
|
|
|
|
|
{ |
307
|
|
|
|
|
|
|
my %native; |
308
|
|
|
|
|
|
|
sub Native { |
309
|
0
|
|
|
0
|
0
|
|
my $op = shift; |
310
|
0
|
0
|
|
|
|
|
return 1 if $op =~ m%^lsp(riv)?%; |
311
|
0
|
0
|
|
|
|
|
if (! $op) { |
312
|
0
|
|
|
|
|
|
($op = (caller(1))[3]) =~ s%.*:%%; |
313
|
|
|
|
|
|
|
} |
314
|
0
|
0
|
|
|
|
|
if (! keys %native) { |
315
|
0
|
|
|
|
|
|
my @usg = grep /^Usage:/, ClearCase::Argv->help->qx; |
316
|
0
|
|
|
|
|
|
for (@usg) { |
317
|
0
|
0
|
|
|
|
|
if (/^Usage:\s*(\w+)\s*(\|\s*(\w+))?/) { |
318
|
0
|
0
|
|
|
|
|
$native{$1} = 1 if $1; |
319
|
0
|
0
|
|
|
|
|
$native{$3} = 1 if $3; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
} |
323
|
0
|
0
|
|
|
|
|
if (exists($native{$op})) { |
|
|
0
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
return 1; |
325
|
|
|
|
|
|
|
} elsif ($op =~ m%^(?:des|lsh)%) { |
326
|
0
|
|
|
|
|
|
return 1; |
327
|
|
|
|
|
|
|
} else { |
328
|
0
|
|
|
|
|
|
return 0; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# This is an enhancement like the ones below but is kept "above the |
334
|
|
|
|
|
|
|
# fold" because wrapping of cleartool man is an integral and generic |
335
|
|
|
|
|
|
|
# part of the module. It runs "cleartool man " as requested, |
336
|
|
|
|
|
|
|
# followed by "perldoc ClearCase::Wrapper" iff is extended below. |
337
|
|
|
|
|
|
|
sub man { |
338
|
0
|
|
|
0
|
0
|
|
$_ = Canonic($_) for @ARGV[1..$#ARGV]; |
339
|
0
|
|
|
|
|
|
my $page = (grep !/^-/, @ARGV)[1]; |
340
|
0
|
0
|
|
|
|
|
return 0 unless $page; |
341
|
0
|
0
|
|
|
|
|
ClearCase::Argv->new(@ARGV)->system if Native($page); |
342
|
0
|
0
|
|
|
|
|
if (exists($ClearCase::Wrapper::{$page})) { |
|
|
0
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# This EV hack causes perldoc to search for the right keyword |
344
|
|
|
|
|
|
|
# within the module's perldoc. |
345
|
0
|
|
|
|
|
|
if (!MSWIN) { |
346
|
0
|
|
|
|
|
|
require Config; |
347
|
0
|
|
|
|
|
|
my $pager = $Config::Config{pager}; |
348
|
0
|
0
|
0
|
|
|
|
$ENV{PERLDOC_PAGER} ||= "$pager +/" . uc($page) |
349
|
|
|
|
|
|
|
if $pager =~ /more|less/; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
} elsif ($page ne $::prog) { |
352
|
0
|
0
|
|
|
|
|
if (!Native($page)) { |
353
|
0
|
|
|
|
|
|
ClearCase::Argv->new(@ARGV)->exec; |
354
|
|
|
|
|
|
|
} else { |
355
|
0
|
0
|
|
|
|
|
exit($? ? 1 : 0); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
} |
358
|
0
|
|
|
|
|
|
my $psep = MSWIN ? ';' : ':'; |
359
|
0
|
|
|
|
|
|
require File::Basename; |
360
|
0
|
|
|
|
|
|
$ENV{PATH} = join($psep, File::Basename::dirname($^X), $ENV{PATH}); |
361
|
0
|
|
0
|
|
|
|
my $module = $ExtMap{$page} || __PACKAGE__; |
362
|
0
|
|
|
|
|
|
Argv->perldoc($module)->exec; |
363
|
0
|
|
|
|
|
|
exit $?; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
1; |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
__END__ |