Alpha_1 Programmers's Manual


Using CVS with Alpha_1

Links

Basics

CVS stores directories of RCS files in a central "repository." RCS is used for revision numbers, tags, modification notices, diffs, etc. Sources are "checked out" for compilation or working tree development.

A CVS working directory has a CVS subdirectory controlled by CVS which contains a small number of files with information about your working directory.

The basic syntax is:

	cvs [options] command [options]
Examples of commands are checkout, diff, history, etc. Most commands have aliases which are shorter.

Examples

cvs -H
Help
cvs command -H
Help on "command"
cvs co module
Checkout a whole module. Creates a directory in $cwd for the module. The name of the directory is determined by the module definition.
cvs update filename
Bring filename up to current revision. Will create the file.
cvs -n -q update
Like make -n. Find out what's new, changed, missing, etc.

CVS vs. Alpha_1 Checkout et al

CVS has some differences compared to our home-grown Alpha_1 checkin system that will require us to work a little differently:

Terminology

CVS Equivalents of Alpha_1 Programs

Here are some equivalents of typical Alpha_1 commands:

Getting Sources to Your Working Dir

Alpha1: cd $w/whatever
	cp $a/whatever/files... .
	# Or
        checkout file
	# Or
        checkout -m files...
CVS:    cd $w/whatever
        cvs update files...
Cvs "update" does not ask for a reason. The "commit" (alias "ci") command always asks for the reason. You need to use a cvs command to get a copy of the source on your working dir so CVS knows which revision you have. The update command will create files for you so you DON'T want to just copy files from the source tree to your working tree.

Checking In Changes

Alpha1: checkin existingfiles...
CVS:    cvs ci -m "Reason" existingfiles... 

Alpha1: checkin newfiles...
CVS:    cvs add newfiles...
	cvs ci -m "Reason" newfiles... 
	# Or (can't do this with Alpha_1 checkin)
	cvs add new-binary-file
	cvs ci -m "Reason" new-binary-file 
	cvs admin -ko new-binary-file
Cvs uses the term "commit" but has the alias "ci" (checkin). To add a new file is a two-step process. The "admin" command is for binary files to make sure the RCS keyword expansion doesn't erroneously corrupt the binary data when the files are checked out. You only need to do this once.

Retiring/Renaming

Alpha1: retire files...
CVS:    cvs remove files...
        cvs ci files... -m "Reason"
Cvs is not particularly good at renaming or moving things. To rename, add a new file and remove the old one as above. Document the rename with the log message or even in the file header itself. The new file will have no history so we need to know the old file name to find the past change history (cvs keeps things in the "Attic" when you remove them).

Retaining History

You can retain the history when you move (rename) a file, but it is a more involved process (see the CVS manual for a comparison of renaming options). In the method described below, the source file is effectively moved, but the RCS file is copied. This is an important distinction! This method preserves the history of the file across the move. The old file will still be there if you checkout the sources with a symbolic tag that applies to the old file. After the RCS file is copied, the tags are removed from the new copy so that the file in its new location is not checked out in this case.

The disadvantage of this method is that if you checkout sources by date (-D) with a date previous to the move, the file will show up in both locations. This should not be a big problem with program source files since the makefiles should contain the correct set of files for a given date and the extraneous file should do no harm. Keep this in mind, however, when deciding to use this method.

Here is a detailed description of what to do:

History

Alpha1: checkhist file
# For diffs:
CVS:    cvs diff file
# For reasons and change history:
CVS:    cvs log file

Alpha1: a1chgs [options]
CVS:    cvs [options] history [options] 
Alpha1: cvs-chgs [options]
Alpha1: cvs-diff [revision] rel-path
Alpha1: cvs-log revision rel-path

Alpha1: check mueller
CVS:    ???
The Alpha_1 "check" command is not supported very well in CVS but without locking there's not much need for it. Cvs "history" can tell you something, but with our suggested style of use (see Alpha_1 Working Trees) it is not that useful. Some new scripts are described below that wrap CVS commands.

