This is ossdev.info, produced by makeinfo version 4.3 from
../book/ossdev/main.texi.

START-INFO-DIR-ENTRY
* CVS Book: (cvsbook).          A CVS tutorial and reference.
END-INFO-DIR-ENTRY

Copyright (C) 1999, 2000 Karl Fogel <kfogel@red-bean.com>

This document is free software; you can redistribute and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This document is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

This manual describes how to use and administer CVS (Concurrent Versions
System).  It is part of a larger work entitled `Open Source Development
With CVS'; please see the introduction for details.

This is version 1.21 of this manual.


File: ossdev.info,  Node: Tracking Third-Party Sources (Vendor Branches),  Next: Exporting For Public Distribution,  Prev: Going Out On A Limb (How To Work With Branches And Survive),  Up: Advanced CVS

Tracking Third-Party Sources (Vendor Branches)
==============================================

Sometimes a site will make local changes to a piece of software received
from an outside source.  If the outside source does not incorporate the
local changes (and there might be many legitimate reasons why it can't),
the site has to maintain its changes in each received upgrade of the
software.

CVS can help with this task, via a feature known as "vendor branches".
In fact, vendor branches are the explanation behind the puzzling (until
now) final two arguments to cvs import: the vendor tag and release tag
that I glossed over in *Note An Overview of CVS::.

Here's how it works.  The initial import is just like any other initial
import of a CVS project (except that you'll want to choose the vendor
tag and release tag with a little care):

     floss$ pwd
     /home/jrandom/theirproj-1.0
     floss$ cvs import -m "Import of TheirProj 1.0" theirproj Them THEIRPROJ_1_0
     N theirproj/INSTALL
     N theirproj/README
     N theirproj/src/main.c
     N theirproj/src/parse.c
     N theirproj/src/digest.c
     N theirproj/doc/random.c
     N theirproj/doc/manual.txt
     
     No conflicts created by this import
     
     floss$

Then you check out a working copy somewhere, make your local
modifications, and commit:

     floss$ cvs -q co theirproj
     U theirproj/INSTALL
     U theirproj/README
     U theirproj/doc/manual.txt
     U theirproj/doc/random.c
     U theirproj/src/digest.c
     U theirproj/src/main.c
     U theirproj/src/parse.c
     floss$ cd theirproj
     floss$ emacs src/main.c src/digest.c
      ...
     floss$ cvs -q update
     M src/digest.c
     M src/main.c
     floss$ cvs -q ci -m "changed digestion algorithm; added comment to main"
     Checking in src/digest.c;
     /usr/local/newrepos/theirproj/src/digest.c,v  <--  digest.c
     new revision: 1.2; previous revision: 1.1
     done
     Checking in src/main.c;
     /usr/local/newrepos/theirproj/src/main.c,v  <--  main.c
     new revision: 1.2; previous revision: 1.1
     done
     floss$

A year later, the next version of the software arrives from Them, Inc.,
and you must incorporate your local changes into it.  Their changes and
yours overlap slightly.  They've added one new file, modified a couple
of files that you didn't touch, but also modified two files that you
modified.

First you must do another import, this time from the new sources.
Almost everything is the same as it was in the initial import - you're
importing to the same project in the repository, and on the same vendor
branch.  The only thing different is the release tag:

     floss$ pwd
     /home/jrandom/theirproj-2.0
     floss$ cvs -q import -m "Import of TheirProj 2.0" theirproj Them THEIRPROJ_2_0
     U theirproj/INSTALL
     N theirproj/TODO
     U theirproj/README
     cvs import: Importing /usr/local/newrepos/theirproj/src
     C theirproj/src/main.c
     U theirproj/src/parse.c
     C theirproj/src/digest.c
     cvs import: Importing /usr/local/newrepos/theirproj/doc
     U theirproj/doc/random.c
     U theirproj/doc/manual.txt
     
     2 conflicts created by this import.
     Use the following command to help the merge:
     
            cvs checkout -jThem:yesterday -jThem theirproj
     
     floss$

My goodness - we've never seen CVS try to be so helpful.  It's actually
telling us what command to run to merge the changes.  And it's almost
right, too!  Actually, the command as given works (assuming that you
adjust yesterday to be any time interval that definitely includes the
first import but not the second), but I mildly prefer to do it by
release tag instead:

     floss$ cvs checkout -j THEIRPROJ_1_0 -j THEIRPROJ_2_0 theirproj
     cvs checkout: Updating theirproj
     U theirproj/INSTALL
     U theirproj/README
     U theirproj/TODO
     cvs checkout: Updating theirproj/doc
     U theirproj/doc/manual.txt
     U theirproj/doc/random.c
     cvs checkout: Updating theirproj/src
     U theirproj/src/digest.c
     RCS file: /usr/local/newrepos/theirproj/src/digest.c,v
     retrieving revision 1.1.1.1
     retrieving revision 1.1.1.2
     Merging differences between 1.1.1.1 and 1.1.1.2 into digest.c
     rcsmerge: warning: conflicts during merge
     U theirproj/src/main.c
     RCS file: /usr/local/newrepos/theirproj/src/main.c,v
     retrieving revision 1.1.1.1
     retrieving revision 1.1.1.2
     Merging differences between 1.1.1.1 and 1.1.1.2 into main.c
     U theirproj/src/parse.c
     floss$

Notice how the import told us that there were two conflicts, but the
merge only seems to claim one conflict.  It seems that CVS's idea of a
conflict is a little different when importing than at other times.
Basically, import reports a conflict if both you and the vendor modified
a file between the last import and this one.  However, when it comes
time to merge, update sticks with the usual definition of "conflict" -
overlapping changes.  Changes that don't overlap are merged in the usual
way, and the file is simply marked as modified.

A quick diff verifies that only one of the files actually has conflict
markers:

     floss$ cvs -q update
     C src/digest.c
     M src/main.c
     floss$ cvs diff -c
     Index: src/digest.c
     ===================================================================
     RCS file: /usr/local/newrepos/theirproj/src/digest.c,v
     retrieving revision 1.2
     diff -c -r1.2 digest.c
     *** src/digest.c        1999/07/26 08:02:18     1.2
     -- src/digest.c        1999/07/26 08:16:15
     ***************
     *** 3,7 ****
     -- 3,11 ----
      void
      digest ()
      {
     + <<<<<<< digest.c
        printf ("gurgle, slorp\n");
     + =======
     +   printf ("mild gurgle\n");
     + >>>>>>> 1.1.1.2
      }
     Index: src/main.c
     ===================================================================
     RCS file: /usr/local/newrepos/theirproj/src/main.c,v
     retrieving revision 1.2
     diff -c -r1.2 main.c
     *** src/main.c  1999/07/26 08:02:18     1.2
     -- src/main.c  1999/07/26 08:16:15
     ***************
     *** 7,9 ****
     -- 7,11 ----
      {
        printf ("Goodbye, world!\n");
      }
     +
     + /* I, the vendor, added this comment for no good reason. */
     floss$

From here, it's just a matter of resolving the conflicts as with any
other merge:

     floss$ emacs  src/digest.c  src/main.c
      ...
     floss$ cvs -q update
     M src/digest.c
     M src/main.c
     floss$ cvs diff src/digest.c
     cvs diff src/digest.c
     Index: src/digest.c
     ===================================================================
     RCS file: /usr/local/newrepos/theirproj/src/digest.c,v
     retrieving revision 1.2
     diff -r1.2 digest.c
     6c6
     <   printf ("gurgle, slorp\n");
     --
     >   printf ("mild gurgle, slorp\n");
     floss$

Then commit the changes

     floss$ cvs -q ci -m "Resolved conflicts with import of 2.0"
     Checking in src/digest.c;
     /usr/local/newrepos/theirproj/src/digest.c,v  <--  digest.c
     new revision: 1.3; previous revision: 1.2
     done
     Checking in src/main.c;
     /usr/local/newrepos/theirproj/src/main.c,v  <--  main.c
     new revision: 1.3; previous revision: 1.2
     done
     floss$

and wait for the next release from the vendor.  (Of course, you'll also
want to test that your local modifications still work!)

-------------------------------------------------------------


File: ossdev.info,  Node: Exporting For Public Distribution,  Next: The Humble Guru,  Prev: Tracking Third-Party Sources (Vendor Branches),  Up: Advanced CVS

Exporting For Public Distribution
=================================

CVS is a good distribution mechanism for developers, but most users will
obtain the software through a downloadable package instead.  This
package is generally not a CVS working copy - it's just a source tree
that can be easily configured and compiled on the user's system.

However, CVS does offer a mechanism to help you create that package,
namely the `cvs export' command.  To "export" a project is just like
checking out a working copy of the project, except that it checks out
the project tree _without_ any `CVS' administrative subdirectories.
That is to say, you don't get a working copy, you just get a source
tree that knows nothing about where it came from or what the CVS
versions of its files are.  Thus, the exported copy is just like what
the public sees after it downloads and unpacks a distribution.
Assuming the project is arranged to be directly compilable from a
working copy (and it certainly should be!), then it will still be
compilable from the exported copy.

The `export' command works like `checkout', except that it requires a
tag name or date.  For example, here we tag the project with a release
name, and then export based on that:

     floss$ pwd
     /home/jrandom/myproj
     floss$ cvs -q tag R_1_0
     T README.txt
     T hello.c
     T a-subdir/whatever.c
     T a-subdir/subsubdir/fish.c
     T b-subdir/random.c
     floss$ cd ..
     floss$ cvs -d /usr/local/newrepos -q export -r R_1_0 -d myproj-1.0 myproj
     U myproj-1.0/README.txt
     U myproj-1.0/hello.c
     U myproj-1.0/a-subdir/whatever.c
     U myproj-1.0/a-subdir/subsubdir/fish.c
     U myproj-1.0/b-subdir/random.c
     floss$ cd myproj-1.0
     floss$ ls
     README.txt  a-subdir  b-subdir  hello.c

