Various changes and additions for UCM and testing things
authorAndrew DeFaria <Andrew@DeFaria.com>
Tue, 10 Apr 2018 02:59:32 +0000 (19:59 -0700)
committerAndrew DeFaria <Andrew@DeFaria.com>
Tue, 10 Apr 2018 02:59:32 +0000 (19:59 -0700)
39 files changed:
bin/allmach
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: 0755]
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/OSDep.pm
lib/Utils.pm
rc/bash_login
rc/clearcase
rc/clearcase.conf
rc/client_scripts/GD
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: 0755]
test/testclearcase.pl
test/testclearquest.pl
test/testspreadsheet.pl [changed mode: 0755->0644]
test/testspreadsheet.xls [changed mode: 0644->0755]

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
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 100755 (executable)
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..651d33c 100644 (file)
@@ -87,10 +87,10 @@ 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:\\IBMRational\\RationalSDLC\\Clearcase';
 
-    $CCHOME = 'D:\\Program Files\\Rational\\Clearcase'
+    $CCHOME = 'D:\\IBMRational\\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
@@ -580,7 +580,7 @@ Array of output lines from the cleartool command execution.
   # run as a plain user who does not have cleartool in their path.
   my $cleartool;
   
-  if ($ARCH =~ /Win/ or $ARCH eq 'cygwin') {
+  if ($ARCHITECTURE =~ /Win/ or $ARCHITECTURE eq 'cygwin') {
     $cleartool = 'cleartool';
   } elsif (-x '/opt/rational/clearcase/bin/cleartool') {
     $cleartool = '/opt/rational/clearcase/bin/cleartool';
@@ -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..cf765a2 100644 (file)
@@ -49,30 +49,24 @@ 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,15 +103,15 @@ 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
@@ -155,7 +149,7 @@ Returns:
   return $self->{name};
 } # name
 
-sub pvob () {
+sub pvob() {
   my ($self) = @_;
   
 =pod
@@ -193,14 +187,14 @@ 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 +202,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
 
@@ -247,35 +229,18 @@ Ouput from cleartool
 =for html </blockquote>
 
 =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}); 
+  $comment = Clearcase::_setComment $comment;
 
-  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(
+    "mkbl $comment $opts -view " . $view->tag . ' ' . $self->{name}
+  );
 } # create
 
-sub remove (\%) {
-  my ($self, %opts) = @_;
+sub remove($) {
+  my ($self, $opts) = @_;
 
 =pod
 
@@ -315,14 +280,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);
+  $opts ||= '';
   
-  return;
+  return $Clearcase::CC->execute(
+    "rmbl $opts -force " . $self->{name} . '@' . $self->{pvob}->name
+  ):
 } # remove
 
 sub attributes () {
@@ -362,13 +324,13 @@ 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
@@ -448,7 +410,7 @@ value.
     $cmd .= " -predeccsor";
   } # if
   
-  $Clearcase::CC->execute ($cmd);
+  $Clearcase::CC->execute($cmd);
   
   return if $Clearcase::CC->status;
   
@@ -456,13 +418,13 @@ value.
 
   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..640cecb
--- /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}->name);
+} # 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..26661a5
--- /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});
+} # 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..8db0f86
--- /dev/null
@@ -0,0 +1,342 @@
+=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}->name);
+} # rmProject
+
+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..496bee3 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,12 +88,12 @@ 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 () {
@@ -171,8 +172,8 @@ 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 baseline
+=item project
 
-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
+
+=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 
+    ('rmstream -f ' . $self->{name} . '@' . $self->{pvob}->name);
+} # rmStream
+
+sub rebase($;$) {
+  my ($self, $baseline, $opts) = @_;
+
+=pod
+
+=head2 rebase
 
-UCM Project this stream belongs to
+Rebases a UCM Stream
 
-=item PVOB (Required)
+Parameters:
 
-Project Vob
+=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,61 @@ Ouput from cleartool
 
 =cut
 
-  return $Clearcase::CC->execute 
-    ('rmstream -f ' . $self->{name} . "\@" . $self->{pvob});
-} # rmStream
+  $opts ||= '';
+
+  $opts .= ' -baseline ' . $baseline  .
+           ' -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 baselines () {
   my ($self) = @_;
@@ -356,15 +423,57 @@ An array of baseline objects for this stream
 
   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 +483,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..a31cb88 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
@@ -1402,9 +1407,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 +1615,7 @@ is also returned.
     
   my $query = $self->{session}->BuildQuery ($table);
   
-  foreach (@fields) {
+  for (@fields) {
     eval {$query->BuildField ($_)};
     
     if ($@) {
@@ -1618,7 +1623,7 @@ is also returned.
       
       carp $@;
     } # if
-  } # foreach
+  } # for
 
   $self->_parseConditional ($query, $condition);
 
