Chapter 8. Revising a Directory Structure

In preceding lessons, you saw that ClearCase provides version-control of directory elements as well as file elements. Ordinary version-control systems handle the fact that the contents of source files change from release to release. ClearCase directory elements enable handling of additional kinds of release-to-release changes: files added, deleted, and renamed; files moved to a different directory; even major directory tree overhauls.

In this lesson, you'll do some new development that involves creating a new version of directory element src. Before going on, however, let's take a few moments to clarify what a version of a directory element contains. Like a standard UNIX directory, a version of a ClearCase directory element contains a list of names. The following kinds of objects can be named in a directory version:

Whenever you wish to change a directory's list of names, you must create a new version of the directory. This means checking out the directory, modifying it, and checking it back in. Modifications to a directory include:

Get your bearings

At the end of the preceding lesson, you were in the src directory, in a shell set to view USER_HOST_tut. Verify that you are still in the same situation.

% cleartool pwv -short
USER_HOST_tut
% pwd
VOBTAG/src

If you've gotten lost, you may need to use a full pathname to find the source directory.

cd VOBTAG/src

If this command fails, it is probably because you exited the shell that was set to your view. Enter the following commands to reestablish your view context and your working directory within the VOB.

cleartool setview USER_HOST_tut
cd VOBTAG/src

Compare versions of a directory

In Lesson 4, you changed config specs in order to access “old” versions of the src source directory. An alternative method is to use version-extended pathname to reach directly into the version tree of a directory element. For example, you can examine the Release 1 contents of src and its Release 3 contents without having to change your config spec at all.

% cd ..
% cleartool ls -vob_only src@@/main/REL1
src@@/main/REL1/Makefile@@
src@@/main/REL1/hello.c@@
% cleartool ls -vob_only src@@/main/REL3
src@@/main/REL3/Makefile@@
src@@/main/REL3/hello.c@@
src@@/main/REL3/hello.h@@
src@@/main/REL3/util.c@@

Several times during this tutorial, you have used syntax like src@@/main/REL1 to name a version of a file element. Version-extended pathnames for file and directory versions have exactly the same format. Since src is a directory element, ls is the appropriate command for examining the contents of one of its versions. For versions of file elements, cat or more is appropriate.

As always, the -vob_only option excludes view-private objects and derived objects. Without this option, the ls listing would include both the currently existing view-private and derived objects and the “old” versions selected by the view.

Were you expecting to see particular versions of the source files in these listings? This would be incorrect—a directory version does not contain versions of elements; it only contains names of elements.