Notice how, since the `export' command is not invoked from within a
working copy, it's necessary to use the global `-d' option to tell CVS
which repository to use.  Also, in this particular example, we exported
into an explicitly named directory (`myproj-1.0') instead of defaulting
to the project's name (`myproj'), since there was a working copy of
that name already present.  This situation is not uncommon.

After the exported copy is created, as in the above example, the
following might be sufficient to complete the release, if the project is
a simple one:

     floss$ tar cf myproj-1.0.tar myproj-1.0
     floss$ gzip --best myproj-1.0.tar
     floss$ ls
     myproj/   myproj-1.0/   myproj-1.0.tar.gz
     floss$ rm -rf myproj-1.0
     floss$ mv myproj-1.0.tar.gz /home/ftp/pub/myproj/

Of course, running all of these commands by hand is rare.  More often,
`cvs export' is called from within some script that handles all aspects
of release and packaging process.  Given that there are often several
"test" releases leading up to each public release, it is desirable that
the procedures for creating a releasable package be highly automated.


File: ossdev.info,  Node: The Humble Guru,  Prev: Exporting For Public Distribution,  Up: Advanced CVS

The Humble Guru
===============

If you read and understood (and better yet, experimented with)
everything in this chapter, you may rest assured that there are no big
surprises left for you in CVS - at least until someone adds a major new
feature to CVS.  Everything you need to know to use CVS on a major
project has been presented.

Before that goes to your head, let me reiterate the suggestion, first
made in Chapter 4, that you subscribe to the <info-cvs@gnu.org> mailing
list.  Despite having the impoverished signal-to-noise ratio common to
most Internet mailing lists, the bits of signal that do come through
are almost always worth the wait.  I was subscribed during the entire
time I wrote this chapter (indeed, for all previous chapters as well),
and you would be amazed to know how many important details I learned
about CVS's behavior from reading other people's posts.  If you're
going to be using CVS seriously, and especially if you're the CVS
administrator for a group of developers, you can benefit a lot from the
shared knowledge of all the other serious users out there.


File: ossdev.info,  Node: Tips And Troubleshooting,  Next: CVS Reference,  Prev: Advanced CVS,  Up: Top

Tips And Troubleshooting
************************

I've said in earlier chapters that CVS is not "black box" software.
Black boxes don't let you peek inside; they don't give you internal
access so that you can fix (or break) things.  The premise is that the
black box usually doesn't need to be fixed.  Most of the time, the
software should work perfectly, so users don't need internal access.
But when black boxes do fail, they tend to fail completely.  Any problem
at all is a showstopper, because there aren't many options for repair.

CVS is more like a perfectly transparent box - except without the box.
Its moving parts are exposed directly to the environment, not
hermetically sealed off, and bits of that environment (unexpected file
permissions, interrupted commands, competing processes, whatever) can
sometimes get inside the mechanism and gum up the gears.  But even
though CVS does not always work perfectly, it rarely fails completely,
either.  It has the advantage of graceful degradation; the degree to
which it doesn't work is usually proportional to the number and severity
of problems in its environment.  If you know enough about what CVS is
trying to do - and how it's trying to do it - you'll know what to do
when things go wrong.

Although I can't list all of the problems that you might encounter, I've
included some of the more common ones here.  This chapter is divided
into two sections: The first describes those parts of the environment to
which CVS is most sensitive (mainly repository permissions and the
working copy administrative area), and the second describes some of the
most frequently encountered problems and their solutions.  By seeing how
to handle these common situations, you will get a feeling for how to
approach any unexpected problem in CVS.

* Menu:

* The Usual Suspects::                       Things that often cause trouble.
* General Troubleshooting Tips::             General diagnostic techniques.
* Some Real Life Problems (With Solutions):: A compendium of actual problems.


File: ossdev.info,  Node: The Usual Suspects,  Next: General Troubleshooting Tips,  Up: Tips And Troubleshooting

The Usual Suspects
==================

As a CVS administrator (read "field doctor"), you will find that 90
percent of your users' problems are caused by inconsistent working
copies, and the other 90 percent by incorrect repository permissions.
Therefore, before looking at any specific situations, I'll give a quick
overview of the working copy administrative area and review a few
important things about repository permissions.

* Menu:

* The Working Copy Administrative Area::
* Repository Permissions::


File: ossdev.info,  Node: The Working Copy Administrative Area,  Next: Repository Permissions,  Up: The Usual Suspects

The Working Copy Administrative Area
------------------------------------

You've already seen the basics of working copy structure in *Note An
Overview of CVS::; in this section, we'll go into a bit more detail.
Most of the details concern the files in the CVS/ administrative
subdirectories.  You already know about Entries, Root, and Repository,
but the CVS/ subdirectory can also contain other files, depending on the
circumstances.  I'll describe those other files here, partly so they
don't surprise you when you encounter them, and partly so you can fix
them if they ever cause trouble.

`CVS/Entries.Log'
=================

Sometimes, a file named `CVS/Entries.Log' will mysteriously appear.
The sole purpose of this file is to temporarily cache minor changes to
CVS/Entries, until some operation significant enough to be worth
rewriting the entire Entries file comes along.  CVS has no ability to
edit the Entries file in place; it must read the entire file in and
write it back out to make any change.  To avoid this effort, CVS
sometimes records small changes in Entries.Log, until the next time it
needs to rewrite Entries.

The format of Entries.Log is like Entries, except for an extra letter at
the beginning of each line. `A' means that the line is to be added to
the main Entries file, and `R' means it is to be removed.

For the most part, you can ignore Entries.Log; it's rare that a human
has to understand the information it contains.  However, if you're
reading over an Entries file to debug some problem in a working copy,
you should also examine Entries.Log.

`CVS/Entries.Backup'
====================

The CVS/Entries.Backup file is where CVS actually writes out a new
Entries file, before renaming it to `Entries' (similar to the way it
writes to temporary RCS files in the repository and then moves them to
their proper name when they're complete).  Because it becomes Entries
when it's complete, you'll rarely see an Entries.Backup file; if you do
see one, it probably means CVS got interrupted in the middle of some
operation.

`CVS/Entries.Static'
====================

If the CVS/Entries.Static file exists, it means that the entire
directory has not been fetched from the repository.  (When CVS knows a
working directory is in an incomplete state, it will not bring
additional files into that directory.)

The Entries.Static file is present during checkouts and updates and
removed immediately when the operation is complete.  If you see
Entries.Static, it means that CVS was interrupted, and its presence
prevents CVS from creating any new files in the working copy.  (Often,
running `cvs update -d' solves the problem and removes Entries.Static.)

The absence of Entries.Static does not necessarily imply that the
working copy contains all of the project's files.  Whenever a new
directory is created in the project's repository, and someone updates
their working copy without passing the -d flag to update, the new
directory will not be created in the working copy.  Locally, CVS is
unaware that there is a new directory in the repository, so it goes
ahead and removes the Entries.Static file when the update is complete,
even though the new directory is not present in the working copy.

`CVS/Tag'
=========

If the CVS/Tag file is present, it names a tag associated, in some
sense, with the directory.  I say "in some sense" because, as you know,
CVS does not actually keep any revision history for directories and,
strictly speaking, cannot attach tags to them.  Tags are attached to
regular files only or, more accurately, to particular revisions in
regular files.

However, if every file in a directory is on a particular tag, CVS likes
to think of the entire directory as being on the tag, too.  For example,
if you were to check out a working copy on a particular branch:

     floss$ cvs co -r Bugfix_Branch_1

and then add a file inside it, you'd want the new file's initial
revision to be on that branch, too.  For similar reasons, CVS also needs
to know if the directory has a nonbranch sticky tag or date set on it.

Tag files contain one line.  The first character on the line is a
single-letter code telling what kind of tag it is, and the rest of the
line is the tag's name.  Currently, CVS uses only these three
single-letter codes:

   * T - A branch tag

   * N - A nonbranch (regular) tag

   * D - A sticky date, which occurs if a command such as

          floss$ cvs checkout -D 1999-05-15 myproj

     or

          floss$ cvs update -D 1999-05-15 myproj

     is run.


(If you see some other single-letter code, it just means that CVS has
added a new tag type since this chapter was written.)

You should not remove the Tag file manually; instead, use
`cvs update -A'.

Rarities
========

There are a few other files you may occasionally find in a CVS/
subdirectory:

   * CVS/Checkin.prog, CVS/Update.prog

   * CVS/Notify, CVS/Notify.tmp

   * CVS/Base/, CVS/Baserev, CVS/Baserev.tmp

   * CVS/Template

These files are usually not the cause of problems, so I'm just listing
them (see *Note CVS Reference:: for their full descriptions).

Portability And Future Extension
================================

As features are added to CVS, new files (not listed here) may appear in
working copy administrative areas.  As new files are added, they'll
probably be documented in the Cederqvist manual, in the node `Working
Directory Storage'.  You can also start looking in src/cvs.h in the
source distribution, if you prefer to learn from code.

Finally, note that all CVS/* files - present and future - use whatever
line-ending convention is appropriate for the working copy's local
system (for example, LF for Unix or CRLF for Windows).  This means that
if you transport a working copy from one kind of machine to the other,
CVS won't be able to handle it (but then, you'd have other problems,
because the revision-controlled files themselves would have the wrong
line-end conventions for their new location).


File: ossdev.info,  Node: Repository Permissions,  Prev: The Working Copy Administrative Area,  Up: The Usual Suspects

Repository Permissions
----------------------

CVS does not require any particular repository permission scheme - it
can handle a wide variety of permission arrangements.  However, to avoid
getting confusing behaviors, you should make sure your repository setup
meets at least the following criteria:

   * If a user wants any kind of access at all - even read-only access
     - to a given subdirectory of the repository, she usually needs file
     system-level write permission to that subdirectory.  This is
     necessary because CVS creates temporary lock files in the
     repository to ensure data consistency.  Even read-only operations
     (such as checkout or update) create locks, to signal that they
     need the data to stay in one state until they're done.

     As noted in *Note Repository Administration::, you can get around
     this writeability requirement by setting the LockDir parameter in
     CVSROOT/config, like this:

          LockDir=/usr/local/cvslocks

     Of course, then you would need to make sure the directory
     /usr/local/cvslocks is writeable by all CVS users.  Either way,
     most CVS operations, including read-only ones, are going to
     require a writeable directory somewhere.  By default, that
     directory is the project's repository; if you're very security
     conscious, you can change it to be somewhere else.

   * Make sure the CVSROOT/history file is world-writeable (if it
     exists at all).  If the history file exists, most CVS operations
     attempt to append a record to it; if the attempt fails, the
     operation exits with an error.

     Unfortunately (and inexplicably), the history file is not born
     world-writeable when you create a new repository with cvs init.  At
     least with the current version of CVS, you should explicitly
     change its permissions after you create a new repository (or just
     remove it, if you want to disable history logging entirely).

     (This problem may go away - I just now submitted a patch to the CVS
     maintainers that makes the history file world-writeable when you
     initialize a new repository.  So perhaps if you get a more recent
     version of CVS than the one available now (September 1999), it
     won't be a problem for you.)

   * For security purposes, you almost certainly want to make sure that
     most CVS users do not have Unix-level write access to the CVSROOT
     directory in the repository.  If someone has checkin access to
     CVSROOT, they can edit commitinfo, loginfo, or any of the other
     trigger files to invoke a program of their choice - they could
     even commit a new program if the one they want isn't on the system
     already.  Therefore, you should assume that anyone who has commit
     access to CVSROOT is able to run arbitrary commands on the system.



File: ossdev.info,  Node: General Troubleshooting Tips,  Next: Some Real Life Problems (With Solutions),  Prev: The Usual Suspects,  Up: Tips And Troubleshooting

General Troubleshooting Tips
============================

The bulk of this chapter is organized into a series of questions and
answers, similar to an Internet FAQ (Frequently Asked Questions)
document.  These are all based on actual CVS experiences.  But before we
look at individual cases, let's take a moment to consider CVS
troubleshooting from a more general point of view.

The first step in solving a CVS problem is usually to determine whether
it's a working copy or repository problem.  The best technique for doing
that, not surprisingly, is to see if the problem occurs in working
copies other than the one where it was first noticed.  If it does, it's
likely a repository issue; otherwise, it's probably just a local issue.

Working copy problems tend to be encountered more frequently, not
because working copies are somehow less reliable than repositories, but
because each repository usually has many working copies.  Although most
working copy knots can be untied with enough patience, you may
occasionally find it more time-efficient simply to delete the working
copy and check it out again.

Of course, if checking out again takes too long, or there is
considerable uncommitted state in the working copy that you don't want
to lose, or if you just want to know what's wrong, it's worth digging
around to find the cause of the problem.  When you start digging around,
one of the first places to look is in the CVS/ subdirectories.  Check
the file contents and the file permissions.  Very occasionally, the
permissions can mysteriously become read-only or even unreadable.  (I
suspect this is caused by users accidentally mistyping Unix commands
rather than any mistake on CVS's part.)

Repository problems are almost always caused by incorrect file and
directory permissions.  If you suspect a problem may be due to bad
repository permissions, first find out the effective repository user ID
of the person who's having the trouble.  For all local and most remote
users, this is either their regular username or the username they
specified when they checked out their working copy.  If they're using
the pserver method with user-aliasing (see the section *Note Anonymous
Access:: in *Note Repository Administration::), the effective user ID is
the one on the right in the CVSROOT/passwd file.  Failure to discover
this early on can cause you to waste a lot of time debugging the wrong
thing.

And now, without further ado...


File: ossdev.info,  Node: Some Real Life Problems (With Solutions),  Prev: General Troubleshooting Tips,  Up: Tips And Troubleshooting

Some Real Life Problems (With Solutions)
========================================

All of these situations are ones I've encountered in my real-life
adventures as a CVS troubleshooter (plus a few items that are not really
problems, just questions that I've heard asked so often that they may as
well be answered here).  The list is meant to be fairly comprehensive,
and it may repeat material you've seen in earlier chapters.

The situations are listed according to how frequently they seem to
arise, with the most common ones first.

* Menu:

* CVS says it is waiting for a lock; what does that mean?::
* CVS claims a file is failing Up-To-Date check; what do I do?::
* The pserver access method is not working::
* The pserver access method is STILL not working::
* My commits seem to happen in pieces instead of atomically::
* CVS keeps changing file permissions; why does it do that?::
* CVS on Windows complains it cannot find my .cvspass file; why?::
* My working copy is on several different branches; help?::
* When I do export -d I sometimes miss recent commits::
* I get an error about val-tags; what should I do?::
* I am having problems with sticky tags; how do I get rid of them?::
* Checkouts/updates exit with error saying cannot expand modules::
* I cannot seem to turn off watches::
* My binary files are messed up::
* CVS is not doing line-end conversion correctly::
* I need to remove a subdirectory in my project; how do I do it?::
* Can I copy .cvspass files or portions of them?::
* I just committed some files with the wrong log message::
* I need to move files around without losing revision history::
* How can I get a list of all tags in a project?::
* How can I get a list of all projects in a repository?::
* Some commands fail remotely but not locally; how should I debug?::
* I do not see my problem covered in this chapter::
* I think I have discovered a bug in CVS; what do I do?::
* I have implemented a new feature for CVS; to whom do I send it?::
* How can I keep up with changes to CVS?::


File: ossdev.info,  Node: CVS says it is waiting for a lock; what does that mean?,  Next: CVS claims a file is failing Up-To-Date check; what do I do?,  Up: Some Real Life Problems (With Solutions)

CVS says it is waiting for a lock; what does that mean?
-------------------------------------------------------

If you see a message like this

     cvs update: [22:58:26] waiting for qsmith's lock in /usr/local/newrepos/myproj

it means you're trying to access a subdirectory of the repository that
is locked by some other CVS process at the moment.  A process is being
run in that directory so it may not be in a consistent state for other
CVS processes to use.

However, if the wait message persists for a long time, it probably means
that a CVS process failed to clean up after itself, for whatever reason.
It can happen when CVS dies suddenly and unexpectedly, say, due to a
power failure on the repository machine.

The solution is to remove the lock files by hand from the repository
subdirectory in question.  Go into that part of the repository and look
for files named `#cvs.lock' or that begin with `#cvs.wfl' or
`#cvs.rfl'.  Compare the file's timestamps with the start times of any
currently running CVS processes.  If the files could not possibly have
been created by any of those processes, it's safe to delete them.  The
waiting CVS processes eventually notice when the lock files are gone -
this should take about 30 seconds - and allow the requested operation
to proceed.

See the node `Locks' in the Cederqvist manual for more details.


File: ossdev.info,  Node: CVS claims a file is failing Up-To-Date check; what do I do?,  Next: The pserver access method is not working,  Prev: CVS says it is waiting for a lock; what does that mean?,  Up: Some Real Life Problems (With Solutions)

CVS claims a file is failing Up-To-Date check; what do I do?
------------------------------------------------------------

Don't panic - it just means that the file has changed in the repository
since the last time you checked it out or updated it.

Run `cvs update' on the file to merge in the changes from the
repository.  If the received changes conflict with your local changes,
edit the file to resolve the conflict.  Then try your commit again - it
will succeed, barring the possibility that someone committed yet another
revision while you were busy merging the last changes.


File: ossdev.info,  Node: The pserver access method is not working,  Next: The pserver access method is STILL not working,  Prev: CVS claims a file is failing Up-To-Date check; what do I do?,  Up: Some Real Life Problems (With Solutions)

The pserver access method is not working
----------------------------------------

The most common, less obvious cause of this problem is that you forgot
to list the repository using an `--allow-root' option in your inetd
configuration file.

Recall this example /etc/inetd.conf line from *Note Repository
Administration:::

     cvspserver stream tcp nowait root /usr/local/bin/cvs cvs \
               --allow-root=/usr/local/newrepos pserver

(In the actual file, this is all one long line, with no backslash.)

The `--allow-root=/usr/local/newrepos' portion is a security measure,
to make sure that people can't use CVS to get pserver access to
repositories that are not supposed to be served remotely.  Any
repository intended to be accessible via pserver must be mentioned in an
`--allow-root'.  You can have as many different `--allow-root' options
as you need for all of your system's repositories (or anyway, as many
as you want until you bump up against your inetd's argument limit).

See *Note Repository Administration:: for more details on setting up the
password-authenticating server.


File: ossdev.info,  Node: The pserver access method is STILL not working,  Next: My commits seem to happen in pieces instead of atomically,  Prev: The pserver access method is not working,  Up: Some Real Life Problems (With Solutions)

The pserver access method is STILL not working
----------------------------------------------

Okay, if the problem is not a missing `--allow-root', here are a few
other possibilities:

   * The user has no entry in the CVSROOT/passwd file, and the
     CVSROOT/config file has SystemAuth=no so CVS will not fall back on
     the system password file (or SystemAuth=yes, but the system
     password file has no entry for this user either).

   * The user has an entry in the CVSROOT/passwd file, but there is no
     user by that name on the system, and the CVSROOT/passwd entry does
     not map the user to any valid system username.

   * The password is wrong (but CVS is usually pretty good about
     informing the user of this, so that's probably not the answer).

   * Everything is set up correctly with the passwd files and in
     /etc/inetd.conf, but you forgot an entry like this in
     /etc/services:

          cvspserver      2401/tcp

     so inetd is not even listening on that port to pass connections
     off to CVS.



File: ossdev.info,  Node: My commits seem to happen in pieces instead of atomically,  Next: CVS keeps changing file permissions; why does it do that?,  Prev: The pserver access method is STILL not working,  Up: Some Real Life Problems (With Solutions)

My commits seem to happen in pieces instead of atomically
---------------------------------------------------------

That's because CVS commits happen in pieces, not atomically. :-)

More specifically, CVS operations happen directory by directory.  When
you do a commit (or an update, or anything else, for that matter)
spanning multiple directories, CVS locks each corresponding repository
directory in turn while it performs the operation for that directory.

For small- to medium-sized projects, this is rarely a problem - CVS
manages to do its thing in each directory so quickly that you never
notice the nonatomicity.  Unfortunately, in large projects, scenarios
like the following can occur (imagine this taking place in a project
with at least two deep, many-filed subdirectories, A and B):

  1. User qsmith starts a commit, involving files from both
     subdirectories.  CVS commits the files in B first (perhaps because
     qsmith specified the directories on the command line in that
     order).

  2. User jrandom starts a cvs update.  The update, for whatever reason,
     starts with working copy directory A (CVS makes no guarantees
     about the order in which it processes directories or files, if
     left to its own devices).  Note that there is no locking
     contention, because qsmith is not active in A yet.

  3. Then, qsmith's commit finishes B, moves on to A, and finishes A.

  4. Finally, jrandom's update moves on to B and finishes it.


Clearly, when this is all over, jrandom's working copy reflects qsmith's
changes to B but not A.  Even though qsmith intended the changes to be
committed as a single unit, it didn't happen that way.  Now jrandom's
working copy is in a state that qsmith never anticipated.

The solution, of course, is for jrandom to do another cvs update to
fetch the uncaught changes from qsmith's commit.  However, that assumes
that jrandom has some way of finding out in the first place that he only
got part of qsmith's changes.

There's no easy answer to this quandary.  You simply have to hope that
the inconsistent state of the working copy will somehow become apparent
(maybe the software won't build, or jrandom and qsmith will have a
conversation that's confusing until they realize what must have
happened).

CVS's failure to provide _atomic_ transaction guarantees is widely
considered a bug.  The only reason that locks are not made at the top
level of the repository is that this would result in intolerably
frequent lock contentions for large projects with many developers.
Therefore, CVS has chosen the lesser of two evils, reducing the
contention frequency but allowing the possibility of interleaved reads
and writes.  Someday, someone may modify CVS (say, speeding up
repository operations) so that it doesn't have to choose between two
evils; until then, we're stuck with nonatomic actions.

For more information, see the node `Concurrency' in the Cederqvist
manual.


File: ossdev.info,  Node: CVS keeps changing file permissions; why does it do that?,  Next: CVS on Windows complains it cannot find my .cvspass file; why?,  Prev: My commits seem to happen in pieces instead of atomically,  Up: Some Real Life Problems (With Solutions)

CVS keeps changing file permissions; why does it do that?
---------------------------------------------------------

In general, CVS doesn't do a very good job of preserving permissions on
files.  When you import a project and then check it out, there is no
guarantee that the file permissions in the new working copy will be the
same as when the project was imported.  More likely, the working copy
files will be created with the same standard permissions that you
normally get on newly created files.

However, there is at least one exception.  If you want to store
executable shell scripts in the project, you can keep them executable in
all working copies by making the corresponding repository file
executable:

     floss$ ls -l /usr/local/newrepos/someproj
     total 6
     -r--r--r--   1 jrandom  users         630 Aug 17 01:10 README.txt,v
     -r-xr-xr-x   1 jrandom  users        1041 Aug 17 01:10 scrub.pl,v*
     -r--r--r--   1 jrandom  users         750 Aug 17 01:10 hello.c,v

Notice that although the file is executable, it is still read-only, as
all repository files should be (remember that CVS works by making a
temporary copy of the RCS file, doing everything in the copy, and then
replacing the original with the copy when ready).

When you import or add an executable file, CVS preserves the executable
bits, so if the permissions were correct from the start, you have
nothing to worry about.  However, if you accidentally add the file
before making it executable, you must go into the repository and
manually set the RCS file to be executable.

The repository permissions always dominate.  If the file is
nonexecutable in the repository, but executable in the working copy, the
working copy file will also be nonexecutable after you do an update.
Having your files' permissions silently change can be extremely
frustrating.  If this happens, first check the repository and see if you
can solve it by setting the appropriate permissions on the corresponding
RCS files.

A feature called `PreservePermissions' has recently been added to CVS
that may alleviate some of these problems.  However, using this feature
can cause other unexpected results (which is why I'm not recommending
it unconditionally here).  Make sure you read the nodes `config' and
`Special Files' in the Cederqvist before putting
`PreservePermissions=yes' in CVSROOT/config.


File: ossdev.info,  Node: CVS on Windows complains it cannot find my .cvspass file; why?,  Next: My working copy is on several different branches; help?,  Prev: CVS keeps changing file permissions; why does it do that?,  Up: Some Real Life Problems (With Solutions)

CVS on Windows complains it cannot find my .cvspass file; why?
--------------------------------------------------------------

For pserver connections, CVS on the client side tries to find the
.cvspass file in your home directory.  Windows machines don't have a
natural "home" directory, so CVS consults the environment variable
`%HOME%'.  However, you have to be very careful about how you set HOME.
This will work:

     set HOME=C:

This will not:

     set HOME=C:\

That extra backslash is enough to confuse CVS, and it will be unable to
open `C:\\.cvspass'.

So, the quick and permanent solution is to put

     set HOME=C:

into your autoexec.bat and reboot.  CVS pserver should work fine after
that.


File: ossdev.info,  Node: My working copy is on several different branches; help?,  Next: When I do export -d I sometimes miss recent commits,  Prev: CVS on Windows complains it cannot find my .cvspass file; why?,  Up: Some Real Life Problems (With Solutions)

My working copy is on several different branches; help?
-------------------------------------------------------

You mean different subdirectories of your working copy somehow got on
different branches?  You probably ran updates with the -r flag, but from
places other than the top level of the working copy.

No big deal.  If you want to return to the trunk, just run this

     cvs update -r HEAD

or this

     cvs update -A

from the top directory.  Or, if you want to put the whole working copy
on one of the branches, do this:

     cvs update -r Branch_Name

There's nothing necessarily wrong with having one or two subdirectories
of your working copy on a different branch than the rest of it, if you
need to do some temporary work on that branch just in those locations.
However, it's usually a good idea to switch them back when you're done
- life is much less confusing when your whole working copy is on the
same line of development.


File: ossdev.info,  Node: When I do export -d I sometimes miss recent commits,  Next: I get an error about val-tags; what should I do?,  Prev: My working copy is on several different branches; help?,  Up: Some Real Life Problems (With Solutions)

When I do export -d I sometimes miss recent commits
---------------------------------------------------

This is due to a clock difference between the repository and local
machines.  You can solve it by resetting one or both of the clocks, or
specifying a different date as the argument to -D.  It's perfectly
acceptable to specify a date in the future (such as -D tomorrow), if
that's what it takes to compensate for the time difference.


File: ossdev.info,  Node: I get an error about val-tags; what should I do?,  Next: I am having problems with sticky tags; how do I get rid of them?,  Prev: When I do export -d I sometimes miss recent commits,  Up: Some Real Life Problems (With Solutions)

I get an error about val-tags; what should I do?
------------------------------------------------

If you see an error like this:

     cvs [export aborted]: cannot write /usr/local/myproj/CVSROOT/val-tags: \
        Operation not permitted

it means the user CVS is running as does not have permission to write to
the CVSROOT/val-tags file.  This file stores valid tag names, to give
CVS a fast way to determine what tags are valid.  Unfortunately, CVS
sometimes modifies this file even for operations that are read-only with
respect to the repository, such as checking out a project.

This is a bug in CVS and may be fixed by the time you read this.  Until
then, the solution is either to make val-tags world-writeable or,
failing that, to remove it or change its ownership to the user running
the CVS operation.  (You'd think just changing the permissions would be
enough, but on several occasions I've had to change the ownership, too.)


File: ossdev.info,  Node: I am having problems with sticky tags; how do I get rid of them?,  Next: Checkouts/updates exit with error saying cannot expand modules,  Prev: I get an error about val-tags; what should I do?,  Up: Some Real Life Problems (With Solutions)

I am having problems with sticky tags; how do I get rid of them?
----------------------------------------------------------------

Various CVS operations cause the working copy to have a "sticky tag",
meaning a single tag that corresponds to each revision for each file
(in the case of a branch, the sticky tag is applied to any new files
added in the working copy).  You get a sticky tagged working area
whenever you check out or update by tag or date, for example:

     floss$ cvs update -r Tag_Name

or

     floss$ cvs checkout -D '1999-08-16'

If a date or a nonbranch tag name is used, the working copy will be a
frozen snapshot of that moment in the project's history - so naturally
you will not be able to commit any changes from it.

To remove a sticky tag, run update with the -A flag

     floss$ cvs update -A

which clears all the sticky tags and updates each file to its most
recent trunk revision.


File: ossdev.info,  Node: Checkouts/updates exit with error saying cannot expand modules,  Next: I cannot seem to turn off watches,  Prev: I am having problems with sticky tags; how do I get rid of them?,  Up: Some Real Life Problems (With Solutions)

Checkouts/updates exit with error saying cannot expand modules
--------------------------------------------------------------

This is just a case of a bad error message in CVS; probably someone will
get around to fixing it sooner or later, but meanwhile it may bite you.
The error message looks something like this:

     floss$ cvs co -d bwf-misc user-space/bwf/writings/misc
     cvs server: cannot find module `user-space/bwf/writings/misc' - ignored
     cvs [checkout aborted]: cannot expand modules

CVS appears to be saying that there's something wrong with the
CVSROOT/modules file.  However, what's really going on is a permission
problem in the repository.  The directory I'm trying to check out isn't
readable, or one of its parents isn't readable.  In this case, it was a
parent:

     floss$ ls -ld /usr/local/cvs/user-space/bwf
     
     drwx------  19 bwf      users        1024 Aug 17 01:24 bwf/

Don't let that egregiously wrong error message fool you - this is a
repository permission problem.


File: ossdev.info,  Node: I cannot seem to turn off watches,  Next: My binary files are messed up,  Prev: Checkouts/updates exit with error saying cannot expand modules,  Up: Some Real Life Problems (With Solutions)

I cannot seem to turn off watches
---------------------------------

You probably did

     floss$ cvs watch remove

on all the files, but forgot to also do:

     floss$ cvs watch off

A hint for diagnosing watch problems: Sometimes it can be immensely
clarifying to just go into the repository and examine the CVS/fileattr
files directly.  See *Note Repository Administration:: for more
information about them.


File: ossdev.info,  Node: My binary files are messed up,  Next: CVS is not doing line-end conversion correctly,  Prev: I cannot seem to turn off watches,  Up: Some Real Life Problems (With Solutions)

My binary files are messed up
-----------------------------

Did you remember to use -kb when you added them?  If not, CVS may have
performed line-end conversion or RCS keyword substitution on them.  The
easiest solution is usually to mark them as binary

     floss$ cvs admin -kb foo.gif

and then commit a fixed version of the file.  CVS will not corrupt the
new commit or any of the commits thereafter, because it now knows the
file is binary.


File: ossdev.info,  Node: CVS is not doing line-end conversion correctly,  Next: I need to remove a subdirectory in my project; how do I do it?,  Prev: My binary files are messed up,  Up: Some Real Life Problems (With Solutions)

CVS is not doing line-end conversion correctly
----------------------------------------------

If you're running the CVS client on a non-Unix platform and are not
getting the line-end conventions that you want in some working copy
files, it's usually because they were accidentally added with -kb when
they shouldn't have been.  This can be fixed in the repository with,
believe it or not, the command:

     floss$ cvs admin -kkv FILE

The -kkv means to do normal keyword substitution and implies normal
line-end conversions as well.  (Internally, CVS is a bit confused about
the difference between keyword substitution and line-end conversion.
This confusion is reflected in the way the -k options can control both
parameters.)

Unfortunately, that admin command only fixes the file in the repository
- your working copy still thinks the file is binary.  You can hand edit
the CVS/Entries line for that file, removing the -kb, but that won't
solve the problem for any other working copies out there.


File: ossdev.info,  Node: I need to remove a subdirectory in my project; how do I do it?,  Next: Can I copy .cvspass files or portions of them?,  Prev: CVS is not doing line-end conversion correctly,  Up: Some Real Life Problems (With Solutions)

I need to remove a subdirectory in my project; how do I do it?
--------------------------------------------------------------

Well, you can't exactly remove the subdirectory, but you can remove all
of the files in it (first remove them, then cvs remove them, and then
commit).  Once the directory is empty, people can have it automatically
pruned out of their working copies by passing the -P flag to update.


File: ossdev.info,  Node: Can I copy .cvspass files or portions of them?,  Next: I just committed some files with the wrong log message,  Prev: I need to remove a subdirectory in my project; how do I do it?,  Up: Some Real Life Problems (With Solutions)

Can I copy .cvspass files or portions of them?
----------------------------------------------

Yes, you can.  You can copy `.cvspass' files from machine to machine,
and you can even copy individual lines from one .cvspass file to
another.  For high-latency servers, this may be faster than running cvs
login from each working copy machine.

Remember that if you transport a .cvspass file between two machines with
different line-ending conventions, it probably won't work (of course,
you can probably do the line-end conversion manually without too much
trouble).

