Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
###############################################################################
2
# CLASS Clearcase::LsCmd
3
# This class inherits from the CCCmpdProc and executes the cleartool command
4
# "ls" with args "-recurse -long" to list all files in cwd.
5
#
6
# It overrider the CCProcess member to process the resultant output from the ls
7
# command and store information about all files/dirs in and below the pwd.
8
# 
9
# It uses the CCIgnore class to determine if a file should be ignored or included
10
# in the processing of the cmd output.
11
#
12
# It stores as a result of the command for each file/dir
13
# NAME      = The full path of the file (as defined by CCCmdProc)
14
# STATE     = File NAME State (CHECKEDOUT, CHECKIN, PRIVATE)
15
# VERSION   = If state=CHECKEDIN Then current version of NAME in view 
16
#             If state=CHECKEDOUT Then version of NAME that the checkout was from
17
# ANNOTATION= Any Special Annotations returned by ls on NAME
18
###############################################################################
19
 
20
package Clearcase::LsCmd;
21
 
22
use strict;
23
use Cwd qw/ abs_path /;
24
use DeployUtils::Logger;
25
use Clearcase::IgnoreList;
26
use Clearcase::CmdProc;
27
 
28
use vars qw( @ISA );
29
 
30
@ISA = qw( Clearcase::CmdProc );
31
 
32
# Globally defined states
33
our $StateCheckedIn  = "CHECKEDIN";
34
our $StateCheckedOut = "CHECKEDOUT";
35
our $StatePrivate    = "PRIVATE";
36
 
37
#==============================================================================
38
#   Constructor
39
#==============================================================================
40
sub new
41
{
42
    my $obclass = shift;
43
    my $class = ref($obclass) || $obclass;
44
    my $dir = shift;
45
 
46
    LogDebug("Clearcase::LsCmd::new Instantiating new object of class $class");
47
 
48
    # if no dir of dir is "." the get full absolute path, abs_path returns path with "/" regardless of platform
49
    $dir = abs_path(".") if ( ! defined($dir) || $dir eq "." );    
50
    # however if passed in make sure we change \ to /
51
    $dir =~ s|\\|/|g;
52
 
53
    # Call base class's constructor
54
    my $self = $class->SUPER::new();
55
 
56
    # Add this class's data to the class object
57
    $self->{_FINDDIR} = $dir;
58
    $self->{_IGNOREFILES} = 1;
59
    $self->{_IGNORECOUNT} = 0;
60
 
61
    #indexes used
62
    # State index is a hash of hashes of arrays.  The contents of _STATE are hashes keyed on global states
63
    # These hashes contain an array of element numbers into the FILEINFO array
64
    # The branch & annotation are similar but keyed on branches and annotations
65
    $self->{_STATE}      = {};
66
    $self->{_BRANCH}     = {};
67
    $self->{_ANNOTATION} = {};
68
 
69
    bless($self, $class);
70
 
71
    # set Clearcase command and arg
72
    $self->CCcmd("ls");
73
    $self->CCargs("-long");
74
 
75
    return $self;
76
}   # new
77
 
78
 
79
#==============================================================================
80
#   ignoreFiles
81
# Sets & returns the ignore files variable that determines whether to use the 
82
# IgnoreFiles class for files to ignore
83
#==============================================================================
84
sub ignoreFiles
85
{
86
    my $self = shift;
87
 
88
    if ( @_ )
89
    {
90
        $self->{_IGNOREFILES} = shift;
91
        LogDebug("ClearCase::LsCmd::ignoreFiles Set to $self->{_IGNOREFILES}");
92
    }
93
    return $self->{_IGNOREFILES};
94
}   # ignoreFiles
95
 
96
 
97
#==============================================================================
98
#   CCexecute
99
# simply adds dir to args and runs base class CCexecute
100
#==============================================================================
101
sub CCexecute
102
{
103
    my $self = shift;
104
    my $args = $self->CCargs();
105
 
106
    # search directory first
107
    $self->CCargs("$args -directory $self->{_FINDDIR}");
108
    $self->SUPER::CCexecute();
109
    # now serach the contents
110
    $self->CCargs("$args -recurse $self->{_FINDDIR}");
111
    $self->SUPER::CCexecute();
112
 
113
}   # CCexecute
114
 