Note: There was no need to change to the parent directory in this step. You can “dive into” the version tree of the current directory with a version-extended pathname like .@@/main/REL1. Similar comments apply to performing a checkout of the current working directory (which you'll do soon). Since this format is a bit confusing at first, we used a more intuitive command sequence.


Prepare to do some new development

The new development work involves splitting the work of file hello.c into two parts. In previous releases, hello.c both composed a message and displayed it. Now, the job of composing the message will be implemented by a hello_msg() function, whose source code is in a new file, msg.c. The main() function in hello.c will now simply display whatever message is composed by hello_msg().

(This change might by motivated by the desire to create variants of the hello program, which present their messages in different ways. For example, an xhello variant might display the message in an X Window System window.)

Checkout the source directory

Your work involves creating a new source file, msg.c, which you (naturally) wish to place under source control. In other words, you wish to modify the src directory element by adding the name msg.c. Before you make this modification, you must first checkout the directory.

% cleartool checkout -nc src
Checked out "src" from version "/main/2".

Create a new file element

The mkelem (“make element”) command creates a new element.

% cd src
% cleartool mkelem msg.c
Creation comments for "msg.c":
new file to generate message
.
Created element "msg.c" (type "text_file").
Checked out "msg.c" from version "/main/0".

ClearCase automatically chooses text_file as the element type, because it recognizes the .c file name suffix on msg.c. Versions of text_file elements are stored efficiently, as deltas in a single data container file, in much the same way as SCCS or RCS versions.

The mkelem command automatically performs a checkout of the new file element, so that you can edit it immediately.

Checkin the source directory

The creation of the msg.c file element is the only change you need to make to the current directory, so check it in.

% cleartool checkin .
Default:
Added file element "msg.c".
Checkin comments for ".":  ("." to accept default)
.
Checked in "." version "/main/3".

You need not keep the src directory checked-out in order to modify the files within it. (Remember that you modified files often in the preceding lessons, all without having to checkout the src directory.) Directories and files are closely related, but they evolve independently:

  • Checking out a file allows you to change its contents (for example, with a text editor).

  • Checking out a directory allows you to change its contents—the names of file elements (and other directory elements)—for example, by creating new elements, renaming elements, and removing elements.

Compare the new directory to its predecessor

ClearCase includes the ability to diff directories. Let's confirm our change to the src directory.

% cleartool diff -predecessor .
********************************
<<< directory 1: /_tmp/gdvob/src@@/main/2
>>> directory 2: .
********************************
-----------------------------|---------------[ added ]-------
                            -| msg.c  09-Feb.16:31 USER

Modify the new source file

The new source file, msg.c, is currently empty. Let's “write” some code in the usual way (for this tutorial), by copying it from the repository.

% cp /usr/atria/doc/tutorial/ms.1 msg.c
% cat msg.c
#include "hello.h"

  char *
  hello_msg() {
   static char msg[256];

   sprintf (msg,
   "Hello, %s!\nYour home directory is %s.\nIt is now %s.\n",
             env_user(),
             env_home(),
             env_time() );

    return msg;
  }

Modify the old source files

In addition to creating msg.c, your task involves modifying hello.c, hello.h, and the Makefile. Since this is ground that we've covered before, let's do it without much ceremony.

% cleartool checkout -nc hello.c hello.h Makefile
Checked out "hello.c" from version "/main/3".
Checked out "hello.h" from version "/main/1".
Checked out "Makefile" from version "/main/2".
% cp /usr/atria/doc/tutorial/hc.4 hello.c
% cleartool diff -pred hello.c
********************************
<<< file 1: VOBTAG/src/hello.c@@/main/3
>>> file 2: hello.c
********************************
---------[changed 4-6]-------------|-------[changed to 4]------
printf("Hello, %s!\n", env_user() +|     printf(hello_msg());
printf("Your home directory is %s.+|-
printf("It is now %s.\n", env_time+| 
% cp /usr/atria/doc/tutorial/hh.2 hello.h
% cleartool diff -pred hello.h
********************************
<<< file 1: VOBTAG/src/hello.h@@/main/1
>>> file 2: hello.h
********************************
-----------[after 7]----------|----------[inserted 8]---------
                             -|   extern char *hello_msg();
                              |-
% cp /usr/atria/doc/tutorial/mk.3 Makefile
% cleartool diff -pred Makefile
********************************
<<< file 1: VOBTAG/src/Makefile@@/main/2
>>> file 2: Makefile
********************************
------------[changed 3-4]------------|-------[changed to 3-4]--------
hello: hello.o util.o                | hello: hello.o util.o msg.o
    $(MKTUT_CC) -o hello hello.o u+  |   $(MKTUT_CC) -o hello hello.o u+
                                    -|-
-------------[after 11]--------------|----------[inserted 12-14]-----
                                    -| msg.o:
                                     |         $(MKTUT_CC) -c msg.c
                                     | 

                                     |-
------------[changed 13]-------------|----------[changed to 16]------
     rm -f hello hello.o util.o      |   rm -f hello hello.o util.o msg+

These commands prove (once again) that a directory need not be checked-out when you modify the contents of its files.

Rebuild the program

That's all the editing to be done. Let's compile.

% clearmake -v hello
Cannot reuse "hello.o" - version mismatch for "hello.c"

======== Rebuilding "hello.o" ========
        cc -c hello.c
Will store derived object "VOBTAG/src/hello.o"
========================================================

Cannot reuse "util.o" - version mismatch for "hello.h"

======== Rebuilding "util.o" ========
        cc -c util.c
Will store derived object "VOBTAG/src/util.o"
========================================================

No candidate in current view for "msg.o"

======== Rebuilding "msg.o" ========
        cc -c msg.c
Will store derived object "VOBTAG/src/msg.o"
========================================================

Must rebuild "hello" - due to rebuild of subtarget "hello.o"

======== Rebuilding "hello" ========
        cc -o hello hello.o util.o msg.o
Will store derived object "VOBTAG/src/hello"
========================================================

Note that clearmake rebuilds all the object modules, since you've edited all the source files for this program.

Test the program

Make sure that the hello program still runs correctly.

% ./hello
Hello, USER!
Your home directory is /home/USER.
It is now DATESTRING.

What files need to be checked in?

You've made quite a few source changes. It may be difficult to recall exactly which files you have checked out. The command lscheckout –cview –short saves you the trouble of having to remember.

% cleartool lscheckout -cview -short
Makefile
hello.c
hello.h
msg.c

Compare this listing with that in Step 26, when you used the –cview option, but not the –short option.

Checkin the sources

The file name list displayed by the preceding command is exactly what you need to specify to the next command, checkin. The C shell `!!` idiom incorporates this list into the checkin command, as the list of files to be checked in.

% cleartool checkin -c "modularize msg generation + display" `!!`
Checked in "Makefile" version "/main/3".
Checked in "hello.c" version "/main/4".
Checked in "hello.h" version "/main/2".
Checked in "msg.c" version "/main/1".