New Alpha_1 Scripts

There are some new Alpha_1 scripts for inquiring about changes to the system. The cvs-chgs script is meant to be equivalent to the old a1chgs script. There are two helper scripts cvs-diff which reports the diff between a given revision and the previous revision, and cvs-log which reports the log message (reason for the change) for a given revision.

Here's an example:

6 [res/mueller] velo.cs> cvs-chgs -H
Usage: cvs-chgs [-H] [-[dr]] [-t n] [-u user] [-D date]
    Default: Brief listing of todays checkins.
    -r Brief listing plus the reason.
    -d Full diff listing
    -t n    (tail -n) List the last "n" checkins.
    -u user List only checkins for "user".
    -D date Change since "date".
    -H Print this.

7 [res/mueller] velo.cs> cvs-chgs

M 04/27 10:46 mueller 1.2 src/lib/object/makefile
M 04/27 10:48 mueller 1.2 src/kernel/lib/features/makefile
A 04/27 10:50 mueller 1.1 src/kernel/lib/alpha1/obj1/anch_param.C
M 04/27 10:50 mueller 1.3 src/kernel/lib/alpha1/obj1/makefile
A 04/27 10:50 mueller 1.1 src/kernel/lib/alpha1/obj2/bb_anch_param.C
M 04/27 10:50 mueller 1.2 src/kernel/lib/alpha1/obj2/makefile
M 04/27 12:17 mueller 1.11 src/sys/pgm/util/cvs-update.csh
A 04/27 12:17 mueller 1.1 src/sys/pgm/util/cvs-chgs.csh
A 04/27 12:18 mueller 1.1 src/sys/pgm/util/cvs-diff.csh
A 04/27 12:18 mueller 1.1 src/sys/pgm/util/cvs-log.csh
M 04/27 12:18 mueller 1.4 src/sys/pgm/util/makefile

8 [res/mueller] velo.cs> cvs-chgs -t 4 -r

A 04/27 12:17 mueller 1.1 src/sys/pgm/util/cvs-chgs.csh
revision 1.1
date: 1995/04/27 18:17:58;  author: mueller;  state: Exp;
Add scripts for monitoring src changes
--------------------------------------------------------------
A 04/27 12:18 mueller 1.1 src/sys/pgm/util/cvs-diff.csh
revision 1.1
date: 1995/04/27 18:18:00;  author: mueller;  state: Exp;
Add scripts for monitoring src changes
--------------------------------------------------------------
A 04/27 12:18 mueller 1.1 src/sys/pgm/util/cvs-log.csh
revision 1.1
date: 1995/04/27 18:18:02;  author: mueller;  state: Exp;
Add scripts for monitoring src changes
--------------------------------------------------------------
M 04/27 12:18 mueller 1.4 src/sys/pgm/util/makefile
revision 1.4
date: 1995/04/27 18:18:04;  author: mueller;  state: Exp;  lines: +1 -0
Add scripts for monitoring src changes
--------------------------------------------------------------
The helper scripts are used by cvs-chgs, but you can use them directly if you just want to see one particular diff, or log message. They each take two arguments, the revision number and the relative path to the source file. (Using cvs-chgs and then cut & paste works well.)

If you leave out the optional revision number first argument to the cvs-diff script, it defaults to the latest revision.

9 [res/mueller] velo.cs> cvs-log 1.4 src/sys/pgm/util/makefile
revision 1.4
date: 1995/04/27 18:18:04;  author: mueller;  state: Exp;  lines: +1 -0
Add scripts for monitoring src changes

10 [res/mueller] velo.cs> cvs-diff 1.4 src/sys/pgm/util/makefile