@@ -1762,7 +1767,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 +1781,7 @@ Hash of name/value pairs for all the fields in $table
         $record{$_} = _UTC2Localtime ($record{$_});
       } # if
     } # if
-  } # foreach
+  } # for
 
   $self->_setError;
   
@@ -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
 
@@ -2324,7 +2333,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 +2341,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 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";
index c8807d0..39677cc 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,15 @@ 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
+  TERM=xterm
 fi
 
 # Set colors
@@ -90,14 +93,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 +147,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 +220,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 +304,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..3317a01 100644 (file)
@@ -4077,36 +4077,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}
index fb2993c..2d00db9 100644 (file)
@@ -27,9 +27,9 @@ 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
+export PERL5LIB=/cleartrig/ent/SNSD/muos/ccadm_tools/vobs/ranccadm/scripts/lib:$PERL5LIB
 
 export TZ="US/Arizona"
 
@@ -37,7 +37,7 @@ 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"
+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"
 
 alias xemacs="ssh muosbldforge2 xemacs"
 
@@ -46,9 +46,17 @@ export EDITOR="ssh muosbldforge2 xemacs"
 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
+
+# Additional paths...
+append_to_path "/c/Program Files/IBM/RationalSDLC/common"
+append_to_path "/d/Program Files/IBM/RationalSDLC/common"
+append_to_path "/c/Program Files/IBM/RationalSDLC/Clearquest/cqcli/bin"
+append_to_path "/d/Program Files/IBM/RationalSDLC/Clearquest/cqcli/bin"
+append_to_path "/c/Program Files/IBM/RationalSDLC/ClearCase/bin"
+append_to_path "/d/Program Files/IBM/RationalSDLC/ClearCase/bin"
old mode 100755 (executable)
new mode 100644 (file)
index 88a4ba0..1f8dcdc 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,17 +114,18 @@ 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" = "xterm"          -o \
+         "$TERM" = "xtermc"         -o \
+         "$TERM" = "xterm-256color" -o \
+         "$TERM" = "vt220" ]; then
+      ROOT="\[${ROOT_COLOR}\]Wizard\[$NORMAL\] "
+    else
+      ROOT="Wizard "
     fi
   else
     ROOT=""
