Views, ConfigSpecs, and ClearStart

Using the correct view when doing development under ClearCase is about 90% of your site's SCM policy. This is ClearCase's great weakness: Defining the view can be a daunting task for a user. If the view is poorly defined, the user might be examining the wrong versions of the various files, or modifying these files on the wrong branch. Most users never quite understand how views work, and tend to hack at the ConfigSpec until they think they have what they want. Much of a ClearCase Administrator's time will be spent on view problems.

Fortunately, there are several steps that will take care of many of these problems and make your life, and the lives of your developers much happier:


Never Define Views Under the User's HOME Directory

One of the biggest no-nos in ClearCase Administration is allowing views to be defined under a user's HOME directory. This only invites the user to play with the view outside of ClearCase. Many users will copy files in and out of the view directory, or simply delete the view directory because it takes up so much room.

There are several ways of handling this problem. If you use ClearStart, you can have ClearStart automatically create the views under a defined $viewdir. If you don't use ClearStart, you can write your own "mkview" function in either Bourne Shell, Kornshell, BASH, or Z-Shell:

mkview()
{
if [ "" != "$2" -o "" = "$1" ]
    then
        echo "Usage: mkview <view_name>"
        echo "    where <view_name> is the name of your view"
        exit 2
    fi
    cleartool -tag mkview $1 $viewdir/${1}.vws
}
This new "mkview" command is easier to use than the standard ClearCase one which requires the "-tag" flag, and the name of the directory where you want to store the view. Therefore, users are more likely to use the easier to use "mkview" instead of "cleartool mkview" command.

If you use C-shell or Turbo-C shell, you will have to define the "mkview" command as a shell script.


What is ClearStart?

ClearStart is a utility that allows you, the Source Configuration Manager, to define a set of view templates to be used for your site. Users run ClearStart in order to start up a view. If the view already exists, it is started. If not, ClearStart will automatically create the correct view, and then starts the view. There is no longer a difference between creating and using a view.

ClearStart also changes the way most sites use views. In most sites, users only have one or two views which they constantly edit to see the correct version of the elements stored under ClearCase. This leads to view corruptions, and problems with view private files from one task suddenly showing up in another task.

Under ClearStart, the user will have one view for each separate task they perform. Private view files stay only with the task that created them. Users no longer edit their views, causing incorrect ConfigSpecs to be defined.

Since the SCM controls the views, the SCM can use the views to enforce policy decisions. Suddenly, making SCM policy is quicker and easier, there are fewer problems to handle in ClearCase, and users have an easier time using ClearCase in their jobs.

ClearStart is available from the ClearCase Rational Customer Support Website (http://clearcase.rational.com). You must have a "user password" and "user account" in order to access this Website. However, this is nothing more than your ClearCase license host's user id, and the ClearCase license code. Go to the user Contribution Area and take a look at Software Package T0026.


How to Use ClearStart

To use ClearStart, you must understand how a ConfigSpec works. ClearStart allows you to use variables in order to help create a ConfigSpec. Although the documentation of ClearStart is fairly complete, some people still have problems making it work. Here's a quick tutorial by example that should help you build your own ClearStart templates:


The Basic Development View

Take a look at this ConfigSpec:
element * CHECKEDOUT
element * /main/davidw/LATEST
element * INT-REL-1.3.44 -mkbranch davidw
This is a typical ConfigSpec defined for a programmer doing development work. The branch /main/davidw is the branch where all development is taking place. The base view for development is release INT-REL-1.3.44 which is probably an internal release of the last release that has been approved for development. The programmer is using INT-REL-1.3.44 instead of /main/LATEST in order to have a stable base for development. This is a typical configspec that developers will use.


Generalizing the View

Unfortunately, the above ConfigSpec is very specific, it is only for user davidw, and is based off of a particular release. However, imagine if we decided to make this a template that programmers could use as a base for defining their own views. It would probably look something like this:

element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:BASE_RELEASE] -mkbranch [:BRANCH:]
The programmer would simply put their branch's name where [:BRANCH:] occurs, and substitute their base release for [:BASE_RELEASE:]. This is the heart of the ClearStart template. ClearStart will take this template, and plug in these values for the programmer. The only question is how does ClearStart know which values to use.