===================================================================
RCS file: /res/alpha1/src/cvs/src/sys/pgm/util/makefile,v
retrieving revision 1.3
retrieving revision 1.4
diff -c -r1.3 -r1.4
*** 1.3 1995/04/11 21:28:59
--- 1.4 1995/04/27 18:18:04
***************
*** 17,22 ****
--- 17,23 ----
  SCRIPTS =     a1chgs a1make a1pwd aldb any-files      \
                build carousel cdemo checka1news checked-out-listing    \
                  checkin-everything check-makes copy-down cvs-update   \
+               cvs-chgs cvs-diff cvs-log                               \
                data depends-upon                                       \
                  depends-upon-proc diff-copies diff-copy diff-someone  \
                  diff-src echo-and-do echo-stderr empty executable     \

Alpha_1 Reference Tree

For compilation and read access to the code, user alpha1 will have a read-only copy of the entire source tree "checked out" as a reference tree. This will be what $a is now. As part of the nightly global makes the reference tree will be updated to get the latest changes using: cvs -r update -d. One nice side-effect is this will eliminate the need for the current "safe-include" directory since the reference tree will not be in a state of flux during the day as people check things in.

Alpha_1 Working Trees

Cvs is geared towards working trees where you have a complete copy of the sources for a module. Conceptually, we could define a module for every file, but that would be impractical. Keeping a copy of the entire source tree (30Meg) on working trees is also impractical. There is a compromise that CVS supports. Generally CVS commands apply recursively and will create any files that are missing from a working tree (including missing directories). However, if a special file (Entries.Static) exists on a CVS subdirectory, CVS will only apply the command to the files that actually exist on that directory (plus any files are explicitly listed in the command). See the FAQ included below.

This allows us to make a bare working tree with no files as a starting point and you can only have the files you are actually working on in your working tree. It doesn't hurt to have other files around (except for possible extra compilation) since CVS is good at telling you what you have compared to the source tree and updating your files when you want. I have written a script that will run over an entire working tree and make the CVS administrative files reflect the actual contents of your working directories.

