This chapter presents brief scenarios, showing how common development policies can be implemented and enforced with ClearCase.
| Policy #1 | “All changes to sources should be recorded and comments should be provided.” |
Each ClearCase command that modifies a VOB automatically creates one or more event records. Many such commands (for example, checkin) prompt for a comment. The event record automatically includes the user's name, date, comment, host machine, and description of what was changed.
To prevent users from subverting the system by providing empty or meaningless comments, you might create a pre-operation trigger type to monitor the checkin operation. The trigger action script could analyze the user's comment (passed in an environment variable), disallowing “bad” ones (for example, those shorter than 10 words).
% mktrtype -element -global -preop checkin \
-exec comment_policy.sh CommentPolicy
Trigger action script:
#!/bin/sh
#
# comment_policy
#
ACCEPT=0
REJECT=1
WORDCOUNT=`echo $CLEARCASE_COMMENT | wc -w`
if [ $WORDCOUNT -ge 10 ] ; then
exit $ACCEPT
else
exit $REJECT
fi
|
| Policy #2 | “The system must track the progress of each source file through the official approval stages.” |
A process-control system must be able to track the progress of individual files. Ideally, the system will shepherd the file through various intermediate states, until it is finally declared “ready”. Attributes fit this model naturally — you can create a string-valued attribute type, Status, which accepts only a specified set of values.
% cleartool mkattype -c "standard file levels" \
-enum '"inactive","under_devt","QA_approved"' Status
Created attribute type "Status".
|
A Status attribute will be applied to many different versions of an element. Early versions on a branch might get the attribute with "inactive" and "under_dvt" values; later versions the "QA_approved" value. The same value might be used for several versions, or moved from an earlier version to a later version.
To enforce conscientious application of the status attribute to versions of all source files, you might create an CheckStatus trigger type much like the CommentPolicy trigger type in the preceding scenario. The associated trigger action script would disallow checkin of versions that had no Status attribute.
Trigger definition:
% mktrtype -element -global -preop checkin \
-exec check_status.sh CheckStatus
|
Trigger action script:
#!/bin/sh
#
# check_status
#
ACCEPT=0
REJECT=1
ATTYPE="Status"
if [ "`cleartool find $CLEARCASE_XPN \
-version 'attype($ATTYPE)' -print`" ]
then
exit $REJECT
else
exit $ACCEPT
fi
|
| Policy #3 | “All the versions that went into the building of Release 2 — and only those versions — should be labeled REL2.” |
After Release 2 is built and tested, you can create label type REL2, using the mklbtype command. You can then attach REL2 as a version label to the appropriate source versions, using the mklabel command.
What are the appropriate versions? If Release 2 was built “from the bottom up” in a particular view, you can label the versions selected by that view:
% cleartool mklabel -recurse REL2 top-level-directory |
Alternatively, you can use the configuration records (CRs) of the release's derived objects to drive the labeling process:
.. on June 17:
% clearmake vega
.. sometime later, after QA approves the build:
% cleartool mklbtype REL2
.. and then:
% cleartool mklabel -config vega@@17-Jun.18:05 REL2
|
Using CRs to attach version labels assures accurate and complete labeling, even if users have created new versions since the release build. You need not stop development while quality-assurance and release procedures are performed.
To prevent version label REL2 from being used further, lock the label type:
% cleartool lock -lbtype REL2
... and then:
% cleartool lock -nusers vobadm -lbtype REL2
|
The -nusers option provides a controlled “escape hatch” — the object will be locked to all users, except the specified ones.
| Policy #4 | “Fixes to a past release must be performed in isolation, starting with the exact configuration of versions that went into that release.” |
This policy fits perfectly with ClearCase's baselevel-plus-changes development model. First, a REL2 label must be attached to the release configuration, as described in the preceding scenario. Then, a view configured with the following config spec implements the policy:
element * CHECKEDOUT element * .../rel2_bugfix/LATEST element * REL2 -mkbranch rel2_bugfix |
If all fixes are performed in one or views with this configuration, all the changes will be isolated on branches of type rel2_bugfix. The -mkbranch clause causes such branches to be created automatically, as needed, when element are checked out.
This config spec selects versions from rel2_bugfix branches, where branches of this type exist; it creates such a branch whenever a REL2 version would be checked out.
| Policy #5 | “Users should be isolated from changes.” |
ClearCase views provide isolation from other users' changes. Using just a few configuration rules, you can specify exactly which changes you wish to see, and which you wish to exclude. Some examples:
Your own work, plus all the versions that went into the building of Release 2:
element * CHECKEDOUT element * REL2 |
Your own work on the main branch, plus the checked-in versions as of Sunday evening
element * CHECKEDOUT element * /main/LATEST -time Sunday.18:00 |
Your own work, along with new versions created in the graphics directory, plus the versions that went into last night's build
element * CHECKEDOUT element graphics/* /main/LATEST element * -config myprog@@12-Jul.00:30 |
Your own work, plus whatever versions either you (jones) or mary have checked in today, plus the most recent QAed versions:
element * CHECKEDOUT
element * /main/{ created_since(06:00) && \
( created_by(jones) || created_by(mary) ) }
element * /main/{QAed=="TRUE"}
|
You can use the config spec “include” facility to set up standard sets of configuration rules to be incorporated by users into their personal config specs:
element * CHECKEDOUT element msg.c /main/18 include /usr/cspecs/rules_for_rel2_maintenance |
| Policy #6 | “Public header files may not be changed until further notice.” |
The lock command is designed to enforce such “temporary” policies:
Lock all header files:
% cleartool lock src/pub/*.h |
Lock the headers for all users except Mary and Fred:
% cleartool lock -nusers mary,fred src/pub/*.h |
Lock all header files, not just public ones:
% cleartool lock -eltype c_header |
Lock an entire VOB:
% cleartool lock -vob /vobs/myproj |
| Policy #7 | “Whenever anyone changes the GUI, mail should be sent to the Doc Group, for a documentation update.” |
Post-operation triggers are designed to support such notification-oriented policies. First, create a trigger type that sends mail, then attach it to the relevant elements.
Trigger definition:
% cleartool mktrtype -nc -element -postop checkin \
-exec informwriters.sh InformWriters
Created trigger type "InformWriters".
|
Attaching triggers to existing elements:
Place the trigger on the inheritance list of all existing directory elements within the GUI source tree:
% cleartool find /vobs/gui_src -type d \
-exec 'mktrigger -recurse -nattach InformWriters
$CLEARCASE_PN'
|
Place the trigger on the attached list of all existing file elements within the GUI source tree:
#!/bin/sh
#
# check_status
#
DOC_GROUP="john george"
mail $DOC_GROUP << 'ENDMAIL'
New version of element created: $CLEARCASE_PN
by: $CLEARCASE_USER
Comment string:
---------------
$CLEARCASE_COMMENT
ENDMAIL
|
| Policy #8 | “C-language source files may not be checked-in unless they pass our quality metrics.” |
Pre-operation triggers can run any user-defined programs, and can cancel the operations that trigger them. You might have your own metrics program, or you might run lint(1). Suppose that you have defined an element type, c_source, for C language files (*.c).
% cleartool mktrtype -element -global \
-eltype c_source \
-preop checkin \
-exec 'apply_metrics.sh $CLEARCASE_PN' ApplyMetrics
|
This trigger type ApplyMetrics is global — it will fire on a checkin of any element of type c_source. (When a new c_source element is created, it will be monitored automatically.) If a user attempts to check in a c_source file that fails the apply_metrics.sh test, the checkin operation will be disallowed.
![]() | Note: The apply_metrics.sh script could read the value of $CLEARCASE_PN from its environment. But having it accept a file name argument provides flexibility: the script can be invoked as a trigger action, but developers can also use it “manually”. |
| Policy #9 | “All changes (ECOs) should be tagged with the number of the bug they are intending to fix.” |
Define ECO as an integer-valued attribute type. Define a global trigger type, EcoTrigger, which fires whenever a new version is created, using a built-in operations to set the ECO attribute to a bug number (which is read from the developer's environment).
Attribute definition:
% cleartool mkattype -c "bug number associated with change" \
-vtype integer ECO
Created attribute type "ECO".
|
Trigger definition:
% cleartool mktrtype -element -global -postop checkin \
-mkattr 'ECO=$ECONUM' EcoTrigger
Created trigger type "EcoTrigger".
|
Create a distinct branch type for each ECO number (for example, bug253). Fixes for a bug go onto the appropriate branch, and can be merged into whichever releases wished to incorporate those changes.
Here is the config spec for a view in which to work on ECO #253, a fix to Release 4.3:
element * CHECKEDOUT element * .../bug253/LATEST element * REL4.3 -mkbranch bug253 |
Using branches allows different bugfix projects to be isolated from one another. All the work can still can be integrated, by using multiple configuration rules:
element * CHECKEDOUT element * .../bug253/LATEST element * .../bug247/LATEST element * .../bug239/LATEST |
| Policy #10 | “Each source code module should have a pointer to an associated design document.” |
Requirements tracing applications can be implemented with ClearCase hyperlinks, which associate pairs of VOB object. The association should be at the version level (rather than the branch or element level): each version of a source code module should be associated with a particular version of a related design document (see Figure 20-1.)
ClearCase's hyperlink inheritance feature makes the implementation easy:
When the source module, hello.c, and the design document, hello_dsn.doc, are both updated, a new hyperlink is created connecting the two updated versions.
When either the source module or the design document gets a minor update, no hyperlink-level change is required — the new version automatically inherits the hyperlink connection of its predecessor.
When either the source module or the design document gets a significant update that renders the connection invalid, a null-ended hyperlink effectively severs the connection.
Using the -ihlink option when describing version /main/2 of the source module lists the hyperlink inherited from version /main/1 (Figure 20-2):
| Policy #11 | “A set of files form a group and should be checked out together.” |
Related files often live in a common directory and can be checked-out with a wildcard:
% cleartool checkout -c "Fix rendering bug" graphics/*.c |
When the files are not co-located, you can implement this policy by using an attribute to annotate elements, and by using a find query to supply a list of arguments to checkout.
% cleartool mkattype -c "group identifier" ElemGroup
Created attribute type "ElemGroup".
% cleartool mkattr ElemGroup '"graphics subsystem"' \
file1@@ \
subd/file2@@ \
../subd/file3@@ ...
Created attribute "ElemGroup" on "file1@@/main/14".
Created attribute "ElemGroup" on "subd/file2@@/main/8".
Created attribute "ElemGroup" on "../subd/file3@@/main/10".
...
< ... whenever checkout is to be performed:
% cleartool checkout -c "Fix rendering bug" \
`cleartool find . -element ' \
ElemGroup="graphics"' -nxname -print`
|