@@ -131,9 +133,10 @@ function set_prompt {
 
   if [ "$TERM" = "vt100"          -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..b9e5425 100644 (file)
@@ -30,28 +30,30 @@ 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" = "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..10a4179 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\
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 100755 (executable)
index 0000000..c240d95
--- /dev/null
@@ -0,0 +1,21 @@
+################################################################################
+#
+# 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:               view2
+viewpath:               /net/$viewhost
+viewstore:              $viewpath/local/view2c
index f0cfde9..42e3152 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)
+
+=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 Getopt::Long;
 use Term::ANSIColor qw(:constants);
 
-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 (@ucmobjs, $order);
+
+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 ($vbs, $vws, %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) {
+    if (ref $opts{$_} eq 'ARRAY') {
+      my $name = $_;
+      $log->msg("$name:\t$_") for (@{$opts{$_}});
+    } else {
+      $log->msg("$_:\t$opts{$_}");
+    }  # 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);
+
+  push @ucmobjs, $pvob unless $status;
+
+  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->msg('Unmounting vob ' . $vob->tag);
+
+  ($status, @output) = $vob->umount;
+
+  $log->msg('Removing vob ' . $vob->tag);
+
+  ($status, @output) = $vob->remove;
+
+  $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");
 
-my ($status, @output) = $Clearcase::CC->execute ('-ver');
+  $log->log($_) for (@output);
 
-error 'Clearcase is not installed on this system', 1
-  if $status;
+  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 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
   
-display YELLOW . "Global Clearcase Variables\n" . RESET;
+  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 $status = 0;
+
+  # Need to remove UCM objects in the opposite order in which we created them
+  for (reverse @ucmobjs) {
+    my ($rc, @output);
+
+    if (ref $_ eq 'Clearcase::UCM::Pvob') {
+      $log->msg('Removing Pvob ' . $_->tag);
+
+      $status += DestroyVob $_;
+    } else {
+      $log->msg('Removing ' . ref ($_) . ' ' . $_->name);
+
+      ($rc, @output) = $_->remove;
+
+      $status += $rc;
+    } # if
+  } # for
+
+  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");
+
+  if ($status != 0) {
+    $log->log($_) for (@output);
+  } # if
+
+  return $status;
+} # SetupTest
+
+sub SetupUCMTest() {
+  my $status;
+
+  $log->msg("Creating UCM Pvob $Clearcase::VOBTAG_PREFIX/tc.pvob");
+
+  ($status, $test_pvob) = CreatePvob("$Clearcase::VOBTAG_PREFIX/tc.pvob"); 
+  
+  return $status;
+} # SetupUCMTest
+
+sub CreateUCMProject() {
+  # Get the root folder to put this project into (may create folders later)
+  my $folder = Clearcase::UCM::Folder->new('tc.folder', $test_pvob);
+
+  $test_project = Clearcase::UCM::Project->new('tc.project', $folder, $test_pvob);
+
+  $log->msg('Creating UCM Project tc.project');
+
+  my ($status, @output) = $test_project->create();
+
+  $log->log($_) for (@output);
+
+  push @ucmobjs, $test_project unless $status;
+
+  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);
+
+  push @ucmobjs, $test_intstream unless $status;
+
+  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);
+
+  push @ucmobjs, $test_devstream unless $status;
+
+  return $status;
+} # CreateUCMIntStream
+
+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);
+
+  push @ucmobjs, $test_component unless $status;
+
+  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);
+
+  push @ucmobjs, $test_intview unless $status;
+
+  $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);
+
+  push @ucmobjs, $test_devview unless $status;
+
+  $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);
+
+  push @ucmobjs, $test_baseline unless $status;
+
+  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);
+
+  push @ucmobjs, $test_activity unless $status;
+
+  return $status;
+} # CreateUCMActivity
+
+sub RebaseStream($$;$) {
+  my ($stream, $baseline, $opts) = @_;
+
+  my ($status, @output) = $stream->rebase($baseline, $opts);
+
+  $log->log($_) for (@output);
+
+  return $status;
+} # RebaseStream
+
+sub RecommendBaseline($) {
+  my ($baseline) = @_;
+
+  my ($status, @output) = $test_intstream->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 += CreateUCMDevView;
+  $status += CreateUCMComponent;
+  $status += AddModifiableComponent;
+  $status += RebaseStream($test_intstream, 'tc.component_INITIAL', '-complete');
+  $status += RecommendBaseline('tc.component_INITIAL');
+  $status += CreateUCMBaseline;
+  $status += RebaseStream($test_devstream, 'tc.baseline', '-complete');
+  $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{base}  = 1;
+$opts{clean} = 1;
+
+GetOptions(
+  \%opts,
+  'verbose' => sub { set_verbose },
+  'debug'   => sub { set_debug },
+  'usage'   => sub { Usage },
+  'config=s',
+  'base!',
+  'ucm!',
+  'clean!',
+) 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
+for (keys %default_opts) {
+  $opts{$_} = $default_opts{$_} if !$opts{$_};
+} # for
+
+$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
+$Clearcase::VOBTAG_PREFIX = $ENV{TMP} || '/tmp';
+
+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} and !$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>
+
+L<FindBin>
+
+L<Getopt::Long|Getopt::Long>
+
+L<Term::ANSIColor|Term::ANSIColor>
 
-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..9870e21 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env cqperl
 use strict;
 use warnings;
 
@@ -118,27 +118,28 @@ use lib "$FindBin::Bin/../lib";
 
 use Clearquest;
 use Display;
+use Logger;
 use TimeUtils;
 use Utils;
 