ClearStart Directives

ClearStart uses a series of directives to add functionality into your ConfigSpec which the ClearStart release notes refer to these directives as "ClearStart Properties". Each directive stand on a line by itself and start with #ClearStart_. One type of directives sets the value of variables used in ClearStart templates.

This directive is #ClearStart_Subst:. After the directive, you set the value of the variable with an equal sign. Very similar to the way you would do it in Bourne shell, except, instead of using a dollar sign like Bourne shell, ClearStart uses a brace/colon pairing:

#ClearStart_Subst: variable = [:value:]     #ClearStart
variable=$value                             #Unix Shell
In order to match our original ConfigSpec, we could have done the following:

#ClearStart_Subst: BRANCH = davidw
#ClearStart_Subst: BASE_RELEASE = INT-REL-1.3.44
element * CHECKEDOUT
element * /main/[:MR:]/LATEST
element * [:RELEASE:] -mkbranch [:MR:]

Inputing the Value of ClearStart Variables

Of course, this doesn't do anything much more than before. Although the ConfigSpec is now using variables, the values still have to be defined in the ConfigSpec. What is needed is a way ClearStart can read these values off of Standard Input (STDIN). Fortunately, like the Unix shell and like Perl, ClearStart can use the Standard Output of a program (like a shell script or Perl script) and use it to initialize ClearStart variables:

#ClearStart_Subst: BRANCH = `getBranch`     #ClearStart
BRANCH=`getBranch`                          #Unix Bourne Shell
$BRANCH = `getBranch`;                      #Perl
So, all we have to do is write a simple shell script (or Perl script) that allows a user to input the MR number, and then we echo this MR Number back out to STDOUT. Here's a simple program called getBranch:

#! /bin/sh

# Name: getBranch
# Purpose: Ask what is the branch name to use
#

echo "What is the name of the branch you wish to use">&2
read branch

echo "$branch"
Notice that the output of the "echo" statement was redirect from standard output to standard error. Otherwise, ClearStart (just like Unix or Perl) would assume the prompt is part of the program's output. Basically, this program just prompts the user for the name of the branch, then echos it into STDOUT.

In Kornshell, you use the -u2 tells the print (or echo) statement to print to STDERR instead of STDOUT:

#! /bin/ksh

# Name: getBranch
# Purpose: Ask what is the branch name to use
#

print -u2 "What is the name of the branch you wish to use"
read branch

print "$branch"
Here's another way in Kornshell:

#! /bin/ksh

# Name: getBranch
# Purpose: Ask which Branch to use
#

read branch?"What is the name of the branch you wish to use? "
print "$mr"
The read var?prompt command in Kornshell is nice because it prints the prompt onto STDERR for you.

And now for you Perl fans:


    #! /usr/atria/bin/Perl

    # Name: getBranch
    # Purpose: Ask which branch to use
    #

    print STDERR "What is the name of the branch you wish to use? "
    chop($mr = );
    print "$mr\n"
Notice again I could not print my prompt to STDOUT, so I redirected it to STDERR. Of course, the getBranch program is a bit too simple. None of the versions of this program verifies whether I am allowed to use the branch, or whether the branch actually exists. Here is a nice Kornshell version that uses the "select" statement:

#! /bin/ksh

# Name: getBranch
# Find the name of the development branch

PS3="Which development Sandbox would you like to use: "
select branch from "task1 task2 task3"
do
[ "" != "$branch" ] && break
done

#
# Modify Branch Name by prepending User's ID
#

branch="${id}_${branch}"

#
# Now see if branch exists. If it doesn't create the branch
# 

if $cleartool desc brtype:$branch@$AdminVOB > /dev/null 2>&1
then
	:		#Branch Exists
else
	$cleartool mkbrtype -nc brtype:$branch@$AdminVOB > /dev/null 2>&1
	if [ $? -ne 0 ]
	then
	    print -u2 "ERROR: Couldn't make branch $branch!!"
	    exit 2
	fi
fi

    #
    # Branch selected, now print it out
    #

print "$branch"
Not perfect. Some of the Kornshell variables aren't defined (what's $id? what's $cleartool? Actually, I have them defined in my ClearCase User Environment), but it does give you a basic idea of a typical shell script.

Notice how nicely the Kornshell's select statement works. Select takes the list of parameters given (in this case "task1, "task2", "task3") and presents them as a menu. The select statement can also do error checking (in this case, simply verifying that a valid option was selected by seeing if the select variable got a value). The best part of it all is that the select statement does all of its outputing onto STDERR. It is as if Kornshell's select statement was made for ClearStart.

One more thing you might notice about this script. If the branch selected doesn't exist, the script automatically creates the branch type.

The following is a Kornshell version of the "getRelease" shell script to get the base release number. Here, I generate the list of Releases by getting a listing of labels that begin with "INT_REL". Releases that I don't want users to use as a baseline can be locked with the -obsolete flag so they don't show up in an "cleartool lstype" command.

For the error checking aspect, I use Kornshell's "select" statement. The "select" statement is very similar to a "for" statement in syntax, but builds a little menu of the items in the list instead of looping though them. You then select the item from the menu.

The Kornshell "select" statement then verifies the choice, and best of all, it does all this without printing a thing to STDOUT. I normally will program in Perl, but the Kronshell "select" statement seems almost designed with ClearStart in mind. Many of my shell scripts for ClearStart use the same structure as the script below. Create a listing of valid entries, set up a "select" statement, then print the entry picked from the select statement:

# /bin/ksh

# Name: getRelease
# Purpose: Ask which Release to use
#

#
# Define Constants
#

prefix="INT_REL"		#Prefix of the ClearCase Label Used
AdminVOB="$CCENV_ADMINVOB"	#Administration VOB
     
#
# Get a List of All Possible Release Labels
#

releaseList="$(cleartool lstype -fmt "%n\n" -kind lbtype \
-invob $AdminVOB | grep "^${prefix}")"

if [ "" = "$releaseList" ]
then
	print -u2 "ERROR: View cannot be set: No Releases Avalable"
	exit 2
fi

#
# Have User Select Release from Release List
#

PS3="
Base View on Release Number: "
     
print -u2 "\n"
select release in $releaseList
do
	[ "" != "$release" ] && break
done

#
# Output Release Label Selected for ClearStart
#

print "$release"
Again, this ConfigSpec is a duplicate of the one before. Except, intead of using constants to define my variable values ("davidw" and "RINT-REL-1.3.4") I use the results of the shell scripts above:

#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: BRANCH = `getBranch`
element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:RELEASE:] -mkbranch [:BRANCH:]
So, now we have a ClearStart template that can be used. The shell scripts "getRelease" and "getBranch" are placed in a directory that is in the user's $PATH. When a user runs ClearStart, ClearStart will now put this template onto the ClearStart menu. Or does it?


Describing the ClearStart Template

There is one minor problem with the Above ConfigSpec Template. In order for ClearStart to display a particular ConfigSpec on its menu, it needs a description of what that ConfigSpec does. This description is what gets displayed in the menu. So, we need another ClearStart directive called #ClearStart_Desc: to describe what the ConfigSpec does. The following ConfigSpec is just like the one above, but now has the #ClearStart_Desc: directive:

#ClearStart_Desc: Standard Development View
#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: BRANCH = `getBranch`

element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:RELEASE:] -mkbranch [:BRANCH:]
Now, this Template ConfigSpec can be used in ClearStart. It has a View Description of the template in the #ClearStart_Desc: directive (needed by all ClearStart Templates), and it has instructions on how to build the actual view from the template. However, there are still a couple of problems. When this Template gets displayed in the ClearStart menu, the user builds a view. Next time this user starts ClearStart, this view should also appear in the ClearStart menu so the user can reselect it instead of rebuilding it.