The working style for this type of CVS tree is:

  1. Create an empty (skeleton) working tree (with CVS administrative directories). There is one you can copy with cp -rp /res/alpha1/wrk/cvs-wrk/* $w. Move your current working directory elsewhere for the moment.
  2. Use cd $w/workdir; cvs update file to get files into your working directories. (Emacs ^C-w should be made to do this.)
  3. Use cvs ci files to checkin changes (does not remove the files).
  4. Just rm files when you no longer need them. Run fix-cvs-entries script over your working tree to get CVS files back in sync after removing files.
A suggested practice is to run fix-cvs-entries and then cvs -n -q update over your working tree before you start work each day. It's not fatal if the CVS files and the directory contents are out of sync, especially since they only get out of sync when you remove files. You may see some warnings and messages like: "file foo.C needs to be checked out." Beware, however, that update will not create any new files or directories that have been created by others for any directory with a ./CVS/Entries.Static file. You can get them by issuing an "update" command explicitly for those files/directories.

Real Example

Here's an example starting with a copy of the bare skeleton working tree.
190 [mueller/cvs] velo.cs> cd $w$cmds
191 [cvs/cmds] velo.cs> ls
CVS
194 [cvs/cmds] velo.cs> cvs update set-envars set-envars.sh
U set-envars
U set-envars.sh
196 [cvs/cmds] velo.cs> ls
CVS             set-envars      set-envars.sh

# Make some changes....

197 [cvs/cmds] velo.cs> cvs status
cvs status: Examining .
===================================================================
File: set-envars        Status: Locally Modified

    Version:            1.1.1.1 Thu Mar 30 12:46:57 1995
    RCS Version:        1.1.1.1 /res/alpha1/src/cvs/cmds/set-envars,v
    Sticky Tag:         (none)
    Sticky Date:        (none)
    Sticky Options:     (none)

===================================================================
File: set-envars.sh     Status: Locally Modified

    Version:            1.1.1.1 Thu Mar 30 12:46:58 1995
    RCS Version:        1.1.1.1 /res/alpha1/src/cvs/cmds/set-envars.sh,v
    Sticky Tag:         (none)
    Sticky Date:        (none)
    Sticky Options:     (none)

198 [cvs/cmds] velo.cs> cvs -n update
cvs update: Updating .
M set-envars
M set-envars.sh
199 [cvs/cmds] velo.cs> cvs ci -m "Set RCSBIN to /usr/local/gnu/bin for CVS"
cvs commit: Examining .
cvs commit: Committing .
Checking in set-envars;
/res/alpha1/src/cvs/cmds/set-envars,v  <--  set-envars
new revision: 1.2; previous revision: 1.1
done
Checking in set-envars.sh;
/res/alpha1/src/cvs/cmds/set-envars.sh,v  <--  set-envars.sh
new revision: 1.2; previous revision: 1.1
done

Converting Existing Working Trees

If you have significant work in your current working tree, here is how to proceed. The following assumes your current working tree is /res/alpha1/wrk/$USER
	cd $w/..
	# Save current tree
	mv $USER $USER.old
	# Copy skeleton CVS tree
	cp -rp cvs-wrk $USER
	cd $USER.old
	# List all files in old tree
	find . -type f -print
The find will look something like this:
345 velo.cs> find . -type f -print
./include/a1defaults.h
./include/a1_stream.h
./include/anch_param.h
./include/attribute.h
./include/basic.h
./include/dl/dl_dev.h
./include/dl/dl_seg.h
./include/dl/dl_window.h
./include/dl/mfc_dev.h
./include/dl/r_dev.h
./include/except.h
...
You need to grab this output and massage it into two scripts using emacs keyboard macros, awk, or whatever. First you need to use cvs update to get current versions of all the files you had in your old tree. This should look something like this:
# Your NEW CVS tree
cd $w
cvs update include/a1_stream.h
cvs update include/a1defaults.h
cvs update include/anch_param.h
cvs update include/attribute.h
cvs update include/basic.h
cvs update include/dl/dl_dev.h
cvs update include/dl/dl_seg.h
cvs update include/dl/dl_window.h
cvs update include/dl/mfc_dev.h
cvs update include/dl/r_dev.h
cvs update include/except.h
...
Now your CVS tree has current copies of every source file you had in your old working tree. Now you replace these copies with your old working files like this:
# Connect to your OLD working tree
cd ../$USER.old
cp include/a1_stream.h ../$USER/include/a1_stream.h
cp include/a1defaults.h ../$USER/include/a1defaults.h
cp include/anch_param.h ../$USER/include/anch_param.h
cp include/attribute.h ../$USER/include/attribute.h
cp include/basic.h ../$USER/include/basic.h
cp include/dl/dl_dev.h ../$USER/include/dl/dl_dev.h
cp include/dl/dl_seg.h ../$USER/include/dl/dl_seg.h
cp include/dl/dl_window.h ../$USER/include/dl/dl_window.h
cp include/dl/mfc_dev.h ../$USER/include/dl/mfc_dev.h
cp include/dl/r_dev.h ../$USER/include/dl/r_dev.h
cp include/except.h ../$USER/include/except.h
...
Now your new CVS working tree is ready to go. CVS can now tell you if someone checks in new versions of these files in the future and help you with the merging, etc.

Alpha_1 Modules

If you choose to use cvs co for entire modules, the modules are defined in $CVSROOT/CVSROOT/modules. This file itself can be checked out and worked on like any other file in the repository.

There are CVS modules for the top-level directories of $a:

There is a module a1src is for the whole source tree. There are modules for most of the alpha1 directories named after the shell variables we use.

To work on an entire module:

  1. Connect to the parent directory in your working tree. For example
    cd $w$klib
    
    if you want to checkout $alib. CVS does not care where you are connected and alway works relative to the current directory. You must have a working tree structure that matches the source tree in order for our build system (make) to work so you need to be connected to the right place before you use checkout.
  2. Move or remove your current partially populated working subtree. Eg:
    cd $w$klib
    mv alpha1 save-alpha1
    # Or
    rm -r alpha1 
    
  3. Checkout the module:
    cd $w$klib
    cvs co alib
    
    If you skip step 2 "checkout" will work but CVS will still think you have a partial copy. So it is best to let CVS create the whole subtree.
  4. Copy files into the new CVS subtree or start editing.
  5. Use cvs update from now on (now that you've checked out the whole module).
Here's another example of checking out an entire module.
    cd $w
    cvs co man
    cd man
    # Make some changes ...
    # Check status
    cvs -n -q update
    # Incorporate someone else's changes
    cvs update html/shape_edit/shape_edit.html
    cvs diff
    cvs ci -m "Checkin my changes"

Original A1 Import

The Alpha_1 sources were imported as of March 30, 1995. The source tree was copied to $a2/alpha1/a1src.3.30.95 and machine generated files removed (*.elc, _*, [IDO]*). A new directory "rootfiles" was created and the Copyright and RESTRICTED.RIGHTS files moved into it because cvs only deals with directories. The cvs commands used to import were:
cd $a/emacs
cvs import -m "Original alpha1 import" emacs A1SRC alpha1-95-03
cd $a/src
cvs import -m "Original alpha1 import" src A1SRC alpha1-95-03
cd $a/include
cvs import -m "Original alpha1 import" include A1SRC alpha1-95-03
cd $a/cmds
cvs import -m "Original alpha1 import" cmds A1SRC alpha1-95-03
cd $w/rootfiles
cvs import -m "Original alpha1 import" rootfiles A1SRC alpha1-95-03
cd $a/data
cvs import -m "Original alpha1 import" data A1SRC alpha1-95-03
cd $a/tst
cvs import -m "Original alpha1 import" tst A1SRC alpha1-95-03
The import commands tag the entire source tree with name "alpha1-95-03" for future reference (i.e.: the origin sources can be checked out by this name). Import puts the original on a special "branch" labeled 1.1.1. The initial revision number for each file is 1.1.1.1 (on the branch). The first modification of each file results in revision 1.2 (on the main branch). See the manual for more on tags and branching.

Useful FAQ's

4D.10 Where did the ./CVS/Entries.Static file come from? What is it for?

  Each CVS working directory contains a ./CVS/Entries file listing
  the files managed by CVS in that working directory.  Normally, if
  the "update" command finds a file in the Repository that is not in
  the ./CVS/Entries file, "update" copies the appropriate revision
  of the "new" file out of the Repository and adds the filename to
  the Entries file.  This happens for files:

     1. Added to the Repository from another working directory.
     2. Dragged out of the Attic when switching branches with
	"update -A" or "update -r".
     3. Whose names were deleted from the ./CVS/Entries file.

  If the ./CVS/Entries.Static file exists, CVS will only bring out
  revisions of files that are contained in either ./CVS/Entries or
  ./CVS/Entries.Static.  If a Repository file is found in *neither*
  file, it is ignored.

  The ./CVS/Entries.Static file is created when you check out an
  individual file or a module that creates working directories that
  don't contain all files in the corresponding Repository directory.
  In those cases, without an ./CVS/Entries.Static file, a simple
  "update" would bring more files out of the Repository than the
  original "checkout" wanted.

  The ./CVS/Entries.Static file can be removed by hand.  It is
  automatically removed if you run "update -d" to create new
  directories (even if no new directories are created).
  (Internally, since "checkout" turns on the '-d' flag and calls the
  "update" routine, a "checkout" of a module or directory that
  writes into an existing directory will also remove the
  ./CVS/Entries.Static file.)

Summary of Alpha_1 CVS Use


Alpha_1 Programmer's Manual Home Page
Alpha_1 Programmer's Manual. Version 95.06.
Copyright © 1995, University of Utah
alpha1@gr.utah.edu