|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package ClearCase::SyncTree;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = '0.60';  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require 5.004;  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
918
 | 
 use strict;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use Cwd;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
77
 | 
    | 
| 
10
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
 use File::Basename;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
136
 | 
    | 
| 
11
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1081
 | 
 use File::Compare;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1324
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
12
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1016
 | 
 use File::Copy;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6080
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
    | 
| 
13
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
8
 | 
 use File::Find;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
    | 
| 
14
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use File::Path;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
68
 | 
    | 
| 
15
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use File::Spec 0.82;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
    | 
| 
16
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1055
 | 
 use ClearCase::Argv 1.34 qw(chdir);  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51628
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
120
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
1
 | 
  
 50
  
 | 
 
 | 
  
1
  
 | 
 
 | 
11
 | 
 use constant MSWIN => $^O =~ /MSWin|Windows_NT/i ? 1 : 0;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
110
 | 
    | 
| 
19
 | 
1
 | 
  
 50
  
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 use constant CYGWIN => $^O =~ /cygwin/i ? 1 : 0;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
559
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $lext = '.=lnk=';	# special extension for pseudo-symlinks  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
24
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $proto = shift;  | 
| 
25
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $class;  | 
| 
26
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($class = ref($proto)) {  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Make a (deep) clone of the invoking instance  | 
| 
28
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	require Clone;  | 
| 
29
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	Clone->VERSION(0.12);	# 0.10 has a known bug  | 
| 
30
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return Clone::clone($proto);  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
32
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $class = $proto;  | 
| 
33
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $self = {@_};  | 
| 
34
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bless $self, $class;  | 
| 
35
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->comment('By:' . __PACKAGE__);  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Default is to sync file modes unless on ^$%#* Windows.  | 
| 
37
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->protect(1);  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Set up a ClearCase::Argv instance with the appropriate attrs.  | 
| 
39
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->ct;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # By default we'll call SyncTree->fail on any cleartool error.  | 
| 
41
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->err_handler($self, 'fail');  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Set default file comparator.  | 
| 
43
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->cmp_func(\&File::Compare::compare);  | 
| 
44
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub err_handler {  | 
| 
48
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my $self = shift;  | 
| 
49
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $ct = $self->ct;  | 
| 
50
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (@_ >= 2) {  | 
| 
51
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my($obj, $method) = @_;  | 
| 
52
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$method = join('::', ref($obj), $method) unless $method =~ /::/;  | 
| 
53
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$ct->autofail([\&$method, $obj]);  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
55
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$ct->autofail(@_);  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # For internal use only.  Provides a std msg format.  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _msg {  | 
| 
61
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $prog = basename($0);  | 
| 
62
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $type = shift;  | 
| 
63
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $msg = "@_";  | 
| 
64
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     chomp $msg;  | 
| 
65
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return "$prog: $type: $msg\n";  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # For internal use only.  A synonym for die() with a std error msg format.  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub fatal {  | 
| 
70
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     die _msg('Error', @_);  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # For internal use only.  A synonym for warn() with a std error msg format.  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub warning {  | 
| 
75
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     warn _msg('Warning', @_);  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # For internal use only.  Returns the ClearCase::Argv object.  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ct {  | 
| 
80
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $self = shift;  | 
| 
81
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self->{ST_CT} if $self->{ST_CT};  | 
| 
82
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (!defined(wantarray)) {  | 
| 
83
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $ct = ClearCase::Argv->new({autochomp=>1, outpathnorm=>1});  | 
| 
84
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$ct->syxargs($ct->qxargs);  | 
| 
85
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$self->{ST_CT} = $ct;  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
87
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self->{ST_CT};  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # For internal use only.  Returns a clone of the ClearCase::Argv object.  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clone_ct {  | 
| 
92
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $self = shift;  | 
| 
93
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $ct = $self->ct->clone(@_);  | 
| 
94
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     my $af = $self->ct->autofail  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           unless $_[0] and (ref($_[0]) eq 'HASH') and exists $_[0]->{autofail};  | 
| 
96
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $ct->autofail($af) if $af && ref($af); #Cloning doesn't share the value  | 
| 
97
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $ct;  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub gen_accessors {  | 
| 
101
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
5
 | 
     my @key = map {uc} @_;  | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
    | 
| 
102
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
     no strict 'refs';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
151
 | 
    | 
| 
103
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     for (@key) {  | 
| 
104
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 	my $var = "ST_$_";  | 
| 
105
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
 	my $meth = lc;  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	*$meth = sub {  | 
| 
107
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
 	    my $self = shift;  | 
| 
108
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $self->{$var} = shift if @_;  | 
| 
109
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    return $self->{$var};  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
111
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
93
 | 
     }  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 gen_accessors(qw(protect remove reuse vreuse lblver ignore_co overwrite_co  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		 snapdest ctime lbtype inclb cmp_func rellinks dstview));  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub gen_flags {  | 
| 
116
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
3
 | 
     my @key = map {uc} @_;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
117
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
     no strict 'refs';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
978
 | 
    | 
| 
118
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     for (@key) {  | 
| 
119
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
 	my $var = "ST_$_";  | 
| 
120
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	my $meth = lc;  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	*$meth = sub {  | 
| 
122
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 	    my $self = shift;  | 
| 
123
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{$var} = 1 if $_[0] || !defined(wantarray);  | 
| 
124
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    return $self->{$var};  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
126
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     }  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 gen_flags(qw(label_mods no_cr no_cmp));  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub comment {  | 
| 
131
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
132
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $cmnt = shift;  | 
| 
133
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (ref $cmnt) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
134
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_COMMENT} = $cmnt;  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($cmnt) {  | 
| 
136
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_COMMENT} = ['-c', $cmnt];  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
138
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_COMMENT};  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub normalize {  | 
| 
142
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
143
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     chomp(my $path = shift);  | 
| 
144
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dv = $self->dstview;  | 
| 
145
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $md = $self->mvfsdrive if MSWIN;  | 
| 
146
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for ($path) {  | 
| 
147
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (MSWIN) {  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    s%^$md:%%;  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    s%^[\\/]\Q$dv%%;  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    s%\\%/%g;  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $_ = "$md:/$dv$_";  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (CYGWIN) {  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # 4 cases: unc; /view/x user mount; view drive; mvfs drive/tag  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    s%^/(/?view/$dv|cygdrive/\w(/$dv)?)%%;  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $_ = "//view/$dv$_";  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
157
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    s%^/view/$dv%%;  | 
| 
158
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $_ =  "/view/$dv$_";  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
160
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	s%/\.?$%%;  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
162
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $path;  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub canonicalize {  | 
| 
166
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
167
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $base = shift;  | 
| 
168
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (@_) {  | 
| 
169
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	$_ = File::Spec->canonpath(join('/', $base, $_))  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			if $_ && ! File::Spec->file_name_is_absolute($_);  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Returns -other and -do private files. Checkouts are handled separately.  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _lsprivate {  | 
| 
176
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
     my $self = shift;  | 
| 
177
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $implicit_dirs = shift;  | 
| 
178
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $base = $self->dstbase;  | 
| 
179
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dv = $self->dstview;  | 
| 
180
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct({autofail=>0, stderr=>0});  | 
| 
181
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @vp;  | 
| 
182
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for ($ct->argv('lsp', [qw(-oth -do -s -inv), "$base/.", '-tag', $dv])->qx) {  | 
| 
183
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$_ = $self->normalize($_);  | 
| 
184
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	push(@vp, $_) if m%^\Q$base/%;  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
186
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     push(@vp, grep {$ct->des([qw(-s)], "$_/.\@\@")->stdout(0)->system}  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
187
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	   @{$self->{ST_IMPLICIT_DIRS}})  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			         if $self->{ST_IMPLICIT_DIRS} && $implicit_dirs;  | 
| 
189
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return @vp;  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _lsco {  | 
| 
193
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
     my $self = shift;  | 
| 
194
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $base = $self->_mkbase;  | 
| 
195
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct;  | 
| 
196
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sil = $self->clone_ct(stderr=>0, autofail=>0);  | 
| 
197
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %co;  | 
| 
198
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for ($ct->lsco([qw(-s -cvi -a)], $base)->qx) {  | 
| 
199
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$_ = $self->normalize($_);  | 
| 
200
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	$co{$_}++ if m%^\Q$base/% || $_ eq $base;  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
202
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $dir (@{$self->{ST_IMPLICIT_DIRS}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
203
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dad = dirname($dir);  | 
| 
204
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$co{$dad}++ if $sil->lsco([qw(-s -cvi -d)], $dad)->qx;  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
206
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return wantarray? sort keys %co : scalar keys %co;  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub mvfsdrive {  | 
| 
210
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
211
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (MSWIN && ! $self->{ST_MVFSDRIVE}) {  | 
| 
212
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
17
 | 
        no strict 'subs';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
    | 
| 
213
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
6
 | 
        use vars '$Registry';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1151
 | 
    | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        require Win32::TieRegistry;  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        # HKLM is read-only for non-admins so open read-only  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        Win32::TieRegistry->import('TiedRef', '$Registry', qw(KEY_READ));  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        my $LMachine = $Registry->Open('LMachine', {Access => KEY_READ});  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $self->{ST_MVFSDRIVE} = $LMachine->{SYSTEM}->  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        {CurrentControlSet}->{Services}->{Mvfs}->{Parameters}->{drive};  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        die "$0: Error: unable to find MVFS drive" unless $self->{ST_MVFSDRIVE};  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
222
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_MVFSDRIVE};  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ccsymlink {  | 
| 
226
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $dst = shift;  | 
| 
227
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return 1 if -l $dst;  | 
| 
228
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return 0 unless MSWIN || CYGWIN;  | 
| 
229
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = new ClearCase::Argv({autochomp=>1, stderr=>0});  | 
| 
230
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $ct->des([qw(-fmt %m)], $dst)->qx eq 'symbolic link';  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # readlink might work under some conditions (CC version, mount options, ...)  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub readcclink {  | 
| 
235
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $dst = shift;  | 
| 
236
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ret = readlink $dst;  | 
| 
237
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     return $ret if $ret || !(MSWIN || CYGWIN);  | 
| 
238
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = new ClearCase::Argv({autochomp=>1});  | 
| 
239
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ret = $ct->ls($dst)->qx;  | 
| 
240
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ret =~ s%\\%/%g if MSWIN;  | 
| 
241
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return (($ret =~ s/^.*? --> (.*)$/$1/)? $ret : '');  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub srcbase {  | 
| 
245
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
246
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (@_) {  | 
| 
247
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $sbase = File::Spec->rel2abs(shift);  | 
| 
248
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$sbase =~ s%\\%/%g;	# rel2abs forces native (\) separator  | 
| 
249
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$sbase =~ s%/\.$%%;	# workaround for bug in File::Spec 0.82  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# File::Spec::Win32::rel2abs leaves trailing / on drive letter root.  | 
| 
251
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$sbase =~ s%/*$%% if $sbase ne '/';  | 
| 
252
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_SRCBASE} = $sbase;  | 
| 
253
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 	*src_slink = sub { return -l shift };  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
254
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 	*src_rlink = sub { return readlink shift };  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
255
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (MSWIN || CYGWIN) {  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $ct = $self->clone_ct({autofail=>1, autochomp=>1});  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $olddir = getcwd;  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->_chdir($sbase) || die "$0: Error: $sbase: $!";  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($ct->pwv(['-s'])->qx !~ /\s+NONE\s+/) {  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		*src_slink = \&ccsymlink;  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		*src_rlink = \&readcclink;  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->_chdir($olddir);  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
266
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_SRCBASE};  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dstbase {  | 
| 
270
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
271
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (@_) {  | 
| 
272
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dbase = shift;  | 
| 
273
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	-e $dbase || mkpath($dbase, 0, 0777) || die "$0: Error: $dbase: $!";  | 
| 
274
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $ct = $self->clone_ct({autofail=>1, autochomp=>1});  | 
| 
275
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $olddir = getcwd;  | 
| 
276
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ct->_chdir($dbase) || die "$0: Error: $dbase: $!";  | 
| 
277
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dbase = getcwd;  | 
| 
278
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dv = $ct->pwv(['-s'])->qx;  | 
| 
279
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	die "$0: Error: destination base ($dbase) not in a view/VOB context"  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 						if !$dv || $dv =~ m%\sNONE\s%;  | 
| 
281
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->dstview($dv);  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# We need to derive the current vob of the dest path, which we  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# do by cd-ing there temporarily and running "ct desc -s vob:.".  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# But with a twist because of @%$* Windows.  | 
| 
285
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dvob;  | 
| 
286
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!($dvob = $self->dstvob)) {  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # We need this weird hack to get a case-correct version of the  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # dest path, in case the user typed it in random case. There  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # appears to be a bug in CC 4.2; "ct desc vob:foo" fails if  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # "foo" is not the right case even if MVFS is set to be  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # case insensitive. This is caseid v0869595, bugid CMBU00055321.  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # Since Windows mount points must be at the root level,  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # we assume the vob tag must be the root dir name. We must  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # still then look that up in lsvob to get the tag case right.  | 
| 
295
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (MSWIN) {  | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my @vobs = $ct->lsvob(['-s'])->qx;  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dirpart = (File::Spec->splitpath($dbase, 1))[1];  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		for my $name (File::Spec->splitdir($dirpart)) {  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    last if $dvob;  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    next unless $name;  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    for my $vob (@vobs) {  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			if ($vob =~ m%^[/\\]$name$%i) {  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			    ($dvob = $vob) =~ s%\\%/%g;  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			    last;  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    }  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
309
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$dvob = $ct->desc(['-s'], "vob:.")->qx;  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
311
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->dstvob($dvob);  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# On Windows, normalize the specified dstbase to use the  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# MVFS drive (typically M:), e.g. M:\view-name\vob-tag\path...  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# This avoids all kinds of problems with using the view  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# via a different drive letter or a UNC (\\view) path.  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Similarly, on UNIX we normalize to a view-extended path  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# even if we're already in a set view because it's the  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# lowest common denominator. Also, if the set view differs  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# from the 'dest view', the dest view should win.  | 
| 
321
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (MSWIN) {  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $dbase =~ s%\\%/%g;  | 
| 
323
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
 	    use vars '%RegHash';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10995
 | 
    | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    require Win32::TieRegistry;  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    Win32::TieRegistry->import('TiedHash', '%RegHash');  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $mdrive = $self->mvfsdrive;  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $dbase = getcwd;  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $dbase =~ s%.*?$dvob%$mdrive:/$dv$dvob%i;  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
330
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $dbase = getcwd;  | 
| 
331
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (CYGWIN) {  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        $dbase =~ s%^/(/?view/$dv|cygdrive/\w)%%;  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$dbase = "//view/$dv$dbase";  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
335
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        $dbase =~ s%^/view/$dv%%;  | 
| 
336
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$dbase = "/view/$dv$dbase";  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
339
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ct->_chdir($olddir) || die "$0: Error: $olddir: $!";  | 
| 
340
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_DSTBASE} = $dbase;  | 
| 
341
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	(my $dvb = $dbase) =~ s%^(.*?$dvob).*$%$1%;  | 
| 
342
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->snapdest(1) unless -e "$dvb/@@";  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
344
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_DSTBASE};  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # We may have created a view-private parent tree, so must  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # work our way upwards till we get to a versioned dir.  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _mkbase {  | 
| 
350
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
     my $self = shift;  | 
| 
351
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (! $self->{ST_MKBASE}) {  | 
| 
352
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $mbase = $self->dstbase;  | 
| 
353
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dvob = $self->dstvob;  | 
| 
354
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	(my $dext = $mbase) =~ s%(.*?$dvob)/.*%$1%;  | 
| 
355
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $ct = $self->clone_ct({stdout=>0, stderr=>0, autofail=>0});  | 
| 
356
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	while (1) {  | 
| 
357
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    last if length($mbase) <= length($dext);  | 
| 
358
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    last if -d $mbase && ! $ct->desc(['-s'], "$mbase/.@@")->system;  | 
| 
359
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    push(@{$self->{ST_IMPLICIT_DIRS}}, $mbase);  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $mbase = dirname($mbase);  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
362
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_MKBASE} = $mbase;  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
364
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_MKBASE};  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dstvob {  | 
| 
368
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
369
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (@_) {  | 
| 
370
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_DSTVOB} = shift;  | 
| 
371
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_DSTVOB} =~ s%\\%/%g;  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
373
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_DSTVOB};  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub srclist {  | 
| 
377
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
378
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $type = ref($_[0]) ? ${shift @_} : 'NORMAL';  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
379
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sbase = $self->srcbase;  | 
| 
380
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     die "$0: Error: must specify src base before src list" if !$sbase;  | 
| 
381
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (@_) {  | 
| 
382
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	next if $_ eq $sbase;  | 
| 
383
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (m%^(?:[a-zA-Z]:)?$sbase[/\\]*(.+)%) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
384
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$1}->{type} = $type;  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-e "$sbase/$_") {  | 
| 
386
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$_}->{type} = $type;  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
388
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warn "Warning: $_: no such file or directory\n";  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub srcmap {  | 
| 
394
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
395
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $type = ref($_[0]) ? ${shift @_} : 'NORMAL';  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
396
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %sdmap = @_;  | 
| 
397
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sbase = $self->srcbase;  | 
| 
398
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dbase = $self->dstbase;  | 
| 
399
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     die "$0: Error: must specify src base before src map" if !$sbase;  | 
| 
400
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     die "$0: Error: must specify dst base before src map" if !$dbase;  | 
| 
401
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (keys %sdmap) {  | 
| 
402
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (m%^(?:[a-zA-Z]:)?\Q$sbase\E[/\\]*(.*)$%) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
403
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $key = $1;  | 
| 
404
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$key}->{type} = $type;  | 
| 
405
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my($dst) = ($sdmap{$_} =~ m%^\Q$dbase\E[/\\]*(.+)$%);  | 
| 
406
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$key}->{dst} = $dst;  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-e $_) {  | 
| 
408
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$_}->{type} = $type;  | 
| 
409
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($sdmap{$_} =~ m%^\Q$dbase\E[/\\]*(.+)$%) {  | 
| 
410
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_SRCMAP}->{$_}->{dst} = $1;  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
412
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_SRCMAP}->{$_}->{dst} = $sdmap{$_};  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-e "$sbase/$_") {  | 
| 
415
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$_}->{type} = $type;  | 
| 
416
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_SRCMAP}->{$_}->{dst} = $sdmap{$_};  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
418
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warn "Warning: $_: no such file or directory\n";  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub eltypemap {  | 
| 
424
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
425
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     %{$self->{ST_ELTYPEMAP}} = @_ if @_;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
426
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_ELTYPEMAP} ? %{$self->{ST_ELTYPEMAP}} : ();  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dstcheck {  | 
| 
430
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
431
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dbase = $self->dstbase;  | 
| 
432
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     die "$0: Error: must specify dest base before dstcheck" if !$dbase;  | 
| 
433
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @existing = ();  | 
| 
434
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (-e $dbase) {  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Check for view private files under the dest base.  | 
| 
436
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @vp = $self->_lsprivate(0);  | 
| 
437
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $n = @vp;  | 
| 
438
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $s = $n == 1 ? '' : 's';  | 
| 
439
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $es = $n == 1 ? 's' : '';  | 
| 
440
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	die "$0: Error: $n view-private file$s exist$es under $dbase:\n @vp\n"  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 									if @vp;  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Check for checkouts under the dest base.  | 
| 
443
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@existing = $self->_lsco;  | 
| 
444
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$n = @existing;  | 
| 
445
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$s = $n >= 2 ? 's' : '';  | 
| 
446
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if ($n == 0) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # do nothing  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif ($self->ignore_co) {  | 
| 
449
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warning "skipping $n checkout$s under $dbase";  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif ($self->overwrite_co) {  | 
| 
451
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warning "overwriting $n checkout$s under $dbase";  | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
453
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    fatal("$n checkout$s found under $dbase");  | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
456
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->{ST_PRE} = { map {$_ => 1} @existing };  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Comparator function used to implement the -vreuse option  | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # If the default comparaison fails, look at versions of suitable size  | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # in the version tree, and apply the comparaison to them.  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # If a suitable version is found, add it to a list of versions on which  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # to apply a label.  | 
| 
464
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub vtcomp {  | 
| 
465
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my($self, $src, $dst) = @_;  | 
| 
466
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $cmp = $self->cmp_func;  | 
| 
467
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $lb = $self->lblver;  | 
| 
468
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($lb) {  | 
| 
469
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $lblver = "$dst\@\@/$lb";  | 
| 
470
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dst = $lblver if -r $lblver;  | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
472
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return 0 unless $cmp->($src, $dst);  | 
| 
473
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $vt = ClearCase::Argv->lsvtree([qw(-a -s -nco)]);  | 
| 
474
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @vt = reverse grep {m%[\\/]\d*$%} $vt->args($dst)->qx;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
475
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     chomp @vt;  | 
| 
476
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sz = -s $src;  | 
| 
477
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (@vt) {  | 
| 
478
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         next if -s $_ != $sz;  | 
| 
479
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!$cmp->($src, $_)) {  | 
| 
480
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    push @{$self->{ST_LBL}}, $_;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
481
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    return 0;  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
484
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return 1;  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _needs_update {  | 
| 
488
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
     my($self, $src, $dst, $comparator) = @_;  | 
| 
489
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $update = 0;  | 
| 
490
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     if (src_slink($src) && ccsymlink($dst)) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
491
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $srctext = src_rlink($src);  | 
| 
492
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $desttext = readcclink $dst;  | 
| 
493
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	$update = !defined($comparator) || ($srctext ne $desttext);  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (! src_slink($src) && ! ccsymlink($dst)) {  | 
| 
495
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!defined($comparator)) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
496
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $update = 1;  | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif ($self->vreuse) {  | 
| 
498
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $update = $self->vtcomp($src, $dst);  | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-s $src != -s $dst) {  | 
| 
500
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $update = 1;  | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
502
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $update = &$comparator($src, $dst);  | 
| 
503
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
504
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->failm("failed comparing $src vs $dst: $!") if $update < 0;  | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
506
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$update = 1;  | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
508
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     if ($update && (!exists($self->{ST_PRE}->{$dst}) || $self->overwrite_co)) {  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
509
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return 1;  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
511
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return 0;  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub checkcs {  | 
| 
516
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
517
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my($dest) = @_;  | 
| 
518
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = ClearCase::Argv->new({autofail=>1, autochomp=>1});  | 
| 
519
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $pwd = getcwd;  | 
| 
520
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ct->_chdir($dest) || die "$0: Error: $dest: $!";  | 
| 
521
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $dest = getcwd;  | 
| 
522
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @cs = grep /^\#\#:BranchOff: *root/, $ct->argv('catcs')->qx;  | 
| 
523
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ct->_chdir($pwd) || die "$0: Error: $pwd: $!";  | 
| 
524
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return scalar @cs;  | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
526
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub analyze {  | 
| 
528
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
529
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $type = ref($_[0]) ? ${shift @_} : 'NORMAL';  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
530
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sbase = $self->srcbase;  | 
| 
531
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dbase = $self->dstbase;  | 
| 
532
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     die "$0: Error: must specify dest base before analyzing" if !$dbase;  | 
| 
533
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     die "$0: Error: must specify dest vob before analyzing" if !$self->dstvob;  | 
| 
534
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->_mkbase;  | 
| 
535
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->{branchoffroot} = $self->checkcs($dbase);  | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Derive the add and modify lists by traversing the src map and  | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # comparing src/dst files.  | 
| 
538
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     delete $self->{ST_ADD};  | 
| 
539
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     delete $self->{ST_MOD};  | 
| 
540
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @sl = $dbase eq $self->{ST_MKBASE}? sort grep{-d $_}  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       $self->clone_ct->find($dbase, qw(-type l -print))->qx : ();  | 
| 
542
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     map { $_ = "/$_" } @sl if CYGWIN; # mismatch between conventions  | 
| 
543
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (@sl) {  | 
| 
544
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my %sl = map{ $_ => 1} @sl;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
545
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $l (@sl) {  | 
| 
546
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $s = $l;  | 
| 
547
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $s =~ s%^\Q$dbase\E/(.*)$%$1%;  | 
| 
548
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (exists $self->{ST_SRCMAP}->{$s}) {  | 
| 
549
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$s = join('/', $sbase, $s);  | 
| 
550
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		delete $sl{$l} if src_slink($s);  | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
553
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@sl = sort keys %sl;  | 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
555
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $comparator = $self->no_cmp ? undef : $self->cmp_func;  | 
| 
556
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SRC: for (sort keys %{$self->{ST_SRCMAP}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
557
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	next if $self->{ST_SRCMAP}->{$_}->{type} &&  | 
| 
558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_SRCMAP}->{$_}->{type} !~ /$type/;  | 
| 
559
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $src = join('/', $sbase, $_);  | 
| 
560
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	$src = $_ unless -e $src || src_slink($src);  | 
| 
561
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	my $dst = join('/', $dbase, $self->{ST_SRCMAP}->{$_}->{dst} || $_);  | 
| 
562
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $s (@sl) {  | 
| 
563
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($dst =~ /^\Q$s\E/) {  | 
| 
564
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_DIRLNK}->{$s} = 1;  | 
| 
565
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_ADD}->{$_}->{src} = $src;  | 
| 
566
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_ADD}->{$_}->{dst} = $dst;  | 
| 
567
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		next SRC;  | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# It's possible for a symlink to not satisfy -e if it's dangling.  | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Case-insensitive file test operators are a problem on Windows.  | 
| 
572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# You cannot modify files when they don't exist under the proper name.  | 
| 
573
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	if (! ecs($dst) && ! ccsymlink($dst)) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
574
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_ADD}->{$_}->{src} = $src;  | 
| 
575
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->{ST_ADD}->{$_}->{dst} = $dst;  | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (! -d $src || src_slink($src)) {  | 
| 
577
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($self->_needs_update($src, $dst, $comparator)) {  | 
| 
578
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_MOD}->{$_}->{src} = $src;  | 
| 
579
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_MOD}->{$_}->{dst} = $dst;  | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
581
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
582
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
583
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_DIRLNK}) {  | 
| 
584
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @rem;  | 
| 
585
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @slst = sort keys %{$self->{ST_DIRLNK}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
586
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (reverse @slst) {  | 
| 
587
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for my $l (@slst) {  | 
| 
588
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if (/^\Q$l\E./) {  | 
| 
589
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    push @rem, $_;  | 
| 
590
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    last;  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
592
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
594
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delete @{$self->{ST_DIRLNK}}{@rem} if @rem;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
595
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unlink $self->{ST_DIRLNK} unless keys %{$self->{ST_DIRLNK}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Last, check for subtractions but only if asked - it's potentially  | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # expensive and error-prone.  | 
| 
599
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return unless $self->remove;  | 
| 
600
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my(%dirs, %files, %xfiles);  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $wanted = sub {  | 
| 
602
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 	my $path = $File::Find::name;  | 
| 
603
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return if $path eq $dbase;  | 
| 
604
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if ($path =~ /lost\+found/) {  | 
| 
605
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $File::Find::prune = 1;  | 
| 
606
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    return;  | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Get a relative path from the absolute path.  | 
| 
609
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	(my $relpath = $path) =~ s%^\Q$dbase\E\W?%%;  | 
| 
610
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (ccsymlink($path)) { # Vob link  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
611
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $files{$relpath} = $path;  | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-d $path) {  | 
| 
613
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $dirs{$path} = $relpath;  | 
| 
614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-f $path) {  | 
| 
615
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $files{$relpath} = $path;  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
617
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
618
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     find($wanted, $dbase);  | 
| 
619
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %dst2src;  | 
| 
620
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (keys %{$self->{ST_SRCMAP}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
621
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dst = $self->{ST_SRCMAP}->{$_}->{dst};  | 
| 
622
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dst2src{$dst} = $_ if $dst;  | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
624
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (sort keys %files) {  | 
| 
625
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	next if $self->{ST_SRCMAP}->{$_} && !$self->{ST_SRCMAP}->{$_}->{dst};  | 
| 
626
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$xfiles{$files{$_}}++ if !$dst2src{$_};  | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
628
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->{ST_SUB}->{exfiles} = \%xfiles;  | 
| 
629
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->{ST_SUB}->{dirs} = \%dirs;  | 
| 
630
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub preview {  | 
| 
633
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
634
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $indent = ' ' x 4;  | 
| 
635
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my($adds, $mods, $subs) = (0, 0, 0);  | 
| 
636
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_DIRLNK}) {  | 
| 
637
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dl = keys %{$self->{ST_DIRLNK}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
638
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	print "Removing $dl directory symlinks:\n";  | 
| 
639
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (sort keys %{$self->{ST_DIRLNK}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
640
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    print "${indent}$_\n";  | 
| 
641
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
642
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
643
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_ADD}) {  | 
| 
644
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$adds = keys %{$self->{ST_ADD}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
645
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	print "Adding $adds elements:\n";  | 
| 
646
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (sort keys %{$self->{ST_ADD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
647
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    printf "$indent%s +=>\n\t%s\n", $self->{ST_ADD}->{$_}->{src},  | 
| 
648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			 $self->{ST_ADD}->{$_}->{dst};  | 
| 
649
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
650
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
651
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_MOD}) {  | 
| 
652
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$mods = keys %{$self->{ST_MOD}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
653
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	print "Modifying $mods elements:\n";  | 
| 
654
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (sort keys %{$self->{ST_MOD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
655
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    printf "$indent%s ==>\n\t%s\n", $self->{ST_MOD}->{$_}->{src},  | 
| 
656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			 $self->{ST_MOD}->{$_}->{dst};  | 
| 
657
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
658
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
659
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     if ($self->remove && $self->{ST_SUB}) {  | 
| 
660
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @exfiles = sort keys %{$self->{ST_SUB}->{exfiles}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
661
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$subs = @exfiles;  | 
| 
662
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	print "Subtracting $subs elements:\n" if $subs;  | 
| 
663
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (@exfiles) {  | 
| 
664
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    printf "$indent%s\n", $_;  | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
667
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $total = $adds + $mods + $subs;  | 
| 
668
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     print "Element change summary: add=$adds modify=$mods subtract=$subs\n";  | 
| 
669
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $total;  | 
| 
670
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
671
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
672
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub pbrtype {  | 
| 
673
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
674
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $bt = shift;  | 
| 
675
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct;  | 
| 
676
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $vob = $self->{ST_DSTVOB};  | 
| 
677
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!defined($self->{ST_PBTYPES}->{$bt})) {  | 
| 
678
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $tc = $ct->des([qw(-fmt %[type_constraint]p)],  | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			                              "brtype:$bt\@$vob")->qx;  | 
| 
680
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_PBTYPES}->{$bt} = ($tc =~ /one version per branch/);  | 
| 
681
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
682
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_PBTYPES}->{$bt};  | 
| 
683
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
684
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
685
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub branchco {  | 
| 
686
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
687
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dir = shift;  | 
| 
688
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @ele = @_;  | 
| 
689
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct({autochomp=>0});  | 
| 
690
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $rc;  | 
| 
691
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{branchoffroot}) {  | 
| 
692
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	foreach my $e (@ele) {  | 
| 
693
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $sel = $ct->ls(['-d'], $e)->autochomp(1)->qx;  | 
| 
694
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($sel =~ /^(.*?) +Rule:.*-mkbranch (.*?)\]?$/) {  | 
| 
695
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my ($ver, $bt) = ($1, $2);  | 
| 
696
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $sil = $self->clone_ct({stdout=>0, stderr=>0});  | 
| 
697
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $main = 'main';  | 
| 
698
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if ($sil->des(['-s'], "$e\@\@/main/0")->system) {  | 
| 
699
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $main = ($ct->lsvtree($e)->autochomp(1)->qx)[0];  | 
| 
700
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $main =~ s%^[^@]*\@\@[\\/](.*)\r?$%$1%;  | 
| 
701
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
702
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $re = $self->pbrtype($bt) ?  | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  qr([\\/]${main}[\\/]$bt[\\/]\d+$) : qr([\\/]$bt[\\/]\d+$);  | 
| 
704
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if ($ver =~ m%$re%) {  | 
| 
705
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $rc |= $ct->co($self->comment, $e)->system;  | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		} else {  | 
| 
707
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my $r = $ct->mkbranch([@{$self->comment}, '-ver',  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
708
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					      "/${main}/0", $bt], $e)->system;  | 
| 
709
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    if ($r) {  | 
| 
710
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$rc = 1;  | 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    } else {  | 
| 
712
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			if ($ver !~ m%\@\@[\\/]${main}[\\/]0$%) {  | 
| 
713
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			    $rc |= $dir ?  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				$ct->merge(['-to', $e],  | 
| 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					   $ver)->stdout(0)->system :  | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				$ct->merge(['-ndata', '-to', $e],  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					   $ver)->stdout(0)->system;  | 
| 
718
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			    unlink("$e.contrib");  | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    }  | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
723
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$rc |= $ct->co($self->comment, $e)->system;  | 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
725
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
727
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$rc = $ct->co($self->comment, @ele)->system;  | 
| 
728
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
729
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $rc;  | 
| 
730
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
731
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub rmdirlinks {  | 
| 
733
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
734
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return unless $self->{ST_DIRLNK};  | 
| 
735
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $lsco = ClearCase::Argv->lsco([qw(-s -d -cview)]);  | 
| 
736
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (sort {$b cmp $a} keys %{$self->{ST_DIRLNK}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
737
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dad = dirname $_;  | 
| 
738
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->branchco(1, $dad) unless $lsco->args($dad)->qx;  | 
| 
739
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->clone_ct->rm($_)->system;  | 
| 
740
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delete $self->{ST_SUB}->{exfiles}->{$_}; #If it is there  | 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
742
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
743
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
744
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub mkrellink {  | 
| 
745
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $src) = @_;  | 
| 
746
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $txt = src_rlink($src);  | 
| 
747
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sbase = $self->srcbase;  | 
| 
748
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     return $txt unless $self->{ST_RELLINKS} and ($txt =~ /^$sbase/);  | 
| 
749
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $txt =~ s%^$sbase/(.*)%$1%;  | 
| 
750
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $src =~ s%^$sbase/(.*)%$1%;  | 
| 
751
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @t = split m%/%, $txt;  | 
| 
752
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @s = split m%/%, $src;  | 
| 
753
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $i = 0;  | 
| 
754
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     while ($t[$i] eq $s[$i]) {  | 
| 
755
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$i++;  | 
| 
756
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	shift @t;  | 
| 
757
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	shift @s;  | 
| 
758
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
759
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     while ($i++ < $#s) { unshift @t, '..'; }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
760
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $txt = join '/', @t;  | 
| 
761
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $txt;  | 
| 
762
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
763
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
764
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Remove spurious names from restored directory  | 
| 
765
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub skimdir {  | 
| 
766
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $dst, $pfx) = @_;  | 
| 
767
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $flt = qr{^(\Q$pfx\E.*?)(?:/.*)?$}; # paths normalized  | 
| 
768
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     opendir(DIR, $dst);  | 
| 
769
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @f = grep !m%^\.\.?$%, readdir DIR;  | 
| 
770
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     closedir DIR;  | 
| 
771
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %ok = map {$_ => 1} grep s%$flt%$1%, keys %{$self->{ST_SRCMAP}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
772
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (@f) {  | 
| 
773
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $f = $pfx . $_;  | 
| 
774
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_SUB}->{exfiles}->{join('/', $dst, $_)}++ unless $ok{$f};  | 
| 
775
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
776
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
777
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub vtree {  | 
| 
779
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $dir) = @_;  | 
| 
780
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!exists $self->{ST_VT}->{$dir}) {  | 
| 
781
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $vt = ClearCase::Argv->lsvtree({autochomp=>1}, [qw(-a -s -nco)]);  | 
| 
782
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# optimization: branch/0 of a directory is either empty or duplicate  | 
| 
783
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @vt = reverse grep { m%[/\\](\d+)$% && $1>=1 } $vt->args($dir)->qx;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
784
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->{ST_VT}->{$dir} = \@vt;  | 
| 
785
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
786
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $self->{ST_VT}->{$dir};  | 
| 
787
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
788
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
789
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Once a directory version was found, move it first in the list for next tries  | 
| 
790
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub raise_dver {  | 
| 
791
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $i, $dir) = @_;  | 
| 
792
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return unless $i;  | 
| 
793
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $vt = $self->{ST_VT}->{$dir};  | 
| 
794
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ver = splice @{$vt}, $i, 1;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
795
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unshift @{$vt}, $ver;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
796
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
797
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
798
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Reuse from removed elements, or create as view private, directories  | 
| 
799
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub reusemkdir {  | 
| 
800
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $dref, $rref) = @_;  | 
| 
801
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my (%found, %dfound, %priv);  | 
| 
802
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $snapview = $self->snapdest;  | 
| 
803
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ds = ClearCase::Argv->desc({stderr=>1},[qw(-s)]);  | 
| 
804
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dm = ClearCase::Argv->desc([qw(-fmt %m)]);  | 
| 
805
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $rm = ClearCase::Argv->rm;  | 
| 
806
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $lsco = ClearCase::Argv->lsco([qw(-s -d -cview)]);  | 
| 
807
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ln = ClearCase::Argv->ln;  | 
| 
808
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $dst (sort keys %{$dref}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
809
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	next if $dfound{$dst};  | 
| 
810
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $reused;  | 
| 
811
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my($name, $dir) = fileparse($dst);  | 
| 
812
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!$priv{$dir}) {  | 
| 
813
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  if ($rref->{$dst}) {  | 
| 
814
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->branchco(1, $dir) unless $lsco->args($dir)->qx;  | 
| 
815
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $rm->args($dst)->system;  | 
| 
816
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  }  | 
| 
817
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  my $i = -1; #index in the vtree list  | 
| 
818
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	VER: for (@{$self->vtree($dir)}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
819
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $i++;  | 
| 
820
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dirext = "$_/$name";  | 
| 
821
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # case-insensitive file test operator on Windows is a problem  | 
| 
822
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($snapview ? $ds->args($dirext)->qx !~ /Error:/ : ecs($dirext)) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
823
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      next if $dm->args($dirext)->qx eq 'file element';  | 
| 
824
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      while (ccsymlink($dirext)) {  | 
| 
825
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$name = readcclink $dirext;  | 
| 
826
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$name =~ s/\@\@$//;  | 
| 
827
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$dirext = "$_/$name";  | 
| 
828
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# consider only relative, and local symlinks  | 
| 
829
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		next VER if !ecs($dirext) ||  | 
| 
830
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  $dm->args($dirext)->qx eq 'file element';  | 
| 
831
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      }  | 
| 
832
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $reused = 1;  | 
| 
833
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $self->raise_dver($i, $dir);  | 
| 
834
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $self->branchco(1, $dir) unless $lsco->args($dir)->qx;  | 
| 
835
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $ln->args($dirext, $dst)->system;  | 
| 
836
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      # Need to reevaluate all the files under this dir  | 
| 
837
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      # The case of implicit dirs, is recorded as '.'  | 
| 
838
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      my $d = $dref->{$dst} eq '.'? '' : $dref->{$dst} . '/';  | 
| 
839
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $self->skimdir($dst, $d) if $self->remove;  | 
| 
840
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      my $cmp = $self->no_cmp ? undef : $self->cmp_func;  | 
| 
841
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      my @keys = sort $d? grep m%^\Q$d\E%, keys %{$self->{ST_ADD}}  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
842
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		: keys %{$self->{ST_ADD}};  | 
| 
843
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      for my $e (@keys) {  | 
| 
844
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $edst = join '/', $self->dstbase, $e;  | 
| 
845
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my @intdir = split m%/%, $e;  | 
| 
846
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		pop @intdir;  | 
| 
847
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if (@intdir) {  | 
| 
848
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  my $dd = $self->dstbase;  | 
| 
849
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  my $pf = '';  | 
| 
850
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  while (my $id = shift @intdir) {  | 
| 
851
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $dd = join '/', $dd, $id;  | 
| 
852
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $pf = $pf . $id . '/';  | 
| 
853
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		    $self->skimdir($dd, $pf) if -d $dd && !$dfound{$dd}++;  | 
| 
854
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  }  | 
| 
855
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
856
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# Problem: does it match the type under srcbase?  | 
| 
857
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		if (-d $edst and !ccsymlink($edst)) { # We know it is empty  | 
| 
858
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  opendir(DIR, $edst);  | 
| 
859
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  my @f = grep !m%^\.\.?$%, readdir DIR;  | 
| 
860
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  closedir DIR;  | 
| 
861
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  if (@f) {  | 
| 
862
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $self->branchco(1, $edst)  | 
| 
863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		      unless $lsco->args($edst)->qx;  | 
| 
864
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $rm->args(map{join '/', $edst, $_} @f)->system;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
865
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  }  | 
| 
866
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  $dfound{$edst}++; #Skip in this loop  | 
| 
867
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  next;  | 
| 
868
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
869
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if (exists($self->{ST_ADD}->{$e}->{dst})) {  | 
| 
870
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  my $src = $self->{ST_ADD}->{$e}->{src};  | 
| 
871
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  my $dst = $self->{ST_ADD}->{$e}->{dst};  | 
| 
872
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  if (-e $dst) {  | 
| 
873
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $self->{ST_MOD}->{$e} = $self->{ST_ADD}->{$e}  | 
| 
874
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		      if $self->_needs_update($src, $dst, $cmp);  | 
| 
875
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $found{$e}++; #Remove from the add list  | 
| 
876
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  }  | 
| 
877
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
878
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      }  | 
| 
879
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      last;  | 
| 
880
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
881
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  }  | 
| 
882
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
883
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!$reused) {  | 
| 
884
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $err;  | 
| 
885
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    mkpath($dst, {error => \$err, verbose => 0, mode => 0777});  | 
| 
886
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    $self->failm(join(': ', %{$err->[0]})) if $err and @{$err};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
887
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $priv{"${dst}/"}++;  | 
| 
888
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
889
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
890
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return %found;  | 
| 
891
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
892
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
893
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # recursively record parent directories, and clashing objects to remove  | 
| 
894
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub recadd {  | 
| 
895
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $src, $dst, $dir, $rm, $seen) = @_;  | 
| 
896
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dad = dirname($dst);  | 
| 
897
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     return if $seen->{$dad}++ || (-d $dad && !ccsymlink($dad)); #exists, normal  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
898
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sdad = dirname($src);  | 
| 
899
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->recadd($sdad, $dad, $dir, $rm, $seen);  | 
| 
900
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     $rm->{$dad}++ if -f $dad || ccsymlink($dad); #something clashing: remove  | 
| 
901
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $dir->{$dad} = $sdad;  | 
| 
902
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
903
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
904
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub add {  | 
| 
905
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
906
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $sbase = $self->srcbase;  | 
| 
907
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $mbase = $self->_mkbase;  | 
| 
908
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct;  | 
| 
909
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return if ! $self->{ST_ADD};  | 
| 
910
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->reuse) { # First, reuse parent directories  | 
| 
911
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my (%dir, %rm, %dseen);  | 
| 
912
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# in the way if added in _mkbase as view private; ignore failures  | 
| 
913
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	rmdir($_) for reverse sort @{$self->{ST_IMPLICIT_DIRS}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
914
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $d (sort keys %{$self->{ST_ADD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
915
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $src = $self->{ST_ADD}->{$d}->{src};  | 
| 
916
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dst = $self->{ST_ADD}->{$d}->{dst};  | 
| 
917
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    $dir{$dst} = $d if -d $src && !src_slink($src); # empty dir  | 
| 
918
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $self->recadd($d, $dst, \%dir, \%rm, \%dseen);  | 
| 
919
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
920
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my %found = $self->reusemkdir(\%dir, \%rm);  | 
| 
921
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delete $self->{ST_ADD}->{$_} for keys %found;  | 
| 
922
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
923
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (sort keys %{$self->{ST_ADD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
924
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $src = $self->{ST_ADD}->{$_}->{src};  | 
| 
925
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dst = $self->{ST_ADD}->{$_}->{dst};  | 
| 
926
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $err;  | 
| 
927
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	if (-d $src && ! src_slink($src)) { # Already checked in the reuse case  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
928
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    -e $dst || mkpath($dst, {error=>\$err, verbose=>0, mode=>0777});  | 
| 
929
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    $self->failm(join(': ', %{$err->[0]})) if $err and @{$err};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
930
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (-e $src) {  | 
| 
931
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dad = dirname($dst);  | 
| 
932
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    -d $dad || mkpath($dad, {error=>\$err, verbose=>0, mode=>0777});  | 
| 
933
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    $self->failm(join(': ', %{$err->[0]})) if $err and @{$err};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
934
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (src_slink($src)) {  | 
| 
935
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		open(SLINK, ">$dst$lext") || $self->failm("$dst$lext: $!");  | 
| 
936
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		print SLINK $self->mkrellink($src), "\n";;  | 
| 
937
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		close(SLINK);  | 
| 
938
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
939
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_CI_FROM}->{$_} = $self->{ST_ADD}->{$_}  | 
| 
940
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					   if !exists($self->{ST_PRE}->{$dst});  | 
| 
941
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
942
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} elsif (src_slink($src)) { #Dangling symlink: import  | 
| 
943
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    open(SLINK, ">$dst$lext") || $self->failm("$dst$lext: $!");  | 
| 
944
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    print SLINK $self->mkrellink($src), "\n";;  | 
| 
945
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    close(SLINK);  | 
| 
946
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
947
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->failm("$src: no such file or directory");  | 
| 
948
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
949
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
950
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @candidates = sort $self->_lsprivate(1),  | 
| 
951
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			  map { $_->{dst} } values %{$self->{ST_CI_FROM}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
952
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return if !@candidates;  | 
| 
953
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We'll be separating the elements-to-be into files and directories.  | 
| 
954
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my(%files, @symlinks, %dirs);  | 
| 
955
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If the parent directories of any of the candidates are  | 
| 
956
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # already versioned, we'll need to check them out unless  | 
| 
957
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # it's already been done.  | 
| 
958
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @dads = sort map {dirname($_)} @candidates;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
959
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %lsd = map {split(/\s+Rule:\s+/, $_, 2)}  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
960
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$ct->argv('ls', [qw(-d -nxn -vis -vob)], @dads)->qx;  | 
| 
961
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $dad (keys %lsd) {  | 
| 
962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# If already checked out, nothing to do.  | 
| 
963
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	next if ! $lsd{$dad} || $lsd{$dad} =~ /CHECKEDOUT$/;  | 
| 
964
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Now we know it's an element which needs to be checked out.  | 
| 
965
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dad =~ s%\\%/%g if MSWIN;  | 
| 
966
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dirs{$dad}++;  | 
| 
967
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
968
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->branchco(1, keys %dirs) if keys %dirs;  | 
| 
969
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Process candidate directories here, then do files below.  | 
| 
970
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $mkdir = $self->clone_ct->mkdir({autofail=>0, autochomp=>0},  | 
| 
971
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				                               $self->comment);  | 
| 
972
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $cand (@candidates) {  | 
| 
973
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (! -d $cand) {  | 
| 
974
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($cand =~ /$lext$/) {  | 
| 
975
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		push(@symlinks, $cand);  | 
| 
976
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
977
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$files{$cand} = 1;  | 
| 
978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
979
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next;  | 
| 
980
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
981
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Now we know we're dealing with directories.  These cannot  | 
| 
982
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# exist at mkelem time so we move them aside, make  | 
| 
983
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# a versioned dir, then move all the files from the original  | 
| 
984
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# back into the new dir (still as view-private files).  | 
| 
985
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $tmpdir = "$cand.$$.keep.d";  | 
| 
986
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!rename($cand, $tmpdir)) {  | 
| 
987
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warn "$0: Error: can't rename '$cand' to '$tmpdir': $!\n";  | 
| 
988
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->fail;  | 
| 
989
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next;  | 
| 
990
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
991
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if ($mkdir->args($cand)->system) {  | 
| 
992
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warn "Warning: unable to rename $tmpdir back to $cand!"  | 
| 
993
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		                                unless rename($tmpdir, $cand);  | 
| 
994
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->fail;  | 
| 
995
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next;  | 
| 
996
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
997
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!opendir(DIR, $tmpdir)) {  | 
| 
998
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warn "$0: Error: $tmpdir: $!";  | 
| 
999
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->fail;  | 
| 
1000
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next;  | 
| 
1001
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1002
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	while (defined(my $i = readdir(DIR))) {  | 
| 
1003
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    next if $i eq '.' || $i eq '..';  | 
| 
1004
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    rename("$tmpdir/$i", "$cand/$i") || $self->failm("$cand/$i: $!");  | 
| 
1005
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1006
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	closedir DIR;  | 
| 
1007
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	rmdir $tmpdir || warn "$0: Error: $tmpdir: $!";  | 
| 
1008
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1009
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1010
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Optionally, reconstitute an old element of the same name if present.  | 
| 
1011
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->reuse) {  | 
| 
1012
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $snapview = $self->snapdest;  | 
| 
1013
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $ds = ClearCase::Argv->desc({stderr=>1}, [qw(-s)]);  | 
| 
1014
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dm = ClearCase::Argv->desc([qw(-fmt %m)]);  | 
| 
1015
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $ln = ClearCase::Argv->ln;  | 
| 
1016
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my %reused;  | 
| 
1017
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $elem (keys %files) {  | 
| 
1018
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my($name, $dir) = fileparse($elem);  | 
| 
1019
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $i = -1;  | 
| 
1020
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  DVER:  | 
| 
1021
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (@{$self->vtree($dir)}) {  | 
| 
1022
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$i++;  | 
| 
1023
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dirext = "$_/$name@@";  | 
| 
1024
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# case-insensitive file test operator on Windows is a problem  | 
| 
1025
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if ($snapview ? $ds->args($dirext)->qx !~ /Error:/ :  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1026
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 							    ecs("$_/$name")) {  | 
| 
1027
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    next if $dm->args("$_/$name")->qx =~ /^directory /;  | 
| 
1028
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    while (ccsymlink("$_/$name")) {  | 
| 
1029
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		        $name = readcclink "$_/$name";  | 
| 
1030
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$name =~ s/\@\@$//;  | 
| 
1031
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 			next DVER if !ecs("$_/$name") ||  | 
| 
1032
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			            $dm->args("$_/$name")->qx =~ /^directory /;  | 
| 
1033
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    }  | 
| 
1034
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $reused{$elem} = 1;  | 
| 
1035
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    delete $files{$elem};  | 
| 
1036
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    unlink($elem);  | 
| 
1037
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $ln->args("$_/$name", $elem)->system;  | 
| 
1038
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $self->raise_dver($i, $dir);  | 
| 
1039
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    last;  | 
| 
1040
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1041
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1042
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1043
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# If any elements were "reconstituted", they must be taken off the  | 
| 
1044
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# list of elems to be checked in explicitly, since 'ct ln' is  | 
| 
1045
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# just a directory op.  | 
| 
1046
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my %xkeys;  | 
| 
1047
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	if (!$self->no_cr && %reused) {  | 
| 
1048
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (keys %{$self->{ST_CI_FROM}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1049
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		if (exists($self->{ST_CI_FROM}->{$_})  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1050
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& exists($self->{ST_CI_FROM}->{$_}->{dst})  | 
| 
1051
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& exists($reused{$self->{ST_CI_FROM}->{$_}->{dst}})) {  | 
| 
1052
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $xkeys{$_} = 1;  | 
| 
1053
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1054
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1055
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (keys %xkeys) {  | 
| 
1056
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		delete $self->{ST_CI_FROM}->{$_};  | 
| 
1057
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1058
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1059
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Also, reconstituted elements may now be candidates for  | 
| 
1060
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# modification. Re-analyze the status for these. If any of  | 
| 
1061
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# them differ from their counterparts in the src area, copy  | 
| 
1062
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# them from the ADD list to the MOD list.  | 
| 
1063
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $comparator = $self->no_cmp ? undef : $self->cmp_func;  | 
| 
1064
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $elem (keys %{$self->{ST_ADD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1065
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (exists($reused{$self->{ST_ADD}->{$elem}->{dst}})) {  | 
| 
1066
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $src = $self->{ST_ADD}->{$elem}->{src};  | 
| 
1067
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dst = $self->{ST_ADD}->{$elem}->{dst};  | 
| 
1068
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if ($self->_needs_update($src, $dst, $comparator)) {  | 
| 
1069
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $self->{ST_MOD}->{$elem} = $self->{ST_ADD}->{$elem};  | 
| 
1070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1071
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1072
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1073
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1074
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (sort keys %{$self->{ST_CI_FROM}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1075
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $dst = $self->{ST_CI_FROM}->{$_}->{dst};  | 
| 
1076
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if ($files{$dst}) {  | 
| 
1077
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $src = $self->{ST_CI_FROM}->{$_}->{src};  | 
| 
1078
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    copy($src, $dst) || $ct->failm("$_: $!");  | 
| 
1079
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    utime(time(), (stat $src)[9], $dst) ||  | 
| 
1080
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	                                    warn "Warning: $dst: touch failed";  | 
| 
1081
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1082
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1083
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Now do the files in one fell swoop.  | 
| 
1084
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ct->mkelem($self->comment, sort keys %files)->system if %files;  | 
| 
1085
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1086
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Deal with symlinks.  | 
| 
1087
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $symlink (@symlinks) {  | 
| 
1088
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	(my $lnk = $symlink) =~ s/$lext$//;  | 
| 
1089
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (!open(SLINK, $symlink)) {  | 
| 
1090
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    warn "$symlink: $!";  | 
| 
1091
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next;  | 
| 
1092
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1093
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	chomp(my $txt = );  | 
| 
1094
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	close SLINK;  | 
| 
1095
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unlink $symlink;  | 
| 
1096
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ct->ln(['-s'], $txt, $lnk)->system;  | 
| 
1097
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1098
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1099
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Tried to use Cwd::abs_path, but it behaves differently on Cygwin and UNIX  | 
| 
1101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub absdst {  | 
| 
1102
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $dir, $f) = @_;  | 
| 
1103
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($f =~ /^\./) {  | 
| 
1104
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $sep = qr{[/\\]};  | 
| 
1105
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @d = split $sep, $dir;  | 
| 
1106
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	while ($f =~ s/^(\.\.?$sep)//) {  | 
| 
1107
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    pop @d if $1 =~ /^\.{2}/;  | 
| 
1108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1109
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dir = join '/', @d;  | 
| 
1110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1111
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return File::Spec->catfile($dir, $f);  | 
| 
1112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub modify {  | 
| 
1115
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
1116
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return if !keys %{$self->{ST_MOD}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1117
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my(%files, %symlinks);  | 
| 
1118
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (keys %{$self->{ST_MOD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1119
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (src_slink($self->{ST_MOD}->{$_}->{src})) {  | 
| 
1120
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $symlinks{$_}++;  | 
| 
1121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
1122
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $files{$_}++;  | 
| 
1123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1125
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $rm = $self->clone_ct('rmname');  | 
| 
1126
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ln = $self->clone_ct('ln');  | 
| 
1127
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ln->opts('-s', $ln->opts);  | 
| 
1128
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $lsco = ClearCase::Argv->lsco([qw(-s -d -cview)]);  | 
| 
1129
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $comparator = $self->no_cmp ? undef : $self->cmp_func;  | 
| 
1130
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (keys %files) {  | 
| 
1131
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my (@toco, @del);  | 
| 
1132
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $key (sort keys %files) {  | 
| 
1133
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $src = $self->{ST_MOD}->{$key}->{src};  | 
| 
1134
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dst = $self->{ST_MOD}->{$key}->{dst};  | 
| 
1135
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $new;  | 
| 
1136
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (ccsymlink($dst)) {  | 
| 
1137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        # The source is a file, but the destination is a symlink: look  | 
| 
1138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        # (recursively) at what this one points to, and link in this  | 
| 
1139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        # file.  | 
| 
1140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        # Build up the path of the destination, in such a way that it  | 
| 
1141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        # may be found, or not, in the hash.  | 
| 
1142
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dangling;  | 
| 
1143
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $sep = qr%[/\\]%;  | 
| 
1144
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dst1 = $dst;  | 
| 
1145
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        while (ccsymlink($dst1)) {  | 
| 
1146
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my $tgt = readcclink $dst1;  | 
| 
1147
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my $dir = dirname $dst1;  | 
| 
1148
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $tgt = $self->absdst($dir, $tgt) unless $tgt =~ m%^[/\\]%;  | 
| 
1149
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $tgt =~ s%\\%/%g if MSWIN;  | 
| 
1150
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    if (-e $tgt) {  | 
| 
1151
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$dst1 = $tgt;  | 
| 
1152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    } else {  | 
| 
1153
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$dangling = 1;  | 
| 
1154
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			last;  | 
| 
1155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    }  | 
| 
1156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1157
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dir = dirname($dst);  | 
| 
1158
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->branchco(1, $dir) unless $lsco->args($dir)->qx;  | 
| 
1159
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->clone_ct->rm($dst)->system; #remove the first symlink  | 
| 
1160
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		if ($dangling || !$self->{ST_SUB}->{exfiles}->{$dst1}) {  | 
| 
1161
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    if (!copy($src, $dst)) {  | 
| 
1162
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			warn "$0: Error: $dst: $!\n";  | 
| 
1163
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$rm->fail;  | 
| 
1164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    }  | 
| 
1165
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    utime(time(), (stat $src)[9], $dst) ||  | 
| 
1166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		      warn "Warning: $dst: touch failed";  | 
| 
1167
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $self->clone_ct->mkelem($self->comment, $dst)->system;  | 
| 
1168
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $new = 1;  | 
| 
1169
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    delete $self->{ST_MOD}->{$key};  | 
| 
1170
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    push @del, $key;  | 
| 
1171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		} else {  | 
| 
1172
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my $dir1 = dirname($dst1);  | 
| 
1173
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		    $self->branchco(1, $dir1)  | 
| 
1174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		              unless ($dir eq $dir1) || $lsco->args($dir1)->qx;  | 
| 
1175
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $self->clone_ct->mv($dst1, $dst)->system;  | 
| 
1176
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    delete $self->{ST_SUB}->{exfiles}->{$dst1}; #done already  | 
| 
1177
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    if (!$self->_needs_update($src, $dst, $comparator)) {  | 
| 
1178
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			delete $self->{ST_MOD}->{$key};  | 
| 
1179
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			push @del, $key;  | 
| 
1180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    }  | 
| 
1181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1183
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    push(@toco, $dst) unless exists($self->{ST_PRE}->{$dst}) || $new;  | 
| 
1184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1185
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->branchco(0, @toco) if @toco;  | 
| 
1186
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delete @files{@del};  | 
| 
1187
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (sort keys %files) {  | 
| 
1188
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $src = $self->{ST_MOD}->{$_}->{src};  | 
| 
1189
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dst = $self->{ST_MOD}->{$_}->{dst};  | 
| 
1190
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next if exists($self->{ST_PRE}->{$dst});  | 
| 
1191
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($self->no_cr) {  | 
| 
1192
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if (!copy($src, $dst)) {  | 
| 
1193
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    warn "$0: Error: $dst: $!\n";  | 
| 
1194
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $rm->fail;  | 
| 
1195
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    next;  | 
| 
1196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1197
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		utime(time(), (stat $src)[9], $dst) ||  | 
| 
1198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				            warn "Warning: $dst: touch failed";  | 
| 
1199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
1200
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$self->{ST_CI_FROM}->{$_} = $self->{ST_MOD}->{$_};  | 
| 
1201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1204
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (keys %symlinks) {  | 
| 
1205
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my %checkedout = map {$_ => 1} $self->_lsco;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1206
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (sort keys %symlinks) {  | 
| 
1207
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $txt = $self->mkrellink($self->{ST_MOD}->{$_}->{src});  | 
| 
1208
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $lnk = $self->{ST_MOD}->{$_}->{dst};  | 
| 
1209
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dad = dirname($lnk);  | 
| 
1210
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (!$checkedout{$dad}) {  | 
| 
1211
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$checkedout{$dad} = 1 if ! $self->branchco(1, $dad);  | 
| 
1212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1213
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if (!$rm->args($lnk)->system) {  | 
| 
1214
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        my @fil = grep /^\Q$lnk\E/, keys %{$self->{ST_SUB}->{exfiles}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1215
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	        delete @{$self->{ST_SUB}->{exfiles}}{@fil};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1216
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		delete $self->{ST_SUB}->{dirs}{$lnk};  | 
| 
1217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1218
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ln->args($txt, $lnk)->system;  | 
| 
1219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub subtract {  | 
| 
1224
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
1225
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return unless $self->{ST_SUB};  | 
| 
1226
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct;  | 
| 
1227
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %co = map {$_ => 1} $self->_lsco;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1228
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $exnames = $self->{ST_SUB}->{exfiles}; # Entries to remove  | 
| 
1229
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my (%dir, %keep); # Directories respectively to inspect, and to keep  | 
| 
1230
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $dir{dirname($_)}++ for keys %{$exnames};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1231
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $dir{$_}++ for keys %{$self->{ST_SUB}->{dirs}}; # Existed originally  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1232
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dbase = $self->dstbase;  | 
| 
1233
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $d (sort {$b cmp $a} keys %dir) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1234
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	next if $keep{$d};  | 
| 
1235
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my ($k) = ($d =~ m%^\Q$dbase\E/(.*)$%);  | 
| 
1236
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	if ($k and $self->{ST_SRCMAP}->{$k}) {  | 
| 
1237
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    delete $exnames->{$d};  | 
| 
1238
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dad = $d;  | 
| 
1239
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    $keep{$dad}++ while $dad = dirname($dad) and $dad gt $dbase;  | 
| 
1240
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next;  | 
| 
1241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1242
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (opendir(DIR, $d)) {  | 
| 
1243
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my @entries = grep !/^\.\.?$/, readdir DIR;  | 
| 
1244
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    closedir(DIR);  | 
| 
1245
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    map { $_ = join('/', $d, $_) } @entries;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1246
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    if (grep { !$exnames->{$_} and $ct->ls(['-s'], $_)->qx !~ /\@$/}  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		  @entries) { # Something not to delete--some version selected  | 
| 
1248
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dad = $d;  | 
| 
1249
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		$keep{$dad}++ while $dad = dirname($dad) and $dad gt $dbase;  | 
| 
1250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    } else {  | 
| 
1251
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		if (@entries) {  | 
| 
1252
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my @co = grep {$co{$_}} @entries; # Checkin before removing  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1253
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    $ct->ci($self->comment, @co)->system if @co;  | 
| 
1254
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    delete @$exnames{@entries}; # Remove the contents  | 
| 
1255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1256
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$exnames->{$d}++; # Add the container  | 
| 
1257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1260
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     delete @$exnames{keys %keep};  | 
| 
1261
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @exnames = keys %{$exnames};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1262
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $dad (map {dirname($_)} @exnames) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1263
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$self->branchco(1, $dad) unless $co{$dad}++;  | 
| 
1264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Force because of possible checkouts in other views. Fail for unreachable  | 
| 
1266
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ct->rm([@{$self->comment}, '-f'], @exnames)->system if @exnames;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub label {  | 
| 
1270
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
1271
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     my $lbtype = shift || $self->lbtype;  | 
| 
1272
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return unless $lbtype;  | 
| 
1273
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dbase = $self->dstbase;  | 
| 
1274
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct({autochomp=>0});  | 
| 
1275
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ctq = $self->clone_ct({stdout=>0});  | 
| 
1276
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ctbool = $self->clone_ct({autofail=>0, stdout=>0, stderr=>0});  | 
| 
1277
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dvob = $self->dstvob;  | 
| 
1278
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $locked;  | 
| 
1279
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($ctbool->lstype(['-s'], "lbtype:$lbtype\@$dvob")->system) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1280
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ct->mklbtype($self->comment, "lbtype:$lbtype\@$dvob")->system;  | 
| 
1281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (!$self->inclb) {  | 
| 
1282
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$locked = $ct->lslock(['-s'], "lbtype:$lbtype\@$dvob")->qx;  | 
| 
1283
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ct->unlock("lbtype:$lbtype\@$dvob")->system if $locked;  | 
| 
1284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Allow for labelling errors, in case of hard links: only the link  | 
| 
1286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # recorded can be labelled, the other being seen as 'removed'  | 
| 
1287
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     if ($self->label_mods || $self->inclb) {  | 
| 
1288
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @mods = $self->_lsco;  | 
| 
1289
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	push @mods, @{$self->{ST_LBL}} if $self->{ST_LBL};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1290
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (@mods) {  | 
| 
1291
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ctbool->mklabel([qw(-nc -rep), $self->inclb], @mods)->system  | 
| 
1292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	                                                      if $self->inclb;  | 
| 
1293
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ctbool->mklabel([qw(-nc -rep), $lbtype], @mods)->system;  | 
| 
1294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
1296
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $lbl = $self->lblver;  | 
| 
1297
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if ($lbl) {  | 
| 
1298
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $ct = $self->clone_ct({autochomp=>1, autofail=>0, stderr=>0});  | 
| 
1299
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    my @rv = grep{ s/^(.*?)(?:@@(.*))/$1/ &&  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			     ($2 =~ /CHECKEDOUT$/ || !-r "$_\@\@/$lbl") }  | 
| 
1301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $ct->ls([qw(-r -vob -s)], $dbase)->qx,  | 
| 
1302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	      $ct->ls([qw(-d -vob -s)], $dbase)->qx;  | 
| 
1303
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ctbool->mklabel([qw(-nc -rep), $lbtype], $dbase, @rv)->system;  | 
| 
1304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
1305
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ctbool->mklabel([qw(-nc -rep -rec), $lbtype], $dbase)->system;  | 
| 
1306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Possibly move the label back to the right versions  | 
| 
1308
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ctbool->mklabel([qw(-nc -rep), $lbtype], @{$self->{ST_LBL}})->system  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	                                                   if $self->{ST_LBL};  | 
| 
1310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# Last, label the ancestors of the destination back to the vob tag.  | 
| 
1311
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my($dad, @ancestors);  | 
| 
1312
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $min = length($self->normalize($dvob));  | 
| 
1313
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for ($dad = dirname($dbase);  | 
| 
1314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			         length($dad) >= $min; $dad = dirname($dad)) {  | 
| 
1315
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    push(@ancestors, $dad);  | 
| 
1316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1317
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ctq->mklabel([qw(-rep -nc), $lbtype], @ancestors)->system  | 
| 
1318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 								if @ancestors;  | 
| 
1319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1320
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->clone_ct->lock("lbtype:$lbtype\@$dbase")->system if $locked;  | 
| 
1321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_addhash {  | 
| 
1324
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
1325
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_ADD}) {  | 
| 
1326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return  | 
| 
1327
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    map { $self->{ST_ADD}->{$_}->{src}, $self->{ST_ADD}->{$_}->{dst} }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1328
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		keys %{$self->{ST_ADD}};  | 
| 
1329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
1330
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return ();  | 
| 
1331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_modhash {  | 
| 
1335
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
1336
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_MOD}) {  | 
| 
1337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return  | 
| 
1338
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    map { $self->{ST_MOD}->{$_}->{src}, $self->{ST_MOD}->{$_}->{dst} }  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1339
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		keys %{$self->{ST_MOD}};  | 
| 
1340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
1341
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return ();  | 
| 
1342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_sublist {  | 
| 
1346
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
1347
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{ST_SUB}) {  | 
| 
1348
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return sort keys %{$self->{ST_SUB}->{exfiles}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
1350
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	return ();  | 
| 
1351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub checkin {  | 
| 
1355
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
1356
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $mbase = $self->_mkbase;  | 
| 
1357
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dad = dirname($mbase);  | 
| 
1358
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @ptime = qw(-pti) unless $self->ctime;  | 
| 
1359
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @cmnt = @{$self->comment};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1360
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct({autochomp=>0});  | 
| 
1361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If special eltypes are registered, chtype them here.  | 
| 
1362
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (my %emap = $self->eltypemap) {  | 
| 
1363
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for my $re (keys %emap) {  | 
| 
1364
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my @chtypes = grep {/$re/} map {$self->{ST_ADD}->{$_}->{dst}}  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1365
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				       keys %{$self->{ST_ADD}};  | 
| 
1366
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    next unless @chtypes;  | 
| 
1367
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->chtype([@cmnt, '-f', $emap{$re}], @chtypes)->system;  | 
| 
1368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Do one-by-one ci's with -from (to preserve CR's) unless  | 
| 
1371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # otherwise requested.  | 
| 
1372
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (! $self->no_cr) {  | 
| 
1373
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (keys %{$self->{ST_CI_FROM}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1374
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $src = $self->{ST_CI_FROM}->{$_}->{src};  | 
| 
1375
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $dst = $self->{ST_CI_FROM}->{$_}->{dst};  | 
| 
1376
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->ci([@ptime, @cmnt, qw(-ide -rm -from), $src], $dst)->system;  | 
| 
1377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1378
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delete @{$self->{ST_MOD}}{keys %{$self->{ST_CI_FROM}}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Check-in first the files modified under the recorded names,  | 
| 
1381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # in case of hardlinks, since checking the other link first  | 
| 
1382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # in a pair would fail.  | 
| 
1383
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @mods;  | 
| 
1384
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     push @mods, $self->{ST_MOD}->{$_}->{dst} for  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1385
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        grep {!ccsymlink($self->{ST_MOD}->{$_}->{dst})} keys %{$self->{ST_MOD}};  | 
| 
1386
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ct->ci([@cmnt, '-ide', @ptime], sort @mods)->system if @mods;  | 
| 
1387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Check in anything not handled above.  | 
| 
1388
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %checkedout = map {$_ => 1} $self->_lsco;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1389
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @todo = grep {m%^\Q$mbase%} keys %checkedout;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1390
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     @todo = grep {!exists($self->{ST_PRE}->{$_})} @todo if $self->ignore_co;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1391
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unshift(@todo, $dad) if $checkedout{$dad};  | 
| 
1392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Sort reverse in case the checked in versions are not selected by the view  | 
| 
1393
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $ct->argv('ci', [@cmnt, '-ide', @ptime], sort {$b cmp $a} @todo)->system  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                                                       if @todo;  | 
| 
1395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Fix the protections of the target files if requested. Unix files  | 
| 
1396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # get careful consideration of bitmasks etc; Windows files just get  | 
| 
1397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # promoted to a+x if their extension looks executable.  | 
| 
1398
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->protect) {  | 
| 
1399
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (MSWIN) {  | 
| 
1400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my @exes;  | 
| 
1401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (keys %{$self->{ST_ADD}}) {  | 
| 
1402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		next unless m%\.(bat|cmd|exe|dll|com|cgi|.?sh|pl)$%i;  | 
| 
1403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		push(@exes, $self->{ST_ADD}->{$_}->{dst});  | 
| 
1404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->argv('protect', [qw(-chmod a+x)], @exes)->system if @exes;  | 
| 
1406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
1407
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my %perms;  | 
| 
1408
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (keys %{$self->{ST_ADD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1409
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $src = $self->{ST_ADD}->{$_}->{src};  | 
| 
1410
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dst = $self->{ST_ADD}->{$_}->{dst};  | 
| 
1411
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $src_mode = (stat $src)[2];  | 
| 
1412
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dst_mode = (stat $dst)[2];  | 
| 
1413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# 07551 represents the only bits that matter to clearcase  | 
| 
1414
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		if (($src_mode & 07551) ne ($dst_mode & 07551) &&  | 
| 
1415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$src !~ m%\.(?:p|html?|gif|mak|rc|ini|java|  | 
| 
1416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				    c|cpp|cxx|h|bmp|ico)$|akefile%x) {  | 
| 
1417
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my $sym = sprintf("%o", ($src_mode & 07775) | 0444);  | 
| 
1418
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    push(@${$perms{$sym}}, $dst);  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1421
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (keys %{$self->{ST_MOD}}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1422
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $src = $self->{ST_MOD}->{$_}->{src};  | 
| 
1423
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dst = $self->{ST_MOD}->{$_}->{dst};  | 
| 
1424
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $src_mode = (stat $src)[2];  | 
| 
1425
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my $dst_mode = (stat $dst)[2];  | 
| 
1426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# 07551 represents the only bits that matter to clearcase  | 
| 
1427
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 		if (($src_mode & 07551) ne ($dst_mode & 07551) &&  | 
| 
1428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$src !~ m%\.(?:p|html?|gif|mak|rc|ini|java|  | 
| 
1429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				    c|cpp|cxx|h|bmp|ico)$|akefile%x) {  | 
| 
1430
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    my $sym = sprintf("%o", ($src_mode & 07775) | 0444);  | 
| 
1431
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		    push(@${$perms{$sym}}, $dst);  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
1433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1434
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    for (keys %perms) {  | 
| 
1435
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$ct->argv('protect', ['-chmod', $_], @${$perms{$_}})->system;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub cleanup {  | 
| 
1442
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
1443
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $mbase = $self->_mkbase;  | 
| 
1444
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $dad = dirname($mbase);  | 
| 
1445
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $ct = $self->clone_ct({autofail=>0});  | 
| 
1446
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @vp = $self->_lsprivate(1);  | 
| 
1447
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (sort {$b cmp $a} @vp) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1448
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (-d $_) {  | 
| 
1449
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    rmdir $_ || warn "$0: Error: unable to remove $_\n";  | 
| 
1450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} else {  | 
| 
1451
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	    unlink $_ || warn "$0: Error: unable to remove $_\n";  | 
| 
1452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1454
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my %checkedout = map {$_ => 1} $self->_lsco;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1455
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @todo = grep {m%^\Q$mbase%} keys %checkedout;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1456
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     @todo = grep {!exists($self->{ST_PRE}->{$_})} @todo  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				    if $self->ignore_co || $self->overwrite_co;  | 
| 
1458
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unshift(@todo, $dad) if $checkedout{$dad};  | 
| 
1459
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($self->{branchoffroot}) {  | 
| 
1460
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	for (sort {$b cmp $a} @todo) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1461
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $b = $ct->ls([qw(-s -d)], $_)->qx;  | 
| 
1462
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $ct->unco([qw(-rm)], $_)->system;  | 
| 
1463
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    if ($b =~ s%^(.*)[\\/]CHECKEDOUT$%$1%) {  | 
| 
1464
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		opendir BR, $b or next;  | 
| 
1465
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		my @f = grep !/^(\.\.?|0|LATEST)$/, readdir BR;  | 
| 
1466
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		closedir BR;  | 
| 
1467
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$ct->rmbranch([qw(-f)], $b)->system unless @f;  | 
| 
1468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    }  | 
| 
1469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
1471
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$ct->unco([qw(-rm)], sort {$b cmp $a} @todo)->system if @todo;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Undo current work and exit. May be called from an exception handler.  | 
| 
1476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub fail {  | 
| 
1477
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
1478
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $rc = shift;  | 
| 
1479
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->ct->autofail(0);	# avoid exception-handler loop  | 
| 
1480
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->cleanup;  | 
| 
1481
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     exit(defined($rc) ? $rc : 2);  | 
| 
1482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub failm {  | 
| 
1485
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my ($self, $msg, $rc) = @_;  | 
| 
1486
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     warn "$0: Error: $msg\n";  | 
| 
1487
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->fail($rc);  | 
| 
1488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub version {  | 
| 
1491
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $self = shift;  | 
| 
1492
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $ClearCase::SyncTree::VERSION;  | 
| 
1493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Here 'ecs' means Exists Case Sensitive. We don't generally  | 
| 
1496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # want the case-insensitive file test operators on Windows.  | 
| 
1497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # The underlying problem is that cleartool is always case  | 
| 
1498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # sensitive. I.e. you can mkelem 'Foo' and then open 'foo'  | 
| 
1499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # if you have the right MVFS settings, but you cannot check  | 
| 
1500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # out or describe 'foo', only 'Foo'.  | 
| 
1501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # This could lead to other problems on Windows though, since you  | 
| 
1502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # may create evil twins if you subtract an old name and  | 
| 
1503
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # then add it under a name which differs only by case.  But at  | 
| 
1504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # least that does work, whereas trying to checkout a path  | 
| 
1505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # with the wrong case does not work at all.  Let the evil twin  | 
| 
1506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # trigger handle the evil twin scenario.  | 
| 
1507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub ecs {  | 
| 
1508
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $file = shift;  | 
| 
1509
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $rc = 0;  | 
| 
1510
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (MSWIN || CYGWIN) {  | 
| 
1511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if (opendir DIR, dirname($file)) {  | 
| 
1512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    my $match = basename($file);  | 
| 
1513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    # Faster than for/last when not found!  | 
| 
1514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    $rc = 1 if grep {$_ eq $match} readdir DIR;  | 
| 
1515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    closedir DIR;  | 
| 
1516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
1517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
1518
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$rc = -e $file;  | 
| 
1519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1520
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $rc;  | 
| 
1521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
1524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |