![]() |
![]() |
![]() |
![]() |
ClearCase: The Ten Best Scripts | ![]() | ||||||||||||||||||||||||||||
![]() | ||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||
Introduction
Rational ClearCase is a Software Configuration Management tool that benefits both small and large software development teams. The complexity of the tool, and the fact that individual developers use it in different ways, can make the life of a Software Configuration Manager quite difficult. Over the last few years I've performed many implementations and presentations with ClearCase. I've observed that even though every project is unique, and each organization has its own approach to solving problems, the same questions about ClearCase usage always come up. Since I didn't want to reinvent the wheel for every project, I collected some of the most useful scripts that I've used during implementations. I made these as generic as possible to increase their applicability across projects. The practice has helped me immensely: I now have a collection of scripts that I can easily use to answer recurring questions about ClearCase usage. This document describes the 10 most useful scripts, which should help make the daily work of a Software Configuration Manager less complicated. Usage
A word of caution: All the scripts described in this document are delivered "as is." There is no official support offered by Rational Software for these scripts. All my scripts were developed in one of three languages: either directly as shell / batch, in Perl, or using the ClearCase API (CAL). I am not a Perl expert, and you will immediately see that my Perl language knowledge is limited, but hopefully these scripts are easy to understand. Nor am I a Visual Basic expert, and after looking over my VB programs you may get the feeling that they could be rewritten in a more optimized way. In any case, feel free to contact me with either your comments or suggestions for improvements that you would like to see in these scripts. The 10 Best Scripts
In this section, we will see the list of the 10 best scripts I have come across in my daily work as a Rational Consultant. I did not personally write all of these scripts. Some of them where written by my Rational TechRep colleagues around the world, so I want to thank all of them for their great contributions and hard work. Special thanks to:
General Considerations
Before writing a script, I always ask myself: what functionality would the user like to achieve? Does she want an improvement in her daily work processes, or just to be able to spend less time on some basic task? After answering these first questions, the next ones I ask myself are about which "language" to use. For this, I have three approaches:
While writing scripts or ClearCase commands, I constantly remind myself that the cleartool command line is my friend; it works the same on UNIX and Windows. Learning all the commands, options, and functionalities has made my life a lot easier. My second best friend while writing scripts is the cleartool man command, which invokes the ClearCase reference manual. There is no better place to get a description of all the command options, and there are always some examples of how commands are used available at the end of the manual pages. I use many cleartool commands infrequently, but there are a few of them I use over and over again, such as cleartool find, cleartool describe, and cleartool lstype. What is also very useful about cleartool commands is that some of them have an -fmt option that formats strings for command output, which is a good way to extract the information you need without many "grep" or "sed" or "awk" statements. For more details about the -fmt option, run a cleartool man fmt_ccase command. As you know, most Windows users do not like to use the old MSDOS command shell. They prefer to have nice GUIs, displaying their work with lots of colors and icons, and for this reason the Clearprompt command is another big friend of mine: it can ask for simple information via the GUI (Windows Explorer or ClearCase Details). Cleartool find . -all
The simplest script that you can write with ClearCase is actually just using the cleartool find command. This command has an -exec option, giving you the ability to invoke an action based on the search results. However, when I am writing a find request I use an iterative process, to ensure that I write the correct command. Since I know that the complexity of this command is pretty high, I prefer to execute steps sequentially, and make improvements after each step, before reaching my final command. Let's use an example (from the cleartool manual) about the cleartool find command. As you can see, I modify the query slowly, to refine my search as I get more information:
Finally, we are using the -all option because by default, the find command only considers the elements that you can actually "see" in your view. With the -all option, I ensure that I am considering every element in the VOB, whether I can see it or not. Cleartool find . -all examples
Here are some examples of cleartool find . -all commands:
Scripts to Recursively checkin / checkout / add
to source control
One of the first questions new ClearCase users ask is: how is it possible to check out or check in all the elements behind a directory recursively, using the ClearCase / Windows Explorer integration? I find myself asking why they would like such functionality. Typically, they have used tools like RCS or CVS, where you need to get a copy of the files to be able to access them (that is, you need to check out all the files). However, there are times when you need to check out or check in everything because your favorite IDE does not accept files that have the "read only" attributes. Here are my solutions. 1. Recursively Check Out and Check In
Checkout
Caution: You need to have local administration rights to be able to customize a ClearCase menu. Start the clearmenuadmin.exe utility, For the check out recursively option, do the following:
When this is done, you can add this new menu entry to the This menu contents pane by pressing the Add button. Position it as desired with the Move up button. After completing this customization, choose Configuration>Apply to apply the changes. Then you can test it in Windows Explorer. Checkin
Caution: You need to have local administration rights to be able to customize a Clearcase menu. Start the clearmenuadmin.exe utility, For the check in recursively option, do the following:
When this is done, you can add this new menu entry to the This menu contents pane by pressing the Add button. Position it as desired with the Move up button. After completing this customization, choose Configuration>Apply to apply the changes. Then you can test it in Windows Explorer. 2. Recursively Add to source control
These two recursive checkout or checkin script / customizations are great, but one customer gave me this additional challenge: also do a recursive add to source control. For me, a recursive add to source control would mean executing clearexport_ffile and clearimport over the command line as the fastest method. Again, though, this was a challenge, so I developed this small script to do the job. Add-to-src-control.bat
These are the contents of the add-to-src-control.bat script: @rem= 'PERL for Windows NT -- ccperl must be in search path
@echo off
ccperl %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
@rem ';
###########################################
# Begin of Perl section
$start_dir = $ARGV\\\\[0\\\\];
#
# Fixed variable
#
$S = "\\";
$list_file = "c:".$S."list_file";
$list_add = "c:".$S."list_add";
$choosed = "c:".$S."choosed";
sub clean_file
{
$status = system("del $list_file > NUL 2> NUL");
$status = system("del $list_add > NUL 2> NUL");
$status = system("del $choosed > NUL 2> NUL");
}
#
# Start of the script...
#
printf("add-to-src-control $start_dir...\n");
clean_file();
$status = system("cleartool ls -view_only -r -s $start_dir > $list_file");
open(LIST_ELEMENT,$list_file);
while ($element=<LIST_ELEMENT>)
{
chop $element;
# printf " Processing $element ";
if ($element =~ /CHECKEDOUT/)
{
# printf(" checkedout file \n");
}
else
{
# printf " view private \n";
printf " Processing $element ...\n";
#
# For files with spaces...
#
if ($element =~ / /)
{
$status = system("cmd /c echo \"$element\" >> $list_add");
}
else
{
$status = system("cmd /c echo $element >> $list_add");
}
}
}
close(LIST_ELEMENT);
if (-e $list_add)
{
$listelement = `type $list_add`;
$listelement =~ s/\n/,/g;
$status = `echo $listelement > $list_add`;
$status = system("clearprompt list -outfile $choosed -dfile $list_add -choices
-prompt \"Choose element(s) to put over version control : \" -prefer_gui");
if ($status != 0)
{
# printf("\n Aborting ...\n");
clean_file();
exit $status;
}
#
$listtoadd = `type $choosed`;
$listtoadd =~ s/\n//g;
printf("\n cleardlg /addtosrc $listtoadd");
$status = system("cleardlg /addtosrc $listtoadd");
clean_file();
exit $status;
}
else
{
# printf("\n No files founded...\n");
clean_file();
exit $status;
}
# End of Perl section
__END__
:endofperl
Installation
Caution: you must have local administration rights to be able to customize a ClearCase menu. Put the add-to-src-control.bat file in your normal script directory. Customize the ClearCase Explorer Menu integration by doing the following:
When this is done, you can add this new menu entry to the This menu contents pane by pressing the Add button. Position it as desired with the Move up button. Also add the menu entries for:
After completing this customization, choose Configuration>Apply to apply the changes. Then you can test it in Windows Explorer. Usage
In the ClearCase-Windows Explorer integration, you will then have a menu entry called "Add to source control (recursively)..."
When you select this item, you will see the following output window:
In this window, you can then select one or more files to put under version control:
In the background, the following window will be displayed:
At this point, you can insert comments about adding the files to version control:
Problems not solved
The trigger script does not work with empty files. If the file you are trying to put under version control is empty, then the following error message is displayed:
Scripts to Remove Old Files
3. Remove old view
\\\\[Many thanks Eric J. Ostrander and Schindler Lift AG\\\\] After using ClearCase for a few years or even months, thousands of views accumulate, and nobody has a clue what they are for. Cleaning up unused views is one of the main tasks facing the ClearCase administrator. But which views do you delete? How do you inform the user that his view will be destroyed? Eric Ostrander once wrote some scripts to delete any view that was not used for 30 days. I delivered them to my customer Schindler Lift, but they felt that just "removing old views" without any notice was not correct; they wanted to send an e-mail to the view's owner first. So I rewrote the script to send an e-mail to the view owner, via the notify.exe utility. Search_view.bat
Here is the script: @rem= 'PERL for Windows NT -- ccperl must be in search path
@echo off
ccperl %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
@rem ';
#
# Views last accessed since 30 days...
#
$days = 30;
#
# ----------------------------
#
if ($ENV{TEMP})
{
$TDIR=$ENV{TEMP};
}
else
{
$TDIR="c:${S}temp";
}
$S = "\\";
$JUNK = $TDIR . $S . "junk";
$NULL = $TDIR . $S . "null";
# Begin of Perl section
printf("Start of the script...\n");
if ($ARGV\\\\[0\\\\] eq "")
{
printf "\n No user specify, please give one !!! \n";
exit 1;
}
$search_user = $ARGV\\\\[0\\\\];
printf("Searching for all views that hasn't been accessed since $days days for
$search_user \n");
chomp(@views = `cleartool lsview -s | findstr $search_user`);
foreach $viewtag (@views)
{
printf("Processing $viewtag: ");
# Determine the last accessed date and owner for the view.
chomp(@properties = `cleartool lsview -properties -full $viewtag`);
foreach $property (@properties)
{
$accessed_line = $property if ( $property =~ /^Last accessed / );
$owner_line = $property if ( $property =~ /^Owner: / );
}
$last_accessed = (split(/\./,(split(/ +/,$accessed_line))\\\\[2\\\\]))\\\\[0\\\\];
($view_day,$view_month,$view_year) = split(/-/,$last_accessed);
$owner = (split(/\\/,(split(/ +/,$owner_line))\\\\[1\\\\]))\\\\[1\\\\];
# Build the view's date string for use with the since.pl script.
if ( $view_year > 80 )
{
$view_year = "19$view_year";
}
else
{
$view_year = "20$view_year";
}
$view_date = "$view_month $view_day $view_year";
# Find out how long ago the view was last accessed. If greater
# than the specified number of days, print out the data.
$diff_days = `ccperl .\\since.pl $view_date $now_date`;
if ( $diff_days > $days )
{
printf("$owner $last_accessed\n");
printf("\t Sending notification for view $viewtag to $owner \n");
system("cmd /c del $JUNK 2> $NULL");
system("echo .
> $JUNK");
system("echo Hello, $owner...
>> $JUNK");
system("echo .
>> $JUNK");
system("echo Your view $viewtag hasnt been used since $days days !!!
>> $JUNK");
system("echo .
>> $JUNK");
system("echo Please check if you still need this view... >>
$JUNK");
system("echo .
>> $JUNK");
system("echo If not, please delete it !
>> $JUNK");
system("echo .
>> $JUNK");
system("echo If not done/used in the next 30 days, it will be
>> $JUNK");
system("echo automatically deleted without notice >>
$JUNK");
system("echo .
>> $JUNK");
system("echo S. Aeschbacher and D. Diebolt
>> $JUNK");
system("echo .
>> $JUNK");
system("notify -s \"View $viewtag...\" -f $JUNK $owner\@rational.com");
system("notify -s \"View $viewtag...\" -f $JUNK ddiebolt\@rational.com");
push(@old_views,"$viewtag");
}
else
{
printf("\n");
}
}
printf("End of the script...\n");
# End of Perl section
__END__
:endofperl
This script uses the since.pl module (following). Since.pl #!/usr/local/bin/perl
# Determine the number of days since a certain date
# or between two dates.
# It will return a -1 if there is something wrong with
# your input values.
# 1.0 11/23/1998 Eric J. Ostrander Created.
# 1.1 09/19/1999 Eric J. Ostrander Modified to calculate days between any two
# arbitrary dates.
# Predefinitions.
@months = split(/ +/,"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
@mlength = split(/ +/,"31 28 31 30 31 30 31 31 30 31 30 31 ");
# Are there the correct number of arguments?
if ( scalar(@ARGV) != 3 && scalar(@ARGV) != 6 ) {
print "Usage: since month day year \\\\[ month day year \\\\]\n";
print " since from-date to-date\n";
print " ex: since Apr 15 1962 Sep 30 1963\n";
print "If to-date is omitted, today's date is assumed.\n";
exit;
}
# What is the from-date?
$req_month = $ARGV\\\\[0\\\\];
$req_day = $ARGV\\\\[1\\\\];
$req_year = $ARGV\\\\[2\\\\];
# What is the to-date?
if ( scalar(@ARGV) == 6 ) {
$month = $ARGV\\\\[3\\\\];
$day = $ARGV\\\\[4\\\\];
$year = $ARGV\\\\[5\\\\];
} else {
($x,$month,$day,$x,$year) = split(/ /,localtime(time));
}
# Is the requested date valid?
$bad = 1;
$i = 0;
foreach $mon (<@months> ) {
if ( "$req_month" eq "$mon" ) { $req_ind = $i; $bad = 0 }
if ( "$month" eq "$mon" ) { $mon_ind = $i }
$i = $i + 1;
}
if ( $req_day > $mlength\\\\[$req_ind\\\\] || $req_year > $year ) { $bad = 1; }
if ( $req_year == $year && $req_ind >= $mon_ind && $req_day > $day ) { $bad = 1; }
if ( $bad == 1 ) { print "-1\n"; exit; }
# Calculate days from Jan. 1, $req_year to today's date.
CALC_DAYS();
$to_days = $days;
# Calculate days from Jan. 1, $req_year to requested date.
$month = $req_month;
$day = $req_day;
$year = $req_year;
CALC_DAYS();
$from_days = $days;
# Subtract the two.
print $to_days - $from_days . "\n";
# The iteration subroutine.
sub CALC_DAYS {
$yr = $req_year;
$days = 0;
ITERATION: while (1) {
$i = 0;
$lpyr = 0;
if ( $yr/4 == int($yr/4) && $yr != 2000 ) { $lpyr = 1; }
foreach $mon (<@months>) {
if ( "$mon" eq "$month" && $yr == $year ) {
$days = $days + $day;
last ITERATION;
} else {
$days = $days + @mlength\\\\[$i\\\\];
if ( "$mon" eq "Feb" ) { $days = $days + $lpyr; }
}
$i = $i + 1;
}
$yr = $yr + 1;
}
}
exit;
Usage
Simply start the search_view.bat file with a username as a parameter. Example:
Enter Z:\cc_tools\batch\RmOldView>search_views.bat ddiebolt and the script starts: Searching for all views that haven't been accessed for 30 days
for ddiebolt
Processing ddiebolt_UCM_Release_3.0_integration:
Processing ddiebolt_test: ddiebolt 12-Jun-02
Sending notification for view ddiebolt_test to ddiebolt
4. Remove view private file
Users create view private files over and over again, filling up the view-storage directory with useless files that you (the administrator) must now clean up. You may also simply want to clean up your views, removing old objects, executables, and so on. Removing the whole view and recreating a new one is just not the solution. Saving the view private files that you want to keep to another location, and then copying them back after creating the new view, is also not the answer. In place of these cumbersome solutions, I've created an elegant script, rmviewprivate.bat, which selects the files to delete and performs the task of cleaning up your views. Rmviewprivate.bat
Here is the script: @rem= 'PERL for Windows NT -- ccperl must be in search path
@echo off
ccperl %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
@rem ';
if ($ENV{TEMP})
{
$TDIR=$ENV{TEMP};
}
else
{
$TDIR="c:${S}temp";
}
$S = "\\";
$LIST_VIEW_ONLY = $TDIR . $S . "list_view_only";
$LIST_SELECTED = $TDIR . $S . "list_selected";
sub do_del_file
{
local($file_to_delete) = @_\\\\[0\\\\];
if (-e $file_to_delete)
{
printf("del \"$file_to_delete\" \n");
$return = system("cmd /c del \"$file_to_delete\"");
}
}
sub do_del_directory
{
local($dir_to_delete) = @_\\\\[0\\\\];
printf("rmdir \/q \/s \"$dir_to_delete\" \n");
$return = system("cmd /c rmdir \/q \/s \"$dir_to_delete\"");
}
# Begin of Perl section
printf("\n Start of the script \n\n");
if ($ARGV\\\\[0\\\\] eq "")
{
printf("\n No directory specified, will use .\n");
$start_dir = ".";
}
else
{
$start_dir = $ARGV\\\\[0\\\\];
}
if (!(-d $start_dir))
{
printf("\n $start_dir is not a directory !!! \n");
exit 1;
}
system("cmd /c del $LIST_VIEW_ONLY 2> NUL");
printf("\n cleartool ls -recurse -view_only $start_dir \n");
chomp(@list_files = `cleartool ls -recurse -view_only $start_dir`);
foreach $file (@list_files)
{
if ( $file =~ /CHECKEDOUT/ )
{
$is_checkedout = $file;
}
else
{
$is_checkedout = "";
}
# printf("\n Processing $file : $is_checkedout \n");
if ("$is_checkedout" eq "")
{
system("cmd /c echo $file, >> $LIST_VIEW_ONLY");
}
}
if (-e $LIST_VIEW_ONLY)
{
$return = system("clearprompt list -outfile $LIST_SELECTED -dfile
$LIST_VIEW_ONLY -choices -prompt \"Please choose files \/ directory to delete\"");
}
else
{
$return = 512;
}
if ("$return" eq "0")
{
open(LIST_ELEMENT,$LIST_SELECTED);
while ($element=<LIST_ELEMENT>)
{
chop $element;
if (!("$element" eq ""))
{
if (-d $element)
{
#printf(" $element is a directory\n");
do_del_directory($element);
}
else
{
#printf(" $element is a file\n");
do_del_file($element);
}
}
}
close(LIST_ELEMENT);
}
system("cmd /c del $LIST_VIEW_ONLY 2> NUL");
system("cmd /c del $LIST_SELECTED 2> NUL");
printf("\n End of the script \n");
# End of Perl section
__END__
:endofperl
Usage
Here is an example of the script in action: Z:\rdn>rmviewprivate.bat
Z:\cc_tools\batch\RmViewPrivate>rmviewprivate.bat
Start of the script
No directory specified, will use .
cleartool ls -recurse -view_only .
del "rmviewprivate.zip"
End of the script
Z:\cc_tools\batch\RmViewPrivate>
You will then see the following window:
Other Administrative Scripts
The Send To menu entry is available in many interfaces: Windows Explorer, ClearCase Explorer, the ClearCase VersionTree Browser, and so on. When using the Version Tree Browser, it is sometimes quite useful to be able to edit an older version (that is, select a version and be able to see its contents). Since we can customize the Send To menu by adding a shortcut, we can easily get this functionality. Adding a Shortcut
Use the following steps to add a shortcut:
Of course, you can also add several other shortcuts: WordPad, Word, ... 5. Send to mkbranch
A ClearCase UNIX user was once complaining to me that the ClearCase GUI utility in UNIX, xclearcase, was "twenty times better" than the Windows one, with more functionality, options, and possibilities available. I asked for an example: what is missing in Windows, but available in Unix? The answer was that you could do an "mkbranch" in the UNIX Version Tree Browser. Then, a few months ago, a new colleague (Benoit Lorendeaux) started at Rational Software Switzerland. He also asked for this functionality. As a challenge, I asked him to create this functionality in Windows. Here is his solution: Installation
We can reuse the concept of customizing the "send to" menu. However, instead of invoking notepad, we will start the following script. Example: execute this command: ccperl script %1Script $version = $ARGV\\\\[0\\\\];
@VOB_list=`cleartool lsVOB -s`;
$index = 0;
$choix = "";
while ($VOB_list\\\\[$index\\\\] ne "") {
# printf($VOB_list\\\\[$index\\\\]);
chomp($choix);
if ($index == 0){
$choix .= $VOB_list\\\\[$index\\\\];
} else {
$choix .= "," . $VOB_list\\\\[$index\\\\];
}
$index++;
}
system("clearprompt list -outfile C:\\choice.txt -items $choix -prompt \"Choose VOB\"");
$data_file="C:\\choice.txt";
open(DAT, $data_file) || die("Could not open file!");
@raw_data=<DAT>;
close(DAT);
$choix = pop(@raw_data);
chomp($choix);
@branch_list=`cleartool lstype -s -kind brtype -inVOB VOB:$choix`;
$index = 0;
$choix = "";
while ($branch_list\\\\[$index\\\\] ne "") {
# printf($branch_list\\\\[$index\\\\]);
chomp($choix);
if ($index == 0){
$choix .= $branch_list\\\\[$index\\\\];
} else {
$choix .= "," . $branch_list\\\\[$index\\\\];
}
$index++;
}
system("clearprompt list -outfile C:\\choice.txt -items $choix -prompt \"Choose branch to
implement\"");
$data_file="C:\\choice.txt";
open(DAT, $data_file) || die("Could not open file!");
@raw_data=<DAT>;
close(DAT);
$choix = pop(@raw_data);
chomp($choix);
$cmd = "cleartool mkbranch -nc -nco -nwarn $choix $version";
system($cmd);
6. VOB backup script
VOB backup has always been a nightmare for ClearCase administrators: you need to safely backup all the VOBs at the same time (which is a time-consuming process), but you also want to keep the VOB lock-time to a minimum (so that normal development, night builds, and MultiSite synchronization can take place). Rational Software has a solution to this nightmare: the VOB_snapshot / VOB_restore functionality. Since I am an old administrator hacker who always wants to have all the solutions on hand, however, I prefer to do it all myself. Introduction
The purpose of this script is to copy the complete VOB-storage directory (for all the local VOBs) to another directory, where it can be easily backed-up. The script should be run automatically via the ClearCase scheduler. Note: the script should cooperate with your backup utility. The Script
This script has been written in Perl so that it provides more output and a better selection of options. Please edit the file, and change the parameter: $TARGETPATH = "d:\\nono"; to the appropriate target directory for the copy. Warning: the target directory should already exist!!! The Script (backupVOB.bat) @rem = ' PERL for Windows NT -- ccperl must be in search path
@echo off
ccperl %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
@rem ';
#
#
# Variable to be modified
#
$TARGETPATH = "d:\\nono";
#
# End Variable to be modified
#
##############################################################################
#
#
# Global variable definition
#
if ($ENV{TEMP}) {
$TDIR=$ENV{TEMP}; }
else {
$TDIR="c:${S}temp";}
$COMPUTERNAME = $ENV{COMPUTERNAME};
$S = "\\";
$PERL = "ccperl";
$NULL = $TDIR . $S . "null";
$JUNK = $TDIR . $S . "junk";
$TMPFX = $TDIR . $S . "." . $$;
$TMP_VOBINFO = $TMPFX . ".VOBstuff";
$COPYCMD = "ccopy ";
$MDEP_TIME_STAMP = 'cmd /c echo y | cmd /c time';
$MDEP_DATE_STAMP = 'cmd /c echo y | cmd /c date';
$MDEP_RMDIR_COMMAND = 'cmd /c rmdir /s ';
$MDEP_RMFILE_COMMAND = 'cmd /c del';
$MDEP_ECHO = 'cmd /c echo';
#
#
# End of global variable definition
#
##############################################################################
#
#
# Function definition
#
sub system_redirect {
local($command) = @_\\\\[0\\\\];
local($ret_status);
local($tmpname);
$tmpname = &mdep_get_tmpname();
$ret_status = system("$command > $tmpname 2>&1");
#
# Don't call mdep_rmfile - it calls system_redirect.
#
system("$MDEP_RMFILE_COMMAND $tmpname");
return $ret_status;
}
sub mdep_rmfile {
local($file) = @_\\\\[0\\\\];
local($status);
if($file eq "") {
return $RTN_PATH_NULL;
}
$status = &system_redirect("$MDEP_RMFILE_COMMAND \"$file\"");
if($status) {
return $RTN_NOT_OK;
}
return $RTN_OK;
}
sub mdep_rmdir {
local($dirpath) = @_\\\\[0\\\\];
local($status);
if($dirpath eq "") {
print "null directory\n";
return(-1);
}
if(! -d $dirpath) {
print "directory $dirpath doesn't exist\n";
return(-1);
}
$status = &system_redirect("$MDEP_ECHO Y | $MDEP_RMDIR_COMMAND \"$dirpath\"");
return($status);
}
sub mdep_get_tmpname {
$VOB_recover_tmpseq++;
return "${TDIR}\\backupVOB.$$.${VOB_recover_tmpseq}";
}
sub mdep_get_time {
local($tmpname);
local($line);
local($date);
local($time);
local($r_string) = "";
$tmpname = &mdep_get_tmpname();
system("$MDEP_DATE_STAMP > $tmpname");
open(GETDATE,$tmpname);
foreach $line (<GETDATE>) {
chop $line;
if($line =~ /The current date is:\s+\\\\[a-zA-Z\\\\]+\s+(.*)/) {
$date = $1; last;
}
}
close(GETDATE);
system("$MDEP_TIME_STAMP > $tmpname");
open(GETTIME,$tmpname);
foreach $line (<GETTIME>) {
chop $line;
if($line =~ /The current time is:\s+(.*)/) {$time = $1; last}
}
close(GETTIME);
&mdep_rmfile($tmpname);
$r_string = "$date $time";
return($r_string);
}
#
#
# End of function definition
#
##############################################################################
$tstamp = &mdep_get_time();
printf "Backup script started : $tstamp \n";
system("cleartool lsVOB -host ${COMPUTERNAME} > $TMP_VOBINFO 2> $JUNK");
open(VOBS,$TMP_VOBINFO);
while ($VOB=<VOBS>) {
($active, $VOBtag, $VOBstrg) = split(/\s+/,$VOB);
print "\nCopying up : $VOBtag to $TARGETPATH$VOBtag \n";
system("cleartool lock VOB:$VOBtag");
if( -d $TARGETPATH.$VOBtag) {
mdep_rmdir($TARGETPATH.$VOBtag); }
system("mkdir $TARGETPATH$VOBtag");
print ".";
system("$COPYCMD $VOBstrg\\groups.sd $TARGETPATH$VOBtag\\groups.sd");
print ".";
system("$COPYCMD $VOBstrg\\identity.sd $TARGETPATH$VOBtag\\identity.sd");
print ".";
system("$COPYCMD $VOBstrg\\replica_uuid $TARGETPATH$VOBtag\\replica_uuid");
print ".";
system("$COPYCMD $VOBstrg\\VOB_oid $TARGETPATH$VOBtag\\VOB_oid");
print ".";
system("$COPYCMD $VOBstrg\\VOB_server.conf $TARGETPATH$VOBtag\\VOB_server.conf");
print ".";
system("$COPYCMD $VOBstrg\\admin $TARGETPATH$VOBtag\\admin");
print ".";
system("$COPYCMD $VOBstrg\\c $TARGETPATH$VOBtag\\c");
print ".";
system("$COPYCMD $VOBstrg\\d $TARGETPATH$VOBtag\\d");
print ".";
system("$COPYCMD $VOBstrg\\db $TARGETPATH$VOBtag\\db");
print ".";
system("$COPYCMD $VOBstrg\\s $TARGETPATH$VOBtag\\s");
print "\n";
system("cleartool unlock VOB:$VOBtag");
print "\n";
}
close(VOBS);
&mdep_rmfile($TMP_VOBINFO);
&mdep_rmfile($JUNK);
$tstamp = &mdep_get_time();
printf "Backup script stopped : $tstamp \n";
__END__
:endofperl
Ccopy.exe
The Perl script uses ClearCase's ccopy.exe to copy the files to the target directory. It has been written so that the access control list (ACL) is also copied over. The ccopy.exe utility is usually in %ATRIAHOME%\etc\utils Warning: ccopy.exe should be in your search path!!! Other Process Steps
BackupVOB.bat Copy backupVOB.bat to the following directory: %ATRIAHOME%\var\scheduler\tasks Ccopy.exe : Copy ccopy.exe to the following directory: %SYSTEMROOT%\system32 Set up the Scheduler: Change the Scheduler permission By default, the ClearCase scheduler has an ACL that grants everyone only "Read" permission. This should be modified to be able to schedule new jobs. To do that: Logon as a member of the "clearcase" group (for example, as ccadmin), and create a small file with the following content: Everyone: Full Then, run the following: cleartool schedule -set -acl filename Create a new task: Go to the following directory: %ATRIAHOME%\var\schedule\tasks And edit the following file: task_registry Add at the end, and put the following: Task.Begin
Task.Id: 102
Task.Name: "Backup/Copy VOB"
Task.Pathname: backupVOB.bat
Task.End
Schedule the task Start the ClearCase Administration Console: Start>Programs>ClearCase Administration>ClearCase Administration Console. Go to the scheduled jobs entry, right click and select new>job. In the Job Properties dialog box, select the Task tab, and choose Backup/Copy VOB. Select the remaining tabs to specify the rest of the scheduling options, such as time, date, frequency, and so on. Once scheduled, it should work! 7. License usage
\\\\[Many thanks to Arjan Ten Hoopen\\\\] ClearCase license usage has always been a big question: since more and more companies have deployed ClearCase company-wide, it is sometimes difficult to keep track of how many licenses are being used across the enterprise. This can cause conflicts when "pick time" comes and you want to do a build, or simply when the number of concurrent users has exceeded the number of licenses. Knowing the extent of ClearCase usage is a big feature to have. Arjan Ten Hoopen developed a full solution for this, based on a scheduled job that displays the results with nice .jpg files. Enclosed is his solution: ClearLicense.zip Installation
Follow the instructions in the readme.doc of Arjan's zip file. Usage
When everything is set up, you can run the script and get a clear picture of the statistical usage of ClearCase licenses. Example:
8. MultiSite with ftp
Introduction
ClearCase MultiSite is an add-on product. The main purpose of MultiSite is the ability to create and synchronize replicas of VOBs from several sites world-wide. To do this, ClearCase MultiSite uses a mechanism that consists of two major steps:
Both of these steps are divided into 3 tasks: Note that tasks 1 and 3 are done via ClearCase MultiSite, that is, with MultiSite's own functionality. But note also that task 2 can be accomplished either with the embedded mechanism of MultiSite, called the shipping_server, or externally, by another procedure (like delivering over ftp, e-mail, and so on). In the case of a disconnected network, ClearCase provides the capability to package up the CCMS information packets and get them to the other site using whatever medium or mechanism you want (shipping server, ftp, email, and so on). Here is a solution that does not use MultiSite's shipping_server, but an ftp server to transfer the packets. Concept
To simplify the MultiSite mechanism, a completely new task script (which has the three embedded synchronization steps) has been developed. The script is called multisite.bat, and resides in: %ATRIAHOME%\var\scheduler\tasks. This script has 3 main steps:
The script has been developed in Perl, and is not difficult to understand, or to change. Debug output can be switched on/off, and it can be run directly from the command line to be tested. A script, called newshipping.bat, has been developed, and resides in %ATRIAHOME%\var\scheduler\tasks. This script does the following:
Scripts
Here are the scripts: Multisite.bat @rem = ' PERL for Windows NT -- ccperl must be in search path
@echo off
set CLEARCASE_VOBLOCKWAIT=120
ccperl %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
@rem ';
$CFG::verbose = 1;
##############################################################################
#
#
# Global variable definition
#
$VOBLOCKWAIT = $ENV{CLEARCASE_VOBLOCKWAIT};
if ($ENV{TEMP}) {
$TDIR=$ENV{TEMP}; }
else {
$TDIR="c:${S}temp";}
$COMPUTERNAME = $ENV{COMPUTERNAME};
$S = "\\";
if ($ENV{TEMP}) {
$TDIR=$ENV{TEMP}; }
else {
$TDIR="c:${S}temp";}
$PERL = "ccperl";
$NULL = $TDIR . $S . "null";
$JUNK = $TDIR . $S . "junk";
$JUNK1 = $TDIR . $S . "junk1";
$JUNK2 = $TDIR . $S . "junk2";
$JUNK3 = $TDIR . $S . "junk3";
$JUNK4 = $TDIR . $S . "junk4";
$JUNK5 = $TDIR . $S . "junk5";
$TMPFX = $TDIR . $S . "." . $$;
$TMP_VOBINFO = $TMPFX . ".VOBstuff";
$TMP_REPLICAINFO = $TMPFX . ".replicastuff";
$TMP_PACKETINFO = $TMPFX . ".packetstuff";
$TMP_SHIPPINGINFO = $TMPFX . ".shippingstuff";
$TMP_RECEIVEINFO = $TMPFX . ".receivestuff";
$TMP_PINGINFO = $TMPFX . ".pingstuff";
$COPYCMD = "ccopy ";
$MDEP_TIME_STAMP = "cmd /c echo y | cmd /c time";
$MDEP_DATE_STAMP = "cmd /c echo y | cmd /c date";
$MDEP_RMDIR_COMMAND = "cmd /c rmdir /s ";
$MDEP_RMFILE_COMMAND = "cmd /c del";
$MDEP_ECHO = "cmd /c echo";
#
#
# End of global variable definition
#
##############################################################################
#
#
# Function definition
#
sub system_redirect {
local($command) = @_\\\\[0\\\\];
local($ret_status);
local($tmpname);
$tmpname = &mdep_get_tmpname();
$ret_status = system("$command > $tmpname 2>&1");
#
# Don't call mdep_rmfile - it calls system_redirect.
#
system("$MDEP_RMFILE_COMMAND $tmpname");
return $ret_status;
}
sub mdep_rmfile {
local($file) = @_\\\\[0\\\\];
local($status);
if($file eq "") {
return $RTN_PATH_NULL;
}
$status = &system_redirect("$MDEP_RMFILE_COMMAND \"$file\"");
if($status) {
return $RTN_NOT_OK;
}
return $RTN_OK;
}
sub mdep_rmdir {
local($dirpath) = @_\\\\[0\\\\];
local($status);
if($dirpath eq "") {
print "null directory\n";
return(-1);
}
if(! -d $dirpath) {
print "directory $dirpath doesn't exist\n";
return(-1);
}
$status = &system_redirect("$MDEP_ECHO Y | $MDEP_RMDIR_COMMAND \"$dirpath\"");
return($status);
}
sub mdep_get_tmpname {
$VOB_recover_tmpseq++;
return "${TDIR}\\backupVOB.$$.${VOB_recover_tmpseq}";
}
sub mdep_get_time {
local($tmpname);
local($line);
local($date);
local($time);
local($r_string) = "";
$tmpname = &mdep_get_tmpname();
system("$MDEP_DATE_STAMP > $tmpname");
open(GETDATE,$tmpname);
foreach $line (<GETDATE>) {
chop $line;
if($line =~ /The current date is:\s+\\\\[a-zA-Z\\\\]+\s+(.*)/) {
$date = $1; last;
}
}
close(GETDATE);
system("$MDEP_TIME_STAMP > $tmpname");
open(GETTIME,$tmpname);
foreach $line (<GETTIME>) {
chop $line;
if($line =~ /The current time is:\s+(.*)/) {$time = $1; last}
}
close(GETTIME);
&mdep_rmfile($tmpname);
$r_string = "$date $time";
return($r_string);
}
sub dbgprint {
return if (! $CFG::verbose);
system "cmd /c echo @_";
# print @_;
# print STDERR @_ if $CFG::stderr_msgs;
}
#
#
# End of function definition
#
##############################################################################
$tstamp = &mdep_get_time();
printf("Hello Dany...");
dbgprint "MultiSite script started : $tstamp \n";
dbgprint "Maximum Wait time for Lock : $VOBLOCKWAIT minutes";
dbgprint "Phase 1 : syncreplica -export ";
system("cleartool.exe lsVOB -host ${COMPUTERNAME} > $TMP_VOBINFO 2> $JUNK");
open(VOBS,$TMP_VOBINFO);
while ($VOB=<VOBS>) {
($active, $VOBtag, $VOBstrg) = split(/\s+/,$VOB);
system("multitool lsreplica -s -siblings -inVOB $VOBtag > $TMP_REPLICAINFO 2>
$JUNK1");
open(REPLICAS,$TMP_REPLICAINFO);
while ($replica=<REPLICAS>) {
chop $replica;
system("multitool syncreplica -export -ship $replica\@$VOBtag >
$TMP_PACKETINFO 2> $JUNK2");
dbgprint " $VOBtag : $replica \n";
# dbgprint " Standard output : \n";
# system("cmd /c type $TMP_PACKETINFO");
# dbgprint " Standard Error : \n";
# system("cmd /c type $JUNK2");
&mdep_rmfile($TMP_PACKETINFO);
&mdep_rmfile($JUNK2);
}
close(REPLICAS);
&mdep_rmfile($TMP_REPLICAINFO);
&mdep_rmfile($JUNK1);
}
close(VOBS);
&mdep_rmfile($TMP_VOBINFO);
&mdep_rmfile($JUNK);
dbgprint "MyPhase 2 : Shipping_server";
system("ping -n 10 -w 2000 -l 10000 psdev-ftp > $TMP_PINGINFO 2> $JUNK5");
# This is the normal command for the shipping server :
#system("shipping_server -poll > $TMP_SHIPPINGINFO 2> $JUNK3");
# For E+H, another shipping server has been used :
system("cmd /c \"c:\\Program Files\\ClearCase\\var\\scheduler\\tasks\\newshipping.bat\"
> $TMP_SHIPPINGINFO 2> $JUNK3");
#dbgprint " Standard output : \n";
#system("cmd /c type $TMP_SHIPPINGINFO");
#dbgprint " Standard Error : \n";
#system("cmd /c type $JUNK3");
dbgprint "Phase 3 : syncreplica -import ";
system("multitool syncreplica -import -receive > $TMP_RECEIVEINFO 2> $JUNK4");
#dbgprint " Standard output : \n";
#system("cmd /c type $TMP_RECEIVEINFO");
#dbgprint " Standard Error : \n";
#system("cmd /c type $JUNK4");
$tstamp = &mdep_get_time();
dbgprint "MultiSite script stopped : $tstamp";
exit(0);
__END__
:endofperl
newshipping.bat echo "Newshipping started..."
attrib -r "C:\Program Files\ClearCase\var\shipping\ms_ship\outgoing\sync*"
ftp -v -s:"C:\Program Files\ClearCase\var\scheduler\tasks\sendinput.txt"
copy "C:\Program Files\ClearCase\var\shipping\ms_ship\outgoing\sync*" "C:\Program
Files\ClearCase\var\shipping\ms_ship\outgoing\archive"
del "C:\Program Files\ClearCase\var\shipping\ms_ship\outgoing\sync*"
copy "C:\Program Files\ClearCase\var\shipping\ms_ship\outgoing\sh_*" "C:\Program
Files\ClearCase\var\shipping\ms_ship\outgoing\archive"
del "C:\Program Files\ClearCase\var\shipping\ms_ship\outgoing\sh_*"
ftp -v -s:"C:\Program Files\ClearCase\var\scheduler\tasks\getinput.txt"
sendinput.txt open ftp-server
ftpuser
ftpuser
cd "/multisite/ftp/outgoing"
lcd "C:\Program Files\ClearCase\var\shipping\ms_ship\outgoing"
hash
binary
prompt
mput sync*
quit
getinput.txt open ftp-server
ftpuser
ftpuser
cd "/multisite/ftp/outgoing"
lcd "C:\Program Files\ClearCase\var\shipping\ms_ship\incoming"
hash
binary
prompt
mget sync*
quit
Scheduler
A new task needs to be added to the ClearCase scheduler to automatically run the multisite.bat script. See the ClearCase scheduler documentation to learn how best to set it up. Limitations
The workaround presented in the preceding paragraphs has the following limitations:
9. Copy Merge
Sometimes elements in ClearCase VOBs cannot be merged: they may be binary files, objects, or executables. Nevertheless, if you want to do parallel development, or you are using UCM, you need to perform merge operations. Having a way to specify that you don't want to merge a file, but just "copy-over" the version (either from the source branch or the target branch) is a welcome feature. Michel Lohr, of Rational Software Netherlands, developed a solution. Here is his solution: CopyMerge.zip Installation
Follow the instructions of Forced copy merger.doc Usage
Once you perform a merge of a file with type manager, the special_merge will produce the following dialog box:
10. Compare label
Introduction
ClearCase, by default, does not have any GUI functionality to compare two labels and produce a list of all versions that differ between the two labels sets. This functionality, however, does exist over the command line with the cleartool find command. So, lets make a compare function over the GUI!!! Installation
Caution: You NEED to have local administration rights to be able to create this customization. The customization is done by user profile. First, start the clearmenuadmin.exe utility. For the "compare label" option, do the following: On the Object type tab, select the VOB object. Choose checked-in as the Object state. In the Available menu Choices pane, press the new button, and enter the following information in the appropriate fields: Menu Text: Compare labels... Then, you can add this new menu entry to the This menu contents pane by pressing the add button, and position it as desired with the Move up button. Usage
Using Windows Explorer, select the VOB, click the right mouse button, and the new Compare labels... menu should appear. The following dialog box will display:
If you don't have a view called "Administration_Views", then the following dialog box will appear first:
You then need to choose one of the views for the tool to work properly. Next, choose a VOB from the drop-down list. You can either select to compare any two labels, or compare the latest from a branch and a label.
Choose the first label / branch, then choose a second label. Click compare to start the compare process, as shown in the following figure.
The menu item Edit>Show only local is for displaying either the list of local labels / branches, or the labels / branches coming from the AdminVOB.
After comparing, the results will be displayed in a new dialog box:
You can then select the text and copy/paste it to your favorite application. Finally, choose File>Quit (or Ctrl-Q) to close the whole application.
The source of "CompareLabel.exe"
The application CompareLabel.exe has been developed with Visual Basic v6.0 and the ClearCase Automation Library (COM) called "CAL". The Visual Basic project is called "CompareLabel.vbp", and has the following forms:
Also, a Visual Basic module called "General Definition.bas" is used. You can see the logic of the application in the source files: comparelabel.zip. Conclusion
I have worked more then seven years with ClearCase, sometimes quite intensively. Every day, I discover new features and new ideas to make life better for both developers and ClearCase administrators. In this article, we've seen simple scripts (with just a command), Perl scripts, and even full integrations written in Visual Basic and CAL. These 10 scripts provide several ways to extend ClearCase functionality to meet your needs. | ||||||||||||||||||||||||||||||
![]() |
About the Authors | ||
![]() |
Daniel Dieboltis a Senior Technical Representative, with Rational Software in Switzerland. He can be reached via e-mail at DIDA@ch.ibm.com. |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Comments about this article? | ![]() | |
![]() |
![]() |
![]() |
![]() |
Back to Top | ![]() | |
![]() |
![]() |
![]() |