115
#==============================================================================
116
#   CCprocess overrides base class's CCProcess to process result
117
#==============================================================================
118
sub CCprocess
119
{
120
    my $self = shift;
121
    my $line;
122
    my ($name, $state, $version, $branch, $annotation ) = ( "", "", "", "", "" );
123
    my $index;
124
    my $dirRE = $self->{_FINDDIR};
125
 
126
    # Change the search RE for the findDir so that all occurances of "/" in path are changed to "[/\\]" 
127
    # to match either type of path separator
128
    $dirRE =~ s|/|\[/\\\\\]|g;
129
 
130
NEXTLINE:
131
    while ( $line = $self->getline() )
132
    {
133
        chomp $line;
134
        $line =~ s/\r//g;    # remove carraige returns
135
 
136
        # ignore blank lines or lines with directory ".*" with quotes
137
        next NEXTLINE if ( $line =~ /^\s*$/ || $line =~ /directory\s*\".*\":/ );
138
 
139
        if ( $line =~ /^view private object\s*(.*)\s*$/ )
140
        {
141
            $name       = $1;
142
            $state      = $StatePrivate;
143
            $version    = "";
144
            $branch     = "";
145
            $annotation = "";
146
            if ( $self->{_IGNOREFILES} && Clearcase::IgnoreList->ignoreFile($name) )
147
            {
148
                LogDebug("Clearcase::LsCmd::CCProcess Ignoring Private file $name");
149
                $self->{_IGNORECOUNT}++;
150
                next NEXTLINE;
151
            }
152
        }
153
        elsif ( $line =~ /^(?:directory |)version\s*(.*)\@\@(.*)$/ )
154
        {
155
            # got the file name, & rest of line
156
            $name = $1;
157
            $line = $2;
158
 
159
            # remove the Rule: from the end of the line as we dont need it
160
            $line =~ s/\s*Rule: .*$//;
161
 
162
            # Check for annotations & store, removing from line
163
            $line =~ s/\s*\[(.*)\]\s*$//;
164
            if ( defined($1) )
165
            {   $annotation = $1; }
166
            else
167
            {   $annotation = ""; }
168
 
169
            # See if Checked out state
170
            if ( $line =~ /^.*CHECKEDOUT from (.*)$/ )
171
            {
172
                $state = $StateCheckedOut;
173
                $version = $1;  # version is version checked out from
174
            }
175
            else
176
            {
177
                $state = $StateCheckedIn;
178
                $version = $line;
179
            }
180
            $branch = $version;
181
            # remove version number and dir separator from version to get branch
182
            $branch =~ s|[/\\]\d*$||;
183
        }
184
        else
185
        {
186
            LogError("-x", "Clearcase::LsCmd::CCprocess Unknown Input Line as follows");
187
            LogError("$line");
188
        }                                                                        
189
 
190
        # Remove findDir from path if find dir is same as pwd, makes it less clutered
191
        $name =~ s|$dirRE|\.| if ( $self->CCcwd() =~ m|^$dirRE| );
192
 
193
        # Add name to file list and set it as current element
194
        $index = $self->addToFileList($name);
195
        # now add other elements, the index is remembered in the base class
196
        $self->updateCurrentFile("STATE", $state, "VERSION", $version, "ANNOTATION", $annotation);
197
 
198
        # update indexes
199
        push(@{$self->{_STATE}{$state}}, $index);
200
        push(@{$self->{_BRANCH}{$branch}}, $index) if ( $branch ne "" );
201
        push(@{$self->{_ANNOTATION}{$annotation}}, $index) if ( $annotation ne "" );
202
    }
203
}   # process
204
 
205
 
206
#==============================================================================
207
#   getNumByState - Returns the number of items found by state
208
#==============================================================================
209
sub getNumByState
210
{
211
    my $self = shift;
212
    my $state = shift;
213
    my $retval;
214
 
215
    if ( $state eq $StateCheckedIn )
216
    {
217
        $retval = $#{$self->{_STATE}{$StateCheckedIn}} + 1;
218
    }
219
    elsif ( $state eq $StateCheckedOut )
220
    {
221
        $retval = $#{$self->{_STATE}{$StateCheckedOut}} + 1;
222
    }
223
    elsif ( $state eq $StatePrivate )
224
    {
225
        $retval = $#{$self->{_STATE}{$StatePrivate}} + 1;
226
    }
227
    else
228
    {
229
        LogError("Clearcase::LsCmd::getNumByState Invalid State supplied");
230
    }
231
    return $retval;
232
}   # getNumByState
233
 
234
 
235
#==============================================================================
236
#   getListByState - Returns a reference to an array of files by state
237
#==============================================================================
238
sub getListByState
239
{
240
    my $self = shift;
241
    my $state = shift;
242
    my @retval;
243
 
244
    if ( $state eq $StateCheckedIn )
245
    {
246
        foreach my $index ( @{$self->{_STATE}{$StateCheckedIn}} )
247
        {
248
            push(@retval, $self->getElement($index)->{NAME});
249
        }
250
    }
251
    elsif ( $state eq $StateCheckedOut )
252
    {
253
        foreach my $index ( @{$self->{_STATE}{$StateCheckedOut}} )
254
        {
255
            push(@retval, $self->getElement($index)->{NAME});
256
        }
257
    }
258
    elsif ( $state eq $StatePrivate )
259
    {
260
        foreach my $index ( @{$self->{_STATE}{$StatePrivate}} )
261
        {
262
            push(@retval, $self->getElement($index)->{NAME});
263
        }
264
    }
265
    else
266
    {
267
        LogError("Clearcase::LsCmd::getListByState Invalid State supplied");
268
    }
269
    return \@retval;
270
}   # getListByState
271
 
272
 
273
#==============================================================================
274
#   getNumBranches - Returns number of branches found
275
#==============================================================================
276
sub getNumBranches
277
{
278
    my $self = shift;
279
    return scalar keys %{$self->{_BRANCH}};
280
}   # getNumBranches
281
 
282
 
283
#==============================================================================
284
#   getListBranches - Returns a reference to an array of branches found
285
#==============================================================================
286
sub getListBranches
287
{
288
    my $self = shift;
289
    my @retval;
290
 
291
    @retval = keys %{$self->{_BRANCH}};
292
    return \@retval;
293
}   # getListBranches
294
 
295
 
296
#==============================================================================
297
#   getNumFilesByBranch - Returns the number of files associated to the supplied branch
298
#==============================================================================
299
sub getNumFilesByBranch
300
{
301
    my $self = shift;
302
    my $branch = shift;
303
    my $retval = undef;
304
 
305
    if ( defined($branch) && defined($self->{_BRANCH}{$branch}) )
306
    {
307
        $retval = $#{$self->{_BRANCH}{$branch}} + 1;
308
    }
309
    return $retval;
310
}   # getNumFilesByBranch
311
 
312
 
313
#==============================================================================
314
#   getListFilesByBranch - Returns a reference to an array of files found in the
315
# supplied branch
316
#==============================================================================
317
sub getListFilesByBranch
318
{
319
    my $self = shift;
320
    my $branch = shift;
321
    my @retval;
322
 
323
    if ( defined($branch) && defined($self->{_BRANCH}{$branch}) )
324
    {
325
        foreach my $index ( @{$self->{_BRANCH}{$branch}} )
326
        {
327
            push(@retval, $self->getElement($index)->{NAME});
328
        }
329
    }
330
    return \@retval;
331
}   # getListFilesByBranch
332
 
333
 
334
#==============================================================================
335
#   getNumAnnotations - Returns number of Annotations found
336
#==============================================================================
337
sub getNumAnnotations
338
{
339
    my $self = shift;
340
    return scalar keys %{$self->{_ANNOTATION}};
341
}   # getNumAnnotations
342
 
343
 
344
#==============================================================================
345
#   getListAnnotations - Returns a reference to an array of Annotations found
346
#==============================================================================
347
sub getListAnnotations
348
{
349
    my $self = shift;
350
    my @retval;
351
 
352
    @retval = keys %{$self->{_ANNOTATION}};
353
    return \@retval;
354
}   # getListAnnotations
355
 
356
 
357
#==============================================================================
358
#   getNumFilesByAnnotation - Returns the number of files associated to the supplied Annotation
359
# If supplied is all then it returns the total number of files with annotations
360
#==============================================================================
361
sub getNumFilesByAnnotation
362
{
363
    my $self = shift;
364
    my $annotation = shift;
365
    my $retval = undef;
366
 
367
    if ( defined($annotation) )
368
    {
369
        if ( $annotation =~ /all/i )
370
        {
371
            $retval = 0;
372
            foreach my $annot ( keys %{$self->{_ANNOTATION}} )
373
            {
374
                $retval += $#{$self->{_ANNOTATION}{$annot}} + 1
375
            }
376
        }
377
        if ( defined($self->{_ANNOTATION}{$annotation}) )
378
        {
379
            $retval = $#{$self->{_ANNOTATION}{$annotation}} + 1;
380
        }
381
    }
382
    return $retval;
383
}   # getNumFilesByAnnotation
384
 
385
 
386
#==============================================================================
387
#   getListFilesByAnnotation - Returns a reference to an array of files found 
388
# with the supplied Annotation
389
#==============================================================================
390
sub getListFilesByAnnotation
391
{
392
    my $self = shift;
393
    my $annotation = shift;
394
    my @retval;
395
 
396
    if ( defined($annotation) && defined($self->{_ANNOTATION}{$annotation}) )
397
    {
398
        foreach my $index ( @{$self->{_ANNOTATION}{$annotation}} )
399
        {
400
            push(@retval, $self->getElement($index)->{NAME});
401
        }
402
    }
403
    return \@retval;
404
}   # getListFilesByAnnotation
405
 
406
 
407
#==============================================================================
408
# getNumIgnored
409
# Returns the number of files ignored.
410
#==============================================================================
411
sub getNumIgnored
412
{
413
    my $self = shift;
414
 
415
    return $self->{_IGNORECOUNT};
416
}   # getNumIgnored
417
1;