Merge branch 'master' of git+ssh://github.com/adefaria/clearscm
authorAndrew DeFaria <Andrew@DeFaria.com>
Tue, 3 Jul 2018 05:04:54 +0000 (22:04 -0700)
committerAndrew DeFaria <Andrew@DeFaria.com>
Tue, 3 Jul 2018 05:04:54 +0000 (22:04 -0700)
48 files changed:
aws/Display.pyc [deleted file]
bin/allmach
bin/rexec.pl
cc/etf.pl
cc/testcc.conf [deleted file]
cc/testcc.pl [deleted file]
cc/testclearcase.pl [new file with mode: 0644]
conf/adefaria@gmail.com-takeout.zip [deleted file]
cq/cqinfo.pl
cqtool/cqtool.pl [changed mode: 0755->0644]
data/allmach [new file with mode: 0644]
data/machines [new file with mode: 0644]
data/windows [new file with mode: 0644]
lib/Clearcase.pm
lib/Clearcase/UCM/Activity.pm
lib/Clearcase/UCM/Baseline.pm
lib/Clearcase/UCM/Component.pm [new file with mode: 0644]
lib/Clearcase/UCM/Folder.pm [new file with mode: 0644]
lib/Clearcase/UCM/Project.pm [new file with mode: 0644]
lib/Clearcase/UCM/Pvob.pm
lib/Clearcase/UCM/Stream.pm
lib/Clearcase/UCM/Streams.pm [new file with mode: 0644]
lib/Clearcase/UCM/testinfo.txt [new file with mode: 0644]
lib/Clearcase/View.pm
lib/Clearcase/Vob.pm
lib/Clearcase/Vobs.pm
lib/Clearquest.pm
lib/Logger.pm
lib/OSDep.pm
lib/Utils.pm
maps/bin/checkaddress.pl [changed mode: 0644->0755]
maps/test.pl [changed mode: 0644->0755]
rantest/rantest [changed mode: 0644->0755]
rc/bash_login
rc/clearcase
rc/clearcase.conf
rc/client_scripts/GD [changed mode: 0644->0755]
rc/client_scripts/ICANN [changed mode: 0755->0644]
rc/functions
rc/perldb
rc/set_colors
rc/set_path
rc/system
test/testclearcase.conf [new file with mode: 0644]
test/testclearcase.pl
test/testclearquest.pl
test/testspreadsheet.xls [changed mode: 0644->0755]
web/favicon.ico [changed mode: 0755->0644]

