Removed /usr/local from CDPATH
[clearscm.git] / CCDB / update.pl
1 #!/usr/bin/perl
2
3 =pod
4
5 =head1 NAME $RCSfile: update.pl,v $
6
7 Updates the CCDB database
8
9 =head1 VERSION
10
11 =over
12
13 =item Author
14
15 Andrew DeFaria <Andrew@ClearSCM.com>
16
17 =item Revision
18
19 $Revision: 1.4 $
20
21 =item Created:
22
23 Fri Mar 11 19:09:52 PST 2011
24
25 =item Modified:
26
27 $Date: 2011/05/05 18:37:05 $
28
29 =back
30
31 =head1 SYNOPSIS
32
33  Usage update.pl: [-u|sage] [-ve|rbose] [-deb|ug]
34  
35                   [-vo|b <vob>]
36  
37                   [[-p|vob <pvob>]|
38                    [[-p|vob <pvob> -a|ctivity <activity>]|
39                     [-p|vob <pvob> -b|aseline <baseline>]|
40                     [-p|vob <pvob> -s|tream <stream>]]]
41                     
42                   [-o|plog [<vob>]]
43                   
44                   [-c|heckchangesets]
45                    
46  Where:
47    -u|sage:       Displays usage
48  
49    -ve|rbose:     Be verbose
50    -deb|ug:       Output debug messages
51    
52    -vo|b <vob>:           Vob to process
53  
54    -p|vob <pvob>:         PVOB to operate on
55    -a|ctivity <activity>: Activity to process
56    -b|aseline <baseline>: Baseline to process
57    -s|tream <stream>:     Stream to process
58    
59    -o|plog [<vob>]:       Process oplog (Default: All vobs)
60    
61    -ch
62      
63 =head1 DESCRIPTION
64
65 This script updates the CCDB database with Clearcase UCM meta data. It operates
66 in 2 modes.
67
68 =head2 Update mode
69
70 In this mode, indicated by specifying either no options or a -pvob and 
71 optionally one of -activity, -baseline or -stream, update.pl will query 
72 Clearcase and gather all metadata for the specified option. 
73
74 You can run update.pl with no paramters to process all pvobs in the current
75 registry region of you can specify a -pvob to process. This is generally how
76 the script is run. Note you can parallelize update.pl by running it multiple
77 times each with its own -pvob. In this case the script will log activity to
78 update.<pvob>.log.
79
80 Or you can run "fix ups" to add individual activities, baselines or streams by
81 specifying -activity (or -baseline/-stream) and its -pvob. Note however that
82 the object is not validated (In such cases we don't check that say activity and
83 pvob are valid - we just add them to the database).
84
85 Additionally you can use -vob to add a vob to CCDB. This should be a relatively
86 infrequent operation and it is necessary to add vobs that -oplog will process.
87
88 =head2 Check Change Sets mode
89
90 Even with this script initially popullating CCDB and with the appropriate 
91 triggers set to fire to keep CCDB up to date, and even with -oplog mode to apply
92 changes from other sites the CCDB may still become out of sync with Clearcase. 
93 This is due to the fact that orphaned files can effect change set membership in
94 UCM and Clearcase does not call any triggers or otherwise notify you of the 
95 problem. To illustrate, if the user is running under UCM and checks out a 
96 directory, makes an element and checks it in, but then cancels the checkout of
97 the directory, Clearcase is forced to orphan the file by placing it in 
98 lost+found. A warning is issued to the user, however no triggers are called. 
99
100 Investigating the change set we see that the elements that were orphaned are
101 indicated in the change set but their paths have been altered to indicate that
102 the elements are in lost+found! One would think that Clearcase would fire the
103 chactivity trigger but it seems that trigger is only fired when elements change
104 from one activity to another. In this case the elements are changing, but the
105 activity is the same activity. To me this is a bug and Clearcase should fire the
106 chactivity trigger with CLEARCASE_ACTIVITY == CLEARCASE_TO_ACTIVITY. If this 
107 were the case we could handle this situation with triggers.
108
109 Check change set mode instead goes through all of the changesets in CCDB and
110 verifies that the changeset in CCDB matches the changeset as listed by 
111 lsactivity -long. If not it updates it. This is an intense activity that will
112 be time consuming but I can see no other way to fix up this problem.
113
114 =cut
115
116 use strict;
117 use warnings;
118
119 use FindBin;
120 use Getopt::Long;
121
122 use lib "$FindBin::Bin/lib", "$FindBin::Bin/../lib";
123
124 use CCDB;
125 use Clearcase;
126 use Clearcase::Vob;
127 use Clearcase::UCM;
128 use Clearcase::UCM::Activity;
129 use Clearcase::Element;
130 use Display;
131 use Logger;
132 use TimeUtils;
133 use Utils;
134
135 my $VERSION  = '$Revision: 1.4 $';
136   ($VERSION) = ($VERSION =~ /\$Revision: (.*) /);
137
138 my (%opts, %totals, $log);
139
140 my $ccdb = CCDB->new;
141
142 # Forwards
143 sub ProcessFolder ($$);
144
145 sub changeset ($$) {
146   my ($activity, $pvob) = @_;
147   
148   $pvob = Clearcase::vobtag $pvob;
149   
150   my $cmd = "lsact -fmt \"%[versions]CQp\" $activity\@$pvob";
151
152   my ($status, @output) = $Clearcase::CC->execute ($cmd);
153
154   $log->err ("Unable to execute $cmd\n" . join ("\n", @output), $status)
155     if $status;
156
157   # Need to split up change set. It's presented to us as quoted and space 
158   # separated however the change set elements themselves can have spaces in 
159   # them! e.g.:
160   #
161   #   "/vob/foo/file name with spaces@@/main/1", "/vob/foo/file name2@@/main/2"
162   #
163   # So we'll split on '", ""'! Note that this will leave us with the first
164   # element with a leading '"' and the last element with a trailing '"' which
165   # we will have to handle.
166   #
167   # Additionally we will call collapseOverExtendedViewPathname to normalize
168   # the over extended pathnames to element hashes.
169   my (@changeset);
170   
171   @output = split /\", \"/, $output[0]
172     if $output[0];
173   
174   foreach (@output) {
175     # Skip any cleartool warnings. We are getting warnings of the form:
176     # "A version in the change set of activity "63332.4" is currently 
177     # unavailable". Probably some sort of subtle corruption that we can ignore.
178     # (It should be fixed but we aren't going to be doing that here!)
179     next if /cleartool: Warning/;
180
181     # Strip any remaining '"'s
182     s/^\"//; s/\"$//;
183
184     # Remove vob prefix but keep the leading "/"
185     $_ = '/' . Clearcase::vobname $_;
186     
187     my %element = Clearcase::Element::collapseOverExtendedVersionPathname $_;
188     
189     push @changeset, \%element;
190   } # foreach
191   
192   return @changeset;
193 } # changeset
194
195 sub baselineActivities (%) {
196   my (%baseline) = @_;
197   
198   my $pvobTag = Clearcase::vobtag $baseline{pvob};
199   
200   my $cmd = "lsbl -fmt \"%[activities]p\" $baseline{name}\@$pvobTag";
201   
202   my ($status, @output) = $Clearcase::CC->execute ($cmd);
203   
204   $log->err ("Unable to execute $cmd\n" . join ("\n", @output), $status)
205     if $status;
206     
207   $output[0] ||= '';
208
209   return split / /, $output[0];
210 } # baselineActivities
211
212 sub UpdatePvob ($) {
213   my ($pvob) = @_;
214   
215   my %pvob = $ccdb->GetVob ($pvob);
216   
217   return if %pvob;
218   
219   my ($err, $msg) = $ccdb->AddVob ({
220     name => $pvob,
221     type => 'ucm',
222   });
223   
224   if ($err) {
225     $log->err ("Unable to add pvob:$pvob\n$msg");
226   } else {
227     $totals{'Pvobs added'}++;
228       
229     $log->msg ("Added pvob:$pvob");
230   } # if
231   
232   return;
233 } # UpdatePvob
234
235 sub UpdateFolder ($$) {
236   my ($folder, $pvob) = @_;
237   
238   my %folder = $ccdb->GetFolder ($folder, $pvob);
239   
240   return if %folder;
241   
242   my ($err, $msg) = $ccdb->AddFolder ({
243     name => $folder,
244     pvob => $pvob,
245   });
246   
247   if ($err) {
248     $log->err ("Unable to add folder:$folder\n$msg");
249   } else {
250     $totals{'Folders added'}++;
251     
252     $log->msg ("Added folder:$folder");
253   } # if
254   
255   return;
256 } # UpdateFolder
257
258 sub UpdateSubfolder ($$$) {
259   my ($parent, $subfolder, $pvob) = @_;
260   
261   my %subfolder = $ccdb->GetSubfolder ($parent, $subfolder, $pvob);
262   
263   return if %subfolder;
264   
265   my ($err, $msg) = $ccdb->AddSubfolder ({
266     parent    => $parent,
267     subfolder => $subfolder,
268     pvob      => $pvob,
269   });
270   
271   if ($err) {
272     $log->err ("Unable to add subfolder:$parent/$subfolder\n$msg");
273   } else {
274     $totals{'Subfolders added'}++;
275     
276     $log->msg ("Added subfolder:$parent/$subfolder");
277   } # if
278   
279   return;
280 } # UpdateSubfolder
281
282 sub UpdateProject ($$$) {
283   my ($project, $folder, $pvob) = @_;
284   
285   my %project = $ccdb->GetProject ($project, $folder, $pvob);
286   
287   return if %project;
288   
289   my ($err, $msg) = $ccdb->AddProject ({
290     name   => $project,
291     folder => $folder,
292     pvob   => $pvob,
293   });
294   
295   if ($err) {
296     $log->err ("Unable to add project:$project folder:$folder pvob:$pvob\n$msg");
297   } else {
298     $totals{'Projects added'}++;
299     
300     $log->msg ("Added Project:$project");
301   } # if
302   
303   return;
304 } # UpdateProject
305
306 sub UpdateStream ($$) {
307   my ($name, $pvob) = @_;
308   
309   my %stream = $ccdb->GetStream ($name, $pvob);
310     
311   return if %stream;
312
313   # Determine the integration stream for this stream's project. First get
314   # project for the stream.
315   my $pvobTag = Clearcase::vobtag ($pvob);
316
317   my $cmd = "lsstream -fmt \"%[project]p\" $name\@$pvobTag";
318   
319   my ($status, @output) = $Clearcase::CC->execute ($cmd);
320   
321   if ($status) {
322     $log->err ("Unable to execute $cmd\n" . join ("\n", @output));
323
324     return;
325   } # if
326
327   # Now get the intergration stream for this project
328   $cmd = "lsproject -fmt \"%[istream]p\" $output[0]\@$pvobTag";
329   
330   ($status, @output) = $Clearcase::CC->execute ($cmd);
331   
332   if ($status) {
333     $log->err ("Unable to execute $cmd\n" . join ("\n", @output));
334     
335     return;
336   } # if
337
338   my $type = 'integration'
339     if $name eq $output[0];
340
341   my ($err, $msg) = $ccdb->AddStream ({
342     name => $name,
343     pvob => $pvob,
344     type => $type,    
345   });
346
347   if ($err) {
348     $log->err ( "Unable to add stream:$name\n$msg");
349   } else {
350     $log->msg ("Added stream:$name");
351     $totals{'Streams added'}++;
352   } # if
353 } # UpdateStream
354
355 sub UpdateChangeset ($$$) {
356   my ($activity, $pvob, $element) = @_;
357   
358   my %element = (
359     name    => '/' . Clearcase::vobname $element->pname,
360     version => $element->version,
361   );
362   
363   my %changeset = $ccdb->GetChangeset (
364     $activity, 
365     '/' . Clearcase::vobname $element->pname,
366     $element->version,
367     $pvob,
368   );
369   
370   return if %changeset;
371   
372   my ($err, $msg) = $ccdb->AddChangeset ({
373     activity => $activity,
374     element  => $element{name},
375     version  => $element{version},
376     pvob     => $pvob,
377       
378   });
379   
380   if ($err) {
381     $log->err ("Unable to add changeset activity:$activity "
382              . "element:$element{name}$Clearcase::SFX$element{version}\n$msg");
383   } else {
384     $totals{'Changesets added'}++;
385
386     $log->msg ("Linked activity:$activity -> element:$element{name}");  
387   } # if
388
389   return;
390 } # UpdateChangeset
391
392 sub UpdateActivity ($$) {
393   my ($name, $pvob) = @_;
394   
395   my %activity = $ccdb->GetActivity ($name, $pvob);
396     
397   return if %activity;
398
399   my ($err, $msg) = $ccdb->AddActivity ({
400     name => $name,
401     pvob => $pvob,
402   });
403
404   if ($err) {
405     $log->err ("Unable to add activity:$name\n$msg");
406   } else {
407     $totals{'Activities added'}++;
408
409     $log->msg ("Added activity $name");
410   } # if
411   
412   return;  
413 } # UpdateActivity
414
415 sub UpdateBaselineActivityXref (%) {
416   my (%baseline) = @_;
417   
418   $log->msg ("Processing Baseline Activities for $baseline{name}");
419
420   my %baselineActivityXref = (
421     baseline => $baseline{name},
422     pvob     => $baseline{pvob},
423   );
424   
425   foreach (baselineActivities %baseline) {
426     my ($err, $msg);
427     
428     # Often activities in a baseline have not yet been added so add them here.
429     # (Not sure why this is the case...)
430     
431     my %existingRec = $ccdb->GetActivity ($_, $baseline{pvob});
432     
433     UpdateActivity $_, $baseline{pvob}
434       unless %existingRec;
435     
436     $baselineActivityXref{activity} = $_;
437     
438     %existingRec = $ccdb->GetBaselineActivityXref (
439       $baselineActivityXref{baseline},
440       $baselineActivityXref{activity},
441       $baselineActivityXref{pvob}
442     );
443     
444     unless (%existingRec) {
445       ($err, $msg) = $ccdb->AddBaselineActivityXref (\%baselineActivityXref);
446
447       if ($err) {
448         $log->err ("Unable to add baseline:$baselineActivityXref{name}"
449                  . " activity: $baselineActivityXref{activity}\n"
450                  . $msg
451         );
452       } else {
453         $totals{'Baseline Activity Xrefs added'}++;
454       } # if
455     } # unless
456   } # foreach
457
458   $log->msg ("Processed Baseline Activities for $baseline{name}");
459   
460   return;
461 } # UpdateBaselineActivityXref
462
463 sub UpdateBaseline ($$) {
464   my ($name, $pvob) = @_;
465   
466   my %baseline = $ccdb->GetBaseline ($name, $pvob);
467     
468   return if %baseline;
469
470   my ($err, $msg) = $ccdb->AddBaseline ({
471     name => $name,
472     pvob => $pvob, 
473   });
474
475   if ($err) {
476     $log->err ("Unable to add baseline:$name\n$msg");
477   } else {
478     $totals{'Baselines added'}++;
479     
480     $log->msg ("Added baseline:$name");
481     
482     my %baseline = $ccdb->GetBaseline ($name, $pvob);
483       
484     UpdateBaselineActivityXref (%baseline);
485   } # if
486   
487   return;
488 } # Updatebaseline
489
490 sub UpdateStreamActivityXref ($$$) {
491   my ($stream, $activity, $pvob) = @_;
492   
493   my %streamActivityXref = $ccdb->GetStreamActivityXref (
494     $stream,
495     $activity,
496     $pvob,
497   );
498   
499   return if %streamActivityXref;
500   
501   my ($err, $msg) = $ccdb->AddStreamActivityXref ({
502     stream   => $stream,
503     activity => $activity,
504     pvob     => $pvob,
505   });
506   
507   if ($err) {
508     $log->err ("Unable to add stream_activity_xref stream:$stream "
509              . "activity:$activity\n$msg");
510     return;
511   } else {
512     $totals{'Stream Activity Xrefs added'}++;
513     
514     $log->msg ("Linked stream:$stream -> activity:$activity");  
515   } # if
516
517   return;
518 } # UpdateStreamActivityXref
519
520 sub ProcessElements ($$) {
521   my ($name, $pvob) = @_;
522   
523   $log->msg ("Finding changeset for activity:$name");
524   
525   my $activity = Clearcase::UCM::Activity->new ($name, $pvob);
526   
527   foreach ($activity->changeset) {
528     my ($element) = $_;
529     
530     # Remove vob prefix but keep the leading "/"
531     my $elementName = '/' . Clearcase::vobname $element->pname;
532         
533     $log->msg (
534       "Processing element:$elementName"
535     . $Clearcase::SFX
536     . $element->version
537     );
538
539     UpdateChangeset $name, $pvob, $element;    
540   } # foreach;
541   
542   $log->msg ("Processed changeset for activity:$name");
543
544   return;
545 } # ProcessElements
546
547 sub ProcessActivities ($$) {
548   my ($stream, $pvob) = @_;
549   
550   $log->msg ("Finding activities in stream:$stream");
551   
552   my $pvobTag = Clearcase::vobtag ($pvob);
553   
554   my $cmd = "lsstream -fmt \"%[activities]p\" $stream\@$pvobTag";
555   
556   my ($status, @output) = $Clearcase::CC->execute ($cmd);
557
558   if ($status) {
559     $log->err ("Unable to execute $cmd\n" . join ("\n", @output), $status);
560     
561     return;
562   } # if
563
564   $output[0] ||= '';
565   
566   foreach (sort split / /, $output[0]) {
567     next if /^DEFAULT.*NO_CHECKIN/;
568
569     UpdateActivity ($_, $pvob);
570     
571     $totals{'Activities processed'}++;
572     
573     UpdateStreamActivityXref $stream, $_, $pvob;
574     
575     ProcessElements $_, $pvob;
576   } # foreach
577   
578   $log->msg ("Processed activities in stream:$stream");
579   
580   return;
581 } # ProcessActivities
582
583 sub ProcessBaselines ($$) {
584   my ($stream, $pvob) = @_;
585   
586   $log->msg ("Finding baselines in stream:$stream");
587   
588   my $pvobTag = Clearcase::vobtag ($pvob);
589   
590   my $cmd = "lsbl -stream $stream\@$pvobTag -short";
591   
592   my ($status, @baselines) = $Clearcase::CC->execute ($cmd);
593
594   if ($status) {
595     $log->err ("Unable to execute $cmd\n" . join ("\n", @baselines));
596
597     return;
598   } # if
599
600   foreach (sort @baselines) {
601     UpdateBaseline ($_, $pvob);
602     
603     $totals{'Baselines processed'}++;
604   } # foreach
605   
606   $log->msg ("Processed baselines in stream:$stream");
607   
608   return;
609 } # ProcessBaselines
610
611 sub ProcessStream ($$) {
612   my ($name, $pvob) = @_;
613
614   $totals{'Streams processed'}++;
615   
616   UpdateStream $name, $pvob;
617   
618   ProcessActivities $name, $pvob;
619   ProcessBaselines  $name, $pvob;
620   
621   return;
622 } # ProcessStream
623
624 sub ProcessProject ($$$) {
625   my ($project, $folder, $pvob) = @_;
626   
627   my $pvobTag = Clearcase::vobtag $pvob;  
628
629   $log->msg ("Processing project:$project\@$pvobTag");
630
631   UpdateProject ($project, $folder, $pvob);  
632
633   my $cmd = "lsstream -short -in $project\@$pvobTag";
634   
635   my ($status, @output) = $Clearcase::CC->execute ($cmd); 
636   
637   if ($status) {
638     $log->err ("Unable to execute $cmd\n" . join ("\n", @output));
639     
640     return;
641   } # if
642   
643   foreach (@output) {
644     ProcessStream $_, $pvob;
645   } # foreach
646
647   return;
648 } # ProcessProject
649
650 sub ProcessFolder ($$) {
651   my ($folder, $pvob) = @_;
652
653   my $pvobTag = Clearcase::vobtag $pvob;
654   
655   $log->msg ("Processing folder:$folder\@$pvobTag");
656   
657   UpdateFolder ($folder, $pvob);
658
659   my $cmd = "lsfolder -fmt \"%[contains_folders]p\" $folder\@$pvobTag";
660   
661   my ($status, @output) = $Clearcase::CC->execute ($cmd);
662   
663   if ($status) {
664     $log->err ("Unable to execute command $cmd (Status: $status)\n"
665             . join ("\n", @output), 1);
666             
667      return;
668   } # if
669
670   $output[0] ||= '';
671   
672   foreach (split / /, $output[0]) {
673     ProcessFolder $_, $pvob;
674
675     UpdateSubfolder ($folder, $_, $pvob);    
676   } # foreach
677
678   $cmd = "lsfolder -fmt \"%[contains_projects]p\" $folder\@$pvobTag";
679   
680   ($status, @output) = $Clearcase::CC->execute ($cmd);
681
682   if ($status) {
683     $log->err ("Unable to execute command $cmd (Status: $status)\n"
684             . join ("\n", @output), 1);
685
686     return;
687   } # if
688   
689   $output[0] ||= '';
690   
691   foreach (split / /, $output[0]) {
692     ProcessProject $_, $folder, $pvob;
693   } # foreach
694   
695   return;
696 } # ProcessFolder
697
698 sub ProcessPvob ($) {
699   my ($pvobName) = @_;
700   
701   $log->msg ("Processing pvob:$pvobName");
702   
703   UpdatePvob $pvobName;
704
705   ProcessFolder ('RootFolder', $pvobName);
706   
707   return;
708   
709   $log->msg ("Finding streams in pvob:$pvobName");
710   
711   my $pvob = Clearcase::vobtag ($pvobName);
712   
713   my $cmd = "lsstream -invob $pvob -short";
714   my ($status, @streams) = $Clearcase::CC->execute ($cmd);
715
716   $log->err ("Unable to execute $cmd\n" . join ("\n", @streams), $status)
717     if $status;
718
719   my %stream = (
720     pvob => $pvobName,
721   );
722
723   foreach (sort @streams) {
724     $stream{name} = $_;
725     
726     $totals{'Streams processed'}++;
727     
728     ProcessStream     $stream{name}, $stream{pvob};
729   } # foreach
730   
731   $totals{'Pvobs processed'}++;
732
733   $log->msg ("Finished processing pvob:$pvobName");
734   
735   return;
736 } # ProcessPvob
737
738 sub ProcessVob ($) {
739   my ($name) = @_;
740   
741   my ($err, $msg);
742
743   my %existingRec = $ccdb->GetVob ($name);
744     
745   unless (%existingRec) {
746     my $vob = Clearcase::Vob->new (Clearcase::vobtag $name);
747   
748     # If vob doesn't exist then $vob is just an empty shell. Check to see if
749     # another field is present to make sure the vob really exists. A vob should
750     # always have a region, for example.
751     return
752       unless $vob->region;
753       
754     my $vobRegistryAttributes = $vob->vob_registry_attributes;
755     
756     my $type = ($vobRegistryAttributes and 
757                 $vobRegistryAttributes =~ /ucmvob/) ? 'ucm' : 'base';
758                  
759     ($err, $msg) = $ccdb->AddVob ({
760       name => $name,
761       type => $type,
762     });
763   
764     if ($err) {
765       $log->err ("Unable to add vob $name (Error: $err)\n$msg");
766     } else {
767       $totals{'Vobs added'}++;
768     } # if
769   } # unless
770   
771   return;
772 } # ProcessVob
773
774 # Main
775 local $| = 1;
776
777 my $startTime = time;
778
779 GetOptions (
780   \%opts,
781   'verbose' => sub { set_verbose },
782   'usage'   => sub { Usage },
783   'activity=s',
784   'baseline=s',
785   'checkchangeset',
786   'pvob=s',
787   'stream=s',
788   'vob=s',
789 ) or Usage "Unknown option";
790
791 my $nbrOpts = 0;
792
793 $nbrOpts++ if $opts{pvob};
794 $nbrOpts++ if $opts{activity};
795 $nbrOpts++ if $opts{baseline};
796 $nbrOpts++ if $opts{stream};
797 $nbrOpts++ if $opts{vob};
798
799 Usage "Cannot specify -checkchangeset and any other options"
800   if $opts{checkchangeset} and $nbrOpts != 0;
801
802 Usage "Cannot specify -vob and any other options"
803   if $opts{vob} and ($nbrOpts != 1 or $opts{checkchangeset});
804
805 my $me = $FindBin::Script;
806    $me =~ s/\.pl$//;
807
808 if ($opts{activity} and $opts{pvob} and
809    ($opts{baseline} or  $opts{stream})) {
810   Usage "If -activity is specified then -pvob should be the only other "
811       . "option";
812   exit 1;
813 } elsif ($opts{baseline} and $opts{pvob} and
814         ($opts{activity} or  $opts{stream})) {
815   Usage "If -baseline is specified then -pvob should be the only other "
816       . "option";
817   exit 1;
818 } elsif ($opts{stream}   and $opts{pvob} and
819         ($opts{activity} or  $opts{baseline})) {
820   Usage "If -stream is specified then -pvob should be the only other option";
821   exit 1;
822 } elsif ($opts{pvob}) {
823   $nbrOpts = 0;
824   
825   $nbrOpts++ if $opts{activity};
826   $nbrOpts++ if $opts{baseline};
827   $nbrOpts++ if $opts{stream};  
828
829   if ($nbrOpts != 0 and $nbrOpts > 1) {
830     Usage "If -pvob is specified then it must be used alone or in "
831         . "conjunction\nwith only one of -activity, -baseline or -stream "
832         . "must be specified\n";
833     exit 1;
834   } # fi
835 } # if
836
837 if ($opts{activity} and $opts{pvob}) {
838   $log = Logger->new;
839
840   $log->msg ("$FindBin::Script V$VERSION");
841
842   UpdateActivity ($opts{activity}, $opts{pvob});
843 } elsif ($opts{baseline} and $opts{pvob}) {
844   $log = Logger->new;
845
846   $log->msg ("$FindBin::Script V$VERSION");
847
848   UpdateBaseline ($opts{baseline}, $opts{pvob});
849 } elsif ($opts{stream} and $opts{pvob}) {
850   $log = Logger->new;
851
852   $log->msg ("$FindBin::Script V$VERSION");
853
854   UpdateStream ($opts{stream}, $opts{pvob});
855 } elsif ($opts{pvob}) {
856   $log = Logger->new (name => "$me.$opts{pvob}");
857
858   $log->msg ("$FindBin::Script V$VERSION");
859   
860   ProcessPvob $opts{pvob};
861 } elsif ($opts{checkchangeset}) {
862   error "The -checkchangeset option is not implemented yet", 1;
863 } elsif ($opts{vob}) {
864   $log = Logger->new;
865   
866   $log->msg ("$FindBin::Script V$VERSION");
867   
868   ProcessVob $opts{vob};
869 } else {
870   $log = Logger->new;
871   
872   my $UCM = Clearcase::UCM->new;
873
874   $log->msg ("$FindBin::Script V$VERSION");
875
876   ProcessPvob $_
877     foreach ($UCM->pvobs);
878 } # if
879
880 display_duration $startTime, $log;
881
882 $totals{Errors} = $log->errors;
883
884 Stats \%totals, $log;