-my ($cq, %opts);
+my ($cq, %opts, $log);
 
 sub displayRecord (%) {
   my (%record) = @_;
   
-  display '-' x 79;
+  $log->msg ('-' x 79);
   
-  foreach (keys %record) {
-    display_nolf "$_: ";
+  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
@@ -149,7 +150,7 @@ sub displayResults (@) {
   if (@records) {
     displayRecord %$_ foreach (@records);
   } else {
-    display "Did not find any records";
+    $log->msg ('Did not find any records');
   } # if
   
   return;
@@ -160,11 +161,11 @@ sub testGetRecord ($$;@) {
   
   my $startTime = time;
   
-  display "Testing get table: $table key: $key";
+  $log->msg ("Testing get table: $table key: $key");
   
   displayRecord $cq->get ($table, $key, @fields);
   
-  display_duration $startTime;
+  display_duration $startTime, $log;
   
   return;
 } # testGetRecord
@@ -174,17 +175,17 @@ sub testFindRecord ($$;@) {
   
   my $startTime = time;
   
-  display "Testing find table: $table condition: $condition";
+  $log->msg ("Testing find table: $table condition: $condition");
   
   my ($result, $nbrRecs) = $cq->find ($table, $condition, @fields);
 
-  display "$nbrRecs records qualified";
+  $log->msg ("$nbrRecs records qualified");
 
-  while (my %record = $cq->getNext ($result)) {
+  while (my %record = $cq->getNext($result)) {
     displayRecord %record;
   } # while
   
-  display_duration $startTime;
+  display_duration $startTime, $log;
   
   return;
 } # testFindRecord
@@ -194,13 +195,13 @@ sub testModifyRecord ($$;%) {
   
   my $startTime = time;
   
-  display "Testing modify table: $table key: $key";
+  $log->msg ("Testing modify table: $table key: $key");
   
   $cq->modify ($table, $key, undef, \%update);
   
   $cq->checkErr;
   
-  display_duration $startTime;
+  display_duration $startTime, $log;
   
   return;
 } # testModifyRecord
@@ -226,13 +227,13 @@ sub testChangeState ($$) {
     $update{Stability_Issue} = 'Assert';
   } # if
   
-  display "Testing change state table: $table key: $key action: $action";
+  $log->msg ("Testing change state table: $table key: $key action: $action");
   
   $cq->modify ($table, $key, $action, \%update);
   
   $cq->checkErr;
   
-  display_duration $startTime; 
+  display_duration $startTime, $log
   
   return; 
 } # testChangeState
@@ -242,13 +243,13 @@ sub testAddRecord ($%) {
   
   my $startTime = time;
   
-  display "Testing adding table: $table";
+  $log->msg ("Testing adding table: $table");
   
-  $cq->add ($table, \%record, qw(Projects VersionStr));
+  $cq->add ($table, \%record);
   
   $cq->checkErr;
   
-  display_duration $startTime;  
+  display_duration $startTime, $log;
   
   return;
 } # testAddRecord
@@ -258,13 +259,13 @@ sub testDeleteRecord ($$) {
   
   my $startTime = time;
   
-  display "Testing deleting table: $table key: $key";
+  $log->msg ("Testing deleting table: $table key: $key");
   
   $cq->delete ($table, $key);
   
   $cq->checkErr;
 
-  display_duration $startTime;
+  display_duration $startTime, $log;
   
   return;
 } # testDeleteRecord
@@ -318,57 +319,61 @@ $opts{add}    = 1 if $opts{delete};
 
 my $startTime = time;
 
+$log = Logger->new;
+
 $cq = Clearquest->new (%opts);
 
-display_nolf 'Connecting to Clearquest database ' . $cq->connection;
+$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 ('');
+  display_duration $startTime, $log;
 } # unless
 
 $cq->setOpts (emptyStringForUndef => 1);
 
 if ($opts{get}) {
   # Get record by key
-  testGetRecord 'Project', 'Athena';
+  testGetRecord 'WOR', 'XTST100000019'; 
 
   # Get record by condition
-  testFindRecord 'VersionInfo', 'Deprecated = 1';
+  testFindRecord 'WOR', 'Owner = "ccadm"';
 
   # Get record by key with field list
-  testFindRecord 'VersionInfo', 'VersionStr = 1.0', ('VersionStr',   'Deprecated');
+  testFindRecord 'WOR', 'Owner = "ccadm"', ('id', 'Headline',   'Owner');
 
   # Get record by condition with field list
-  testFindRecord 'CategorySub', 'Category="Software"', ('Category', 'CategoryType', 'SubCategory');
+  testFindRecord 'WOR', 'Owner = "ccadm"', ('id', 'Headline', 'Owner');
 } # if
 
 if ($opts{add}) {
   # Add a record
-  testAddRecord    'VersionInfo', (
-    VersionStr => '2.0',
-    Projects   => ['Island', '21331', 'Hera'],
-    Visibility => 'Nokia Corporation',
+  testAddRecord    'Component', (
+    Name          => $FindBin::Script,
+    Description   => 'This is a test component',
   );
 } # if
 
 if ($opts{modify}) {
   # Modify a record
-  testModifyRecord ('VersionInfo', '1.0', (
-    Deprecated => 1,
-    Projects   => ['Island', 'Athena'],
-  ));
+  my $newDescription = 'This is a modified test component';
+
+  testModifyRecord ('Component', $FindBin::Script, (Description => $newDescription));
+
+  # Make sure the modification happened
+  my %component = $cq->get ('Component', $FindBin::Script, ('Description'));
+
+  if ($component{Description} ne $newDescription) {
+    $log->err ('Modification of Component.Description failed!');
+  } # if
 } # if
 
 if ($opts{change}) {
@@ -378,9 +383,9 @@ if ($opts{change}) {
 
 if ($opts{add}) {
   # Delete that record
-  testDeleteRecord 'VersionInfo', '2.0';
+  testDeleteRecord 'Component', $FindBin::Script;
 } # if
 
-display_nolf 'Total process time ';
+$log->msg ('Total process time ', 1);
 
-display_duration $processStartTime;
+display_duration $processStartTime, $log;
old mode 100755 (executable)
new mode 100644 (file)
old mode 100644 (file)
new mode 100755 (executable)