Hello,

I believe I have found a bug in CVS-1.10.8 (RCS version 5.7).

Suppose two users have a file checked out at revision 1.1.
Suppose user A cvs removes the file and commits, which moves the
file into the attic and creates a dead revision 1.2 which is
otherwise identical to 1.1.  Then user B modifies the file, and
does a `cvs update', which produces the following output:

  cvs update: Updating .
  RCS file: /tmp/kduda/repos/Attic/file,v
  retrieving revision 1.1
  retrieving revision 1.2
  Merging differences between 1.1 and 1.2 into file
  file already contains the differences between 1.1 and 1.2

This is user B's only warning that something funny is going on
(what are the chances that someone else made exactly the same
changes to the file?) and it's a very easy warning to ignore.  A
subsequent `cvs update' by user B produces no warnings.  Then,
user B commits.  At this point, the log of the file looks odd to
me:

  + /tmp/kduda/cvs-1.10.8/src/cvs log file
  RCS file: /tmp/kduda/repos/Attic/file,v
  Working file: file
  head: 1.3
  branch:
  locks: strict
  access list:
  symbolic names:
  keyword substitution: kv
  total revisions: 3;   selected revisions: 3
  description:
  ----------------------------
  revision 1.3
  date: 2000/06/20 16:18:06;  author: kduda;  state: Exp;  lines: +1 -0
  now in bogus state
  ----------------------------
  revision 1.2
  date: 2000/06/20 16:18:05;  author: kduda;  state: dead;  lines: +0 -0
  removing file
  ----------------------------
  revision 1.1
  date: 2000/06/20 16:18:03;  author: kduda;  state: Exp;
  adding file
  =============================================================================

The file is in the Exp state on the main trunk, yet is located in
the Attic!  I thought this combination was not possible.  In any
case, it causes `cvs update' to miss the file for user A:

  + /tmp/kduda/cvs-1.10.8/src/cvs update
  cvs update: Updating .
  cvs update: Updating CVSROOT
  + /tmp/kduda/cvs-1.10.8/src/cvs status file
  ===================================================================
  File: no file file            Status: Needs Checkout
  
     Working revision:  No entry for file
     Repository revision:       1.3     /tmp/kduda/repos/Attic/file,v

Note that `cvs update' does nothing, yet `cvs status file'
reports that the file needs checkout.  User A's tree and user B's
tree remain in this inconsistent state (where user A does not
have the file, but user B does) indefinitely.

The attached shell script reproduces the problem.  I'd recommend
running it from an empty subdirectory of /tmp.

This cvs "issue" has caused enough trouble for my development
team that I'd be game to take a stab at fixing it if I thought I
understood what the right behavior was.  I would very much
appreciate any insight into this issue.  As a starting point, my
own best guess follows.

One way to fix this would be to have `cvs update' search the
Attic.  Another would be to have `cvs commit' move the file from
the Attic if its state is not Dead.  With either of these fixes,
at least user A's tree and user B's tree would wind up in a
consistent state.  However, it seems like things actually went
wrong earlier --- shouldn't user B be required to `cvs add' the
file in order to change the state from `Dead' to `Exp'?  I feel
there was a remove/update conflict that user B was never required
to face, and that this is the underlying problem.  I feel the
file should be list as conflicting ("C") until user B does either
a cvs add or a /bin/rm.  Is my understanding of remove/update
conflicts flawed?  Is my understanding of what `cvs update' is
supposed to accomplish flawed?  I can be reached at 650-433-4028.

Thanks,
        -Ken

Kenneth Duda
CTO, There
<[EMAIL PROTECTED]>
650-433-4028
 

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

#!/bin/sh
set -x
CVS=cvs
CVSROOT="$PWD/repos"
export CVSROOT
TREE1="$PWD/tree1"
TREE2="$PWD/tree2"
mkdir "$CVSROOT"
mkdir "$TREE1"
mkdir "$TREE2"
cvs init
cd "$TREE1"
"$CVS" checkout .
echo hello > file
"$CVS" add file
"$CVS" commit -m 'adding file' file
cd "$TREE2"
"$CVS" checkout .
cd "$TREE1"
rm file
"$CVS" remove file
"$CVS" commit -m 'removing file' file
cd "$TREE2"
echo there >> file
"$CVS" update
"$CVS" commit -m 'now in bogus state' file
"$CVS" status file
"$CVS" log file
cd "$TREE1"
"$CVS" update
"$CVS" status file
"$CVS" log file
echo 'Notice that after updating both trees, one tree has "file" and one does not.'
echo 'Notice that its status in tree1 is "needs checkout" yet "cvs update" does not 
see it.'

Reply via email to