diff --git a/aws/Display.pyc b/aws/Display.pyc
deleted file mode 100644 (file)
index efbc9ff..0000000
Binary files a/aws/Display.pyc and /dev/null differ
index 23ed8e5..6bbddde 100755 (executable)
@@ -64,11 +64,11 @@ function trap_intr {
 # Column 4 ClearCase Version (if applicable)
 # Column 5 Owner (if known)
 # Column 6 Usage (if known)
-#oldIFS=$IFS
-#IFS=":"
+oldIFS=$IFS
+IFS=":"
 declare -i nbr_of_machines=0
-#sed -e "/^#/d" $machines |
-while read machine; do
+IFS=:
+while read machine model os cc owner usage; do
   machines[nbr_of_machines]=$machine
   let nbr_of_machines=nbr_of_machines+1
 done < <(grep -v ^# $machines)
@@ -86,7 +86,7 @@ while [ $i -lt $nbr_of_machines ]; do
   export currmachine=${machines[i]}
   # Execute command. Note if no command is given then the effect is to
   # ssh to each machine.
-  echo -e "${CYAN}${machines[i]}$NORMAL\c"
+  echo -e "${B_AQUA}${machines[i]}$NORMAL\c"
   echo -e ":$cmd"
   if [ $# -gt 0 ]; then
     if [ "$root_ssh" = "true" ]; then
index 1770744..4cc0eff 100755 (executable)
@@ -36,7 +36,7 @@ $Date: 2008/02/29 15:09:15 $
                  [-use|rname <username>] [-p|assword <password>]
                  [-log]
                  -m|achines <host1>,<host2>,...
-                 
+
               <command>
 
  Where:
index 5975409..bae1728 100755 (executable)
--- a/cc/etf.pl
+++ b/cc/etf.pl
@@ -70,7 +70,7 @@ trigger.
  TODO: Is cleartool find really needed? I mean since we are going through
        the extended version namespace don't we by default find all
        subdirectories?
+
 This script will use cleartool find to process all directory elements from
 $startingDir (Default '.'). For each version of the directory a hash will be
 built up containing all of the element names in that directory version.
@@ -167,8 +167,8 @@ sub reportDir (%) {
       $log->msg ("File: $filename");
 
       foreach (@oids) {
-       $log->msg ("\tOID: $$_{OID} ($$_{count})");
-       $log->msg ("\tFirst detected \@: $$_{version}");
+        $log->msg ("\tOID: $$_{OID} ($$_{count})");
+        $log->msg ("\tFirst detected \@: $$_{version}");
       } # foreach
     } # if
   } # foreach
@@ -231,7 +231,7 @@ sub processDir ($) {
     if $directory eq '.';
 
   my $displayName = "$directory$Clearcase::SFX$version";
-   
+
   # We only want to deal with branches and numbered versions. Non-numbered
   # versions which are not branches represent labels and baselines which are
   # just aliases for directory and file elements. Branches represent recursion
@@ -287,7 +287,7 @@ sub processDir ($) {
           last;
         } # if
       } # foreach
-        
+
       unless ($found) {
         # If we didn't find a match then make a new %objInfo starting with a
         # count of 1. Also save this current $version, which is the first
@@ -380,7 +380,7 @@ sub processDirs ($) {
 
   close $dirs
     or $log->err ("Unable to close $cmd - $!");
-    
+
   return $total{'evil twins'};
 } # processDirs
 
diff --git a/cc/testcc.conf b/cc/testcc.conf
deleted file mode 100644 (file)
index a2d4c2b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-################################################################################
-#
-# File:         testcc.conf
-# Revision:     2.0
-# Description:  Parameters for testcc
-#
-# Author:       Andrew@DeFaria.com
-# Created:      Thu Sep  6 14:05:55 MST 2007
-# Modified:
-# Language:     Conf
-#
-# (c) Copyright 2007, Andrew@DeFaria.com, all rights reserved.
-#
-#################################################################################
-vobhost:                gdvob1
-vobpath:                /net/$vobhost
-vobstore:               $vobpath/local/gdvob1a
-
-viewhost:               view1
-viewpath:               /net/$viewhost
-viewstore:              $viewpath/local/view1a
\ No newline at end of file
diff --git a/cc/testcc.pl b/cc/testcc.pl
deleted file mode 100644 (file)
index 659e7ef..0000000
+++ /dev/null
@@ -1,562 +0,0 @@
-#!/bin/bin/perl
-
-=pod
-
-=head1 NAME $RCSfile: testcc.pl,v $
-
-Test Clearcase
-
-=head1 VERSION
-
-=over
-
-=item Author
-
-Andrew DeFaria <Andrew@ClearSCM.com>
-
-=item Revision
-
-$Revision: 1.6 $
-
-=item Created:
-
-Tue Apr 10 13:14:15 CDT 2007
-
-=item Modified:
-
-$Date: 2011/01/09 01:01:32 $
-
-=back
-
-=head1 SYNOPSIS
-
- Usage testcc.pl: [-u|sage] [-ve|rbose] [-d|ebug]
-                  [-c|onfig <file>] [-vi|ewstore <viewstore>] 
-                  [-vo|bstore <vobstore>]
-
- Where:
-   -u|sage:     Displays usage
-   -ve|rbose:   Be verbose
-   -d|ebug:     Output debug messages
-
-   -c|onfig <file>: Config file (Default: testcc.conf)
-   -vi|ewstore:     Path to view storage area
-   -vo|bstore:      Path to vob storage area
-
-=head1 DESCRIPTION  
-
-Clearcase smoke tests. Perform simple Clearcase operations to validate that
-Clearcase minimally works
-
-=cut
-
-use strict;
-use warnings;
-
-use FindBin;
-use Getopt::Long;
-use Cwd;
-use Term::ANSIColor qw(:constants);
-
-my $libs;
-
-BEGIN {
-  $libs = $ENV{SITE_PERLLIB} ? $ENV{SITE_PERLLIB} : "$FindBin::Bin/../lib";
-
-  die "Unable to find libraries\n" 
-    unless -d $libs;
-} # BEGIN
-
-use lib $libs;
-
-use Clearcase;
-use Clearcase::Element;
-use Clearcase::View;
-use Clearcase::Views;
-use Clearcase::Vob;
-use Clearcase::Vobs;
-use DateUtils;
-use Display;
-use GetConfig;
-use Logger;
-use OSDep;
-use Utils;
-
-# Globals
-my $VERSION = '2.0';
-
-my ($vbs, $vws, %default_opts, %opts);
-
-my $log      = Logger->new;
-my $view     = $Clearcase::VIEWTAG_PREFIX;
-my $view_tag = $FindBin::Script;
-my $vob      = $ENV{TMP} ? $ENV{TMP} : "/tmp"; # Private vob - mount to /tmp!
-my $vob_tag  = $view_tag;
-
-my ($test_view, $test_vob);
-
-# LogOpts: Log the %opts has to the log file so we can tell the options used for
-# this run.
-sub LogOpts () {
-  $log->msg (
-    "$FindBin::Script v$VERSION run at " 
-  . YMDHM
-  . " with the following options:"
-  );
-
-  foreach (sort keys %opts) {
-    if (ref $opts{$_} eq "ARRAY") {
-      my $name = $_;
-      $log->msg ("$name:\t$_") foreach (@{$opts{$_}});
-    } else {
-      $log->msg ("$_:\t$opts{$_}");
-    }  # if
-  } # foreach
-  
-  return;
-} # LogOpts
-
-sub CreateVob () {
-  $log->msg ("Creating vob $vob/$vob_tag");
-
-  $test_vob = Clearcase::Vob->new ("$vob/$vob_tag");
-
-  my ($status, @output) = $test_vob->create ($opts{vobhost}, $vbs);
-
-  $log->log ($_) foreach (@output);
-
-  if ($status != 0) {
-    if ($output[0] =~ /already exists/) {
-      $log->warn ("Vob " . $test_vob->tag . " already exists");
-      return 0;
-    } # if
-  } # if
-
-  return $status;
-} # CreateVob
-
-sub MountVob () {
-  $log->msg ("Mounting vob " . $test_vob->tag);
-
-  # Create mount directory
-  my ($status, @output) = Execute "mkdir -p " . $test_vob->tag . " 2>&1";
-
-  $log->log ($_) foreach (@output);
-
-  ($status, @output) = $test_vob->mount;
-
-  $log->log ($_) foreach (@output);
-
-  return $status;
-} # MountVob
-
-sub DestroyVob () {
-  my ($status, @output);
-
-  ($status, @output) = $Clearcase::CC->execute ("cd");
-
-  $log->msg ("Unmounting vob " . $test_vob->tag);
-
-  ($status, @output) = $test_vob->umount;
-
-  $log->msg ("Removing vob " . $test_vob->tag);
-
-  ($status, @output) = $test_vob->remove;
-
-  $log->log ($_) foreach (@output);
-
-  ($status, @output) = Execute "rmdir " . $test_vob->tag;
-
-  $log->log ($_)
-    foreach (@output);
-
-  return $status;
-} # DestroyVob
-
-sub CreateView () {
-  $log->msg ("Creating view $view_tag");
-
-  $test_view = Clearcase::View->new ($view_tag);
-
-  my ($status, @output) = $test_view->create ($opts{viewhost}, $vws);
-
-  $log->log ($_) foreach (@output);
-
-  if ($status != 0) {
-    if ($output[0] =~ /already exists/) {
-      $log->warn ("View " . $test_view->tag . " already exists");
-      return 0;
-    } # if
-  } # if
-
-  return $status;
-} # CreateView
-
-sub SetView () {
-  $log->msg ("Setting view $test_view->tag");
-
-  my ($status, @output) = $test_view->set;
-
-  $log->log ($_) foreach (@output);
-
-  return $status;
-} # SetView
-
-sub DestroyView () {
-  $log->msg ("Removing view " . $test_view->tag);
-
-  my ($status, @output) = $Clearcase::CC->execute ("cd");
-
-  $log->log ($_) foreach (@output);
-
-  chdir $ENV{HOME}
-    or $log->err ("Unable to chdir $ENV{HOME}", 1);
-
-  ($status, @output) = $test_view->remove;
-
-  $log->log ($_) foreach (@output);
-
-  return $status;
-} # DestroyView
-
-sub CreateViewPrivateFiles (@) {
-  my (@elements) = @_;
-
-  $log->msg ("Creating test files");
-
-  foreach (@elements) {
-    my $file;
-
-    $log->msg ("Creating $_");
-
-    open $file, ">>", $_
-      or $log->err ("Unable to open $_ for writing - $!", 1);
-
-    print $file "This is file $_\n";
-
-    close $file;
-  } # foreach
-  
-  return;
-} # CreateViewPrivateFiles
-
-sub CheckOut ($) {
-  my ($element) = @_;
-
-  my ($status, @output);
-
-  if (ref $element eq "ARRAY") {
-    foreach (@{$element}) {
-      $log->msg ("Checking out $_");
-
-      my $newElement = Clearcase::Element->new ($_);
-
-      ($status, @output) = $newElement->checkout;
-
-      $log->log ($_) foreach (@output);
-      $log->err ("Unable to check out $_", $status) if $status;
-    } # foreach
-  } else {
-    $log->msg ("Checking out $element");
-
-    my $newElement = Clearcase::Element->new ($element);
-
-    ($status, @output) = $newElement->checkout;
-
-    $log->log ($_) foreach (@output);
-    $log->err ("Unable to check out $element", $status) if $status;
-  } # if
-  
-  return;
-} # CheckOut
-
-sub CheckIn ($) {
-  my ($element) = @_;
-
-  my ($status, @output);
-
-  if (ref $element eq "ARRAY") {
-    foreach (@{$element}) {
-      $log->msg ("Checking in $_");
-
-      my $newElement = Clearcase::Element->new ($_);
-
-      ($status, @output) = $newElement->checkin;
-
-      $log->log ($_) foreach (@output);
-      $log->err ("Unable to check in $_", $status) if $status;
-    } # foreach
-  } else {
-    $log->msg ("Checking in $element");
-
-    my $newElement = Clearcase::Element->new ($element);
-
-    ($status, @output) = $newElement->checkin;
-
-    $log->log ($_) foreach (@output);
-    $log->err ("Unable to check in $element", $status) if $status;
-  } # if
-  
-  return;
-} # CheckIn
-
-sub ComparingFiles (@) {
-  my (@elements) = @_;
-
-  foreach (@elements) {
-    my @lines = ReadFile $_;
-
-    $log->err ("Element $_ should contain only two lines", 2) if scalar @lines != 2;
-  } # foreach
-  
-  return;
-} # ComparingFiles
-
-sub MakeElements (@) {
-  my (@elements) = @_;
-
-  foreach (@elements) {
-    $log->msg ("Mkelem $_");
-
-    my $newElement = Clearcase::Element->new ($_);
-
-    my ($status, @output) = $newElement->mkelem;
-
-    $log->log ($_) foreach (@output);
-    $log->err ("Unable to make $_ an element", $status) if $status;
-  } # foreach
-  
-  return;
-} # MakeElements
-
-sub RunTests () {
-  # Simple tests:
-  #
-  #   . Create a few elements
-  #   . Check them in
-  #   . Check them out
-  #   . Modify them
-  #   . Check them in
-  #
-  # Assumptions:
-  #
-  #   . $vob_tag is already created
-  #   . $view_tag is already created
-  #   . View is set and we are in the vob
-  #   . There are no vob elements for @elements
-  my @elements = (
-    "cctest.h",
-    "ccsetup.c",
-    "cctest.c",
-    "Makefile",
-  );
-
-  $log->msg ("Removing test files");
-
-  unlink $_ foreach (@elements);
-
-  $log->msg ("Creating view private files");
-
-  CreateViewPrivateFiles        $log, @elements;
-
-  $log->msg ("Making elements");
-
-  CheckOut      '.';
-  MakeElements  @elements;
-  CheckIn       \@elements;
-  CheckIn       '.';
-
-  $log->msg ("Checking out files");
-
-  CheckOut \@elements;
-
-  $log->msg ("Modifying files");
-
-  CreateViewPrivateFiles @elements;
-
-  $log->msg ("Checking in files");
-
-  CheckIn \@elements;
-
-  $log->msg ("Comparing files");
-
-  ComparingFiles @elements;
-
-  $log->msg ("$FindBin::Script: End Tests");
-
-  return 0;
-} # RunTests
-
-sub Cleanup () {
-  my $status = 0;
-
-  $log->msg ("Cleaning up");
-
-  if ($test_view && $test_view->exists) {
-    $status += DestroyView;
-  } # if
-
-  if ($test_vob && $test_vob->exists) {
-    $status += DestroyVob;
-  } # if
-
-  return $status;
-} # Cleanup
-
-sub SetupTest () {
-  $log->msg ("Setup test environment");
-
-  my $status += CreateVob;
-
-  return $status if $status != 0;
-
-  $status += MountVob;
-
-  return $status if $status != 0;
-
-  $status += CreateView;
-
-  return $status if $status != 0;
-
-  $status += $test_view->start;
-
-  my $dir = $Clearcase::VIEWTAG_PREFIX . $test_view->tag . $test_vob->tag;
-
-  chdir $dir
-    or $log->err ("Unable to chdir to $dir", $status++);
-
-  my @output;
-  
-  ($status, @output) = $Clearcase::CC->execute ("cd $dir");
-
-  if ($status != 0) {
-    $log->log ($_) foreach (@output);
-    $log->err ("Unable to chdir to $dir", $status);
-  } # if
-
-  return $status;
-} # SetupTest
-
-my $conf_file = "$FindBin::Script.conf";
-
-GetOptions (
-  \%opts,
-  "v|verbose"           => sub { set_verbose },
-  "u|usage"             => sub { Usage },
-  "c|onfig=s",
-  "n|etpath=s",
-  "viewstore=s",
-  "vobstore=s",
-) or Usage;
-
-# Read the config file
-if (-f $conf_file) {
-  %default_opts = GetConfig $conf_file;
-} else {
-  $log->err ("Unable to find config file $conf_file", 1);
-} # if
-
-# Overlay default opts if not specified
-foreach (keys %default_opts) {
-  $opts{$_} = $default_opts{$_} if !$opts{$_};
-} # foreach
-
-$vws = "$opts{viewstore}/$view_tag.vws";
-$vbs = "$opts{vobstore}/$vob_tag.vbs";
-
-$log->msg ("START: $FindBin::Script (v$VERSION)");
-
-LogOpts;
-
-my $status = SetupTest;
-
-if ($status == 0) {
-  $status += RunTests;
-} else {
-  $log->err ("Tests not run. Failure occured in SetupTest - check logfile");
-} # if
-
-$status += Cleanup;
-
-if ($status != 0) {
-  $log->err ("$FindBin::Script failed");
-} else {
-  $log->msg ("$FindBin::Script passed");
-} # if
-
-$log->msg ("END: $FindBin::Script (v$VERSION)");
-
-exit $status;
-
-=pod
-
-=head1 CONFIGURATION AND ENVIRONMENT
-
-DEBUG: If set then $debug is set to this level.
-
-VERBOSE: If set then $verbose is set to this level.
-
-TRACE: If set then $trace is set to this level.
-
-=head1 DEPENDENCIES
-
-=head2 Perl Modules
-
-L<Cwd>
-
-L<FindBin>
-
-L<Getopt::Long|Getopt::Long>
-
-L<Term::ANSIColor|Term::ANSIColor>
-
-=head2 ClearSCM Perl Modules
-
-=begin man 
-
- Clearcase
- Clearcase::Element
- Clearcase::View
- Clearcase::Views
- Clearcase::Vob
- Clearcase::Vobs
- DateUtils
- Display
- GetConfig
- Logger
- OSDep
- Utils
-
-=end man
-
-=begin html
-
-<blockquote>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Element.pm">Element</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/View.pm">View</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Views.pm">Views</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Vob.pm">Vob</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Vobspm">Vobs</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/GetConfig.pm">GetConfig</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Logger.pm">Logger</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/OSDep.pm">OSDep</a><br>
-<a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
-</blockquote>
-
-=end html
-
-=head1 BUGS AND LIMITATIONS
-
-There are no known bugs in this script
-
-Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
-
-=head1 LICENSE AND COPYRIGHT
-
-Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
-
-=cut
diff --git a/cc/testclearcase.pl b/cc/testclearcase.pl
new file mode 100644 (file)
index 0000000..cf40c33
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use FindBin;
+use Term::ANSIColor qw(:constants);
+
+use lib "$FindBin::Bin/../lib";
+
+use Clearcase;
+use Display;
+
+my ($status, @output) = $Clearcase::CC->execute ('pwv');
+
+error 'Clearcase is not installed on this system', 1
+  if $status;
+  
+display YELLOW . "Global Clearcase Variables\n" . RESET;
+
+my $view_drive     = $Clearcase::VIEW_DRIVE;
+my $vob_mount      = $Clearcase::VOB_MOUNT;
+my $win_vob_prefix = $Clearcase::WIN_VOB_PREFIX;
+my $vobtag_prefix  = $Clearcase::VOBTAG_PREFIX;
+my $countdb        = $Clearcase::COUNTDB;
+
+display MAGENTA . "View Drive:\t\t"       . RESET . $view_drive;
+display MAGENTA . "VOB Mount:\t\t"        . RESET . $vob_mount;
+display MAGENTA . "Windows VOB prefix:\t" . RESET . $win_vob_prefix;
+display MAGENTA . "VOB Tag Prefix:\t\t"   . RESET . $vobtag_prefix;
+display MAGENTA . "CountDB:\t\t"          . RESET . $countdb;
+
+display CYAN    . "\nGlobal Clearcase Configuration\n" . RESET;
+
+display MAGENTA . "Client:\t\t\t"       . RESET . $Clearcase::CC->client;
+display MAGENTA . "Hardware type:\t\t"  . RESET . $Clearcase::CC->hardware_type;
+display MAGENTA . "License host:\t\t"   . RESET . $Clearcase::CC->license_host;
+display MAGENTA . "OS:\t\t\t"           . RESET . $Clearcase::CC->os;
+display MAGENTA . "Region:\t\t\t"       . RESET . $Clearcase::CC->region;
+display MAGENTA . "Registry host:\t\t"  . RESET . $Clearcase::CC->registry_host;
+display MAGENTA . "Sitename:\t\t"       . RESET . $Clearcase::CC->sitename;
+display MAGENTA . "Version:\t\t"        . RESET . $Clearcase::CC->version;
+
+display GREEN . "\nCleartool Access\n" . RESET;
+
+display_nolf MAGENTA . "Views:\t" . RESET;
+
+($status, @output) = $Clearcase::CC->execute ("lsview -s");
+
+display scalar @output;
+
+display_nolf MAGENTA . "VOBs:\t" . RESET;
+
+($status, @output) = $Clearcase::CC->execute ("lsvob -s");
+
+display scalar @output;
diff --git a/conf/adefaria@gmail.com-takeout.zip b/conf/adefaria@gmail.com-takeout.zip
deleted file mode 100644 (file)
index 2933e2e..0000000
Binary files a/conf/adefaria@gmail.com-takeout.zip and /dev/null differ
index 615312c..0a55148 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env cqperl
 use strict;
 use warnings;
 
old mode 100755 (executable)
new mode 100644 (file)
index 3c85914..cf8d6e0
-#!/usr/bin/env /opt/rational/clearquest/bin/cqperl\r
-##############################################################################\r
-#\r
-# Name: cqtool\r
-#\r
-# Description: cqtool is an interface to Clearquest to perform some simple\r
-#              actions to the RANCQ database. It is used primarily by ucmwb\r
-#              but it also supports a command line interface.\r
-#\r
-#              The following commands are supported:\r
-#\r
-#              activate <wor> <project> <est_hours> <startdate> <enddate>:\r
-#                      Activate WOR\r
-#              assign <wor> <assignee> <project> <planned_hours> <startdate>:\r
-#                      Assign the WOR\r
-#              clone <wor>:\r
-#                      Clones a WOR\r
-#              comment <wor> <comment>\r
-#                      Add a comment to the Notes_Entry field for the WOR\r
-#              complete <wor> <actual_hours>:\r
-#                      Complete WOR\r
-#              createhd:\r
-#                      Create a new Help Desk Ticket\r
-#              createwor:\r
-#                      Create a new WOR\r
-#              effort <wor> <hours>:\r
-#                      Update the WOR's actual hours\r
-#              exit|quit:\r
-#                      Exits cqtool\r
-#              help:\r
-#                      This display\r
-#              link <parent wor> <child wor>:\r
-#                      Link a parent WOR to a child WOR\r
-#              resolve <wor>:\r
-#                      Resolve WOR\r
-#              set <wor> <field> <value>\r
-#                      Set <field> to <value> for the <wor>\r
-#              usage:\r
-#                      Displays command line usage\r
-#              version:\r
-#                      Displays version of cqtool\r
-#\r
-#              Many of these commands simply perform actions on a wor. Two\r
-#              of these commands, createwor and createhd have Perl/Tk GUI\r
-#              interfaces.\r
-#\r
-# Command line usage:\r
-#\r
-# Usage: cqtool\t[-usage|help] [-verbose] [-debug]\r
-#      [-userid <user>] [-password <password>] [<command>]\r
-#\r
-# Where:\r
-#\r
-#   -usage|help:       Display usage\r
-#   -verbose:          Turn on verbose mode\r
-#   -debug:            Turn on debug mode\r
-#   -userid:           User ID to log into Clearquest database as\r
-#   -password:         Password to use\r
-#   <command>          If specified then cqtool executes <command> and\r
-#                      exits\r
-#\r
-# Environment:         cqtool supports the following environment variables\r
-#                      that are used mostly for tesing purposes\r
-#\r
-#      CQ_DBSET:       Clearquest DBSET to open (e.g. XTST3 for testing -\r
-#                      default RANCQ)  \r
-#      CQ_USER:        User name to log into the $CQ_DBSET database with\r
-#      CQ_PASSWORD:    Password to use to log into the $CQ_DBSET with.\r
-#\r
-# Author: Andrew@DeFaria.com\r
-#\r
-# (c) Copyright 2007, General Dynamics, all rights reserved\r
-#\r
-##############################################################################\r
-use strict;\r
-use warnings;\r
-\r
-use CQPerlExt;\r
-use FindBin;\r
-use Getopt::Long;\r
-use Term::ANSIColor qw (:constants);\r
-\r
-use lib ("$FindBin::Bin", "$FindBin::Bin/../lib");\r
-\r
-use SCCM::Misc;\r
-use Display;\r
-use CQTool;\r
-use CreateWORUI;\r
-use CreateHelpDeskUI;\r
-use Logger;\r
-\r
-my $VERSION            = BOLD GREEN . "1.1" . RESET;\r
-my $PROMPT             = BOLD YELLOW . ">>" . RESET;\r
-my $UCMWB_PROMPT       = ">>";\r
-my $DESC               = BOLD RED . "$FindBin::Script" .\r
-                         RESET      " Version " .\r
-                         $VERSION .\r
-                         CYAN ": Program to talk to Clearquest" .\r
-                         RESET;\r
-\r
-# Globals\r
-my $_userid    = $ENV{CQ_USER}  ? $ENV{CQ_USER} : $ENV{USER};\r
-my $_password  = $ENV{CQ_PASSWORD};\r
-my $_db_name   = $ENV{CQ_DBSET} ? $ENV{CQ_DBSET} : "RANCQ";\r
-my $_ucmwb;\r
-\r
-my $_log;\r
-\r
-if (get_debug) {\r
-  $_log = new Logger (\r
-    path => "/tmp",\r
-    append => 1,\r
-  );\r
-} # if\r
-\r
-my %_commands = (\r
-  activate     => \&activate,\r
-  assign       => \&assign,\r
-  clone                => \&clone,\r
-  comment      => \&comment,\r
-  complete     => \&complete,\r
-  createhd     => \&createHelpDesk,\r
-  createwor    => \&createWOR,\r
-  effort       => \&effort,\r
-  exit         => \&shutdown,\r
-  help         => \&help,\r
-  link         => \&linkParentWor2ChildWor,\r
-  quit         => \&shutdown,\r
-  resolve      => \&resolve,\r
-  set          => \&set,\r
-  usage                => \&usage,\r
-  version      => \&announce,\r
-);\r
-\r
-##############################################################################\r
-# Forwards\r
-##############################################################################\r
-sub commandLoop (@);\r
-\r
-##############################################################################\r
-# Main\r
-##############################################################################\r
-MAIN: {\r
-  GetOptions (\r
-    "usage"            => sub { usage () },\r
-    "verbose"          => sub { set_verbose () },\r
-    "debug"            => sub { set_debug () },\r
-    "userid=s"         => \$_userid,\r
-    "password=s"       => \$_password,\r
-    "database=s"       => \$_db_name,\r
-    "ucmwb"            => \$_ucmwb,\r
-  ) || usage ();\r
-\r
-  exit (commandLoop(@ARGV));\r
-} # MAIN\r
-\r
-##############################################################################\r
-# Subroutines\r
-##############################################################################\r
-\r
-#-----------------------------------------------------------------------------\r
-# shutdown (): Ends program\r
-#-----------------------------------------------------------------------------\r
-sub shutdown () {\r
-  exit (0);\r
-} # exit\r
-\r
-#-----------------------------------------------------------------------------\r
-# help (): Displays help\r
-#-----------------------------------------------------------------------------\r
-sub help () {\r
-  display ($DESC);\r
-  display <<END;\r
-\r
-Valid commands are:\r
-\r
-activate <wor> <project> <est_hours> <startdate> <enddate>:\r
-       Activate WOR\r
-assign <wor> <assignee> <project> <planned_hours> <startdate>:\r
-       Assign the WOR\r
-clone <wor>:\r
-       Clones a WOR\r
-comment <wor> <comment>\r
-       Add a comment to the Notes_Entry field for the WOR\r
-complete <wor> <actual_hours>:\r
-       Complete WOR\r
-createhd:\r
-       Create a new Help Desk Ticket\r
-createwor:\r
-       Create a new WOR\r
-effort <wor> <hours>:\r
-       Update the WOR's actual hours\r
-exit|quit:\r
-       Exits $FindBin::Script\r
-help:\r
-       This display\r
-link <parent wor> <child wor>:\r
-       Link a parent WOR to a child WOR\r
-resolve <wor>:\r
-       Resolve WOR\r
-set <wor> <field> <value>\r
-       Set <field> to <value> for the <wor>\r
-usage:\r
-       Displays command line usage\r
-version:\r
-       Displays version of $FindBin::Script\r
-END\r
-} # help\r
-\r
-#-----------------------------------------------------------------------------\r
-# announce (): Announce ourselves\r
-#-----------------------------------------------------------------------------\r
-sub announce () {\r
-  display ($DESC);\r
-} # Announce\r
-\r
-#-----------------------------------------------------------------------------\r
-# dberror ($): Handle errors when talking to Clearquest. Note we need to reset\r
-#             the database connection if an error happens.\r
-#-----------------------------------------------------------------------------\r
-sub dberror ($) {\r
-  my ($msg) = @_;\r
-\r
-  # Need to not only report the error but to reopen the\r
-  # database. Something gets corruppted if we don't!\r
-  error ($msg);\r
-\r
-  closeDB ();\r
-\r
-  openDB ($_userid, $_password, $_db_name);\r
-} # DBError\r
-\r
-#-----------------------------------------------------------------------------\r
-# getEntity ($$): Get an entity from Clearquest\r
-#-----------------------------------------------------------------------------\r
-sub getEntity ($$) {\r
-  my ($recordname, $wor) = @_;\r
-\r
-  my $entity;\r
-\r
-  eval {\r
-    $entity = $CQTool::session->GetEntity ($recordname, $wor);\r
-  };\r
-\r
-  if ($@) {\r
-    chomp $@;\r
-    dberror ($@);\r
-    return undef;\r
-  } else {\r
-    return $entity;\r
-  } # if\r
-} # getEntity\r
-\r
-#-----------------------------------------------------------------------------\r
-# set ($$$): Set $field to $value for $wor\r
-#-----------------------------------------------------------------------------\r
-sub set ($$@) {\r
-  my ($wor, $field, $value) = @_;\r
-\r
-  if (!$wor or $wor eq "") {\r
-    error ("WOR is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$field or $field eq "") {\r
-    error ("Field is required");\r
-    return 1;\r
-  } # if\r
-\r
-  my $entity   = getEntity ("WOR", $wor);\r
-\r
-  return 1 if !$entity;\r
-\r
-  $session->EditEntity ($entity, "modify");\r
-\r
-  $_log->msg ("Modifying $field to \"$value\"") if get_debug;\r
-  eval {\r
-    $entity->SetFieldValue ($field, $value);\r
-  };\r
-\r
-  if ($@) {\r
-    dberror ("$field set failed for WOR $wor:\n$@");\r
-    return 2;\r
-  } # if\r
-\r
-  my $status = $entity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $entity->Revert ();\r
-    error ("$field validate failed for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  $status = $entity->Commit ();\r
-\r
-  if ($status ne "") {\r
-    error ("$field update failed during Submit for $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-   return 0;\r
-} # set\r
-\r
-#-----------------------------------------------------------------------------\r
-# clone ($): Clone a WOR\r
-#-----------------------------------------------------------------------------\r
-sub clone ($) {\r
-  my ($wor) = @_;\r
-\r
-  if (!$wor) {\r
-    error ("WOR not specified!");\r
-    return 1;\r
-  } # if\r
-\r
-  $entity = getEntity ("WOR", $wor);\r
-\r
-  return 1 if !$entity;\r
-\r
-  # Check state\r
-  my $state = $entity->GetFieldValue ("state")->GetValue ();\r
-\r
-  if ($state ne "Closed") {\r
-    error ("WOR $wor not closed - Unable to clone!");\r
-    return 1;\r
-  } # if\r
-\r
-  verbose ("Cloning WOR $wor...");\r
-\r
-  my $result = 0;\r
-\r
-  eval {\r
-    # Currently Clone doesn't return a proper result but eventually...\r
-    $result = $CQTool::session->FireRecordScriptAlias ($entity, "Clone");\r
-  };\r
-\r
-  if ($@) {\r
-    chomp $@;\r
-    dberror ($@);\r
-    return 1;\r
-  } # if\r
-\r
-  return $result;\r
-} # clone\r
-\r
-#-----------------------------------------------------------------------------\r
-# effort ($$): Update actual hours for a WOR\r
-#-----------------------------------------------------------------------------\r
-sub effort ($$) {\r
-  my ($wor, $actualHrs) = @_;\r
-\r
-  return set $wor, "ActualEffort", $actualHrs;\r
-} # effort\r
-\r
-#-----------------------------------------------------------------------------\r
-# comment (): Update the Notes_Entry comment field for a WOR\r
-#-----------------------------------------------------------------------------\r
-sub comment ($) {\r
-  my ($wor) = @_;\r
-\r
-  if (!$wor) {\r
-    error "WOR not defined in call to comment!";\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$_ucmwb) {\r
-    display ("Enter comments below. When finished, enter \".\" on a line by itself or hit ^D:");\r
-  } else {\r
-    # We still need to prompt for the comments however signal UCMWB\r
-    # that command is ready for more input.\r
-    display_nolf ($UCMWB_PROMPT);\r
-  } # if\r
-\r
-  my $comments;\r
-\r
-  while (<STDIN>) {\r
-    last if $_ eq ".\n";\r
-    $comments .= $_;\r
-  } # while\r
-\r
-  chomp $comments;\r
-\r
-  $_log->msg ("Comments:\n$comments") if get_debug;\r
-\r
-  return set $wor, "Note_Entry", $comments;\r
-} # Comment\r
-\r
-#-----------------------------------------------------------------------------\r
-# linkParentWor2ChildWor ($$): Link a child WOR to a parent WOR\r
-#-----------------------------------------------------------------------------\r
-sub linkParentWor2ChildWor ($$) {\r
-  my ($parentWor, $childWor) = @_;\r
-\r
-  my $status;\r
-\r
-  verbose ("Linking $parentWor -> $childWor...");\r
-\r
-  my $childentity      = getEntity ("WOR", $childWor);\r
-  my $parententity     = getEntity ("WOR", $parentWor);\r
-\r
-  return 1 unless $childentity and $parententity;\r
-\r
-  $session->EditEntity ($parententity, "modify");\r
-\r
-  $parententity->AddFieldValue ("wor_children", $childWor);\r
-\r
-  $status = $parententity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $parententity->Revert ();\r
-    error ("Validation failed while attempting to add child WOR $childWor to parent WOR $parentWor:\n$status");\r
-    return 1;\r
-  } # if\r
-\r
-  eval {\r
-    $status = $parententity->Commit ();\r
-  };\r
-\r
-  $status = $@ if $@;\r
-\r
-  if ($status ne "") {\r
-    (error "Commit failed while trying to add child WOR $childWor to parent WOR $parentWor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  debug "Modifying child $childWor...";\r
-  $session->EditEntity ($childentity, "modify");\r
-\r
-  $childentity->SetFieldValue ("wor_parent", $parentWor);\r
-\r
-  $status = $childentity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $childentity->Revert ();\r
-    error "Validation failed while attempting to add parent WOR $parentWor to child WOR $childWor:\n$status";\r
-    return 1;\r
-  } # if\r
-\r
-  eval {\r
-    $status = $childentity->Commit ();\r
-  };\r
-\r
-  $status = $@ if $@;\r
-\r
-  if ($status ne "") {\r
-    error "Commit failed while trying to add parent WOR $parentWor to child WOR $childWor:\n$status";\r
-    return 2;\r
-  } # if\r
-\r
-  return 0;\r
-} # linkParentWor2ChildWor\r
-\r
-#-----------------------------------------------------------------------------\r
-# assign ($$$$): Assign a WOR\r
-#-----------------------------------------------------------------------------\r
-sub assign ($$$$$) {\r
-  my ($wor, $assignee, $project, $plannedHrs, $startDate) = @_;\r
-\r
-  if (!$wor or $wor eq "") {\r
-    error ("WOR is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$assignee or $assignee eq "") {\r
-    error ("Assignee must be specified");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$project or $project eq "") {\r
-    error ("UCM Project is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$startDate or $startDate eq "") {\r
-    error ("Planned Start Date is required");\r
-    return 1;\r
-  } # if\r
-\r
-  my $entity   = getEntity ("WOR", $wor);\r
-\r
-  return 1 if !$entity;\r
-\r
-  my $state    = $entity->GetFieldValue ("state")->GetValue ();\r
-\r
-  if ($state ne "Submitted") {\r
-    error ("WOR $wor is not in Submitted state!\nState: $state");\r
-    return 2;\r
-  } # if\r
-\r
-  $session->EditEntity ($entity, "assign");\r
-\r
-  $entity->SetFieldValue ("ucm_project",       $project)       if $project     ne "";\r
-  $entity->SetFieldValue ("PlannedStart",      $startDate)     if $startDate   ne "";\r
-  $entity->SetFieldValue ("PlannedEffort",     $plannedHrs)    if $plannedHrs  ne "";\r
-  $entity->SetFieldValue ("Owner",             $assignee)      if $assignee    ne "";\r
-\r
-  my $status = $entity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $entity->Revert ();\r
-    error ("Assign failed for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  $status = $entity->Commit ();\r
-\r
-  if ($status ne "") {\r
-    error ("Assign failed during Submit for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  return 0;\r
-} # assign\r
-\r
-#-----------------------------------------------------------------------------\r
-# activate (): Activate a WOR\r
-#-----------------------------------------------------------------------------\r
-sub activate ($$$$$) {\r
-  my ($wor, $project, $estHrs, $startDate, $endDate) = @_;\r
-\r
-  if (!$wor or $wor eq "") {\r
-    error ("WOR is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$project or $project eq "") {\r
-    error ("UCM Project is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$startDate or $startDate eq "") {\r
-    error ("Planned Start Date is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$endDate or $endDate eq "") {\r
-    error ("Planned End Date is required");\r
-    return 1;\r
-  } # if\r
-\r
-  my $entity   = getEntity ("WOR", $wor);\r
-\r
-  return 1 if !$entity;\r
-\r
-  my $state    = $entity->GetFieldValue ("state")->GetValue ();\r
-\r
-  if ($state ne "Assessing") {\r
-    error ("WOR $wor is not in Assessing state!\nstate: $state");\r
-    return 2;\r
-  } # if\r
-\r
-  $session->EditEntity ($entity, "activate");\r
-\r
-  $entity->SetFieldValue ("ucm_project",       $project)       if $project ne "";\r
-  $entity->SetFieldValue ("EstimatedEffort",   $estHrs)        if $estHrs ne "";\r
-  $entity->SetFieldValue ("PlannedStart",      $startDate)     if $startDate ne "";\r
-  $entity->SetFieldValue ("PlannedEnd",                $endDate)       if $endDate ne "";\r
-\r
-  my $status = $entity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $entity->Revert ();\r
-    error ("Activate failed for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  $status = $entity->Commit ();\r
-\r
-  if ($status ne "") {\r
-    error ("Activate failed during Submit for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-   return 0;\r
-} # activate\r
-\r
-#-----------------------------------------------------------------------------\r
-# resolve ($): Resolve a WOR\r
-#-----------------------------------------------------------------------------\r
-sub resolve ($) {\r
-  my ($wor) = @_;\r
-\r
-  if (!$wor or $wor eq "") {\r
-    error ("WOR is required");\r
-    return 1;\r
-  } # if\r
-\r
-  my $entity   = getEntity ("WOR", $wor);\r
-\r
-  return 1 if !$entity;\r
-\r
-  my $state    = $entity->GetFieldValue ("state")->GetValue ();\r
-\r
-  if ($state ne "Working") {\r
-    error ("WOR $wor is not in Working state!\nState: $state");\r
-    return 2;\r
-  } # if\r
-\r
-  $session->EditEntity ($entity, "resolve");\r
-\r
-  my $status = $entity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $entity->Revert ();\r
-    error ("Resolve failed for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  $status = $entity->Commit ();\r
-\r
-  if ($status ne "") {\r
-    error ("Resolve failed during Submit for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-   return 0;\r
-} # resolve\r
-\r
-#-----------------------------------------------------------------------------\r
-# complete ($$): Complete a WOR\r
-#-----------------------------------------------------------------------------\r
-sub complete ($$) {\r
-  my ($wor, $actualHrs) = @_;\r
-\r
-  if (!$wor or $wor eq "") {\r
-    error ("WOR is required");\r
-    return 1;\r
-  } # if\r
-\r
-  if (!$wor or $wor eq "") {\r
-    error ("Actual Hours are required");\r
-    return 1;\r
-  } # if\r
-\r
-  my $entity   = getEntity ("WOR", $wor);\r
-\r
-  return 1 if !$entity;\r
-\r
-  my $state    = $entity->GetFieldValue ("state")->GetValue ();\r
-\r
-  if ($state ne "Verifying") {\r
-    error ("WOR $wor is not in Verifying state!\nState:$state");\r
-    return 2;\r
-  } # if\r
-\r
-  $session->EditEntity ($entity, "complete");\r
-  $entity->SetFieldValue ("ActualEffort", $actualHrs) if $actualHrs ne "";\r
-\r
-  my $status = $entity->Validate ();\r
-\r
-  if ($status ne "") {\r
-    $entity->Revert ();\r
-    error ("Complete failed for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-  $status = $entity->Commit ();\r
-\r
-  if ($status ne "") {\r
-    error ("Complete failed during Submit for WOR $wor:\n$status");\r
-    return 2;\r
-  } # if\r
-\r
-   return 0;\r
-} # Complete\r
-\r
-#-----------------------------------------------------------------------------\r
-# executeCommand (@): Executes a cqtool command\r
-#-----------------------------------------------------------------------------\r
-sub executeCommand (@) {\r
-  my (@args) = @_;\r
-\r
-  my $cmd = lc shift @args;\r
-\r
-  return if $cmd eq "";\r
-\r
-  if ($_commands{$cmd}) {\r
-    if (!$CQTool::session) {\r
-      if ( # Commands that do not require a database connection\r
-         !($cmd eq "exit"      or\r
-           $cmd eq "quit"      or\r
-           $cmd eq "help"      or\r
-           $cmd eq "usage"     or\r
-           $cmd eq "verbose")) {\r
-       verbose "Opening $_db_name as $_userid...";\r
-\r
-       if (!$_password) {\r
-         display_nolf ("${_userid}'s password:");\r
-         `stty -echo`;\r
-         $_password = <STDIN>;\r
-         chomp $_password;\r
-         display ("");\r
-         `stty echo`;\r
-       } # if\r
-\r
-       openDB ($_userid, $_password, $_db_name);\r
-      } # if\r
-    } # if\r
-\r
-    # Treat args: Args that are enclosed in quotes must be\r
-    # combined. For simplicity's sake we will only support matched\r
-    # pairs of double quotes. Anything else results in undefined\r
-    # behavior.\r
-    my (@new_args);\r
-\r
-    foreach (@args) {\r
-      # Quoted argument starting\r
-      if (/^\"(.*)\"$/s) {\r
-       push @new_args, $1;\r
-      } else {\r
-       push @new_args, $_;\r
-      } # if\r
-    } # foreach\r
-\r
-    $_log->msg ("$cmd (" . join (",", @new_args) . ")") if get_debug;\r
-\r
-    return $_commands{$cmd} (@new_args);\r
-  } else {\r
-    error ("Unknown command \"$cmd\" (try help)");\r
-    return 1;\r
-  } # if\r
-} # executeCommand\r
-\r
-#-----------------------------------------------------------------------------\r
-# commandLoop (@): This is the interactive command loop\r
-#-----------------------------------------------------------------------------\r
-sub commandLoop (@) {\r
-  my (@args) = @_;\r
-\r
-  # For single, command line, commands...\r
-  return executeCommand (@args) if @args;\r
-\r
-  announce if !$_ucmwb;\r
-\r
-  while () {\r
-    if (!$_ucmwb) {\r
-      display_nolf ($PROMPT . RESET . UNDERLINE);\r
-    } else {\r
-      display_nolf ($UCMWB_PROMPT);\r
-    } # if\r
-\r
-    # Read command into $_\r
-    $_ = <STDIN>;\r
-    chomp;\r
-\r
-    # If we are not being called by ucmwb, display RESET to stop the\r
-    # UNDERLINE we were using. This keeps the output from being\r
-    # underlined. In ucmwb mode we are not using any of the terminal\r
-    # sequences.\r
-    display_nolf (RESET) if !$_ucmwb;\r
-\r
-    # If the user hit Control-d then a ^D is displayed but we remain\r
-    # on the same line. So output a carriage return and exit 0.\r
-    if (!$_) {\r
-      display ("");\r
-      exit 0;\r
-    } # if\r
-\r
-    # Special handling for set command since we want to take\r
-    # everything after <field> to be a value, and we may get long\r
-    # values that are space separated and space significant\r
-    # (e.g. description?)\r
-    if (/^\s*(\w+)\s+(\w+)\s+(\w+)\s+(.*)/) {\r
-      if (lc $1 eq "set") {\r
-       my $cmd         = $1;\r
-       my $wor         = $2;\r
-       my $field       = $3;\r
-       my $value       = $4;\r
-\r
-       # Change "\n"'s back to \n's\r
-       $value =~ s/\\n/\n/g;\r
-\r
-       executeCommand ($cmd, $wor, $field, "\"$value\"");\r
-      } else {\r
-       executeCommand (split);\r
-      } # if\r
-    } else {\r
-      executeCommand (split);\r
-    } # if\r
-  } # while\r
-} # commandLoop\r
+#!/usr/bin/env /opt/rational/clearquest/bin/cqperl
+##############################################################################
+#
+# Name: cqtool
+#
+# Description: cqtool is an interface to Clearquest to perform some simple
+#              actions to the RANCQ database. It is used primarily by ucmwb
+#              but it also supports a command line interface.
+#
+#              The following commands are supported:
+#
+#              activate <wor> <project> <est_hours> <startdate> <enddate>:
+#                      Activate WOR
+#              assign <wor> <assignee> <project> <planned_hours> <startdate>:
+#                      Assign the WOR
+#              clone <wor>:
+#                      Clones a WOR
+#              comment <wor> <comment>
+#                      Add a comment to the Notes_Entry field for the WOR
+#              complete <wor> <actual_hours>:
+#                      Complete WOR
+#              createhd:
+#                      Create a new Help Desk Ticket
+#              createwor:
+#                      Create a new WOR
+#              effort <wor> <hours>:
+#                      Update the WOR's actual hours
+#              exit|quit:
+#                      Exits cqtool
+#              help:
+#                      This display
+#              link <parent wor> <child wor>:
+#                      Link a parent WOR to a child WOR
+#              resolve <wor>:
+#                      Resolve WOR
+#              set <wor> <field> <value>
+#                      Set <field> to <value> for the <wor>
+#              usage:
+#                      Displays command line usage
+#              version:
+#                      Displays version of cqtool
+#
+#              Many of these commands simply perform actions on a wor. Two
+#              of these commands, createwor and createhd have Perl/Tk GUI
+#              interfaces.
+#
+# Command line usage:
+#
+# Usage: cqtool\t[-usage|help] [-verbose] [-debug]
+#      [-userid <user>] [-password <password>] [<command>]
+#
+# Where:
+#
+#   -usage|help:       Display usage
+#   -verbose:          Turn on verbose mode
+#   -debug:            Turn on debug mode
+#   -userid:           User ID to log into Clearquest database as
+#   -password:         Password to use
+#   <command>          If specified then cqtool executes <command> and
+#                      exits
+#
+# Environment:         cqtool supports the following environment variables
+#                      that are used mostly for tesing purposes
+#
+#      CQ_DBSET:       Clearquest DBSET to open (e.g. XTST3 for testing -
+#                      default RANCQ)  
+#      CQ_USER:        User name to log into the $CQ_DBSET database with
+#      CQ_PASSWORD:    Password to use to log into the $CQ_DBSET with.
+#
+# Author: Andrew@DeFaria.com
+#
+# (c) Copyright 2007, General Dynamics, all rights reserved
+#
+##############################################################################
+use strict;
+use warnings;
+
+use CQPerlExt;
+use FindBin;
+use Getopt::Long;
+use Term::ANSIColor qw (:constants);
+
+use lib ("$FindBin::Bin", "$FindBin::Bin/../lib");
+
+use SCCM::Misc;
+use Display;
+use CQTool;
+use CreateWORUI;
+use CreateHelpDeskUI;
+use Logger;
+
+my $VERSION            = BOLD GREEN . "1.1" . RESET;
+my $PROMPT             = BOLD YELLOW . ">>" . RESET;
+my $UCMWB_PROMPT       = ">>";
+my $DESC               = BOLD RED . "$FindBin::Script" .
+                         RESET      " Version " .
+                         $VERSION .
+                         CYAN ": Program to talk to Clearquest" .
+                         RESET;
+
+# Globals
+my $_userid    = $ENV{CQ_USER}  ? $ENV{CQ_USER} : $ENV{USER};
+my $_password  = $ENV{CQ_PASSWORD};
+my $_db_name   = $ENV{CQ_DBSET} ? $ENV{CQ_DBSET} : "RANCQ";
+my $_ucmwb;
+
+my $_log;
+
+if (get_debug) {
+  $_log = new Logger (
+    path => "/tmp",
+    append => 1,
+  );
+} # if
+
+my %_commands = (
+  activate     => \&activate,
+  assign       => \&assign,
+  clone                => \&clone,
+  comment      => \&comment,
+  complete     => \&complete,
+  createhd     => \&createHelpDesk,
+  createwor    => \&createWOR,
+  effort       => \&effort,
+  exit         => \&shutdown,
+  help         => \&help,
+  link         => \&linkParentWor2ChildWor,
+  quit         => \&shutdown,
+  resolve      => \&resolve,
+  set          => \&set,
+  usage                => \&usage,
+  version      => \&announce,
+);
+
+##############################################################################
+# Forwards
+##############################################################################
+sub commandLoop (@);
+
+##############################################################################
+# Main
+##############################################################################
+MAIN: {
+  GetOptions (
+    "usage"            => sub { usage () },
+    "verbose"          => sub { set_verbose () },
+    "debug"            => sub { set_debug () },
+    "userid=s"         => \$_userid,
+    "password=s"       => \$_password,
+    "database=s"       => \$_db_name,
+    "ucmwb"            => \$_ucmwb,
+  ) || usage ();
+
+  exit (commandLoop(@ARGV));
+} # MAIN
+
+##############################################################################
+# Subroutines
+##############################################################################
+
+#-----------------------------------------------------------------------------
+# shutdown (): Ends program
+#-----------------------------------------------------------------------------
+sub shutdown () {
+  exit (0);
+} # exit
+
+#-----------------------------------------------------------------------------
+# help (): Displays help
+#-----------------------------------------------------------------------------
+sub help () {
+  display ($DESC);
+  display <<END;
+
+Valid commands are:
+
+activate <wor> <project> <est_hours> <startdate> <enddate>:
+       Activate WOR
+assign <wor> <assignee> <project> <planned_hours> <startdate>:
+       Assign the WOR
+clone <wor>:
+       Clones a WOR
+comment <wor> <comment>
+       Add a comment to the Notes_Entry field for the WOR
+complete <wor> <actual_hours>:
+       Complete WOR
+createhd:
+       Create a new Help Desk Ticket
+createwor:
+       Create a new WOR
+effort <wor> <hours>:
+       Update the WOR's actual hours
+exit|quit:
+       Exits $FindBin::Script
+help:
+       This display
+link <parent wor> <child wor>:
+       Link a parent WOR to a child WOR
+resolve <wor>:
+       Resolve WOR
+set <wor> <field> <value>
+       Set <field> to <value> for the <wor>
+usage:
+       Displays command line usage
+version:
+       Displays version of $FindBin::Script
+END
+} # help
+
+#-----------------------------------------------------------------------------
+# announce (): Announce ourselves
+#-----------------------------------------------------------------------------
+sub announce () {
+  display ($DESC);
+} # Announce
+
+#-----------------------------------------------------------------------------
+# dberror ($): Handle errors when talking to Clearquest. Note we need to reset
+#             the database connection if an error happens.
+#-----------------------------------------------------------------------------
+sub dberror ($) {
+  my ($msg) = @_;
+
+  # Need to not only report the error but to reopen the
+  # database. Something gets corruppted if we don't!
+  error ($msg);
+
+  closeDB ();
+
+  openDB ($_userid, $_password, $_db_name);
+} # DBError
+
+#-----------------------------------------------------------------------------
+# getEntity ($$): Get an entity from Clearquest
+#-----------------------------------------------------------------------------
+sub getEntity ($$) {
+  my ($recordname, $wor) = @_;
+
+  my $entity;
+
+  eval {
+    $entity = $CQTool::session->GetEntity ($recordname, $wor);
+  };
+
+  if ($@) {
+    chomp $@;
+    dberror ($@);
+    return undef;
+  } else {
+    return $entity;
+  } # if
+} # getEntity
+
+#-----------------------------------------------------------------------------
+# set ($$$): Set $field to $value for $wor
+#-----------------------------------------------------------------------------
+sub set ($$@) {
+  my ($wor, $field, $value) = @_;
+
+  if (!$wor or $wor eq "") {
+    error ("WOR is required");
+    return 1;
+  } # if
+
+  if (!$field or $field eq "") {
+    error ("Field is required");
+    return 1;
+  } # if
+
+  my $entity   = getEntity ("WOR", $wor);
+
+  return 1 if !$entity;
+
+  $session->EditEntity ($entity, "modify");
+
+  $_log->msg ("Modifying $field to \"$value\"") if get_debug;
+  eval {
+    $entity->SetFieldValue ($field, $value);
+  };
+
+  if ($@) {
+    dberror ("$field set failed for WOR $wor:\n$@");
+    return 2;
+  } # if
+
+  my $status = $entity->Validate ();
+
+  if ($status ne "") {
+    $entity->Revert ();
+    error ("$field validate failed for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+  $status = $entity->Commit ();
+
+  if ($status ne "") {
+    error ("$field update failed during Submit for $wor:\n$status");
+    return 2;
+  } # if
+
+   return 0;
+} # set
+
+#-----------------------------------------------------------------------------
+# clone ($): Clone a WOR
+#-----------------------------------------------------------------------------
+sub clone ($) {
+  my ($wor) = @_;
+
+  if (!$wor) {
+    error ("WOR not specified!");
+    return 1;
+  } # if
+
+  $entity = getEntity ("WOR", $wor);
+
+  return 1 if !$entity;
+
+  # Check state
+  my $state = $entity->GetFieldValue ("state")->GetValue ();
+
+  if ($state ne "Closed") {
+    error ("WOR $wor not closed - Unable to clone!");
+    return 1;
+  } # if
+
+  verbose ("Cloning WOR $wor...");
+
+  my $result = 0;
+
+  eval {
+    # Currently Clone doesn't return a proper result but eventually...
+    $result = $CQTool::session->FireRecordScriptAlias ($entity, "Clone");
+  };
+
+  if ($@) {
+    chomp $@;
+    dberror ($@);
+    return 1;
+  } # if
+
+  return $result;
+} # clone
+
+#-----------------------------------------------------------------------------
+# effort ($$): Update actual hours for a WOR
+#-----------------------------------------------------------------------------
+sub effort ($$) {
+  my ($wor, $actualHrs) = @_;
+
+  return set $wor, "ActualEffort", $actualHrs;
+} # effort
+
+#-----------------------------------------------------------------------------
+# comment (): Update the Notes_Entry comment field for a WOR
+#-----------------------------------------------------------------------------
+sub comment ($) {
+  my ($wor) = @_;
+
+  if (!$wor) {
+    error "WOR not defined in call to comment!";
+    return 1;
+  } # if
+
+  if (!$_ucmwb) {
+    display ("Enter comments below. When finished, enter \".\" on a line by itself or hit ^D:");
+  } else {
+    # We still need to prompt for the comments however signal UCMWB
+    # that command is ready for more input.
+    display_nolf ($UCMWB_PROMPT);
+  } # if
+
+  my $comments;
+
+  while (<STDIN>) {
+    last if $_ eq ".\n";
+    $comments .= $_;
+  } # while
+
+  chomp $comments;
+
+  $_log->msg ("Comments:\n$comments") if get_debug;
+
+  return set $wor, "Note_Entry", $comments;
+} # Comment
+
+#-----------------------------------------------------------------------------
+# linkParentWor2ChildWor ($$): Link a child WOR to a parent WOR
+#-----------------------------------------------------------------------------
+sub linkParentWor2ChildWor ($$) {
+  my ($parentWor, $childWor) = @_;
+
+  my $status;
+
+  verbose ("Linking $parentWor -> $childWor...");
+
+  my $childentity      = getEntity ("WOR", $childWor);
+  my $parententity     = getEntity ("WOR", $parentWor);
+
+  return 1 unless $childentity and $parententity;
+
+  $session->EditEntity ($parententity, "modify");
+
+  $parententity->AddFieldValue ("wor_children", $childWor);
+
+  $status = $parententity->Validate ();
+
+  if ($status ne "") {
+    $parententity->Revert ();
+    error ("Validation failed while attempting to add child WOR $childWor to parent WOR $parentWor:\n$status");
+    return 1;
+  } # if
+
+  eval {
+    $status = $parententity->Commit ();
+  };
+
+  $status = $@ if $@;
+
+  if ($status ne "") {
+    (error "Commit failed while trying to add child WOR $childWor to parent WOR $parentWor:\n$status");
+    return 2;
+  } # if
+
+  debug "Modifying child $childWor...";
+  $session->EditEntity ($childentity, "modify");
+
+  $childentity->SetFieldValue ("wor_parent", $parentWor);
+
+  $status = $childentity->Validate ();
+
+  if ($status ne "") {
+    $childentity->Revert ();
+    error "Validation failed while attempting to add parent WOR $parentWor to child WOR $childWor:\n$status";
+    return 1;
+  } # if
+
+  eval {
+    $status = $childentity->Commit ();
+  };
+
+  $status = $@ if $@;
+
+  if ($status ne "") {
+    error "Commit failed while trying to add parent WOR $parentWor to child WOR $childWor:\n$status";
+    return 2;
+  } # if
+
+  return 0;
+} # linkParentWor2ChildWor
+
+#-----------------------------------------------------------------------------
+# assign ($$$$): Assign a WOR
+#-----------------------------------------------------------------------------
+sub assign ($$$$$) {
+  my ($wor, $assignee, $project, $plannedHrs, $startDate) = @_;
+
+  if (!$wor or $wor eq "") {
+    error ("WOR is required");
+    return 1;
+  } # if
+
+  if (!$assignee or $assignee eq "") {
+    error ("Assignee must be specified");
+    return 1;
+  } # if
+
+  if (!$project or $project eq "") {
+    error ("UCM Project is required");
+    return 1;
+  } # if
+
+  if (!$startDate or $startDate eq "") {
+    error ("Planned Start Date is required");
+    return 1;
+  } # if
+
+  my $entity   = getEntity ("WOR", $wor);
+
+  return 1 if !$entity;
+
+  my $state    = $entity->GetFieldValue ("state")->GetValue ();
+
+  if ($state ne "Submitted") {
+    error ("WOR $wor is not in Submitted state!\nState: $state");
+    return 2;
+  } # if
+
+  $session->EditEntity ($entity, "assign");
+
+  $entity->SetFieldValue ("ucm_project",       $project)       if $project     ne "";
+  $entity->SetFieldValue ("PlannedStart",      $startDate)     if $startDate   ne "";
+  $entity->SetFieldValue ("PlannedEffort",     $plannedHrs)    if $plannedHrs  ne "";
+  $entity->SetFieldValue ("Owner",             $assignee)      if $assignee    ne "";
+
+  my $status = $entity->Validate ();
+
+  if ($status ne "") {
+    $entity->Revert ();
+    error ("Assign failed for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+  $status = $entity->Commit ();
+
+  if ($status ne "") {
+    error ("Assign failed during Submit for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+  return 0;
+} # assign
+
+#-----------------------------------------------------------------------------
+# activate (): Activate a WOR
+#-----------------------------------------------------------------------------
+sub activate ($$$$$) {
+  my ($wor, $project, $estHrs, $startDate, $endDate) = @_;
+
+  if (!$wor or $wor eq "") {
+    error ("WOR is required");
+    return 1;
+  } # if
+
+  if (!$project or $project eq "") {
+    error ("UCM Project is required");
+    return 1;
+  } # if
+
+  if (!$startDate or $startDate eq "") {
+    error ("Planned Start Date is required");
+    return 1;
+  } # if
+
+  if (!$endDate or $endDate eq "") {
+    error ("Planned End Date is required");
+    return 1;
+  } # if
+
+  my $entity   = getEntity ("WOR", $wor);
+
+  return 1 if !$entity;
+
+  my $state    = $entity->GetFieldValue ("state")->GetValue ();
+
+  if ($state ne "Assessing") {
+    error ("WOR $wor is not in Assessing state!\nstate: $state");
+    return 2;
+  } # if
+
+  $session->EditEntity ($entity, "activate");
+
+  $entity->SetFieldValue ("ucm_project",       $project)       if $project ne "";
+  $entity->SetFieldValue ("EstimatedEffort",   $estHrs)        if $estHrs ne "";
+  $entity->SetFieldValue ("PlannedStart",      $startDate)     if $startDate ne "";
+  $entity->SetFieldValue ("PlannedEnd",                $endDate)       if $endDate ne "";
+
+  my $status = $entity->Validate ();
+
+  if ($status ne "") {
+    $entity->Revert ();
+    error ("Activate failed for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+  $status = $entity->Commit ();
+
+  if ($status ne "") {
+    error ("Activate failed during Submit for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+   return 0;
+} # activate
+
+#-----------------------------------------------------------------------------
+# resolve ($): Resolve a WOR
+#-----------------------------------------------------------------------------
+sub resolve ($) {
+  my ($wor) = @_;
+
+  if (!$wor or $wor eq "") {
+    error ("WOR is required");
+    return 1;
+  } # if
+
+  my $entity   = getEntity ("WOR", $wor);
+
+  return 1 if !$entity;
+
+  my $state    = $entity->GetFieldValue ("state")->GetValue ();
+
+  if ($state ne "Working") {
+    error ("WOR $wor is not in Working state!\nState: $state");
+    return 2;
+  } # if
+
+  $session->EditEntity ($entity, "resolve");
+
+  my $status = $entity->Validate ();
+
+  if ($status ne "") {
+    $entity->Revert ();
+    error ("Resolve failed for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+  $status = $entity->Commit ();
+
+  if ($status ne "") {
+    error ("Resolve failed during Submit for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+   return 0;
+} # resolve
+
+#-----------------------------------------------------------------------------
+# complete ($$): Complete a WOR
+#-----------------------------------------------------------------------------
+sub complete ($$) {
+  my ($wor, $actualHrs) = @_;
+
+  if (!$wor or $wor eq "") {
+    error ("WOR is required");
+    return 1;
+  } # if
+
+  if (!$wor or $wor eq "") {
+    error ("Actual Hours are required");
+    return 1;
+  } # if
+
+  my $entity   = getEntity ("WOR", $wor);
+
+  return 1 if !$entity;
+
+  my $state    = $entity->GetFieldValue ("state")->GetValue ();
+
+  if ($state ne "Verifying") {
+    error ("WOR $wor is not in Verifying state!\nState:$state");
+    return 2;
+  } # if
+
+  $session->EditEntity ($entity, "complete");
+  $entity->SetFieldValue ("ActualEffort", $actualHrs) if $actualHrs ne "";
+
+  my $status = $entity->Validate ();
+
+  if ($status ne "") {
+    $entity->Revert ();
+    error ("Complete failed for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+  $status = $entity->Commit ();
+
+  if ($status ne "") {
+    error ("Complete failed during Submit for WOR $wor:\n$status");
+    return 2;
+  } # if
+
+   return 0;
+} # Complete
+
+#-----------------------------------------------------------------------------
+# executeCommand (@): Executes a cqtool command
+#-----------------------------------------------------------------------------
+sub executeCommand (@) {
+  my (@args) = @_;
+
+  my $cmd = lc shift @args;
+
+  return if $cmd eq "";
+
+  if ($_commands{$cmd}) {
+    if (!$CQTool::session) {
+      if ( # Commands that do not require a database connection
+         !($cmd eq "exit"      or
+           $cmd eq "quit"      or
+           $cmd eq "help"      or
+           $cmd eq "usage"     or
+           $cmd eq "verbose")) {
+       verbose "Opening $_db_name as $_userid...";
+
+       if (!$_password) {
+         display_nolf ("${_userid}'s password:");
+         `stty -echo`;
+         $_password = <STDIN>;
+         chomp $_password;
+         display ("");
+         `stty echo`;
+       } # if
+
+       openDB ($_userid, $_password, $_db_name);
+      } # if
+    } # if
+
+    # Treat args: Args that are enclosed in quotes must be
+    # combined. For simplicity's sake we will only support matched
+    # pairs of double quotes. Anything else results in undefined
+    # behavior.
+    my (@new_args);
+
+    foreach (@args) {
+      # Quoted argument starting
+      if (/^\"(.*)\"$/s) {
+       push @new_args, $1;
+      } else {
+       push @new_args, $_;
+      } # if
+    } # foreach
+
+    $_log->msg ("$cmd (" . join (",", @new_args) . ")") if get_debug;
+
+    return $_commands{$cmd} (@new_args);
+  } else {
+    error ("Unknown command \"$cmd\" (try help)");
+    return 1;
+  } # if
+} # executeCommand
+
+#-----------------------------------------------------------------------------
+# commandLoop (@): This is the interactive command loop
+#-----------------------------------------------------------------------------
+sub commandLoop (@) {
+  my (@args) = @_;
+
+  # For single, command line, commands...
+  return executeCommand (@args) if @args;
+
+  announce if !$_ucmwb;
+
+  while () {
+    if (!$_ucmwb) {
+      display_nolf ($PROMPT . RESET . UNDERLINE);
+    } else {
+      display_nolf ($UCMWB_PROMPT);
+    } # if
+
+    # Read command into $_
+    $_ = <STDIN>;
+    chomp;
+
+    # If we are not being called by ucmwb, display RESET to stop the
+    # UNDERLINE we were using. This keeps the output from being
+    # underlined. In ucmwb mode we are not using any of the terminal
+    # sequences.
+    display_nolf (RESET) if !$_ucmwb;
+
+    # If the user hit Control-d then a ^D is displayed but we remain
+    # on the same line. So output a carriage return and exit 0.
+    if (!$_) {
+      display ("");
+      exit 0;
+    } # if
+
+    # Special handling for set command since we want to take
+    # everything after <field> to be a value, and we may get long
+    # values that are space separated and space significant
+    # (e.g. description?)
+    if (/^\s*(\w+)\s+(\w+)\s+(\w+)\s+(.*)/) {
+      if (lc $1 eq "set") {
+       my $cmd         = $1;
+       my $wor         = $2;
+       my $field       = $3;
+       my $value       = $4;
+
+       # Change "\n"'s back to \n's
+       $value =~ s/\\n/\n/g;
+
+       executeCommand ($cmd, $wor, $field, "\"$value\"");
+      } else {
+       executeCommand (split);
+      } # if
+    } else {
+      executeCommand (split);
+    } # if
+  } # while
+} # commandLoop
diff --git a/data/allmach b/data/allmach
new file mode 100644 (file)
index 0000000..1e408cb
--- /dev/null
@@ -0,0 +1,44 @@
+################################################################################
+#
+# File:        machines
+# Description: Defintion of machines for allmach
+# Author:      Andrew@DeFaria.com
+#
+################################################################################
+# Column 1 Machine name
+# Column 2 Model
+# Column 3 OS Version
+# Column 4 ClearCase Version (if applicable)
+# Column 5 Owner (if known)
+# Column 6 Usage (if known)
+cowboys:Sun:Solaris 5.9:7.0.1.0:ccadm:ranvob1/registry server
+patriots:Sun:?:Solaris 5.9:7.0.1.0:ccadm:ranvob2
+rams:Sun:Solaris 5.9:7.0.1.0:ccadm:ranvob3/registry server
+chargers:Sun:Solaris 5.9:70.1.1:ccadm:ranview1
+colts:Sun:Solaris 5.9:7.0.1.0:ccadm:ranview2
+ranbuild1:Sun:Solaris 5.8:7.0.1.0:ccadm:builds
+ranbuild2:Sun:Solaris 5.9:2003.06.10+:ccadm:builds
+ranbuild4:Sun:Solaris 5.9:7.0.1.1:ccadm:builds
+randws119:Sun:Solaris 5.9:7.0.1.1:Hy Truong:Workstation
+randws094:Sun:Solaris 5.10:7.0.1.1:John Hartin:Old workstation
+randws033:Sun:Solaris 5.10:Sam Schwalm:Workstation
+randws103:Sun:Solaris 5.9:7.0.1.1:?:?
+randws106:Sun:Solaris 5.9:2003.06.10+:?:?
+randws113:Sun:Solaris 5.9:7.0.1.1:?:?
+randws114:Sun:Solaris 5.9:2003.06.10+:Tony Trujilo:?
+randws000:Sun:Solaris 5.10:7.0.1.1:?:?
+randws021:?:?:?:?:?
+randws035:?:?:?:ccadm:?
+randws036:?:?:?:ccadm:?
+ranadm1:Sun:Solaris 5.9:?:ccadm:Jumpstart, PowerBroker, NIS, SMTP, DNS, NTP
+ranadm2:Sun:Solaris 5.9:2003.06.10+:ccadm:License server, Sys admin, NIS, Home Directory server
+ranray:Sun:Solaris 5.9:2003.06.10+:ccadm:?
+ranray16:?:?:?:ccadm:Thin client to ranray
+niners:Sun:Solaris 5.9:2003.06.10+:ccadm:?
+randbs:Sun:Solaris 5.9:?:ccadm:CQ DB server/Bldforge
+ranbkp2:?:?:?:ccadm:?
+ranlin03:Redhat Linux:2.4.21-50.Elsmp:?:ccadm:?
+rancpp10:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+rancpp01:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+rancpp02:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+rancpp03:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
diff --git a/data/machines b/data/machines
new file mode 100644 (file)
index 0000000..7d9873e
--- /dev/null
@@ -0,0 +1,38 @@
+################################################################################
+#
+# File:        machines
+# Description: Defintion of machines for allmach
+# Author:      Andrew@DeFaria.com
+#
+################################################################################
+# Column 1 Machine name
+# Column 2 Model
+# Column 3 OS Version
+# Column 4 ClearCase Version (if applicable)
+# Column 5 Owner (if known)
+# Column 6 Usage (if known)
+chargers:Sun:Solaris 5.9:70.1.1:ccadm:ranview1
+colts:Sun:Solaris 5.9:7.0.1.0:ccadm:ranview2
+cowboys:Sun:Solaris 5.9:7.0.1.0:ccadm:ranvob1/registry server
+niners:Sun:Solaris 5.9:2003.06.10+:ccadm:?
+patriots:Sun:?:Solaris 5.9:7.0.1.0:ccadm:ranvob2
+rams:Sun:Solaris 5.9:7.0.1.0:ccadm:ranvob3/registry server
+#ranadm1:Sun:Solaris 5.9:?:ccadm:Jumpstart, PowerBroker, NIS, SMTP, DNS, NTP
+ranadm2:Sun:Solaris 5.9:2003.06.10+:ccadm:License server, Sys admin, NIS, Home Directory server
+ranbkp2:?:?:?:ccadm:?
+ranbuild1:Sun:Solaris 5.8:7.0.1.0:ccadm:builds
+ranbuild2:Sun:Solaris 5.9:2003.06.10+:ccadm:builds
+ranbuild4:Sun:Solaris 5.9:7.0.1.1:ccadm:builds
+rancpp01:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+rancpp02:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+rancpp03:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+rancpp10:Redhat Linux:2.6.18.53.Eel5xen:?:ccadm:?
+#randbs:Sun:Solaris 5.9:?:ccadm:CQ DB server/Bldforge
+randws094:Sun:Solaris 5.10:7.0.1.1:John Hartin:Old workstation
+randws103:Sun:Solaris 5.9:7.0.1.1:?:?
+randws106:Sun:Solaris 5.9:2003.06.10+:?:?
+randws113:Sun:Solaris 5.9:7.0.1.1:?:?
+randws114:Sun:Solaris 5.9:2003.06.10+:Tony Trujilo:?
+randws119:Sun:Solaris 5.9:7.0.1.1:Hy Truong:Workstation
+ranlin03:Redhat Linux:2.4.21-50.Elsmp:?:ccadm:?
+ranray:Sun:Solaris 5.9:2003.06.10+:ccadm:?
diff --git a/data/windows b/data/windows
new file mode 100644 (file)
index 0000000..27250ae
--- /dev/null
@@ -0,0 +1,24 @@
+################################################################################
+#
+# File:        windows
+# Description: Defintion of machines for allmach
+# Author:      Andrew@DeFaria.com
+#
+################################################################################
+# Column 1 Machine name
+# Column 2 Model
+# Column 3 OS Version
+# Column 4 ClearCase Version (if applicable)
+# Column 5 Owner (if known)
+# Column 6 Usage (if known)
+ranframe06:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe07:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe09:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker/Buildforge Console
+ranframe12:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe14:Microsoft:Windows Server 2003:7.0.1.7:ccadm:Frame Maker
+ranframe15:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe16:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe17:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe18:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe19:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
+ranframe20:Microsoft:Windows Server 2003:2003.06.10+:ccadm:Frame Maker
index bb2b745..81822dd 100644 (file)
@@ -80,17 +80,17 @@ use IPC::Open3;
 use OSDep;
 use Display;
 
-my ($clearpid, $clearin, $clearout, $oldHandler);
+my ($clearpid, $clearin, $clearout, $oldHandler, $cleartool);
 
-our $VIEW_DRIVE     = 'M';
+our $VIEW_DRIVE     = $ENV{CLEARCASE_VIEW_DRIVE} || 'M';
 our $VOB_MOUNT      = 'vob';
 our $WIN_VOB_PREFIX = '\\';
 our $SFX            = $ENV{CLEARCASE_XN_SFX} ? $ENV{CLEARCASE_XN_SFX} : '@@';
 
-our $VOBTAG_PREFIX = ($ARCH eq 'windows' or $ARCH eq 'cygwin')
+our $VOBTAG_PREFIX = ($ARCHITECTURE eq 'windows' or $ARCHITECTURE eq 'cygwin')
                    ? $WIN_VOB_PREFIX
-                   : "/$VOB_MOUNT/";
-our $VIEWTAG_PREFIX = ($ARCH eq 'windows' or $ARCH eq 'cygwin')
+                   : "/$VOB_MOUNT";
+our $VIEWTAG_PREFIX = ($ARCHITECTURE eq 'windows' or $ARCHITECTURE eq 'cygwin')
                     ? "$VIEW_DRIVE:"
                     : "${SEPARATOR}view";
 
@@ -112,15 +112,15 @@ our @EXPORT_OK = qw (
 
 BEGIN {
   # Find executables that we rely on
-  if ($ARCH eq 'windows' or $ARCH eq 'cygwin') {
+  if ($ARCHITECTURE eq 'windows' or $ARCHITECTURE eq 'cygwin') {
     # Should really go to the registry for this...
 
     # We can go to the registry pretty easy in Cygwin but I'm not sure how to do
     # that in plain old Windows. Most people either have Clearcase installed on
     # the C drive or commonly on the D drive on servers. So we'll look at both.
-    $CCHOME = 'C:\\Program Files\\Rational\\Clearcase';
+    $CCHOME = 'C:\\Program Files (x86)\\ibm\\RationalSDLC\\Clearcase';
 
-    $CCHOME = 'D:\\Program Files\\Rational\\Clearcase'
+    $CCHOME = 'D:\\Program Files (x86)\\ibm\\RationalSDLC\\Clearcase'
       unless -d $CCHOME;
 
     error 'Unable to figure out where Clearcase is installed', 1
@@ -177,7 +177,7 @@ sub _formatOpts {
 sub _setComment ($) {
   my ($comment) = @_;
 
-  return !$comment ? '-nc' : '-c "' . quotameta $comment . '"';
+  return !$comment ? '-nc' : '-c "' . quotemeta $comment . '"';
 } # _setComment
 
 sub vobname ($) {
@@ -238,7 +238,7 @@ The unique part of the vob name
   if (substr ($tag, 0, 1) eq '\\') {
     $name = substr $tag, 1;
   } elsif (substr ($tag, 0, 1) eq '/') {
-    if ($tag =~ /${Clearcase::VOBTAG_PREFIX}(.+)/) {
+    if ($tag =~ /${Clearcase::VOBTAG_PREFIX}\/(.+)/) {
       $name = $1;
     } # if
   } # if
@@ -578,13 +578,13 @@ Array of output lines from the cleartool command execution.
   # installed under /opt/rational/clearcase/bin. This is needed in case we wish
   # to use these Clearcase objects say in a web page where the server is often
   # run as a plain user who does not have cleartool in their path.
-  my $cleartool;
-  
-  if ($ARCH =~ /Win/ or $ARCH eq 'cygwin') {
-    $cleartool = 'cleartool';
-  } elsif (-x '/opt/rational/clearcase/bin/cleartool') {
-    $cleartool = '/opt/rational/clearcase/bin/cleartool';
-  } # if
+  unless ($cleartool) {
+    if ($ARCHITECTURE =~ /Win/i or $ARCHITECTURE eq 'cygwin') {
+      $cleartool = 'cleartool';
+    } elsif (-x '/opt/rational/clearcase/bin/cleartool') {
+      $cleartool = '/opt/rational/clearcase/bin/cleartool';
+    } # if
+  } # unless
 
   # TODO: Need to catch SIGCHILD here in case the user does something like hit
   # Ctrl-C. Such an action may interrupt the underlying cleartool process and
@@ -627,12 +627,53 @@ Array of output lines from the cleartool command execution.
   pop @output
     if @output and $output[$#output] eq '';
 
-  $self->{status} = $status;
-  $self->{output} = join "\n", @output;
+  $self->{lastcmd} = 'cleartool ' . $cmd;
+  $self->{status}  = $status;
+  $self->{output}  = join "\n", @output;
   
   return ($status, @output);
 } # execute
 
+sub lastcmd() {
+  my ($self) = @_;
+
+=pod
+
+=head2 lastcmd()
+
+Return last command attempted by execute
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Last command attempted by execute
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $self->{lastcmd} ||= '';
+
+  return $self->{lastcmd};
+} # lastcmd
+
 sub new {
   my ($class) = @_;
 
index 8c173c0..bc2e985 100644 (file)
@@ -34,10 +34,10 @@ Provides access to information about Clearcase Activites.
  
  my @changeset = $activity->changeset;
  
- foreach my $element (@changeset) {
+ for my $element (@changeset) {
    display "Element name: "    . $element->pname;
    display "Element verison: " . $element->version;
- } # foreach
+ } # for
 
 =head1 DESCRIPTION
 
@@ -54,29 +54,24 @@ package Clearcase::UCM::Activity;
 use strict;
 use warnings;
 
-use lib '../..';
-
-use Clearcase;
-use Clearcase::Element;
-
 # We should really inherit these from a more generic super class... 
-sub _processOpts (%) {
+sub _processOpts(%) {
   my ($self, %opts) = @_;
 
   my $opts;
   
-  foreach (keys %opts) {
+  for (keys %opts) {
     if ($_ eq 'cq' or $_ eq 'cqe' or $_ eq 'force' or $_ eq 'nc') {
       $opts .= "-$_ ";
     } elsif ($_ eq 'c' or $_ eq 'cfile') {
       $opts .= "-$_ $opts{$_}";
     } # if
-  } # foreach
+  } # for
   
   return $opts;
 } # _processOpts
 
-sub new ($$) {
+sub new($$) {
   my ($class, $activity, $pvob) = @_;
   
 =pod
@@ -113,16 +108,16 @@ Returns:
 
 =cut
   
-  my $self = bless {
+  $class = bless {
     name => $activity,
-    pvob => Clearcase::vobtag ($pvob),
+    pvob => $pvob,
     type => $activity =~ /^(deliver|rebase)./ ? 'integration' : 'regular',
   }, $class; # bless
   
-  return $self;
+  return $class;
 } # new
   
-sub name () {
+sub name() {
   my ($self) = @_;
 
 =pod
@@ -160,7 +155,7 @@ Returns:
   return $self->{name};
 } # name
 
-sub pvob () {
+sub pvob() {
   my ($self) = @_;
   
 =pod
@@ -198,7 +193,7 @@ Returns:
   return $self->{pvob};
 } # pvob
 
-sub type () {
+sub type() {
   my ($self) = @_;
   
 =pod
@@ -236,7 +231,7 @@ Returns:
   return $self->{type};
 } # type
 
-sub contrib_acts () {
+sub contrib_acts() {
   my ($self) = @_;
 
 =pod
@@ -271,12 +266,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{contrib_acts};
+  $self->updateActivityInfo() unless $self->{contrib_acts};
     
   return $self->{contrib_acts};
 } # crm_record
 
-sub crm_record_id () {
+sub crm_record_id() {
   my ($self) = @_;
 
 =pod
@@ -311,12 +306,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{crm_record_id};
+  $self->updateActivityInfo() unless $self->{crm_record_id};
     
   return $self->{crm_record_id};
 } # crm_record_id
 
-sub crm_record_type () {
+sub crm_record_type() {
   my ($self) = @_;
   
 =pod
@@ -351,12 +346,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{crm_record_type};
+  $self->updateActivityInfo() unless $self->{crm_record_type};
   
   return $self->{crm_record_type};
 } # crm_record_type
 
-sub crm_state () {
+sub crm_state() {
   my ($self) = @_;
   
 =pod
@@ -391,12 +386,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{crm_state};
+  $self->updateActivityInfo() unless $self->{crm_state};
   
   return $self->{crm_state};
 } # crm_state
 
-sub headline () {
+sub headline() {
   my ($self) = @_;
   
 =pod
@@ -431,12 +426,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{headline};
+  $self->updateActivityInfo() unless $self->{headline};
   
   return $self->{headline};
 } # headline
 
-sub name_resolver_view () {
+sub name_resolver_view() {
   my ($self) = @_;
   
 =pod
@@ -471,12 +466,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{name_resolver_view};
+  $self->updateActivityInfo() unless $self->{name_resolver_view};
   
   return $self->{name_resolver_view};
 } # name_resolver_view
 
-sub stream () {
+sub stream() {
   my ($self) = @_;
   
 =pod
@@ -511,12 +506,12 @@ Returns:
 
 =cut
 
-  $self->updateActivityInfo () unless $self->{stream};
+  $self->updateActivityInfo() unless $self->{stream};
   
   return $self->{stream};
 } # stream
 
-sub changeset (;$) {
+sub changeset(;$) {
   my ($self, $recalc) = @_;
   
 =pod
@@ -559,7 +554,7 @@ Returns:
   
   my $cmd = "lsact -fmt \"%[versions]CQp\" $self->{name}\@$pvob";
 
-  my ($status, @output) = $Clearcase::CC->execute ($cmd);
+  my ($status, @output) = $Clearcase::CC->execute($cmd);
 
   return ($status, @output)
     if $status;
@@ -581,7 +576,7 @@ Returns:
   @output = split /\", \"/, $output[0]
     if $output[0];
   
-  foreach (@output) {
+  for (@output) {
     # Skip any cleartool warnings. We are getting warnings of the form:
     # "A version in the change set of activity "63332.4" is currently 
     # unavailable". Probably some sort of subtle corruption that we can ignore.
@@ -613,18 +608,28 @@ Returns:
     # Additionally we will set into the $element object the extended name. This
     # is the long pathname that we need to use from our current context to be
     # able to access the element.
-    #$element->setExtendedName ($_);
+    #$element->setExtendedName($_);
     
     push @changeset, $element;
-  } # foreach
+  } # for
   
   $self->{changeset} = \@changeset;
   
   return @changeset;  
 } # changeset
 
-sub create ($$$;$) {
-  my ($self, $stream, $pvob, $headline, $opts) = @_;
+sub exists() {
+  my ($self) = @_;
+
+  my ($status, @output) = $Clearcase::CC->execute(
+    'lsactivity ' . $self->{name} . '@' . $self->pvob->tag
+  );
+
+  return !$status;
+} # exists
+
+sub create($$$;$) {
+  my ($self, $stream, $headline, $opts) = @_;
 
 =pod
 
@@ -638,7 +643,7 @@ Parameters:
 
 =over
 
-=item UCM Stream (required)
+=item UCM Stream(required)
 
 UCM stream this activities is to be created on
 
@@ -674,34 +679,31 @@ Ouput from cleartool
 
 =cut
 
-  # Fill in members
-  $self->{stream}   = $stream;
-  $self->{pvob}     = $pvob;
-  
-  # TODO: Should quote $headline to protect from special characters
-  $self->{headline} = $headline;
-   
+  if ($self->exists) {
+    $self->updateActivityInfo;
+
+    return (0, ());
+  } # if
+
   # Fill in opts   
   $opts ||= '';
-  $opts .= " -headline '$headline'"
-    if $headline;  
+
+  if ($headline) {
+    $self->{headline} = $headline;
+
+    $opts .= " -headline '$headline'";
+  } # if
       
-  # TODO: This should call the exists function
-  # Return the stream name if the stream already exists
-  my ($status, @output) = 
-    $Clearcase::CC->execute ('lsact -short ' . $self->{name}); 
+  $self->{stream} = Clearcase::UCM::Stream->new($stream, $self->{pvob});
 
-  return ($status, @output)
-    unless $status;
-    
-  # Need to create the stream
   return $Clearcase::CC->execute 
-    ("mkactivity $opts -in " . $stream .
-     "\@"                    . $pvob   .
-     ' '                     . $self->{name});
+    ("mkactivity $opts -in " . $stream->{name}    .
+     '@'                     . $self->pvob->{tag} .
+     ' '                     . $self->{name}      .
+     '@'                     . $self->pvob->{tag});
 } # create
 
-sub remove () {
+sub remove() {
   my ($self) = @_;
 
 =pod
@@ -743,10 +745,10 @@ Ouput from cleartool
 =cut
 
   return $Clearcase::CC->execute 
-    ('rmactivity -f ' . $self->{name} . "\@" . $self->{pvob});
+    ('rmactivity -f ' . $self->{name} . "\@" . $self->{pvob}->name);
 } # remove
 
-sub attributes (;%) {
+sub attributes(;%) {
   my ($self, %newAttribs) = @_;
 
 =pod
@@ -783,14 +785,14 @@ Hash of attributes for this activity
 
 =cut
 
-  return $self->Clearcase::attributes (
+  return $self->Clearcase::attributes(
     'activity',
-    "$self->{name}\@" . Clearcase::vobtag ($self->{pvob}),
+    "$self->{name}\@" . $self->{pvob}->name,
     %newAttribs,
   );
 } # attributes
 
-sub updateActivityInfo () {
+sub updateActivityInfo() {
   my ($self) = @_;
 
   # Get all information that can be gotten using -fmt
@@ -806,8 +808,8 @@ sub updateActivityInfo () {
     $fmt  = '%[contrib_acts]CXp==';
   } # if
 
-  $Clearcase::CC->execute (
-    "lsactivity -fmt \"$fmt\" $self->{name}@" . Clearcase::vobtag ($self->{pvob})
+  $Clearcase::CC->execute(
+    "lsactivity -fmt \"$fmt\" $self->{name}@" . $self->{pvob}->name
   );
 
   # Assuming this activity is an empty shell of an object that the user may
@@ -829,9 +831,9 @@ sub updateActivityInfo () {
   $self->{contrib_acts}       = ();
 
   if ($self->type eq 'integration') {
-    foreach (split ', ', $fields[7]) {
-      push @{$self->{contrib_acts}}, Clearcase::UCM::Activity->new ($_);
-    } # foreach
+    for (split ', ', $fields[7]) {
+      push @{$self->{contrib_acts}}, Clearcase::UCM::Activity->new($_);
+    } # for
   } # if
 
   return;  
index 48883e1..389fd63 100644 (file)
@@ -49,30 +49,23 @@ use warnings;
 
 use Carp;
 
-use lib '../..';
-
-use Clearcase;
-use Clearcase::Element;
-use Clearcase::UCM::Activity;
-
-sub _processOpts (%) {
+sub _processOpts(%) {
   my ($self, %opts) = @_;
 
   my $opts;
-  
-  foreach (keys %opts) {
+
+  for (keys %opts) {
     if ($_ eq 'cq' or $_ eq 'cqe' or $_ eq 'force' or $_ eq 'nc') {
       $opts .= "-$_ ";
     } elsif ($_ eq 'c' or $_ eq 'cfile') {
       $opts .= "-$_ $opts{$_}";
     } # if
-  } # foreach
-  
-  
+  } # for
+
   return $opts;
 } # _processOpts
 
-sub new ($$) {
+sub new($$) {
   my ($class, $baseline, $pvob) = @_;
 
 =pod
@@ -109,17 +102,17 @@ Returns:
 
 =cut
 
-  my $self = bless {
+  $class = bless {
     name => $baseline,
-    pvob => Clearcase::vobtag $pvob,
+    pvob => $pvob,
   }, $class; # bless
-    
-  return $self;
+
+  return $class;
 } # new
 
-sub name () {
+sub name() {
   my ($self) = @_;
-    
+
 =pod
 
 =head2 name
@@ -155,9 +148,9 @@ Returns:
   return $self->{name};
 } # name
 
-sub pvob () {
+sub pvob() {
   my ($self) = @_;
-  
+
 =pod
 
 =head2 pvob
@@ -192,15 +185,15 @@ Returns:
 
   return $self->{pvob};
 } # pvob
-  
-sub create ($$;$$) {
-  my ($self, $project, $pvob, $baseline, $opts) = @_;
+
+sub create($;$$$) {
+  my ($self, $view, $comment, $opts) = @_;
 
 =pod
 
 =head2 create
 
-Creates a new UCM Stream Object
+Creates a new UCM Baseline Object
 
 Parameters:
 
@@ -208,21 +201,9 @@ Parameters:
 
 =over
 
-=item UCM Project (required)
-
-UCM Project this stream belongs to
-
-=item PVOB (Required)
-
-Project Vob
-
-=item baseline
-
-Baseline to set this stream to
-
 =item opts
 
-Options: Additional options to use (e.g. -readonly)
+Options: Additional options to use
 
 =back
 
@@ -248,34 +229,17 @@ Ouput from cleartool
 
 =cut
 
-  # Fill in object members
-  $self->{project}  = $project;
-  $self->{pvob}     = $pvob;
-    
-  # Fill in opts   
   $opts ||= '';
-  $opts .= " -baseline $baseline"
-    if $baseline;  
-      
-  $self->{readonly} = $opts =~ /-readonly/;
-  
-  # TODO: This should call the exists function
-  # Return the stream name if the stream already exists
-  my ($status, @output) = 
-    $Clearcase::CC->execute ('lsstream -short ' . $self->{name}); 
-
-  return ($status, @output)
-    unless $status;
-    
-  # Need to create the stream
-  return $Clearcase::CC->execute 
-    ("mkstream $opts -in " . $self->{project} .
-     "\@"                  . $self->{pvob}    .
-     ' '                   . $self->{name});
+
+  $comment = Clearcase::_setComment $comment;
+
+  return $Clearcase::CC->execute(
+    "mkbl $comment $opts -view " . $view->tag . ' ' . $self->{name}
+  );
 } # create
 
-sub remove (\%) {
-  my ($self, %opts) = @_;
+sub remove($) {
+  my ($self, $opts) = @_;
 
 =pod
 
@@ -315,14 +279,11 @@ Remember to check status method for error, and/or output method for output.
 
 =cut
 
-  my $opts = $self->_processOpts (%opts);
-  
-  my $pvob = Clearcase::vobtag ($self->{pvob});
-  
-  my ($status, @output) = $Clearcase::CC->execute 
-    ("rmbl $opts " . $self->{name} . '@' . $pvob);
-  
-  return;
+  $opts ||= '';
+
+  return $Clearcase::CC->execute(
+    "rmbl $opts -force " . $self->{name} . '@' . $self->{pvob}->name
+  );
 } # remove
 
 sub attributes () {
@@ -362,15 +323,15 @@ Hash of attributes for this baseline
 
 =cut
 
-  return $self->Clearcase::attributes (
+  return $self->Clearcase::attributes(
     'baseline',
-    "$self->{name}\@" . Clearcase::vobtag ($self->{pvob})
+    "$self->{name}\@" . $self->{pvob}->name
   );
 } # attributes
 
-sub diff ($;$$) {
+sub diff($;$$) {
   my ($self, $type, $baseline, %opts) = @_;
-  
+
 =pod
 
 =head2 diff
@@ -428,11 +389,11 @@ value.
     croak "Type must be one of activities, versions or baselines in "
         . "Clearcase::UCM::Baseline::diff - not $type";
   } # unless
-  
+
   my $myBaseline = "$self->{name}\@$self->{pvob}";
-  
+
   my $cmd = "diffbl -$type";
-  
+
   if ($baseline) {
     if ($baseline =~ /(\S+):/) {
       unless ($1 eq 'baseline' or $1 eq 'stream') {
@@ -440,30 +401,30 @@ value.
             . "just <baseline>";
       } # unless
     } # if
-    
+
     $baseline .= "\@$self->{pvob}" unless $baseline =~ /\@/;
-    
+
     $cmd .= " $myBaseline $baseline";
   } else {
     $cmd .= " -predeccsor";
   } # if
-  
-  $Clearcase::CC->execute ($cmd);
-  
+
+  $Clearcase::CC->execute($cmd);
+
   return if $Clearcase::CC->status;
-  
+
   my @output = $Clearcase::CC->output;
 
   my %info;
-    
-  foreach (@output) {
+
+  for (@output) {
     next unless /^(\>\>|\<\<)/;
-    
+
     if (/(\>\>|\<\<)\s+(\S+)\@/) {
-      $info{$2} = Clearcase::UCM::Activity->new ($2, $self->{pvob});
+      $info{$2} = Clearcase::UCM::Activity->new($2, $self->{pvob});
     } # if
-  } # foreach
-  
+  } # for
+
   return %info;
 } # diff
 
diff --git a/lib/Clearcase/UCM/Component.pm b/lib/Clearcase/UCM/Component.pm
new file mode 100644 (file)
index 0000000..9727763
--- /dev/null
@@ -0,0 +1,353 @@
+=pod
+
+=head1 NAME $RCSfile: Component.pm,v $
+
+Object oriented interface to UCM Component
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.8 $
+
+=item Created
+
+Fri May 14 18:16:16 PDT 2010
+
+=item Modified
+
+$Date: 2011/11/15 02:00:58 $
+
+=back
+
+=head1 SYNOPSIS
+
+Provides access to information about Clearcase Components.
+
+  my $stream = new Clearcase::UCM::Component($name, $pvob);
+
+=head1 DESCRIPTION
+
+This module implements a UCM Component object
+
+=head1 ROUTINES
+
+The following routines are exported:
+
+=cut
+
+package Clearcase::UCM::Component;
+
+use strict;
+use warnings;
+
+use Carp;
+
+sub new ($$) {
+  my ($class, $name, $pvob) = @_;
+
+=pod
+
+=head2 new
+
+Construct a new Clearcase Component object.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item name
+
+Name of Component
+
+=item pvob
+
+Associated pvob
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Clearcase Component object
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $class = bless {
+    name => $name,
+    pvob => $pvob,
+  }, $class; # bless
+    
+  return $class; 
+} # new
+  
+sub name () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 name
+
+Returns the name of the component
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item name
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{name};
+} # name
+
+sub pvob () {
+  my ($self) = @_;
+  
+=pod
+
+=head2 pvob
+
+Returns the pvob of the component
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item pvob
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{pvob};
+} # pvob
+  
+sub create (;$$) {
+  my ($self, $root, $comment) = @_;
+
+=pod
+
+=head2 create
+
+Creates a new UCM Component Object
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return (0, ()) if $self->exists;
+  
+  $comment = Clearcase::_setComment $comment;
+
+  my $rootOpt;
+
+  if ($root) {
+    if (-d $root) {
+      $self->{root} = $root;
+
+      $rootOpt = "-root $root";
+    } else {
+      carp "Root $root not found";
+    } # if
+  } else {
+    $self->{root} = undef;
+
+    $rootOpt = '-nroot';
+  } # if
+
+  return $Clearcase::CC->execute(
+    "mkcomp $comment $rootOpt " . $self->{name} . '@' . $self->{pvob}->tag
+  );
+} # create
+
+sub remove () {
+  my ($self) = @_;
+
+=pod
+
+=head2 remove
+
+Removes UCM Component
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $Clearcase::CC->execute 
+    ('rmcomp -f ' . $self->name . '@' . $self->pvob->tag);
+} # remove
+
+sub exists() {
+  my ($self) = @_;
+
+=pod
+
+=head3 exists
+
+Returns true if the component exists - false otherwise.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item boolean
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($status, @output) = $Clearcase::CC->execute(
+    'lscomp ' . $self->{name} . '@' . $self->{pvob}->name
+  );
+
+  return !$status;
+} # exists
+
+1;
+
+=head1 DEPENDENCIES
+
+=head2 ClearSCM Perl Modules
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a></p>
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase/UCM/Baseline.pm">Clearcase::UCM::Baseline</a></p>
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase/UCM/Project.pm">Clearcase::UCM::Project</a></p>
+
+=head1 INCOMPATABILITIES
+
+None
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this module.
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2007, ClearSCM, Inc. All rights reserved.
+
+=cut
diff --git a/lib/Clearcase/UCM/Folder.pm b/lib/Clearcase/UCM/Folder.pm
new file mode 100644 (file)
index 0000000..d606d62
--- /dev/null
@@ -0,0 +1,443 @@
+=pod
+
+=head1 NAME $RCSfile: Folder.pm,v $
+
+Object oriented interface to UCM Folders
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.8 $
+
+=item Created
+
+Fri May 14 18:16:16 PDT 2010
+
+=item Modified
+
+$Date: 2011/11/15 02:00:58 $
+
+=back
+
+=head1 SYNOPSIS
+
+Provides access to information about Clearcase Folders.
+
+  my $folder = new Clearcase::UCM::Folder ($name, $pvob);
+
+=head1 DESCRIPTION
+
+This module implements a UCM Folder object
+
+=head1 ROUTINES
+
+The following routines are exported:
+
+=cut
+
+package Clearcase::UCM::Folder;
+
+use strict;
+use warnings;
+
+sub new ($$;$$) {
+  my ($class, $name, $pvob, $parent, $comment) = @_;
+
+=pod
+
+=head2 new
+
+Construct a new Clearcase Folder object.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item folder
+
+Name of folder
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Clearcase Folder object
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $class = bless {
+    name   => $name,
+    pvob   => $pvob,
+    parent => $parent || 'RootFolder',
+  }, $class; # bless
+   
+  $comment = Clearcase::_setComment ($comment);
+
+  my ($status, @output) = $Clearcase::CC->execute (
+    "mkfolder $comment -in " . $class->{parent} . ' ' . $name . '@' . $pvob->tag
+  );
+
+  return $class->updateFolderInfo;
+} # new
+  
+sub name () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 name
+
+Returns the name of the folder
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item folder's name
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{name};
+} # name
+
+sub owner () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 owner
+
+Returns the owner of the folder
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item folder's owner
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{owner};
+} # owner
+
+sub group () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 group
+
+Returns the group of the folder
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item folder's group
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{group};
+} # group
+
+sub pvob () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 pvob
+
+Returns the pvob of the folder
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item folder's pvob
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{pvob};
+} # pvob
+
+sub title () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 title
+
+Returns the title of the folder
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item folder's title
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{title};
+} # title
+
+sub create ($;$) {
+  my ($self, $name, $parentFolder) = @_;
+
+=pod
+
+=head2 create
+
+Creates a new UCM Folder Object
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item name
+
+UCM Folder name
+
+=item parentFolder
+
+Name of parentFolder (Default: RootFolder)
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  # Fill in object members
+  $self->{parentFolder} = $parentFolder;
+
+  $parentFolder ||= 'RootFolder';
+
+  # Need to create the folder
+  return $Clearcase::CC->execute( 
+    "mkfolder $self->{comment} -in " . $parentFolder . '@' . $self->{pvob} .
+    ' '                   . $self->{name}
+  );
+} # create
+
+sub remove () {
+  my ($self) = @_;
+
+=pod
+
+=head2 remove
+
+Removes UCM Folder
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item name
+
+UCM Folder name
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Output from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $Clearcase::CC->execute(
+    'rmfolder -f ' . $self->{name} . "\@" . $self->{pvob}->tag);
+} # rmfolder
+
+sub updateFolderInfo () {
+  my ($self) = @_;
+
+  my ($status, @output) = $Clearcase::CC->execute(
+    "lsfolder -long $self->{name}" . '@'. $self->{pvob}->tag);
+
+  return if $status;
+
+  for (@output) {
+    if (/owner: (.*)/) {
+      $self->{owner} = $1;
+    } elsif (/group: (.*)/) {
+      $self->{group} = $1;
+    } elsif (/title: (.*)/) {
+      $self->{title} = $1;
+    # TODO: Get containing folders and containing projects
+    } # if
+  } # for
+
+  return $self;
+} # updateFolderInfo
+1;
+
+=head1 DEPENDENCIES
+
+=head2 ClearSCM Perl Modules
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a></p>
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase/UCM/Baseline.pm">Clearcase::UCM::Baseline</a></p>
+
+=head1 INCOMPATABILITIES
+
+None
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this module.
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2007, ClearSCM, Inc. All rights reserved.
+
+=cut
diff --git a/lib/Clearcase/UCM/Project.pm b/lib/Clearcase/UCM/Project.pm
new file mode 100644 (file)
index 0000000..350df52
--- /dev/null
@@ -0,0 +1,389 @@
+=pod
+
+=head1 NAME $RCSfile: Project.pm,v $
+
+Object oriented interface to UCM Projects
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.8 $
+
+=item Created
+
+Fri May 14 18:16:16 PDT 2010
+
+=item Modified
+
+$Date: 2011/11/15 02:00:58 $
+
+=back
+
+=head1 SYNOPSIS
+
+Provides access to information about Clearcase UCM Projects.
+
+  my $project = new Clearcase::UCM::Project ($name, $folder, $pvob);
+
+=head1 DESCRIPTION
+
+This module implements a UCM Project object
+
+=head1 ROUTINES
+
+The following routines are exported:
+
+=cut
+
+package Clearcase::UCM::Project;
+
+use strict;
+use warnings;
+
+sub new ($$) {
+  my ($class, $name, $folder, $pvob) = @_;
+
+=pod
+
+=head2 new
+
+Construct a new Clearcase Project object.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item project
+
+Name of project
+
+=item folder
+
+Folder object
+
+=item pvob
+
+Associated Pvob
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Clearcase Project object
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $folder = Clearcase::UCM::Folder->new('RootFolder', $pvob) unless $folder;
+
+  $class = bless {
+    name   => $name,
+    folder => $folder,
+    pvob   => $pvob,
+  }, $class; # bless
+    
+  return $class; 
+} # new
+  
+sub name () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 name
+
+Returns the name of the project
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item project's name
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{name};
+} # name
+
+sub pvob () {
+  my ($self) = @_;
+  
+=pod
+
+=head2 pvob
+
+Returns the pvob of the project
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item project's pvob
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $self->{pvob};
+} # pvob
+  
+sub create (;$) {
+  my ($self, $opts) = @_;
+
+=pod
+
+=head2 create
+
+Creates a new UCM Project Object
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item opts
+
+Optional parameters for cleartool mkproject command
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return (0, ()) if $self->exists;
+
+  $opts ||= '';
+
+  return $Clearcase::CC->execute(
+    "mkproject $opts -in " . $self->{folder}->name . '@' . $self->{pvob}->tag .
+    ' '                    . $self->{name}         . '@' . $self->{pvob}->tag
+  );
+} # create
+
+sub remove () {
+  my ($self) = @_;
+
+=pod
+
+=head2 remove
+
+Removes UCM Project
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $Clearcase::CC->execute 
+    ('rmproject -f ' . $self->{name} . "\@" . $self->{pvob}->tag);
+} # remove
+
+sub change($) {
+  my ($self, $opts) = @_;
+
+=pod
+
+=head2 change
+
+Changes UCM Project
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item opts
+
+Options
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $opts ||= '';
+
+  return $Clearcase::CC->execute 
+    ("chproject $opts " . $self->{name} . "\@" . $self->{pvob}->name);
+} # change
+
+sub exists() {
+  my ($self) = @_;
+
+=pod
+
+=head3 exists
+
+Returns true if the project exists - false otherwise
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item boolean
+
+=back 
+
+=for html </blockquote>
+
+=cut
+
+  my ($status, @output) = $Clearcase::CC->execute(
+    'lsproject ' . $self->{name} . '@' . $self->{pvob}->name
+  );
+
+  return !$status;
+} # exists
+
+1;
+
+=head1 DEPENDENCIES
+
+=head2 ClearSCM Perl Modules
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a></p>
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase/UCM/Folder.pm">Clearcase::UCM::Folder</a></p>
+
+=head1 INCOMPATABILITIES
+
+None
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this module.
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2007, ClearSCM, Inc. All rights reserved.
+
+=cut
index 00fe5e1..0b39949 100644 (file)
@@ -47,11 +47,14 @@ package Clearcase::UCM::Pvob;
 use strict;
 use warnings;
 
-use Clearcase;
-use Clearcase::UCM::Stream;
+# Would be better represented by use parent "Clearcase::Vob" but we're
+# working with old versions of Perl here...
+use base 'Clearcase::Vob';
+
+use Carp;
 
 sub new ($) {
-  my ($class, $name) = @_;
+  my ($class, $tag) = @_;
   
 =pod
 
@@ -65,7 +68,7 @@ Parameters:
 
 =over
 
-=item pvob name
+=item name
 
 Name of pvob
 
@@ -87,21 +90,65 @@ Returns:
 
 =cut  
 
-  my $self = bless {
-    name => $name,
+  croak 'Clearcase::UCM::Pvob: Must specify pvob tag' unless $tag;
+
+  $class = bless {
+    tag => $tag,
   }, $class; # bless
     
-  return $self; 
+  $class->updateVobInfo;
+
+  return $class; 
 } # new
   
-sub name () {
+sub create (;$$$%) {
+  my ($self, $host, $vbs, $comment, %opts) = @_;
+
+=pod
+
+=head2 create
+
+Creates a pvob
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  $opts{ucmproject} = undef;
+
+  return $self->SUPER::create ($host, $vbs, $comment, %opts);
+} # create
+
+sub tag() {
   my ($self) = @_;
 
 =pod
 
-=head2 name
+=head2 tag
 
-Returns the name of the pvob
+Returns the tag of the pvob
 
 Parameters:
 
@@ -121,7 +168,7 @@ Returns:
 
 =over
 
-=item pvob's name
+=item tag
 
 =back
 
@@ -129,7 +176,12 @@ Returns:
 
 =cut
     
-  return $self->{name};
+  return $self->{tag};
+} # tag
+
+# Alias name to tag
+sub name() {
+  goto &tag;
 } # name
 
 sub streams () {
@@ -176,7 +228,7 @@ Returns:
   my @streams;
 
   push @streams, Clearcase::UCM::Stream->new ($_, $self->{name})
-    foreach ($Clearcase::CC->output);
+    for ($Clearcase::CC->output);
 
   return @streams;  
 } # streams
index 0cdc198..618e661 100644 (file)
@@ -28,9 +28,9 @@ $Date: 2011/11/15 02:00:58 $
 
 =head1 SYNOPSIS
 
-Provides access to information about Clearcase Elements.
+Provides access to information about Clearcase Streams.
 
-  my $stream= new Clearcase::UCM::Stream ($name, $pvob);
+  my $stream = new Clearcase::UCM::Stream ($name, $pvob);
 
 =head1 DESCRIPTION
 
@@ -47,11 +47,8 @@ package Clearcase::UCM::Stream;
 use strict;
 use warnings;
 
-use Clearcase;
-use Clearcase::UCM::Baseline;
-
 sub new ($$) {
-  my ($class, $stream, $pvob) = @_;
+  my ($class, $name, $pvob) = @_;
 
 =pod
 
@@ -65,10 +62,14 @@ Parameters:
 
 =over
 
-=item stream name
+=item name
 
 Name of stream
 
+=item pvob
+
+Associated pvob
+
 =back
 
 =for html </blockquote>
@@ -87,17 +88,17 @@ Returns:
 
 =cut
 
-  my $self = bless {
-    name => $stream,
-    pvob => Clearcase::vobtag $pvob,
+  $class = bless {
+    name => $name,
+    pvob => $pvob,
   }, $class; # bless
-    
-  return $self
+
+  return $class
 } # new
-  
+
 sub name () {
   my ($self) = @_;
-    
+
 =pod
 
 =head2 name
@@ -135,7 +136,7 @@ Returns:
 
 sub pvob () {
   my ($self) = @_;
-  
+
 =pod
 
 =head2 pvob
@@ -170,9 +171,9 @@ Returns:
 
   return $self->{pvob};
 } # pvob
-  
-sub create ($$;$$) {
-  my ($self, $project, $pvob, $baseline, $opts) = @_;
+
+sub create ($;$) {
+  my ($self, $project, $opts) = @_;
 
 =pod
 
@@ -186,21 +187,13 @@ Parameters:
 
 =over
 
-=item UCM Project (required)
-
-UCM Project this stream belongs to
-
-=item PVOB (Required)
-
-Project Vob
+=item project
 
-=item baseline
-
-Baseline to set this stream to
+Project that this stream will be created in
 
 =item opts
 
-Options: Additional options to use (e.g. -readonly)
+Options: Additional options to use (e.g. -baseline/-readonly)
 
 =back
 
@@ -226,30 +219,17 @@ Ouput from cleartool
 
 =cut
 
-  # Fill in object members
-  $self->{project}  = $project;
-  $self->{pvob}     = $pvob;
-    
-  # Fill in opts   
+  return (0, ()) if $self->exists;
+
   $opts ||= '';
-  $opts .= " -baseline $baseline"
-    if $baseline;  
-      
+
   $self->{readonly} = $opts =~ /-readonly/;
-  
-  # TODO: This should call the exists function
-  # Return the stream name if the stream already exists
-  my ($status, @output) = 
-    $Clearcase::CC->execute ('lsstream -short ' . $self->{name}); 
-
-  return ($status, @output)
-    unless $status;
-    
-  # Need to create the stream
-  return $Clearcase::CC->execute 
-    ("mkstream $opts -in " . $self->{project} .
-     "\@"                  . $self->{pvob}    .
-     ' '                   . $self->{name});
+
+  return $Clearcase::CC->execute(
+    "mkstream $opts -in "
+       . $project->name . '@' . $self->{pvob}->tag . ' '
+       . $self->name    . '@' . $self->{pvob}->tag
+  );
 } # create
 
 sub remove () {
@@ -267,21 +247,56 @@ Parameters:
 
 =over
 
-=item UCM Project (required)
+=back
 
-UCM Project this stream belongs to
+=for html </blockquote>
 
-=item PVOB (Required)
+Returns:
+
+=for html <blockquote>
 
-Project Vob
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $Clearcase::CC->execute 
+    ('rmstream -f ' . $self->{name} . '@' . $self->{pvob}->name);
+} # rmStream
+
+sub rebase($;$) {
+  my ($self, $opts) = @_;
+
+=pod
+
+=head2 rebase
+
+Rebases a UCM Stream
+
+Parameters:
+
+=for html <blockquote>
+
+=over
 
 =item baseline
 
-Baseline to set this stream to
+Baseline to rebase to
 
 =item opts
 
-Options: Additional options to use (e.g. -readonly)
+Any additional opts
 
 =back
 
@@ -307,9 +322,106 @@ Ouput from cleartool
 
 =cut
 
-  return $Clearcase::CC->execute 
-    ('rmstream -f ' . $self->{name} . "\@" . $self->{pvob});
-} # rmStream
+  $opts ||= '';
+
+  $opts .= ' -stream '   . $self->name . '@' . $self->{pvob}->name;
+
+  return $Clearcase::CC->execute("rebase $opts");
+} # rebase
+
+sub recommend($) {
+  my ($self, $baseline) = @_;
+
+=pod
+
+=head2 recommend
+
+Recommends a baseline in a UCM Stream
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item baseline
+
+Baseline to recommend
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $Clearcase::CC->execute(
+    "chstream -recommended $baseline " . $self->name . '@' . $self->{pvob}->tag
+  );
+} # recommend
+
+sub nrecommended() {
+  my ($self) = @_;
+
+=pod
+
+=head2 nrecommend
+
+Changes stream to not have a recommended baseline
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item $status
+
+Status from cleartool
+
+=item @output
+
+Ouput from cleartool
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  return $Clearcase::CC->execute(
+    'chstream -nrecommended ' . $self->name . '@' . $self->{pvob}->tag
+  );
+} # nrecommended
 
 sub baselines () {
   my ($self) = @_;
@@ -349,22 +461,64 @@ An array of baseline objects for this stream
 =cut
 
   my $cmd = "lsbl -short -stream $self->{name}\@$self->{pvob}";
-  
+
   $Clearcase::CC->execute ($cmd); 
 
   return if $Clearcase::CC->status;
 
   my @baselines;
-  
-  foreach ($Clearcase::CC->output) {
+
+  for ($Clearcase::CC->output) {
     my $baseline = Clearcase::UCM::Baseline->new ($_, $self->{pvob});
-    
+
     push @baselines, $baseline;
-  } # foreach
-  
+  } # for
+
   return @baselines;
 } # baselines
 
+sub exists() {
+  my ($self) = @_;
+
+=pod
+
+=head3 exists
+
+Return true if the stream exists - false otherwise
+
+Paramters:
+
+=for html <blockquote>
+
+=over 
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item boolean
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($status, @output) = $Clearcase::CC->execute(
+    'lsstream ' . $self->{name} . '@' . $self->{pvob}->name
+  );
+
+  return !$status;
+} # exists
+
 1;
 
 =head1 DEPENDENCIES
@@ -374,6 +528,7 @@ An array of baseline objects for this stream
 =for html <p><a href="/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a></p>
 
 =for html <p><a href="/php/scm_man.php?file=lib/Clearcase/UCM/Baseline.pm">Clearcase::UCM::Baseline</a></p>
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase/UCM/Project.pm">Clearcase::UCM::Project</a></p>
 
 =head1 INCOMPATABILITIES
 
diff --git a/lib/Clearcase/UCM/Streams.pm b/lib/Clearcase/UCM/Streams.pm
new file mode 100644 (file)
index 0000000..6d0c99d
--- /dev/null
@@ -0,0 +1,165 @@
+=pod
+
+=head1 NAME $RCSfile: Stream.pm,v $
+
+Object oriented interface to UCM Streams
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.8 $
+
+=item Created
+
+Fri May 14 18:16:16 PDT 2010
+
+=item Modified
+
+$Date: 2011/11/15 02:00:58 $
+
+=back
+
+=head1 SYNOPSIS
+
+Provides access to information about Clearcase Streams.
+
+  my $stream = new Clearcase::UCM::Streams()
+
+=head1 DESCRIPTION
+
+This module implements a UCM Streams object
+
+=head1 ROUTINES
+
+The following routines are exported:
+
+=cut
+
+package Clearcase::UCM::Streams;
+
+use strict;
+use warnings;
+
+sub new ($) {
+  my ($class, $pvob) = @_;
+
+=pod
+
+=head2 new
+
+Construct a new Clearcase Streams object
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item pvob
+
+Pvob object
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item Clearcase Streams object
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  my ($status, @output) =
+    $clearcase::CC->execute('lsstream -short -invob ' . $pvob->tag;
+
+  my $class = bless {
+    streams => @output,
+  }, $class; # bless
+    
+  return $class; 
+} # new
+  
+sub streams () {
+  my ($self) = @_;
+    
+=pod
+
+=head2 streams
+
+Return a list of stream names in an array context or the number of streams in 
+a scalar context.
+
+Parameters:
+
+=for html <blockquote>
+
+=over
+
+=item none
+
+=back
+
+=for html </blockquote>
+
+Returns:
+
+=for html <blockquote>
+
+=over
+
+=item List of streams or number of streams
+
+Array of stream names in an array context or the number of streams in a scalar
+context.
+
+=back
+
+=for html </blockquote>
+
+=cut
+
+  if (wantarray) {
+    return $self->{streams} ? sort @{$self->{streams}) : ();
+  } else {
+    return $self->{streams} ? scalar @{$self->{streams});
+  } # if
+} # streams
+
+1;
+
+=head1 DEPENDENCIES
+
+=head2 ClearSCM Perl Modules
+
+=for html <p><a href="/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a></p>
+
+=head1 INCOMPATABILITIES
+
+None
+
+=head1 BUGS AND LIMITATIONS
+
+There are no known bugs in this module.
+
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (c) 2007, ClearSCM, Inc. All rights reserved.
+
+=cut
diff --git a/lib/Clearcase/UCM/testinfo.txt b/lib/Clearcase/UCM/testinfo.txt
new file mode 100644 (file)
index 0000000..0797c6c
--- /dev/null
@@ -0,0 +1,2 @@
+WOR: RANCQ00090968
+UCM Project: test6@/vobs/killme_pvob
index 7a59cd2..77cfc6a 100644 (file)
@@ -127,8 +127,8 @@ use warnings;
 use Clearcase;
 use Display; 
 
-sub new ($;$) {
-  my ($class, $tag, $region) = @_;
+sub new ($) {
+  my ($class, $tag) = @_;
 
 =pod
 
@@ -172,7 +172,7 @@ Returns:
 
   my $self = bless { tag => $tag }, $class;
 
-  $self->updateViewInfo ($region);
+  $self->updateViewInfo;
 
   return $self;
 } # new
@@ -1170,6 +1170,11 @@ Returns:
   return $self->{tag};
  } # tag
 
+# Alias name to tag
+sub name() {
+  goto &tag;
+} # name
+
 sub text_mode () {
   my ($self) = @_;
   
@@ -1363,7 +1368,7 @@ Returns:
 } # exists
 
 sub create (;$$$) {
-  my ($self, $host, $vws, $region) = @_;
+  my ($self, $host, $vws, $opts) = @_;
     
 =pod
 
@@ -1409,34 +1414,37 @@ Ouput from cleartool
 
 =cut
 
-  $region ||= $Clearcase::CC->region;
-
   if ($self->exists) {
-    $self->updateViewInfo ($region);
+    $self->updateViewInfo;
       
     return (0, ())
   } # if
 
   my ($status, @output);
     
+  $opts ||= '';
+
   if ($host && $vws) {
-    ($status, @output) = 
-      $Clearcase::CC->execute ("mkview -tag $self->{tag} -region $region "
-                          .    "-host $host -hpath $vws -gpath $vws $vws");
+    ($status, @output) = $Clearcase::CC->execute(
+      "mkview -tag $self->{tag} $opts " .
+      "-host $host -hpath $vws -gpath $vws $vws"
+    );
   } else {
     # Note this requires that -stgloc's work and that using -auto is not a 
     # problem.
-    ($status, @output) =
-       $Clearcase::CC->execute ("mkview -tag $self->{tag} -stgloc -auto");
+    ($status, @output) = $Clearcase::CC->execute(
+      "mkview -tag $self->{tag} $opts -stgloc -auto"
+    );
   } # if
 
-  $self->updateViewInfo ($region);
+  $self->updateViewInfo;
 
   return ($status, @output);
 } # create
   
+# TODO Is this used?
 sub createUCM ($$) {
-  my ($self, $stream, $pvob, $region) = @_;
+  my ($self, $stream, $pvob) = @_;
 
 =pod
 
@@ -1482,14 +1490,10 @@ Array of output
 
 =cut
 
-  $region ||= $Clearcase::CC->region;
-  
-  return (0, ())
-    if $self->exists;
+  return (0, ()) if $self->exists;
       
   # Update object members
-  $self->{stream} = $stream;
-  $self->{pvob}   = $pvob;
+  $self->{pvob} = $pvob;
     
   # Need to create the view
   my ($status, @output) = 
@@ -1499,7 +1503,7 @@ Array of output
   return ($status, @output)
     if $status;
       
-  $self->updateViewInfo ($region);
+  $self->updateViewInfo;
 
   return ($status, @output);
 } # createUCM
@@ -1545,12 +1549,13 @@ Ouput from cleartool
 
 =cut
 
-  return (0, ())
-    unless $self->exists;
+  return (0, ()) unless $self->exists;
       
   my ($status, @output);
 
   if ($self->dynamic) {
+    $self->stop;
+
     ($status, @output) = $Clearcase::CC->execute (
        "rmview -force -tag $self->{tag}"
      );
@@ -1744,13 +1749,11 @@ Ouput from cleartool
   return ($status, @output);
 } # set
 
-sub updateViewInfo ($$) {
-  my ($self, $region) = @_;
-
-  $region ||= $Clearcase::CC->region;
+sub updateViewInfo () {
+  my ($self) = @_;
 
   my ($status, @output) = $Clearcase::CC->execute (
-    "lsview -region $region -long -properties -full $self->{tag}"
+    "lsview -long -properties -full $self->{tag}"
   );
 
   # Assuming this view is an empty shell of an object that the user may possibly
index 6c957c0..142c1dc 100644 (file)
@@ -264,6 +264,10 @@ Returns:
   return $self->{shost};
 } # shost
 
+# Alias name to tag
+sub name() {
+  goto &tag;
+} # name
 sub access () {
   my ($self) = @_;
   
@@ -1177,8 +1181,8 @@ Returns:
   return !$status;
 } # exists
 
-sub create (;$$$) {
-  my ($self, $host, $vbs, $comment) = @_;
+sub create (;$$$%) {
+  my ($self, $host, $vbs, $comment, %opts) = @_;
 
 =pod
 
@@ -1232,20 +1236,26 @@ Ouput from cleartool
 
   return (0, ()) if $self->exists;
 
-  $comment = Clearcase::setComment $comment;
+  $comment = Clearcase::_setComment $comment;
 
   my ($status, @output);
 
+  my $additionalOpts = '';
+
+  for (keys %opts) {
+    $additionalOpts .= "-$_ ";
+    $additionalOpts .= "$opts{$_} " if $opts{$_};
+  } # for
+
   if ($host && $vbs) {
     ($status, @output) = $Clearcase::CC->execute (
-      "mkvob -tag $self->{tag} $comment -host $host -hpath $vbs "
+      "mkvob -tag $self->{tag} $comment $additionalOpts -host $host -hpath $vbs "
     . "-gpath $vbs $vbs");
   } else {
     # Note this requires that -stgloc's work and that using -auto is not a 
     # problem.
     ($status, @output) =
-      $Clearcase::CC->execute ("mkvob -tag $self->{tag} $comment "
-    . "-stgloc -auto");
+      $Clearcase::CC->execute ("mkvob -tag $self->{tag} $comment $additionalOpts -stgloc -auto");
   } # if
 
   $self->updateVobInfo;
index 9630a7f..0f2d85f 100644 (file)
@@ -113,7 +113,7 @@ Returns:
 
   # Strip $VOBTAG_PREFIX
   foreach (@output) {
-    if ($ARCH eq 'windows' or $ARCH eq 'cygwin') {
+    if ($ARCHITECTURE eq 'windows' or $ARCHITECTURE eq 'cygwin') {
       s/\\//;
     } else {
       s/$Clearcase::VOBTAG_PREFIX//;
index 1abb5da..b863874 100644 (file)
@@ -232,7 +232,7 @@ my $operatorRE = qr/
 
 END {
   # Insure all instaniated objects have been destroyed
-  $_->DESTROY foreach (@objects);
+  $_->DESTROY for (@objects);
 } # END
 
 # Internal methods
@@ -568,18 +568,18 @@ sub _setFields ($@) {
   } # if
 
   unless (@fields) {
-    # Always return dbid 
-    push @fields, 'dbid' unless grep {$_ eq 'dbid'} @fields;
-    
-    foreach (@{$entityDef->GetFieldDefNames}) {
+    for (@{$entityDef->GetFieldDefNames}) {
       unless ($self->{returnSystemFields}) {
         next if $entityDef->IsSystemOwnedFieldDefName ($_);
       } # unless
              
       push @fields, $_;
-    } # foreach
+    } # for
   } # unless 
 
+  # Always return dbid 
+  push @fields, 'dbid' unless grep {$_ eq 'dbid'} @fields;
+
   return @fields;  
 } # _setFields
 
@@ -616,11 +616,11 @@ sub _setFieldValue ($$$$) {
     # evaluate $fieldValue if $fieldValue is a simple number (e.g. 0, 1, etc.)
     $errmsg = $entity->SetFieldValue ($fieldName, "$fieldValue") if $fieldValue;
   } else {
-    foreach (@$fieldValue) {
+    for (@$fieldValue) {
       $errmsg = $entity->AddFieldValue ($fieldName, $_);
     
       return $errmsg unless $errmsg eq '';
-    } # foreach
+    } # for
   } # unless
   
   return $errmsg;
@@ -743,7 +743,7 @@ The DBID of the newly added record or undef if error.
   } # if
   
   # First process all fields in @ordering, if specified
-  foreach (@ordering) {
+  for (@ordering) {
     if ($values{$_}) {
       $self->{errmsg} = $self->_setFieldValue ($entity, $table, $_, $values{$_});
     } else {
@@ -751,18 +751,18 @@ The DBID of the newly added record or undef if error.
     } # if
     
     last unless $self->{errmsg} eq '';
-  } # foreach
+  } # for
   
   return unless $self->{errmsg} eq '';
   
   # Now process the rest of the values
-  foreach my $fieldName (keys %values) {
+  for my $fieldName (keys %values) {
     next if grep {$fieldName eq $_} @ordering;
 
     $self->{errmsg} = $self->_setFieldValue ($entity, $table, $fieldName, $values{$fieldName});
     
     last unless $self->{errmsg} eq '';
-  } # foreach
+  } # for
 
   $self->_setError ($self->{errmsg});
   
@@ -955,8 +955,8 @@ not the default DBSet as defined in cq.conf.
   return $connectionStr; 
 } # connection
 
-sub checkErr (;$$) {
-  my ($self, $msg, $die) = @_;
+sub checkErr (;$$$) {
+  my ($self, $msg, $die, $log) = @_;
   
 =pod
 
@@ -1009,9 +1009,14 @@ Returns 0 for no error, non-zero if error.
     } # if
 
     if ($die) {
-      croak $msg if $die;
+      $log->err ($msg) if $log;
+      croak $msg;
     } else {
-      print STDERR "$msg\n";
+      if ($log) {
+       $log->err($msg);
+      } else {
+        print STDERR "$msg\n";
+      } # if
       
       return $self->{error};
     } # if
@@ -1339,6 +1344,8 @@ Last error
 
 =cut
   
+  # Watch here as $error can very well be 0 which "if $error" would evaluate
+  # to false leaving $self->{error} undefined
   $self->{error} = $error if defined $error;
 
   return $self->{error};
@@ -1402,9 +1409,9 @@ Fieldtype enum
 
   my $entityDef = $self->{session}->GetEntityDef ($table); 
 
-  foreach (@{$entityDef->GetFieldDefNames}) {
+  for (@{$entityDef->GetFieldDefNames}) {
     $FIELDS{$table}{$_} = $entityDef->GetFieldDefType ($_);
-  } # foreach 
+  } # for 
 
   if (defined $FIELDS{$table}{$fieldName}) {
     return $FIELDS{$table}{$fieldName}
@@ -1610,7 +1617,7 @@ is also returned.
     
   my $query = $self->{session}->BuildQuery ($table);
   
-  foreach (@fields) {
+  for (@fields) {
     eval {$query->BuildField ($_)};
     
     if ($@) {
@@ -1618,7 +1625,7 @@ is also returned.
       
       carp $@;
     } # if
-  } # foreach
+  } # for
 
   $self->_parseConditional ($query, $condition);
 
@@ -1762,7 +1769,7 @@ Hash of name/value pairs for all the fields in $table
   
   my %record;
 
-  foreach (@fields) {
+  for (@fields) {
     my $fieldType = $entity->GetFieldValue ($_)->GetType;
 
     if ($fieldType == $CQPerlExt::CQ_REFERENCE_LIST) {
@@ -1776,7 +1783,7 @@ Hash of name/value pairs for all the fields in $table
         $record{$_} = _UTC2Localtime ($record{$_});
       } # if
     } # if
-  } # foreach
+  } # for
 
   $self->_setError;
   
@@ -1841,8 +1848,6 @@ Hash of name/value pairs for all the fields in $table
   
   @fields = $self->_setFields ($table, @fields);
 
-  return if @fields;
-  
   my $entity;
   
   eval {$entity = $self->{session}->GetEntityByDbId ($table, $dbid)};
@@ -1855,7 +1860,7 @@ Hash of name/value pairs for all the fields in $table
   
   my %record;
 
-  foreach (@fields) {
+  for (@fields) {
     my $fieldType = $entity->GetFieldValue ($_)->GetType;
 
     if ($fieldType == $CQPerlExt::CQ_REFERENCE_LIST) {
@@ -1869,7 +1874,7 @@ Hash of name/value pairs for all the fields in $table
         $record{$_} = _UTC2Localtime ($record{$_});
       } # if
     } # if
-  } # foreach
+  } # for
 
   $self->_setError;
   
@@ -2004,15 +2009,16 @@ while () {
 
   # Format %record  
   while ($column <= $nbrColumns) {
-    my $value = $result->{result}->GetColumnValue ($column);
-    
-    $value ||= '' if $self->{emptyStringForUndef};
+    my $name  = $result->{result}->GetColumnLabel($column);
+    my $value = $result->{result}->GetColumnValue($column++);
 
     # Fix any UTC dates - _UTC2Localtime will only modify data if the data 
     # matches a UTC datetime.
-    $value = _UTC2Localtime ($value);
+    $value = _UTC2Localtime ($value) if $value;
     
-    $record{$result->{result}->GetColumnLabel ($column++)} = $value;
+    $value ||= '' if $self->{emptyStringForUndef};
+
+    $record{$name} = $value;
   } # while
 
   %{$result->{lastRecord}} = %record unless $result->{lastRecord};
@@ -2024,7 +2030,7 @@ while () {
     if ($result->{thisDBID} == $result->{lastDBID}) {
       # Since the dbid's are the same, we have at least one reference list field
       # and we need to compare all fields
-      foreach my $field (keys %record) {
+      for my $field (keys %record) {
         # If the field is blank then skip it
         next if $record{$field} eq '';
         
@@ -2049,7 +2055,7 @@ while () {
           push @{$result->{lastRecord}{$field}}, $record{$field}
             unless grep {/^$record{$field}$/} @{$result->{lastRecord}{$field}};
         } # if
-      } # foreach
+      } # for
     
       # Transfer %lastRecord -> %record
       %record = %{$result->{lastRecord}};      
@@ -2069,6 +2075,9 @@ while () {
   
   $self->_setError;
   
+  # Never return dbid...
+  delete $record{dbid};
+
   return %record;
 } # getNext
 
@@ -2303,7 +2312,9 @@ The $errmsg, if any, when performing the update (empty string for success)
 =cut
   $action ||= 'Modify';
   
-  my %values = %$values;
+  my %values = ();
+
+  %values = %$values if $values;
   
   my $entity;
 
@@ -2324,7 +2335,7 @@ The $errmsg, if any, when performing the update (empty string for success)
   } # if
      
   # First process all fields in @ordering, if specified
-  foreach (@ordering) {
+  for (@ordering) {
     if ($values{$_}) {
       $self->{errmsg} = $self->_setFieldValue ($table, $_, $values{$_});
     } else {
@@ -2332,18 +2343,18 @@ The $errmsg, if any, when performing the update (empty string for success)
     } # if
     
     last unless $self->{errmsg} eq '';
-  } # foreach
+  } # for
   
   return $self->{errmsg} unless $self->{errmsg} eq '';
   
   # Now process the rest of the values
-  foreach my $fieldName (keys %values) {
+  for my $fieldName (keys %values) {
     next if grep {$fieldName eq $_} @ordering;
 
     $self->{errmsg} = $self->_setFieldValue ($entity, $table, $fieldName, $values{$fieldName});
     
     last unless $self->{errmsg} eq '';
-  } # foreach
+  } # for
 
   $self->_setError ($self->{errmsg});
   
index 68fa897..e1fe824 100644 (file)
@@ -513,7 +513,7 @@ Returns:
     $msg = "ERROR: $msg";
   } # if
 
-  $self->log ($msg);
+  $self->msg($msg);
 
   $self->incrementErr;
 
index 37fed79..507e523 100644 (file)
@@ -32,14 +32,14 @@ This module seeks to isolate OS dependences by confining them to this
 module as well as provide convienent references and mechanisms for
 doing things that are different on different OSes.
 
- print "Running on $ARCH\n";
+ print "Running on $ARCHITECTURE\n";
  `$cmd > $NULL 2>&1`;
  my $filename = $app_base . $SEPARATOR . "datafile.txt";
 
 =head1 DESCRIPTION
 
 This module exports several variables that are useful to isolate OS
-dependencies. For example, $ARCH is set to "windows", "cygwin" or the
+dependencies. For example, $ARCHITECTURE is set to "windows", "cygwin" or the
 value of $^O depending on which OS the script is running. This allows
 you to write code that is dependant on which OS you are running
 on. Similarly, $NULL is set to the string "NUL" when running on
@@ -64,19 +64,19 @@ use warnings;
 
 use base 'Exporter';
 
-our $ARCH      = $^O =~ /MSWin/ 
-               ? 'windows'
-               : $^O =~ /cygwin/
-               ? "cygwin"
-               : $^O;
-our $NULL      = $^O =~ /MSWin/ ? 'NUL' : '/dev/null';
-our $SEPARATOR = $^O =~ /MSWin/ ? '\\'  : '/';
-our $TRUE      = 1;
-our $FALSE     = 0;
-our $ROOT      = $^O =~ /MSWin/ ? $ENV {SYSTEMDRIVE} . $SEPARATOR : "/";
+our $ARCHITECTURE = $^O =~ /MSWin/ 
+                  ? 'windows'
+                  : $^O =~ /cygwin/
+                  ? "cygwin"
+                  : $^O;
+our $NULL         = $^O =~ /MSWin/ ? 'NUL' : '/dev/null';
+our $SEPARATOR    = $^O =~ /MSWin/ ? '\\'  : '/';
+our $TRUE         = 1;
+our $FALSE        = 0;
+our $ROOT         = $^O =~ /MSWin/ ? $ENV {SYSTEMDRIVE} . $SEPARATOR : "/";
 
 our @EXPORT = qw (
-  $ARCH
+  $ARCHITECTURE
   $FALSE
   $NULL
   $SEPARATOR
@@ -135,7 +135,7 @@ Returns:
 
 =cut
 
-  if ($ARCH eq "windows" or $ARCH eq "cygwin") {
+  if ($ARCHITECTURE eq "windows" or $ARCHITECTURE eq "cygwin") {
     # Not sure how this relates to Windows/Cygwin environment so just
     # return false
     return $FALSE;
@@ -152,7 +152,7 @@ Returns:
 
 =over
 
-=item $ARCH
+=item $ARCHITECTURE
 
 Set to either "windows", "cygwin" or $^O.
 
index 78af171..f52fe4b 100644 (file)
@@ -156,7 +156,7 @@ Returns:
     or error "Can't write to $errorlog ($!)", 1;
 
   # Change the current directory to /
-  my $ROOT = $ARCH eq "windows" ? "C:\\" : "/";
+  my $ROOT = $ARCHITECTURE eq "windows" ? "C:\\" : "/";
   chdir $ROOT
     or error "Can't chdir to $ROOT ($!), 1";
 
@@ -232,17 +232,11 @@ STDOUT then do so in the $command passed in.
 
 =cut
 
-  # Save $SIG{CHLD} so we can set it to 'DEFAULT' and then restore it later.
-  # Helps when you are doing process handling.
-  my $sigchld = $SIG{CHLD};
-
   local $SIG{CHLD} = 'DEFAULT';
 
   my @output = `$cmd`;
   my $status = $?;
 
-  local $SIG{CHLD} = $sigchld;
-
   chomp @output;
 
   return ($status, @output);
@@ -363,7 +357,7 @@ Returns:
   while () {
     my $key;
 
-    while (not defined ($key = ReadKey -1)) { }
+   while (not defined ($key = ReadKey -1)) { }
 
     if ($key =~ /(\r|\n)/) {
        print "\n";
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c8807d0..8207eae 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # File:         $RCSfile: bash_login,v $
-# Revision:        $Revision: 1.29 $
+# Revision:    $Revision: 1.29 $
 # Description:  bash startup file
 # Author:       Andrew@DeFaria.com
 # Created:      Mon Aug 20 17:35:01  2001
@@ -48,12 +48,19 @@ else
   echo "Warning: Unknown architecture ($KERNEL)"
 fi
 
-# Architectual differences (AKA Silly Sun)
-if [ $ARCHITECTURE = "sun" ]; then
-  alias id=/usr/xpg4/bin/id
-  alias tr=/usr/xpg4/bin/tr
-  
-  export id=/usr/xpg4/bin/id
+# Hack: Just set TERM to xterm
+if [ $ARCHITECTURE = 'sun' ]; then
+  id=/usr/xpg4/bin/id
+  tr=/usr/xpg4/bin/tr
+  TERM=xtermc
+else
+  id=id
+  tr=tr
+  if [ $ARCHITECTURE = 'cygwin' ]; then
+    TERM=cygwin
+  else
+    TERM=xterm
+  fi
 fi
 
 # Set colors
@@ -90,14 +97,6 @@ else
    export SYSNAME="*Unknown Systemname*:"
 fi
 
-# System dependencies
-# Note: I don't like doing this but an alias doesn't work...
-if [ $ARCHITECTURE = "sun" ]; then
-  id=/usr/xpg4/bin/id
-else
-  id=id
-fi
-
 umask 002
 
 if [ "$interactive" = "true" ]; then
@@ -152,10 +151,14 @@ set -o monitor
 set +u
 
 # Shell options
-if [ $ARCHITECTURE != 'Darwin' ]; then
-  if ! grep -qP '5\.(6|7|8|9|10)' /etc/*release; then
-    shopt -s autocd   > /dev/null 2>&1
-    shopt -s dirspell > /dev/null 2>&1
+if [ $ARCHITECTURE != 'Darwin' -a $ARCHITECTURE != 'sun' ]; then
+  ls /etc/*release > /dev/null 2>&1
+
+  if [ $? = 0 ]; then
+    if ! grep -qP '5\.(6|7|8|9|10)' /etc/*release; then
+      shopt -s autocd   > /dev/null 2>&1
+      shopt -s dirspell > /dev/null 2>&1
+    fi
   fi
 fi
 
@@ -221,6 +224,7 @@ if [ "$TERM" = "hpterm"         -o \
      "$TERM" = "sun-color"      -o \
      "$TERM" = "vt100"          -o \
      "$TERM" = "vt220"          -o \
+     "$TERM" = "xtermc"         -o \
      "$TERM" = "xterm"          -o \
      "$TERM" = "xterm-256color" -o \
      "$TERM" = "cygwin" ]; then
@@ -304,6 +308,6 @@ HOME=$saved_home
 export GIT_SSH=/usr/bin/ssh
 
 # Now go home (in case we were not autmatically cd'ed there)
-if [ $(id -u) -ne 0 ]; then
+if [ $($id -u) -ne 0 ]; then
   cd
 fi
index f06a3e0..14a3d88 100644 (file)
 #
 ################################################################################
 if [ $ARCHITECTURE = 'cygwin' ]; then
-  export CCHOME=$(cygpath -u "$(regtool get '/machine/SOFTWARE/Rational Software/RSINSTALLDIR' 2>/dev/null)"/Clearcase 2>/dev/null);
+  # The following should work but fails because they are using /c to mount
+  # the C drive and that messes things up.
+  export CCHOME=$(cygpath -u "$(regtool get '/machine/SOFTWARE/Atria/ClearCase/CurrentVersion/ProductHome' 2>/dev/null)" 2>/dev/null)
+  export CCHOME=/opt/rational/clearcase
 else 
   export CCHOME="/opt/rational/clearcase"
 fi
@@ -4077,36 +4080,48 @@ function _object_selector () {
   fi
 } # _object_selector
 
-complete -o default -F _scm scm ct
-
-complete -F _catcs       catcs
-complete -F _checkin     ci
-complete -F _deliver     deliver
-complete -F _endview     endview
-complete -F _lsactivity  lsact
-complete -F _lsbl        lsbl
-complete -F _lsproject   lsproj
-complete -F _lsfolder    lsfolder llfolder
-complete -F _lsstgloc    lsstgloc
-complete -F _lsstream    lsstream llstream
-complete -F _lsview      lsview llview
-complete -F _lsvob       lsvob llvob
-complete -F _merge       merge
-complete -F _mktag       mktag
-complete -F _mkview      mkview
-complete -F _rebase      rebase
-complete -F _rmtag       rmtag
-complete -F _rmview      rmview
-complete -F _setactivity setact
-complete -F _setcs       setcs
-complete -F _setview     setview
-complete -F _startview   startview
-complete -F _space       space
-complete -F _register    register
-complete -F _uncheckout  unco
-complete -F _unregister  unregister
-
-complete -F _object_selector -o nospace lstype
-complete -F _object_selector -o nospace lltype
-complete -F _object_selector -o nospace lslock
-complete -F _object_selector -o nospace lllock
+if [[ $BASH_VERSION = 2.05* || $BASH_VERSION = 4* ]]; then
+  complete -o default -F _scm scm ct
+
+  complete -F _catcs       catcs
+  complete -F _checkin     ci
+  complete -F _deliver     deliver
+  complete -F _endview     endview
+  complete -F _lsactivity  lsact
+  complete -F _lsbl        lsbl
+  complete -F _lsproject   lsproj
+  complete -F _lsfolder    lsfolder llfolder
+  complete -F _lsstgloc    lsstgloc
+  complete -F _lsstream    lsstream llstream
+  complete -F _lsview      lsview llview
+  complete -F _lsvob       lsvob llvob
+  complete -F _merge       merge
+  complete -F _mktag       mktag
+  complete -F _mkview      mkview
+  complete -F _rebase      rebase
+  complete -F _rmtag       rmtag
+  complete -F _rmview      rmview
+  complete -F _setactivity setact
+  complete -F _setcs       setcs
+  complete -F _setview     setview
+  complete -F _startview   startview
+  complete -F _space       space
+  complete -F _register    register
+  complete -F _uncheckout  unco
+  complete -F _unregister  unregister
+else
+  : echo 'Clearcase command completion broken on old Sun Bash shells'
+fi
+  
+if [[ $BASH_VERSION = 4* ]]; then
+  complete -F _object_selector -o nospace lstype
+  complete -F _object_selector -o nospace lltype
+  complete -F _object_selector -o nospace lslock
+  complete -F _object_selector -o nospace lllock
+elif [[ $BASH_VERSION = 2.05* ]]; then
+  complete -F _object_selector lstype
+  complete -F _object_selector lltype
+  complete -F _object_selector lslock
+  complete -F _object_selector lllock
+  #echo 'Clearcase command completion partially broken on old Sun Bash shells'
+fi
index 3e8c4f4..efd7c53 100644 (file)
@@ -15,7 +15,7 @@ fi
 export LINUX_VOBTAG_PREFIX=/vob
 
 # The default pvob
-export pvob=${VOBTAG_PREFIX}9200_projects
+export pvob=${VOBTAG_PREFIX}
 
 # The default vob
-export dvob="${VOBTAG_PREFIX}9200"
+export dvob=${VOBTAG_PREFIX}
old mode 100644 (file)
new mode 100755 (executable)
index fb2993c..944061c
 ################################################################################
 umask 002
 
-export SITE_PERLLIB=/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/lib
-export PATH=/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/clearcase:$PATH
+if [ -d /cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/lib ]; then
+  export PERL5LIB=/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/lib:$PERL5LIB
+fi
 
-export http_proxy=webgate0.gddsi.com:8080
-export ftp_proxy=webgate0.gddsi.com
+# This no longer work
+#export http_proxy=webgate0.gddsi.com:8080
+#export ftp_proxy=webgate0.gddsi.com
 
 export QTDIR="/usr/local/Trolltech/Qt-4.2.2"
 export QMAKESPEC="$QTDIR/mkspecs/solaris-cc"
@@ -27,7 +29,6 @@ export ORACLE_HOME="/usr/local/oracle/product/9.2"
 
 export CCASE_MAKE_COMPAT=gnu
 
-export CQ_HOME=/opt/rational/clearquest
 export CQ_HELP_BROWSER=firefox
 export CQ_PERLLIB=/opt/rational/common/lib/perl5/5.6.1/sun4-solaris-multi:/opt/rational/common/lib/perl5/5.6.1:/opt/rational/common/lib/perl5/site_perl/5.6.1/sun4-solaris-multi:/opt/rational/common/lib/perl5/site_perl/5.6.1:/opt/rational/common/lib/perl5/site_perl
 
@@ -37,18 +38,30 @@ alias xv=/prj/Synopsis/gccsparcOS5/ccss/utils/xv/xv
 
 export RSU_LICENSE_MAP="/prj/muosran/config/Rational_License_Map"
 
-export LM_LICENSE_FILE="flex2:1850@flex2:15280@ranadm2:19353@ranadm2:19355@ranadm2:2468@ranadm2:1717@flex2:1711@bartlett:1711@flex3:27000@ranadm2:28000@ranadm2:5270@flex2"
-
-alias xemacs="ssh muosbldforge2 xemacs"
-
-export EDITOR="ssh muosbldforge2 xemacs"
+export LM_LICENSE_FILE="1850@ma06app30:flex2:1850@flex2:15280@ranadm2:19353@ranadm2:19355@ranadm2:2468@ranadm2:1717@flex2:1711@bartlett:1711@flex3:27000@ranadm2:28000@ranadm2:5270@flex2"
 
 if [ $(uname) = "SunOS" ]; then
   export QTDIR=/usr/local/Trolltech/Qt-4.2.2
   export ORACLE_HOME="/usr/local/oracle/product/9.2"
-  export CQ_HOME=/opt/rational/clearquest/
+  export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib:/usr/local/lib
 elif [ $(uname) = "Linux" ]; then
   export QTDIR=/usr/local/Trolltech/Qt-4.2.3
   export ORACLE_HOME="/usr/local/oracle/product/10.2.0"
   export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib
-fi
\ No newline at end of file
+fi
+
+# Where the Clearcase view drive is on Windows
+export CLEARCASE_VIEW_DRIVE=X
+
+# Additional paths...
+append_to_path "/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/clearcase"
+append_to_path "/cygcrive/c/Program Files/IBM/RationalSDLC/common"
+append_to_path "/cygcrive/d/Program Files/IBM/RationalSDLC/common"
+append_to_path "/cygcrive/c/Program Files/IBM/RationalSDLC/Clearquest/cqcli/bin"
+append_to_path "/cygcrive/d/Program Files/IBM/RationalSDLC/Clearquest/cqcli/bin"
+append_to_path "/cygcrive/c/Program Files/IBM/RationalSDLC/ClearCase/bin"
+append_to_path "/cygcrive/d/Program Files/IBM/RationalSDLC/ClearCase/bin"
+append_to_path "/cygdrive/c/Program Files (x86)/ibm/gsk8/lib"
+
+# Common CDPATHS
+CDPATH=$CDPATH:/vobs/ranccadm
old mode 100755 (executable)
new mode 100644 (file)
index 88a4ba0..ec2f311 100644 (file)
@@ -60,8 +60,9 @@ function title_bar {
   elif [ "$TERM" = "cygwin" -o \
          "$TERM" = "vt100"  -o \
          "$TERM" = "xterm"  -o \
+         "$TERM" = "xtermc" -o \
          "$TERM" = "xterm-256color" ]; then
-    PS1="\[\e]0;$prefix$current_dir\007\]\[$RED\]$ROOT\[$LIGHT_CYAN\]$SYSNAME:\[$WHITE\]"
+    PS1="\[\e]0;$prefix$current_dir\007\]$ROOT\[$B_YELLOW\]$SYSNAME:\[$B_WHITE\]"
   fi
 } # title_bar
 
@@ -89,9 +90,9 @@ function title {
 # view and a string to indicate that you are root.
 function set_title {
   if [ $($id -u) -eq 0 ]; then
-    ROOT="Wizard "
+    root="Wizard "
   else
-    ROOT=
+    root=
   fi
 
   view_name=$(scm pwv -short 2> /dev/null);
@@ -102,9 +103,9 @@ function set_title {
 
   if [[ $view_name = *NONE* ]]; then
     view_name=""
-    title_bar "$ROOT"
+    title_bar "$root"
   else
-    title_bar "${ROOT}View: $view_name: "
+    title_bar "${root}View: $view_name: "
   fi
 
   icon_name "${SYSNAME##*:}"
@@ -113,27 +114,31 @@ function set_title {
 # Sets prompt on terminals listed.
 function set_prompt {
   if [ $($id -u) -eq 0 ]; then
-    if [ "$TERM"   = "hpterm" -o \
-         "$TERM"   = "hp"     -o \
-         "$TERM"   = "2392A"  -o \
-         "$TERM"   = "dtterm" -o \
-         ! -z "$DTTERM" ]; then
-      ROOT="${RED}Wizard$NORMAL "
-    elif [ "$TERM" = "vt100"          -o \
-           "$TERM" = "xterm"          -o \
-           "$TERM" = "xterm-256color" -o \
-           "$TERM" = "vt220" ]; then
-      ROOT="${BOLD}${BLINK}Wizard$NORMAL "
+    if [ "$TERM" = "hpterm"         -o \
+         "$TERM" = "hp"             -o \
+         "$TERM" = "2392A"          -o \
+         "$TERM" = "dtterm"         -o \
+         "$TERM" = "vt100"          -o \
+         "$TERM" = "cygwin"         -o \
+         "$TERM" = "xterm"          -o \
+         "$TERM" = "xtermc"         -o \
+         "$TERM" = "xterm-256color" -o \
+         "$TERM" = "vt220" ]; then
+      ROOT="\[${ROOT_COLOR}\]Wizard\[$NORMAL\] "
+    else
+      ROOT="Wizard "
     fi
   else
     ROOT=""
   fi
 
   if [ "$TERM" = "vt100"          -o \
+       "$TERM" = "cygwin"         -o \
        "$TERM" = "xterm"          -o \
+       "$TERM" = "xtermc"         -o \
        "$TERM" = "xterm-256color" -o \
        "$TERM" = "vt220" ]; then
-    PS1="$ROOT$BOLD$SYSNAME:$NORMAL"
+    PS1="$ROOT\[$B_YELLOW\]$SYSNAME:\[$B_WHITE\]"
   else
     PS1="$ROOT$SYSNAME:"
   fi
index 54c75b2..cb016f4 100644 (file)
--- a/rc/perldb
+++ b/rc/perldb
@@ -1,2 +1,2 @@
 parse_options ('windowSize=20');
-parse_options ('HistFile=.perldb.hist');
+#parse_options ('HistFile=.perldb.hist');
index 5b283de..10bd8aa 100644 (file)
@@ -30,28 +30,31 @@ if [ "$TERM" = "vt100" -o \
     echo -e "${INVERSE}Inverse$NORMAL"
   fi
 elif [ "$TERM" = "dtterm" -o \
-       "$TERM" = "xterm"     ]; then
-  NORMAL="$esc[39m"
-  RED="$esc[31m"
-  B_RED=$RED
-  GREEN="$esc[32m"
-  B_GREEN=$GREEN
-  YELLOW="$esc[33m"
-  B_YELLOW=$YELLOW
-  BLUE="$esc[34m"
-  B_BLUE=$BLUE
-  MAGENTA="$esc[35m"
-  B_MAGENTA=$MAGENTA
-  AQUA="$esc[36m"
-  B_AQUA=$AQUA
-  WHITE="$esc[36m"
-  B_WHITE=$WHITE
+       "$TERM" = "cygwin" -o \
+       "$TERM" = "xterm"  -o \
+       "$TERM" = "xtermc"    ]; then
+  NORMAL="$esc[0;39m"
+  RED="$esc[0;31m"
+  B_RED="$esc[1;31m"
+  GREEN="$esc[0;32m"
+  B_GREEN="$esc[1;32m"
+  YELLOW="$esc[0;33m"
+  B_YELLOW="$esc[1;33m"
+  BLUE="$esc[0;34m"
+  B_BLUE="$esc[1;34m"
+  MAGENTA="$esc[0;35m"
+  B_MAGENTA="$esc[1;35m"
+  AQUA="$esc[0;36m"
+  B_AQUA="$esc[1;36m"
+  WHITE="$esc[0;37m"
+  B_WHITE="$esc[1;37m"
+  ROOT_COLOR="$esc[1;31m"
 
   if [ "$1" = "-v" ]; then
     echo    "Terminal: $TERM"
     echo -e "${RED}Red$NORMAL\t${B_RED}Bright red$NORMAL"
     echo -e "${GREEN}Green$NORMAL\t${B_GREEN}Bright green$NORMAL"
-    echo -e "${YELLOW}Yellow$NORMAL\t${B_YELLOW}Bright green$NORMAL"
+    echo -e "${YELLOW}Yellow$NORMAL\t${B_YELLOW}Bright yellow$NORMAL"
     echo -e "${BLUE}Blue$NORMAL\t${B_BLUE}Bright blue$NORMAL"
     echo -e "${MAGENTA}Magenta$NORMAL\t${B_MAGENTA}Bright magenta$NORMAL"
     echo -e "${AQUA}Aqua$NORMAL\t${B_AQUA}Bright aqua$NORMAL"
index b39caef..b9b6ed3 100644 (file)
@@ -85,6 +85,7 @@ path_dirs="$path_dirs\
   /usr/local/bin\
   /usr/afsws/bin\
   /usr/afsws\
+  /usr/xpg4/bin\
   /bin\
   /sbin\
   /usr/bin\
@@ -95,6 +96,7 @@ path_dirs="$path_dirs\
   /usr/openwin/bin\
   /usr/kerberos/bin\
   /opt/rational/clearcase/bin\
+  /opt/rational/clearquest/bin\
   /opt/ibm/rationalsdlc/clearcase/bin\
   /opt/ibm/rationalsdlc/clearcase/etc\
   /opt/ibm/rationalsdlc/clearquest/bin\
@@ -110,7 +112,7 @@ path_dirs="$path_dirs\
   /tools/bin\
   $systemroot/System32\
   $systemroot\
-"  
+"
 
 manpath_dirs="\
   /usr/share/man\
@@ -124,7 +126,7 @@ manpath_dirs="\
   /opt/ssh/man\
   /opt/medusa/share/man\
   /usr/afsws/man\
-"  
+"
 
 PATH=
 for component in $path_dirs; do
index 7f16ea4..03a1fb3 100644 (file)
--- a/rc/system
+++ b/rc/system
@@ -23,7 +23,7 @@ SYSNAME=$(echo ${SYSNAME:0:1} | tr [:lower:] [:upper:])$(echo ${SYSNAME:1}   | t
 
 # Aliasing
 case "$SYSNAME" in
-  C02s608vg8wp)
+  Az25jzhxkb2d)
     SYSNAME="Venus"
     ;;
 esac
diff --git a/test/testclearcase.conf b/test/testclearcase.conf
new file mode 100644 (file)
index 0000000..b58626e
--- /dev/null
@@ -0,0 +1,23 @@
+################################################################################
+#
+# File:         testclearcase.conf
+# Revision:     2.0
+# Description:  Parameters for testclearcse.pl
+#
+# Author:       Andrew@DeFaria.com
+# Created:      Thu Sep  6 14:05:55 MST 2007
+# Modified:
+# Language:     Conf
+#
+# (c) Copyright 2007, Andrew@DeFaria.com, all rights reserved.
+#
+#################################################################################
+# Note this conf file is set up for Windows...
+vobhost:                az251dp2ch2d
+vobpath:                //$vobhost
+vobstore:               $vobpath/temp
+
+viewhost:               az251dp2ch2d
+viewpath:               //$vobhost
+viewdrive:              x:
+viewstore:              $viewpath/viewstore
index f0cfde9..545f3d0 100755 (executable)
-#!/usr/bin/perl
+#!/usr/bin/env cqperl
+
+=pod
+
+=head1 NAME $RCSfile: testclearcase.pl,v $
+
+Test Clearcase
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 2.1 $
+
+=item Created:
+
+Tue Apr 10 13:14:15 CDT 2007
+
+=item Modified:
+
+$Date: 2011/01/09 01:01:32 $
+
+=back
+
+=head1 SYNOPSIS
+
+ Usage: testclearcase.pl: [-us|age] [-ve|rbose]
+                          [-c|onfig <file>] [-b|ase] [-uc|m]
+
+ Where:
+   -v|erbose:       Display progress output
+   -d|ebug:         Display debug info
+   -us|age:         Display usage
+
+   -c|onfig <file>: Config file (Default: testclearcase.conf)
+   -[no]b|ase:      Perform base Clearcase tests (Default: base)
+   -[no]uc|m:       Perform UCM Clearcase tests (Default: noucm)
+   -[no]clean:      Cleanup after yourself (Default: clean)
+
+if -ucm is specified then the following additional parameters should be set:
+
+    -username:      Username to connect to Clearquest with (Can set CQ_USERNAME)
+    -password:      Password to use to connect to Clearquest (CQ_PASSWORD)
+    -weburl:        Web URL to use for enabling Clearcase -> Clearquest 
+                    connection (CQ_WEBURL - Do not specify the trailing
+                    "/oslc")
+    -database:      Clearquest database to enable (CQ_DATABASE)
+    -dbset:         Clearquest DBSet (CQ_DBSET)
+    -provider:      Name of provider (Default: CQPROV)
+
+=head1 DESCRIPTION  
+
+Clearcase smoke tests. Perform simple Clearcase operations to validate that
+Clearcase minimally works.
+
+If -ucm is specified then additional UCM related tests are performed.
+
+=cut
+
 use strict;
 use warnings;
 
+use Cwd;
 use FindBin;
-use Term::ANSIColor qw(:constants);
+use Getopt::Long;
+use Pod::Usage;
 
-my $libs;
+use lib "$FindBin::Bin/../lib";
 
-BEGIN {
-  $libs = $ENV{SITE_PERLLIB} ? $ENV{SITE_PERLLIB} : "$FindBin::Bin/../lib";
-
-  die "Unable to find libraries\n" 
-    unless -d $libs;
-} # BEGIN
+use Clearcase;
+use Clearcase::Element;
+use Clearcase::View;
+use Clearcase::Views;
+use Clearcase::Vob;
+use Clearcase::Vobs;
 
-use lib $libs;
+use Clearcase::UCM;
+use Clearcase::UCM::Activity;
+use Clearcase::UCM::Baseline;
+use Clearcase::UCM::Component;
+use Clearcase::UCM::Folder;
+use Clearcase::UCM::Project;
+use Clearcase::UCM::Pvob;
+use Clearcase::UCM::Stream;
 
-use Clearcase;
+use DateUtils;
 use Display;
+use GetConfig;
+use Logger;
+use OSDep;
+use TimeUtils;
+use Utils;
+
+# Globals
+my $VERSION = '2.1';
+
+my (
+  $test_vob,
+  $test_view,
+  $test_pvob,
+  $test_folder,
+  $test_project,
+  $test_activity,
+  $test_baseline,
+  $test_component,,
+  $test_devstream,
+  $test_intstream,
+  $test_devview,
+  $test_intview,
+);
+
+my (%default_opts, %opts);
+
+my ($script) = ($FindBin::Script =~ /^(.*)\.pl/);
+
+my $log = Logger->new;
+
+# LogOpts: Log the %opts has to the log file so we can tell the options used for
+# this run.
+sub LogOpts() {
+  $log->msg(
+    "$script v$VERSION run at " 
+  . YMDHM
+  . ' with the following options:'
+  );
+
+  for (sort keys %opts) {
+    next if /help/ || /usage/ || /password/;
+
+    if (ref $opts{$_} eq 'ARRAY') {
+      my $name = $_;
+
+      for (@{$opts{$_}}) {
+        $log->msg("$name:\t$_") if $_;
+      } # for
+    } else {
+      if ($opts{$_}) {
+        $log->msg("$_:\t$opts{$_}");
+      } else {
+        $log->msg("$_:\t<undef>");
+      } # if
+    }  # if
+  } # for
+
+  return;
+} # LogOpts
+
+sub CreateVob($) {
+  my ($tag) = @_;
+
+  my $vobname = Clearcase::vobname $tag;
+
+  $log->msg ("Creating vob $tag");
+
+  my $newvob = Clearcase::Vob->new($tag);
+
+  my ($status, @output) = $newvob->create($opts{vobhost}, "$opts{vobstore}/$vobname.vbs");
+
+  $log->log($_) for @output;
+
+  return ($status, $newvob);
+} # CreateVob
+
+sub CreatePvob($) {
+  my ($tag) = @_;
+
+  my $vobname = Clearcase::vobname $tag;
+
+  my $pvob = Clearcase::UCM::Pvob->new($tag);
+
+  #my ($status, @output) = $pvob->create($opts{vobhost}, "$opts{vobstore}/$vobname.vbs", 'A test Pvob');
+  my ($status, @output) = $pvob->create($opts{vobhost}, "$opts{vobstore}/$vobname.vbs");
+
+  $log->log($_) for @output;
+
+  return ($status, $pvob);
+} # CreatePvob
+
+sub MountVob($) {
+  my ($vob) = @_;
+
+  $log->msg('Mounting vob ' . $vob->tag);
+
+  # Create mount directory
+  my ($status, @output);
+
+  ($status, @output) = Execute 'mkdir -p ' . $vob->tag . ' 2>&1' unless -d $vob->tag;
+
+  $log->log($_) for @output;
+
+  ($status, @output) = $vob->mount;
+
+  $log->log($_) for @output;
+
+  return $status;
+} # MountVob
+
+sub DestroyVob($) {
+  my ($vob) = @_;
+
+  my ($status, @output);
+
+  ($status, @output) = $Clearcase::CC->execute('cd');
+
+  $log->err('Unable to perform cd command', 1) if $status;
+
+  $log->msg('Unmounting vob ' . $vob->tag);
+
+  ($status, @output) = $vob->umount;
+
+  if ($status) {
+    $log->err('Unable to unmount vob ' . $vob->tag);
+  } else {
+    $log->msg('Umounted vob ' . $vob->tag);
+  } # if
+
+  $log->msg('Removing vob ' . $vob->tag);
+
+  ($status, @output) = $vob->remove;
+
+  if ($status) {
+    $log->err("Failed to execute command " . 
+              $Clearcase::CC->lastcmd . "\n" .
+             join "\t\n", @output);
+  } # if
+
+  $log->log($_) for @output;
+
+  return $status;
+} # DestroyVob
+
+sub CreateView($) {
+  my ($tag) = @_;
+
+  $log->msg("Creating view $tag");
+
+  my $view = Clearcase::View->new($tag);
+
+  my ($status, @output) = $view->create($opts{viewhost}, "$opts{viewstore}/$tag.vws");
+
+  $log->log($_) for @output;
+
+  return ($status, $view);
+} # CreateView
+
+sub SetView($) {
+  my ($view) = @_;
+
+  $log->msg('Setting view ' . $view->tag);
+
+  my ($status, @output) = $view->set;
+
+  $log->log($_) for @output;
+
+  return $status;
+} # SetView
+
+sub StopView($) {
+  my ($view) = @_;
+
+  $log->msg('Stopping view ' . $view->tag);
+
+  my ($status, @output) = $view->stop;
+
+  $log->log($_) for @output;
+
+  return $status;
+} # StopView
+
+sub DestroyView($) {
+  my ($view) = @_;
+
+  $log->msg('Removing view ' . $view->tag);
+
+  my ($status, @output) = $Clearcase::CC->execute('cd');
+
+  $log->log($_) for @output;
+
+  chdir $ENV{HOME}
+    or $log->err("Unable to chdir $ENV{HOME}", 1);
+
+  ($status, @output) = $view->remove;
+
+  $log->log($_) for @output;
+
+  return $status;
+} # DestroyView
+
+sub CreateViewPrivateFiles(@) {
+  my (@elements) = @_;
+
+  $log->msg('Creating test files');
+
+  for (@elements) {
+    my $file;
+
+    $log->msg("Creating $_");
+
+    open $file, '>>', $_
+      or $log->err("Unable to open $_ for writing - $!", 1);
+
+    print $file "This is file $_\n";
+
+    close $file;
+  } # for
+
+  return;
+} # CreateViewPrivateFiles
+
+sub CheckOut($) {
+  my ($element) = @_;
+
+  my ($status, @output);
+
+  if (ref $element eq 'ARRAY') {
+    for (@{$element}) {
+      $log->msg("Checking out $_");
+
+      my $newElement = Clearcase::Element->new($_);
+
+      ($status, @output) = $newElement->checkout;
+
+      $log->log($_) for @output;
+
+      $log->err("Unable to check out $_", $status) if $status;
+    } # for
+  } else {
+    $log->msg("Checking out $element");
+
+    my $newElement = Clearcase::Element->new($element);
+
+    ($status, @output) = $newElement->checkout;
+
+    $log->log($_) for @output;
+
+    $log->err("Unable to check out $element", $status) if $status;
+  } # if
+
+  return;
+} # CheckOut
+
+sub CheckIn($) {
+  my ($element) = @_;
+
+  my ($status, @output);
+
+  if (ref $element eq 'ARRAY') {
+    for (@{$element}) {
+      $log->msg("Checking in $_");
+
+      my $newElement = Clearcase::Element->new($_);
+
+      ($status, @output) = $newElement->checkin;
+
+      $log->log($_) for @output;
+
+      $log->err("Unable to check in $_", $status) if $status;
+    } # for
+  } else {
+    $log->msg("Checking in $element");
+
+    my $newElement = Clearcase::Element->new($element);
+
+    ($status, @output) = $newElement->checkin;
+
+    $log->log($_) for @output;
+
+    $log->err("Unable to check in $element", $status) if $status;
+  } # if
+
+  return;
+} # CheckIn
+
+sub ComparingFiles(@) {
+  my (@elements) = @_;
+
+  for (@elements) {
+    my @lines = ReadFile $_;
+
+    $log->err("Element $_ should contain only two lines", 2) if scalar @lines != 2;
+  } # for
+
+  return;
+} # ComparingFiles
+
+sub MakeElements(@) {
+  my (@elements) = @_;
+
+  for (@elements) {
+    $log->msg("Mkelem $_");
+
+    my $newElement = Clearcase::Element->new($_);
+
+    my ($status, @output) = $newElement->mkelem;
+
+    $log->log($_) for @output;
+
+    $log->err("Unable to make $_ an element", $status) if $status;
+  } # for
+
+  return;
+} # MakeElements
+
+sub RunTests() {
+  # Simple tests:
+  #
+  #   . Create a few elements
+  #   . Check them in
+  #   . Check them out
+  #   . Modify them
+  #   . Check them in
+  #
+  # Assumptions:
+  #
+  #   . $vob_tag is already created
+  #   . $view_tag is already created
+  #   . View is set and we are in the vob
+  #   . There are no vob elements for @elements
+  my @elements = (
+    'cctest.h',
+    'ccsetup.c',
+    'cctest.c',
+    'Makefile',
+  );
+
+  $log->msg("$script: Start Base Clearcase Tests");
+  $log->msg('Removing test files');
+
+  unlink $_ for @elements;
+
+  $log->msg('Creating view private files');
+
+  CreateViewPrivateFiles @elements;
+
+  $log->msg('Making elements');
+
+  CheckOut      '.';
+  MakeElements  @elements;
+  CheckIn       \@elements;
+  CheckIn       '.';
+
+  $log->msg('Checking out files');
+
+  CheckOut \@elements;
+
+  $log->msg('Modifying files');
+
+  CreateViewPrivateFiles @elements;
+
+  $log->msg('Checking in files');
+
+  CheckIn \@elements;
+
+  $log->msg('Comparing files');
+
+  ComparingFiles @elements;
+
+  $log->msg("$script: End Base Clearcase Tests");
+
+  return 0;
+} # RunTests
+
+sub Cleanup(;$$$) {
+  my ($view, $vob) = @_;
+
+  my $status = 0;
+
+  $log->msg('Cleaning up');
+
+  if ($view && $view->exists) {
+    $status += DestroyView($view);
+  } # if
+
+  if ($vob && $vob->exists) {
+    $status += DestroyVob($vob);
+  } # if
+
+  return $status;
+} # Cleanup
+
+sub CleanupUCM() {
+  my ($rc, $status, @output);
+
+  $log->msg('Removing ' . $test_activity->name);
+
+  ($rc, @output) = $test_activity->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  # Need to remove baselines from streams first using rebase (Devstream)
+  $log->msg('Rebasing ' . $test_devstream->name . ' to remove baseline');
+
+  $status += RebaseStream(
+    $test_devstream,
+    ' -dbaseline ' . $test_baseline->name . '@' . $test_baseline->pvob->tag .
+    ' -view '      . $test_devview->name  . ' -complete',
+  );
+
+  # Change intstream to not have a recommended baseline
+  $log->msg('Changing ' . $test_intstream->name . ' to remove recommended baseline');
+
+  ($rc, @output) = $test_intstream->nrecommended;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $status += DestroyView($test_devview);
+
+  $log->msg('Removing ' . $test_baseline->name);
+
+  ($rc, @output) = $test_baseline->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $log->msg('Rebasing ' . $test_intstream->name . ' to remove INITIAL baseline');
+
+  $status += RebaseStream(
+    $test_intstream,
+    ' -dbaseline tc.component_INITIAL' . '@' . $test_intstream->pvob->tag .
+    ' -view ' . $test_intview->name    . ' -complete',
+  );
+
+  $log->msg('Removing ' . $test_component->name . ' from ' . $test_project->name);
+
+  ($rc, @output) = $test_project->change(
+    '-dmodcomp ' . $test_component->name . '@' . $test_project->pvob->tag
+  );
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $log->msg('Removing ' . $test_component->name);
+
+  ($rc, @output) = $test_component->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $status += DestroyView($test_intview);
+
+  $log->msg('Removing '. $test_devstream->name);
+
+  ($rc, @output) = $test_devstream->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $log->msg('Removing ' . $test_intstream->name);
+
+  ($rc, @output) = $test_intstream->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $log->msg('Removing ' . $test_project->name);
+
+  ($rc, @output) = $test_project->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $log->msg('Removing ' . $test_folder->name);
+
+  ($rc, @output) = $test_folder->remove;
+
+  $status += $rc;
+
+  $log->log($_) for @output;
+
+  $log->msg('Removing ' . $test_pvob->name);
+
+  ($rc, @output) = DestroyVob($test_pvob);
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CleanupUCM
+
+sub SetupTest($$) {
+  my ($vob_tag, $view_tag) = @_;
+
+  my ($status, @output);
+
+  $log->msg('Setup test environment');
+
+  my $view = Clearcase::View->new($view_tag);
+
+  if ($view->exists) {
+    $log->msg('Removing old view ' . $view_tag);
+
+    ($status, @output) = $view->remove;
+
+    $log->err('Unable to remove old view ' . $view->tag, $status) if $status;
+  } # if
+
+  ($status, $test_view) = CreateView($view_tag);
+
+  return $status if $status != 0;
+
+  $status = $test_view->start;
+
+  my $vob = Clearcase::Vob->new($vob_tag);
+
+  if ($vob->exists) {
+    $log->msg('Removing old vob ' . $vob_tag);
+
+    ($status, @output) = DestroyVob($vob);
+
+    $log->err('Unable to remove old vob '. $vob->tag, $status) if $status;
+  } # if
+
+  ($status, $test_vob) = CreateVob($vob_tag);
+
+  return $status if $status != 0;
+
+  $status = MountVob($test_vob);
+
+  return $status if $status != 0;
+
+  my $dir = $Clearcase::VIEWTAG_PREFIX . '/' . $test_view->tag . $test_vob->tag;
+
+  chdir $dir
+    or $log->err("Unable to chdir to $dir", ++$status);
+
+  ($status, @output) = $Clearcase::CC->execute("cd $dir");
+
+  $log->log($_) for @output;
+
+  return $status;
+} # SetupTest
+
+sub SetupAttributeTypes() {
+  my @CC_CMI_Types = qw(CONTEXT TASK PROVIDERS);
+
+  my $status = SetView($test_intview);
+
+  return $status if $status;
+
+  for (@CC_CMI_Types) {
+    my $cmd = "mkattype -nc -vtype string CC_CMI_$_";
+
+    my ($rc, @output) = $Clearcase::CC->execute($cmd);
+
+     $status += $rc;
+
+     $log->log($_) for @output;
+  } # for
+
+  return $status;
+} # SetupAttributeTypes
+
+sub CRMRegister() {
+  my $cmd = "crmregister add -database $opts{database} -connection RDE "
+          . "-url $opts{weburl} -username $opts{username} "
+          . "-password $opts{password}";
+
+  my ($status, @output) = Execute $cmd;
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CRMRegister
+
+sub MakeCMProvider() {
+  my $cmd = 'mkcmprovider -vob ' . $test_pvob->tag 
+          . '-type cmcq -version V1_0 -description '
+          . '"RDE CMI CQ Provider" '
+          . '-connection baseurl:' . $opts{weburl} . " $opts{provider}";
+
+  my ($status, @output) = $Clearcase::CC->execute($cmd);
+
+  $log->log($_) for @output;
+
+  return $status;
+} # MakeCMProvider
+
+sub SetupUCMTest() {
+  my $status;
+
+  $log->msg("Register RDE://$opts{username}\@$opts{database}");
+
+  $status = CRMRegister;
+
+  $log->err("Unable to register RDE://$opts{username}\@$opts{database} - Check logfile", $status)
+    if $status;
+
+  $log->msg("Creating UCM Pvob ${Clearcase::VOBTAG_PREFIX}tc.pvob");
+
+  ($status, $test_pvob) = CreatePvob("${Clearcase::VOBTAG_PREFIX}tc.pvob"); 
+
+  MountVob $test_pvob;
+
+  return $status;
+} # SetupUCMTest
+
+sub CreateUCMProject() {
+  # Get the root folder to put this project into (may create folders later)
+  $test_folder = Clearcase::UCM::Folder->new('tc.folder', $test_pvob);
+
+  $test_project = Clearcase::UCM::Project->new('tc.project', $test_folder, $test_pvob);
+
+  $test_project->remove if $test_project->exists;
+
+  $log->msg('Creating UCM Project tc.project');
+
+  my ($status, @output) = $test_project->create;
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateUCMProject
+
+sub CreateUCMIntStream() {
+  $test_intstream = Clearcase::UCM::Stream->new('tc.intstream', $test_pvob);
+
+  $log->msg('Creating UCM Stream tc.intstream');
+
+  my ($status, @output) = $test_intstream->create($test_project, '-integration');
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateUCMIntStream
+
+sub CreateUCMDevStream() {
+  $test_devstream = Clearcase::UCM::Stream->new('tc.devstream', $test_pvob);
+
+  $log->msg('Creating UCM Stream tc.devstream');
+
+  my ($status, @output) = $test_devstream->create($test_project);
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateUCMDevStream
+
+sub CreateUCMComponent() {
+  $test_component = Clearcase::UCM::Component->new('tc.component', $test_pvob);
+
+  $log->msg('Creating UCM Component tc.component');
+
+  my ($status, @output) = $test_component->create(
+    "$Clearcase::VIEWTAG_PREFIX/" . $test_intview->tag . $test_vob->tag
+  );
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateUCMComponent
+
+sub AddModifiableComponent() {
+  my ($status, @output) = $Clearcase::CC->execute(
+    'chproj -nc -amodcomp ' . $test_component->name . '@' . $test_pvob->tag .
+    ' '                     . $test_project->name   . '@' . $test_pvob->tag
+  );
+
+  $log->log($_) for @output;
+
+  return $status;
+} # AddModifiableCOmponent
+
+sub CreateUCMIntView() {
+  $log->msg("Creating UCM Int View tc.intview");
+
+  $test_intview = Clearcase::View->new('tc.intview');
+
+  my ($status, @output) = $test_intview->create(
+    $opts{viewhost}, "$opts{viewstore}/tc.intview.vws",
+    '-stream ' . $test_intstream->name . '@' . $test_pvob->tag
+  );
+
+  $log->log($_) for @output;
+
+  $test_intview->start unless $status;
+
+  return $status;
+} # CreateUCMIntView
+
+sub CreateUCMDevView() {
+  $log->msg("Creating UCM Dev View tc.devview");
+
+  $test_devview = Clearcase::View->new('tc.devview');
+
+  my ($status, @output) = $test_devview->create(
+    $opts{viewhost}, "$opts{viewstore}/tc.devview.vws",
+    '-stream ' . $test_devstream->name . '@' . $test_pvob->tag
+  );
+
+  $log->log($_) for @output;
+
+  $test_devview->start unless $status;
+
+  return $status;
+} # CreateUCMDevView
+
+sub CreateUCMBaseline() {
+  $test_baseline = Clearcase::UCM::Baseline->new('tc.baseline', $test_pvob);
+
+  $log->msg('Creating UCM Baseline tc.baseline');
+
+  my ($status, @output) = $test_baseline->create($test_intview, undef, '-identical');
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateUCMBaseline
+
+sub CreateUCMActivity() {
+  $test_activity = Clearcase::UCM::Activity->new('tc.activity', $test_pvob);
+
+  $log->msg('Creating UCM Activity tc.activity');
+
+  my ($status, @output) = $test_activity->create($test_devstream, 'A UCM Test Activity');
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateUCMActivity
+
+sub RebaseStream($$) {
+  my ($stream, $opts) = @_;
+
+  my ($status, @output) = $stream->rebase($opts);
+
+  $log->log($_) for @output;
+
+  return $status;
+} # RebaseStream
+
+sub RecommendBaseline($$) {
+  my ($stream, $baseline) = @_;
+
+  my ($status, @output) = $stream->recommend($baseline);
+
+  $log->log($_) for @output;
+
+  return $status;
+} # RecommentBaseline
+
+sub RunUCMTests() {
+  my $status = 0;
+
+  $log->msg("$script: Start UCM Clearcase Tests");
+
+  $status += CreateUCMProject;
+  $status += CreateUCMIntStream;
+  $status += CreateUCMDevStream;
+  $status += CreateUCMIntView;
+  $status += SetupAttributeTypes;
+  $status += CreateUCMDevView;
+  $status += CreateUCMComponent;
+  $status += AddModifiableComponent;
+  $status += RebaseStream($test_intstream, '-baseline tc.component_INITIAL -complete');
+  $status += RecommendBaseline($test_intstream, 'tc.component_INITIAL');
+  $status += CreateUCMBaseline;
+  $status += RebaseStream($test_devstream, '-baseline tc.baseline -complete');
+  $status += RecommendBaseline($test_devstream, 'tc.baseline');
+  $status += CreateUCMActivity;
+
+  $log->msg("$script: End UCM Clearcase Tests");
+
+  return $status;
+} # RunUCMTests
+
+## Main
+my $startTime = time;
+my $conf_file = "$FindBin::Bin/$script.conf";
+my $status    = 0;
+
+$opts{help}     = sub { pod2usage };
+$opts{usage}    = sub { pod2usage (-verbose => 2)};
+$opts{base}     = 1;
+$opts{clean}    = 1;
+$opts{username} = $ENV{CQ_USERNAME};
+$opts{password} = $ENV{CQ_PASSWORD};
+$opts{weburl}   = $ENV{CQ_WEBURL};
+
+$opts{weburl}  .= $opts{weburl} ? "/oslc" : undef;
+$opts{database} = $ENV{CQ_DATABASE};
+$opts{dbset}    = $ENV{CQ_DBSET};
+$opts{provider} = $ENV{CQ_PROVIDER} || 'CQPROV';
+
+GetOptions(
+  \%opts,
+  'verbose' => sub { set_verbose },
+  'debug'   => sub { set_debug },
+  'usage'   => sub { Usage },
+  'config=s',
+  'base!',
+  'ucm!',
+  'clean!',
+  'username=s',
+  'database=s',
+  'dbset=s',
+  'provider',
+) || pod2usage;
+
+# Read the config file
+if (-f $conf_file) {
+  %default_opts = GetConfig $conf_file;
+} else {
+  $log->err("Unable to find config file $conf_file", 1);
+} # if
+
+# Overlay default opts if not specified
+for (keys %default_opts) {
+  $opts{$_} = $default_opts{$_} if !$opts{$_};
+} # for
+
+# Check CQ parameters
+if ($opts{ucm}) {
+  for ('username', 'password', 'weburl', 'database', 'dbset', 'provider') {
+    pod2usage "In UCM mode you must specify -$_" unless $opts{$_};
+  } # for
+} # if
+
+$log->msg("$script: Start");
+
+LogOpts;
+
+# Since we are creating private vobs (to avoid complications with having to
+# know and code the registry password when making public vobs), we'll simply
+# change $Clearcase::VOBTAG_PREFIX
+if ($ARCHITECTURE !~ /win/i) {
+  $Clearcase::VOBTAG_PREFIX = $ENV{TMP} . '/' || '/tmp';
+} # if
+
+if ($opts{base}) {
+  $status = SetupTest "${Clearcase::VOBTAG_PREFIX}tc.vob", 'tc.view';
+
+  if ($status == 0) {
+    $status += RunTests;
+  } else {
+    $log->err('Tests not run. Failure occurred in SetupTest - check logfile');
+  } # if
+
+  # Note if we are doing UCM tests then we need the view and vob here...
+  $status += Cleanup($test_view, $test_vob) if $opts{clean} && !$opts{ucm};
+
+  if ($status != 0) {
+    $log->err("$script: Failed (Base Clearcase)");
+  } else {
+    $log->msg("$script: Passed (Base Clearcase)");
+  } # if
+} # if
+
+if ($opts{ucm}) {
+  $status = SetupUCMTest;
+
+  if ($status == 0) {
+    $status += RunUCMTests;
+  } else {
+    $log->err('UCM Tests not run. Failure occurred in SetupUCMTest - check logfile');
+  } # if
+
+  if ($opts{clean}) {
+    $status += CleanupUCM;
+    $status += Cleanup($test_view, $test_vob);
+  } # if
+
+  if ($status != 0) {
+    $log->err("$script: Failed (UCM Clearcase)");
+  } else {
+    $log->msg("$script: Passed (UCM Clearcase)");
+  } # if
+} # if
+
+display_duration $startTime, $log;
+
+$log->msg("$script: End");
+
+exit $status;
+
+=pod
+
+=head1 CONFIGURATION AND ENVIRONMENT
+
+DEBUG: If set then $debug is set to this level.
+
+VERBOSE: If set then $verbose is set to this level.
+
+TRACE: If set then $trace is set to this level.
+
+=head1 DEPENDENCIES
+
+=head2 Perl Modules
+
+L<Cwd>
 
-my ($status, @output) = $Clearcase::CC->execute ('-ver');
+L<FindBin>
 
-error 'Clearcase is not installed on this system', 1
-  if $status;
-  
-display YELLOW . "Global Clearcase Variables\n" . RESET;
+L<Getopt::Long|Getopt::Long>
 
-my $view_drive     = $Clearcase::VIEW_DRIVE;
-my $vob_mount      = $Clearcase::VOB_MOUNT;
-my $win_vob_prefix = $Clearcase::WIN_VOB_PREFIX;
-my $vobtag_prefix  = $Clearcase::VOBTAG_PREFIX;
-my $countdb        = $Clearcase::COUNTDB;
+=head2 ClearSCM Perl Modules
 
-display MAGENTA . "View Drive:\t\t"       . RESET . $view_drive;
-display MAGENTA . "VOB Mount:\t\t"        . RESET . $vob_mount;
-display MAGENTA . "Windows VOB prefix:\t" . RESET . $win_vob_prefix;
-display MAGENTA . "VOB Tag Prefix:\t\t"   . RESET . $vobtag_prefix;
-display MAGENTA . "CountDB:\t\t"          . RESET . $countdb;
+=begin man
 
-display CYAN    . "\nGlobal Clearcase Configuration\n" . RESET;
+ Clearcase
+ Clearcase::Element
+ Clearcase::View
+ Clearcase::Views
+ Clearcase::Vob
+ Clearcase::Vobs
+ DateUtils
+ Display
+ GetConfig
+ Logger
+ OSDep
+ Utils
 
-display MAGENTA . "Client:\t\t\t"       . RESET . $Clearcase::CC->client;
-display MAGENTA . "Hardware type:\t\t"  . RESET . $Clearcase::CC->hardware_type;
-display MAGENTA . "License host:\t\t"   . RESET . $Clearcase::CC->license_host;
-display MAGENTA . "OS:\t\t\t"           . RESET . $Clearcase::CC->os;
-display MAGENTA . "Region:\t\t\t"       . RESET . $Clearcase::CC->region;
-display MAGENTA . "Registry host:\t\t"  . RESET . $Clearcase::CC->registry_host;
-display MAGENTA . "Sitename:\t\t"       . RESET . $Clearcase::CC->sitename;
-display MAGENTA . "Version:\t\t"        . RESET . $Clearcase::CC->version;
+=end man
 
-display GREEN . "\nCleartool Access\n" . RESET;
+=begin html
 
-display_nolf MAGENTA . "Views:\t" . RESET;
+<blockquote>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase.pm">Clearcase</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Element.pm">Element</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/View.pm">View</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Views.pm">Views</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Vob.pm">Vob</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/Vobs.pm">Vobs</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM.pm">UCM</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM/Activity.pm">Activity</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM/Baseline.pm">Baseline</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM/Component.pm">Component</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM/Project.pm">Project</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM/Pvob.pm">Pvob</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Clearcase/UCM/Stream.pm">Stream</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/DateUtils.pm">DateUtils</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Display.pm">Display</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/GetConfig.pm">GetConfig</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Logger.pm">Logger</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/OSDep.pm">OSDep</a><br>
+<a href="http://clearscm.com/php/scm_man.php?file=lib/Utils.pm">Utils</a><br>
+</blockquote>
 
-($status, @output) = $Clearcase::CC->execute ("lsview -s");
+=end html
 
-display scalar @output;
+=head1 BUGS AND LIMITATIONS
 
-display_nolf MAGENTA . "VOBs:\t" . RESET;
+There are no known bugs in this script
 
-($status, @output) = $Clearcase::CC->execute ("lsvob -s");
+Please report problems to Andrew DeFaria <Andrew@ClearSCM.com>.
 
-display scalar @output;
+=head1 LICENSE AND COPYRIGHT
 
-($status, @output) = $Clearcase::CC->execute ("invalid command");
+Copyright (c) 2010, ClearSCM, Inc. All rights reserved.
 
-display $_ foreach (@output);
+=cut
index c659f32..df33056 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env cqperl
 use strict;
 use warnings;
 
@@ -35,11 +35,11 @@ $Date: 2013/03/14 23:39:39 $
 =head1 SYNOPSIS
 
  Usage: testclearquest.pl [-u|sage] [-v|erbose] [-d|ebug]
-                          [-get] [-add] [-modify] [-change] [-delete]                   
+                          [-get] [-add] [-modify] [-change] [-delete]
                           [-username <username>] [-password <password>]
                           [-database <dbname>] [-dbset <dbset>]
                           [-module] [-server <server>] [-port <port>]
-                  
+
  Where:
    -usa|ge:     Displays usage
    -v|erbose:   Be verbose
@@ -51,20 +51,13 @@ $Date: 2013/03/14 23:39:39 $
    -change:     Test change
    -delete:     Test delete
 
-   -use|rname:  Username to open database with (Default: from config file) 
-   -p|assword:  Password to open database with (Default: from config file) 
-   -da|tabase:  Database to open (Default: from config file)
-   -db|set:     Database Set to use (Default: from config file)
-   -m|odule:    Type of Clearquest module to use. Must be one of 'api', 
-                'client', or 'rest'. The 'api' module can only be used if
-                Clearquest is installed locally. The 'client' module can only
-                be successful if a corresponding server is running. And the 
-                'rest' module can only be used if a CQ Web server has been set
-                up and configured (Default: rest)
-   -s|erver:    For module = client or rest this is the name of the server that
-                will be providing the service
-   -p|ort:      For module = client, this is the point on the server to talk
-                through.
+   -use|rname:  Username to open database with (Default: CQ_USERNAME or from
+                config file)
+   -p|assword:  Password to open database with (Default: CQ_PASSWORD or from
+                config file)
+   -da|tabase:  Database to open (Default: CQ_DATABASE or from config file)
+   -db|set:     Database Set to use (Default: CQ_DBSET or from config file)
+
 
 
 =head1 Options
@@ -113,166 +106,290 @@ Database Set name (Default: From cq.conf)
 
 use FindBin;
 use Getopt::Long;
+use Pod::Usage;
 
 use lib "$FindBin::Bin/../lib";
 
 use Clearquest;
+use Clearcase::View;
+use Clearcase::UCM::Activity;
+use Clearcase::UCM::Stream;
+use Clearcase::UCM::Project;
+use Clearcase::UCM::Pvob;
+use DateUtils;
 use Display;
+use Logger;
+use OSDep;
 use TimeUtils;
 use Utils;
 
-my ($cq, %opts);
+my ($cq, %opts, $log, $createView, $test_pvob, $test_project);
 
-sub displayRecord (%) {
+my $status  = 0;
+my $project = 'tc.project';
+
+sub displayRecord(%) {
   my (%record) = @_;
-  
-  display '-' x 79;
-  
-  foreach (keys %record) {
-    display_nolf "$_: ";
-  
+
+  $log->msg('-' x 79);
+
+  for (keys %record) {
+    $log->msg("$_: ", 1);
+
     if (ref $record{$_} eq 'ARRAY') {
-      display join ", ", @{$record{$_}};
+      $log->msg(join ", ", @{$record{$_}});
     } elsif ($record{$_}) {
-      display $record{$_};
+      $log->msg($record{$_});
     } else {
-      display "<undef>";
+      $log->msg('<undef>');
     } # if
-  } # foreach
-  
+  } # for
+
   return;
 } # displayRecord
 
-sub displayResults (@) {
+sub displayResults(@) {
   my (@records) = @_;
-  
+
   if (@records) {
     displayRecord %$_ foreach (@records);
   } else {
-    display "Did not find any records";
+    $log->msg('Did not find any records');
   } # if
-  
+
   return;
 } # displayResults
 
-sub testGetRecord ($$;@) {
+sub GetRecord($$;@) {
   my ($table, $key, @fields) = @_;
-  
-  my $startTime = time;
-  
-  display "Testing get table: $table key: $key";
-  
-  displayRecord $cq->get ($table, $key, @fields);
-  
-  display_duration $startTime;
-  
-  return;
-} # testGetRecord
 
-sub testFindRecord ($$;@) {
-  my ($table, $condition, @fields) = @_;
-  
-  my $startTime = time;
-  
-  display "Testing find table: $table condition: $condition";
-  
-  my ($result, $nbrRecs) = $cq->find ($table, $condition, @fields);
+  $log->msg("Gettng table: $table key: $key");
 
-  display "$nbrRecs records qualified";
+  my %record = $cq->get($table, $key, @fields);
 
-  while (my %record = $cq->getNext ($result)) {
+  if ($cq->checkErr) {
+       $log->err($cq->errmsg);
+  } else {
     displayRecord %record;
+  } # if
+
+  return $cq->error;
+} # GetRecord
+
+sub FindRecord($$;@) {
+  my ($table, $condition, @fields) = @_;
+
+  my $status;
+
+  $log->msg("Finding table: $table condition: $condition");
+
+  my ($result, $nbrRecs) = $cq->find($table, $condition, @fields);
+
+  $log->msg("$nbrRecs records qualified");
+
+  while (my %record = $cq->getNext($result)) {
+    unless ($cq->error) {
+      # Store away the createView.pl script location
+      $createView = $record{ws_cr_view} if $table eq 'Platform_Options';
+
+      displayRecord %record;
+
+      $status += $cq->error;
+    } # unless
   } # while
-  
-  display_duration $startTime;
-  
-  return;
-} # testFindRecord
 
-sub testModifyRecord ($$;%) {
+  return $status
+} # FindRecord
+
+sub ModifyRecord($$;%) {
   my ($table, $key, %update) = @_;
-  
-  my $startTime = time;
-  
-  display "Testing modify table: $table key: $key";
-  
-  $cq->modify ($table, $key, undef, \%update);
-  
-  $cq->checkErr;
-  
-  display_duration $startTime;
-  
-  return;
-} # testModifyRecord
 
-sub testChangeState ($$) {
-  my ($table, $key) = @_;
-  
-  my $startTime = time;
-  
-  my %record = $cq->get ($table, $key, ('State'));
-  
-  $cq->checkErr ("Unable to find $table where key = $key");
-    
-  return if $cq->error;
+  $log->msg("Modifying table: $table key: $key");
+
+  $cq->modify($table, $key, undef, \%update);
+
+  $log->err($cq->errmsg) if $cq->checkErr;
+
+  return $cq->error;
+} # ModifyRecord
+
+sub AssignWOR($) {
+  my ($key) = @_;
+
+  my %record = $cq->get('WOR', $key, ('State'));
+
+  return $cq->error if $cq->checkErr("Unable to find WOR where key = $key");
+
+  my ($action, %update);
+
+  if ($record{State} ne 'Submitted') {
+    $log->err("Cannot assign $key - not in submitted state");
+
+    return 1;
+  } # if
+
+  $action               = 'Assign';
+  $update{PlannedStart} = Today2SQLDatetime;
+  $update{ucm_project}  = $project;
+
+  $log->msg("Testing change WOR state of $key action: $action");
+
+  $cq->modify('WOR', $key, $action, \%update);
+
+  $log->err($cq->errmsg) if $cq->checkErr;
+
+  return $cq->error;
+} # AssignWOR
+
+sub ActivateWOR($) {
+  my ($key) = @_;
+
+  my %record = $cq->get('WOR', $key, ('State'));
+
+  return $cq->error if $cq->checkErr("Unable to find WOR where key = $key");
 
   my ($action, %update);
-  
-  if ($record{State} eq 'Assigned') {
-    $action                  = 'AdminAssignToSubmit';
-    $update{Stability_Issue} = 'User Fault';
+
+  if ($record{State} ne 'Assessing') {
+    $log->err("Cannot activate $key - not in Assessing state");
+
+    return 1;
+  } # if
+
+  $action = 'Activate';
+
+  $log->msg("Testing change WOR state of $key action: $action");
+
+  $cq->modify('WOR', $key, $action);
+
+  $log->err($cq->errmsg) if $cq->checkErr;
+
+  return $cq->error;
+} # ActivateWOR
+
+sub AddRecord($$;$$) {
+  my ($table, $record, $ordering, $returnField) = @_;
+
+  $returnField ||= 'id';
+
+  $log->msg("Adding table: $table");
+
+  my $dbid = $cq->add($table, $record, @$ordering);
+
+  if ($cq->checkErr) {
+    $log->err($cq->errmsg);
+
+    return;
   } else {
-    $action                  = 'Assign';
-    $update{Stability_Issue} = 'Assert';
+    my %record = $cq->getDBID($table, $dbid, ($returnField));
+
+    return $record{$returnField};
   } # if
-  
-  display "Testing change state table: $table key: $key action: $action";
-  
-  $cq->modify ($table, $key, $action, \%update);
-  
-  $cq->checkErr;
-  
-  display_duration $startTime; 
-  
-  return; 
-} # testChangeState
-
-sub testAddRecord ($%) {
-  my ($table, %record) = @_;
-  
-  my $startTime = time;
-  
-  display "Testing adding table: $table";
-  
-  $cq->add ($table, \%record, qw(Projects VersionStr));
-  
-  $cq->checkErr;
-  
-  display_duration $startTime;  
-  
-  return;
-} # testAddRecord
+} # AddRecord
 
-sub testDeleteRecord ($$) {
+sub DeleteRecord($$) {
   my ($table, $key) = @_;
-  
-  my $startTime = time;
-  
-  display "Testing deleting table: $table key: $key";
-  
-  $cq->delete ($table, $key);
-  
-  $cq->checkErr;
-
-  display_duration $startTime;
-  
-  return;
-} # testDeleteRecord
+
+  $log->msg("Deleting table: $table key: $key");
+
+  $cq->delete($table, $key);
+
+  $log->err($cq->errmsg) if $cq->checkErr;
+
+  return $cq->error;
+} # DeleteRecord
+
+sub CreateWOR() {
+  # Try to add a WOR - the following fields are required and some may need 
+  # to be added to stateless records in order for this to succeed. Once you
+  # can add a WOR through the  Clearquest client successfully you should be
+  # able to come up with the values of these  required fields. There are,
+  # however, sometimes when you need to specify ordering to have some fields
+  # set before other fields.
+  my %WOR = (
+    headline           => 'Test WOR',
+    description        => 'This is a test WOR created programmatically',
+    project            => 'MUOS',
+    RCLC_name          => 'Test RCLC',
+    Prod_Arch1         => 'testcode : N/A',
+    work_product_name  => '10 - Software',
+    #Engr_target        => 'Test Engineering Target',
+    work_code_name     => 'RAN-RW2',
+  );
+
+  return AddRecord('WOR', \%WOR, ['project', 'Prod_Arch1']);
+} # CreateWOR
+
+sub CreateView($) {
+  my ($WORID) = @_;
+
+  my ($status, @output) = Execute "$createView $WORID 2>&1";
+
+  $log->log($_) for @output;
+
+  return $status;
+} # CreateView
+
+sub Cleanup($) {
+  my ($WORID) = @_;
+
+  my ($status, @output) = (0, ());
+  my $rc = 0;
+
+  # Remove views created
+  my @tags = (
+    "$ENV{USER}_${project}_intview",
+    "$ENV{USER}_${WORID}_devview",
+  );
+
+  for (@tags) {
+    my $view = Clearcase::View->new($_);
+
+    $log->msg('Removing ' . $view->name);
+
+    ($rc, @output) = $view->remove;
+
+    $status++ if $rc;
+
+    $log->log($_) for @output;
+  } # for
+
+  # Remove streams that were created
+  my @streams = (
+    "$ENV{USER}_${WORID}_${project}_dev",
+  );
+
+  for my $stream (@streams) {
+    my $activity = Clearcase::UCM::Activity->new($WORID, $test_pvob);
+
+    $log->msg('Removing ' . $activity->name);
+
+    ($rc, @output) = $activity->remove;
+
+    $status += $rc;
+
+    $log->log($_) for @output;
+
+    # Streams are downshifted
+    my $stream = Clearcase::UCM::Stream->new(lc $stream, $test_pvob);
+
+    $log->msg('Removing ' . $stream->name);
+
+    ($rc, @output) = $stream->remove;
+
+    $log->log($_) for @output;
+
+    $status++ if $rc;
+  } # for
+
+  return $status;
+} # Cleanup
 
 ## Main
-GetOptions (
+GetOptions(
   \%opts,
-  usage   => sub { Usage },
+  usage   => sub { pod2usage },
+  help    => sub { pod2usage (-verbose => 2)},
   verbose => sub { set_verbose },
   debug   => sub { set_debug },
   'get',
@@ -280,27 +397,33 @@ GetOptions (
   'modify',
   'change',
   'delete',
-  'module=s',
   'username=s',
   'password=s',
   'database=s',
   'dbset=s',
-  'server=s',
-  'port=i',
-) || Usage;
+) || pod2usage;
 
 my $processStartTime = time;
 
+# Since we are creating private vobs (to avoid complications with having to
+# know and code the registry password when making public vobs), we'll simply
+# change $Clearcase::VOBTAG_PREFIX
+if ($ARCHITECTURE !~ /win/i) {
+  $Clearcase::VOBTAG_PREFIX = $ENV{TMP} || '/tmp';
+} # if
+
 local $| = 1;
 
 # Translate any options to ones that the lib understands
-$opts{CQ_USERNAME} = delete $opts{username};
-$opts{CQ_PASSWORD} = delete $opts{password};
-$opts{CQ_DATABASE} = delete $opts{database};
-$opts{CQ_DBSET}    = delete $opts{dbset};
-$opts{CQ_SERVER}   = delete $opts{server};
-$opts{CQ_PORT}     = delete $opts{port};
-$opts{CQ_MODULE}   = delete $opts{module};
+map {$opts{$_} = $Clearquest::OPTS{$_}} keys %Clearquest::OPTS;
+
+$opts{CQ_USERNAME} = delete $opts{username} if $opts{username};
+$opts{CQ_PASSWORD} = delete $opts{password} if $opts{password};
+$opts{CQ_DATABASE} = delete $opts{database} if $opts{database};
+$opts{CQ_DBSET}    = delete $opts{dbset}    if $opts{dbset};
+$opts{CQ_SERVER}   = delete $opts{server}   if $opts{server};
+$opts{CQ_PORT}     = delete $opts{port}     if $opts{port};
+$opts{CQ_MODULE}   = delete $opts{module}   if $opts{module};
 
 # If nothing is set then do everything
 unless ($opts{get}    or
@@ -318,69 +441,115 @@ $opts{add}    = 1 if $opts{delete};
 
 my $startTime = time;
 
-$cq = Clearquest->new (%opts);
+$log = Logger->new;
 
-display_nolf 'Connecting to Clearquest database ' . $cq->connection;
+$cq = Clearquest->new(%opts);
+
+$log->msg('Connecting to Clearquest database ' . $cq->connection . '...', 1);
 
 unless ($cq->connect) {
-  $cq->checkErr ('Unable to connect to database ' . $cq->connection);
-  
+  $cq->checkErr('Unable to connect to database ' . $cq->connection, undef, $log);
+
   if ($cq->module eq 'client') {
-    display 'Unable to connect to server '
-          . $cq->server ()
-          . ':'
-          . $cq->port ();
+    $log->msg('Unable to connect to server ' . $cq->server() . ':' . $cq->port());
   } # if
-  
+
   exit $cq->error;
 } else {
-  display '';
-  display_duration $startTime;
+  $log->msg('connected');
+  display_duration $startTime, $log;
 } # unless
 
-$cq->setOpts (emptyStringForUndef => 1);
+$cq->setOpts(emptyStringForUndef => 1);
 
+# Check a few required stateless records
 if ($opts{get}) {
   # Get record by key
-  testGetRecord 'Project', 'Athena';
+  $status += GetRecord 'Project', 'MUOS- EC';
 
   # Get record by condition
-  testFindRecord 'VersionInfo', 'Deprecated = 1';
-
-  # Get record by key with field list
-  testFindRecord 'VersionInfo', 'VersionStr = 1.0', ('VersionStr',   'Deprecated');
+  $status += FindRecord 'Platform_Options', 'Platform = "Unix"';
 
   # Get record by condition with field list
-  testFindRecord 'CategorySub', 'Category="Software"', ('Category', 'CategoryType', 'SubCategory');
+  $status += FindRecord 'Roles', 'Rank = "Supervisor"', ('user_name', 'teams.Name',   'Rank');
 } # if
 
 if ($opts{add}) {
-  # Add a record
-  testAddRecord    'VersionInfo', (
-    VersionStr => '2.0',
-    Projects   => ['Island', '21331', 'Hera'],
-    Visibility => 'Nokia Corporation',
+  my %component = (
+    Name        => $FindBin::Script,
+    Description => 'This is a test component',
   );
+
+  AddRecord('Component', \%component, undef, 'name');
+
+  $status++ if $cq->error;
 } # if
 
 if ($opts{modify}) {
   # Modify a record
-  testModifyRecord ('VersionInfo', '1.0', (
-    Deprecated => 1,
-    Projects   => ['Island', 'Athena'],
-  ));
+  my $newDescription = 'This is a modified test component';
+
+  $status += ModifyRecord('Component', $FindBin::Script, (Description => $newDescription));
+
+  # Make sure the modification happened
+  my %component = $cq->get('Component', $FindBin::Script, ('Description'));
+
+  $log->err('Modification of Component.Description failed!')
+    if $component{Description} ne $newDescription;
 } # if
 
+DeleteRecord 'Component', $FindBin::Script if $opts{add};
+
+$log->msg('Enable tc.project for integration with Clearquest');
+
+$test_pvob    = Clearcase::UCM::Pvob->new("${Clearcase::VOBTAG_PREFIX}tc.pvob");
+$test_project = Clearcase::UCM::Project->new('tc.project', 'tc.folder', $test_pvob);
+
+my ($rc, @output) = $test_project->change("-force -crmenable $opts{CQ_DATABASE}");
+
+$status += $rc;
+
+$log->log($_) for @output;
+
+$log->msg('Create WOR');
+
+my $WORID = CreateWOR;
+
+unless ($WORID) {
+  $status++;
+
+  exit $status;
+} else {
+  $log->msg("Created WOR $WORID");
+} # unless
+
 if ($opts{change}) {
-  # Change State
-  testChangeState 'Defect', 'apd00000034';
+  my $worStatus;
+
+  $worStatus += AssignWOR   $WORID;
+  $worStatus += ActivateWOR $WORID;
+
+  $status += $worStatus;
+
+  unless ($worStatus) {
+    # If we weren't able to assign and activate the WOR then there's no need
+    # to create the view and no need to clean up unless we created the view.
+    $worStatus = CreateView $WORID;
+
+    $status += Cleanup($WORID) unless $worStatus;
+
+    $status += $worStatus;
+  } # unless
 } # if
 
-if ($opts{add}) {
-  # Delete that record
-  testDeleteRecord 'VersionInfo', '2.0';
+if ($status) {
+  $log->err('Clearquest tests FAILED');
+} else {
+  $log->msg('Clearquest tests PASSED');
 } # if
 
-display_nolf 'Total process time ';
+$log->msg('Total process time ', 1);
+
+display_duration $processStartTime, $log;
 
-display_duration $processStartTime;
+exit $status;
old mode 100644 (file)
new mode 100755 (executable)
old mode 100755 (executable)
new mode 100644 (file)