In order to do this, we simply add another "ClearStart_Desc:" directive to describe the view once it is built. That way, the template has one menu description while the view has another one.

#ClearStart_Desc: Standard Development View
#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: BRANCH = `getBranch`
#ClearStart_Desc: Branch [:BRANCH:] Dev View based on [:RELEASE:]
element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:RELEASE:] -mkbranch [:BRANCH:]
Now we have two #ClearStart_Desc: directives. The top line will be displayed before the view is created. The second one on line #4 will be used when the view is actually created. Notice that [:BRANCH:] and [:RELEASE:] variables are used to help with the description. Now the question is how does ClearStart know which description to use.

ClearStart always uses the first #ClearStart_Desc: directive. In order to use the other ClearStart_Desc: directive, we will have to cut out the original ClearStart_Desc: when the view is created. ClearStart provides another directive called #ClearStart_Begin_Templeate: to handle this problem. When the actual view is created from the template, the actual view's ConfigSpec starts right after the #ClearStart_Begin_Template: line. All we have to do is place this line right before the second #ClearStart_Desc: directive:

#ClearStart_Desc: Standard Development View
#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: BRANCH = `getBranch`
#ClearStart_Begin_Template:
#ClearStart_Desc: Branch [:BRANCH:] Dev View based on [:RELEASE:]
element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:RELEASE:] -mkbranch [:BRANCH:]
Now, when the user runs ClearStart, they get a menu showing all created views for that user and all templates that user could use to build other views. One of the items on the menu is called "Standard Development View". The user chooses that selection, and (via the getRelease and getBranch shell scripts) is then asked for the branch and the release that view will be based upon.

When the user finishes answering these questions, a new view is created, and that view is set. When the user wishes to use that same view over, the user selects "Branch davidw-task1" Dev View based on INT-REL-1.3.44" from the menu, and uses that view.

One final problem remains. What is the ACTUAL name for this view? ClearCase views all have a view tag, but so far we have glossed over the discussion of where ClearStart views get their names. ClearStart Templates are stored under the $CLEARSTART_HOME directory. I usually make this the clearstart directory in my ClearCase Administrative user's HOME directory. The template is a text file with a name. For example, we will call template this "std_dev", and store it in $CCENV_HOME/clearstart/config/std_dev.

The views themselves take the template's name, and prefix the user id. This allows different users to have different views. For example, the name of the created view from "std_dev" would be "davidw__std_dev" for this user. This way, each user could have their own view tag:

tom__std_dev
dick__std_dev
harry__std_dev
davidw__std_dev
This works out well for templates that do not use variable substitution. For example, I might have a standard "Default View":

#ClearStart_Desc: Default View

element * CHECKEDOUT
element * /main/LATEST
Unfortunately, it is possible for a single user to have multiple views based upon this one template. In order to get around this problem, ClearStart appends to the template's name some information that would make this view unique for this user. For example, since this user specified the branch name and the release, these could be appended to the template's name:

davidw__std_dev__davidw-task1_INT-REL-1.3.44
davidw__std_dev__davidw-task1_INT-REL-1.4.01
davidw__std_dev__davidw-task2_INT-REL-1.3.44
davidw__std_dev__davidw-task3_INT-REL-1.3.44
Yes, these view names get very long, but remember that you are selecting them from a menu via a description, and not via the view's actual name. Under ClearStart, you will never be typing something like this:

$cleartool setview davidw__std_dev__davidw-task3_INT-REL-1.3.44
The last thing we need to do is to tell the template what to call our view when the template is completed. To do this, ClearStart uses a special ClearStart directive called NAME. Whatever the value of Name, it will be appended to the template's name. Therefore, it is important for you to verify that your NAME variable will insure unique view names. According to our naming scheme, the NAME variable will be [:BRANCH:]-[:RELEASE:]. It could have very easily been [:RELEASE:]-[:BRANCH:] too. Now our view template looks like this:

#ClearStart_Desc: Standard Development View
#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: BRANCH = `getBranch`
#ClearStart_Subst: NAME = [:BRANCH:]-[:RELEASE:]

#ClearStart_Begin_Template:
#ClearStart_Desc: Branch [:BRANCH:] Dev View based on [:RELEASE:]

element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:RELEASE:] -mkbranch [:BRANCH:]
This is a completed ClearStart view template. If you used the "env" and "environment" files from this site, you could place this template under $CCENV_HOME/clearstart/config, plus the two shell scripts getRelease and getBranch under $CCENV_HOME/bin and play around with with this template. You could also use this template for other types of development views. Here is a favorite of mine:

#ClearStart_Desc: Standard Development View
#ClearStart_Subst: DATE = `date "+%m-%h-19%y"`
#ClearStart_Subst: BRANCH = `getBranch`
#ClearStart_Subst: NAME = [:BRANCH:]-[:DATE:]

#ClearStart_Begin_Template:
#ClearStart_Desc: Branch [:BRANCH:] Dev View as of [:DATE:]

element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
time [:DATE:]
element * /main/{STATUS=="APPROVED"} -mkbranch [:BRANCH:]
Here, I am using the Unix date program to produce a date in the form of dd-mmm-yyyy. This means, when a view is created, I use the date the view was created to create a stable time based view for development work. Testing templates are much simpler:

#ClearStart_Desc: Testing View
#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: NAME = [:RELEASE:]

#ClearStart_Begin_Template:
#ClearStart_Desc: Testing Release [:RELEASE:]

element * [:RELEASE:] -nocheckout
Sometimes, because some testers are not very technical, I will simply create a ClearStart Template without any variables. That way, the tester can select the view from the ClearStart menu without having to answer any questions:

#ClearStart_Desc: Testing Internal Release 3.1.44

element * INT_REL_3.1.44

Further Information

You can setup a special ClearStart template called ".defaults" that allows you to setup certain defaults for all views. My standard one looks like this:

#ClearStart_TMode:      "$CCENV_OSSYS"
#ClearStart_ViewStore:  "$CCENV_VIEWDIR"
The first TMode is a ClearStart directive stating the "TMODE" of the view. Whether this is a MSDOS view or an Unix view. Normally, I make this 'unix' by default, but in mixed environments, you probably want to set $OSSYS to represent the text mode of your view. I also set up a directory where I store all views so that views will be stored outside of the user's HOME directory. This is set in my "env" file.

Another thing I will add to all templates is the "#ClearStart_Obsolete:" directive. This is set to "0" which means that the template isn't obsolete. However, this makes it easy for a user to "Obsolete" their views by simply changing this from "0" to "1". A simple shell script could do this. Basically, an obsolete view won't normally show up in a ClearStart menu so ClearStart menus are not full of views that the user no longer uses. So my ClearStart "Standard Development Template" might looks something like this:

#ClearStart_Desc: Standard Development View
#ClearStart_Obsolete: 0

#ClearStart_Subst: RELEASE = `getRelease`
#ClearStart_Subst: BRANCH = `getBranch`
#ClearStart_Subst: NAME = [:BRANCH:]-[:RELEASE:]

#ClearStart_Begin_Template:
#ClearStart_Desc: Branch [:BRANCH:] Dev View based on [:RELEASE:]

element * CHECKEDOUT
element * /main/[:BRANCH:]/LATEST
element * [:RELEASE:] -mkbranch [:BRANCH:]

Project Orientation

I like to keep a project oriented approach to ClearStart, as well as with the rest of ClearCase. Therefore, all the ClearStart View Templates for a particular project all start with the same two or three letter code. For example, instead of having a view called std_dev, I might call it tek_std_view. This allows me to know which views go with which projects.

Also remember that ClearStart sorts it's menu by the View Template file name. You might want to keep this in mind when you name your view templates. Try to keep the more used ones earlier in the alphabet so they show up on top. Also name your views in such a way that all the views that are similar are together in the menu. For example, release views are together and programming views are together.