[With CVS 1.9, a CVS directory is created in the working directory (at the same level at which one runs "cvs get") only under some circumstances (specifically, if one is checking out a file which exists at top level). In CVS 1.9.2 through 1.9.28, such a directory is always created. There is not agreement among the CVS developers about whether this change was a good one. Some issues: * Without CVS directories there is no place to put the CVS/Template file. One suggestion is to forbid "cvs commit" without arguments from a directory which lacks a CVS directory. * A similar consequence is that CVS doesn't pick up CVS/Root if there is no CVS directory. Unlike CVS/Template, this affects all CVS commands, and I'm sure we can't make "cvs update" in such a directory an error without howls of protest. However, the consequence of missing CVS/Root is probably generally less mysterious than missing CVS/Template. * It might be good to restore the CVS 1.9 behavior until some of this can be sorted out. However, since the 1.9.2 behavior has been in place as long as it has, this too might be disruptive. * "It surprised me when I checked out a single module into an empty directory, then accidentally did an update in that same (previously empty) directory, rather than in the just checked-out module subdir. The result was that lots of other subdirectories (that I didn't want) were checked out -- before there would have been an error." ("update -d", presumably). - Note 1: the toplevel-9 test from the testsuite *expects* the new subdirectories to be created, for whatever that is worth. - Note 2: the correct solution is almost surely related to distinguishing better between a directory which we chose not to check out and one which has been created since we checked out (this is a long-term solution, not a short-term one, though). - Note 3: the problem gets worse if one checks out several modules which live at different places in the tree. Then it will be fairly arbitrary which directories one gets in the "update -d" (this problem also occurs below top-level, but perhaps is particularly likely at top level). * I (kingdon) tried disabling creation of the CVS directory with this patch (the first one below), running the testsuite, and seeing what fails (I just tried this local, not remote). What I found was: (1) serverpatch-6 fails with "there is no version here". At first glance it would seem that "co -r" and "update -A" behave differently than the counterparts without -r and -A. (2) the cvsadm test had trouble running. I didn't pursue this. * Probably making this an option in CVSROOT/config is the best way to go. Main problem is with documenting the consequences of one choice or the other, but this seems better than the alternatives. Here is a preliminary patch (the second one below). So to recap, this file contains: (1) quick and dirty patch to see what the consequences are, and then (2) slightly more complete patch, with the start of code to let one set this in CVSROOT/config. All of this stuff should be have been solved by Noel Cragg's checkin of 26 Jul 1998, which implemented the CVSROOT/config idea. -kingdon] [this is an experiment in trying to restore the CVS 1.9 behavior, to see whether or how much CVS has gotten to rely on the new behavior since then -kingdon] Index: ChangeLog =================================================================== RCS file: /home2/cvsroot/ccvs/src/ChangeLog,v retrieving revision 1.1374 diff -u -r1.1374 ChangeLog --- ChangeLog 1997/12/20 20:22:34 1.1374 +++ ChangeLog 1997/12/21 04:24:25 @@ -1,5 +1,11 @@ Sat Dec 20 19:56:00 1997 Jim Kingdon + * checkout.c (checkout_proc): Don't create CVS directory at top + level. + * sanity.sh (basicb, toplevel): Disable a few of the tests which + test for the directory itself rather than significant user-visible + consequences. + * rcs.c (RCS_delete_revs): Clean up temporary files even if noexec. Without this fix, basica-o5a in sanity.sh would leave files around. Index: checkout.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/checkout.c,v retrieving revision 1.76 diff -u -r1.76 checkout.c --- checkout.c 1997/11/05 20:33:06 1.76 +++ checkout.c 1997/12/21 03:03:29 @@ -820,12 +820,16 @@ /* clean up */ free (reposcopy); +#if 0 + /* See what happens if we don't do this (a la CVS 1.9, I + think). */ /* The top-level CVSADM directory should always be CVSroot_directory. Create it. It may be argued that we shouldn't set any sticky bits for the top-level repository. FIXME? */ build_one_dir (CVSroot_directory, ".", *pargc <= 1); +#endif /* * build dirs on the path if necessary and leave us in the bottom Index: sanity.sh =================================================================== RCS file: /home2/cvsroot/ccvs/src/sanity.sh,v retrieving revision 1.338 diff -u -r1.338 sanity.sh --- sanity.sh 1997/12/15 00:37:44 1.338 +++ sanity.sh 1997/12/21 04:22:30 @@ -843,16 +843,16 @@ : mkdir ${CVSROOT_DIRNAME}/first-dir dotest basicb-1 "${testcvs} -q co first-dir" '' - dotest basicb-1a "test -d CVS" '' + dotest_fail basicb-1a "test -d CVS" '' # In 1b and 1c, the first string matches if we're using absolute # paths, while the second matches if RELATIVE_REPOS is defined # (we're using relative paths). - dotest basicb-1b "cat CVS/Repository" \ +: dotest basicb-1b "cat CVS/Repository" \ "${TESTDIR}/cvsroot/\." \ "\." - dotest basicb-1c "cat first-dir/CVS/Repository" \ +: dotest basicb-1c "cat first-dir/CVS/Repository" \ "${TESTDIR}/cvsroot/first-dir" \ "first-dir" @@ -954,13 +954,13 @@ "${testcvs} -q co -d newdir -r release-1 first-dir/Emptydir first-dir/sdir2" \ 'U newdir/first-dir/Emptydir/sfile1 U newdir/first-dir/sdir2/sfile2' - dotest basicb-9a "test -d CVS" '' + dotest_fail basicb-9a "test -d CVS" '' # In 9b through 9f, the first string matches if we're using # absolute paths, while the second matches if RELATIVE_REPOS # is defined (we're using relative paths). - dotest basicb-9b "cat CVS/Repository" \ +: dotest basicb-9b "cat CVS/Repository" \ "${TESTDIR}/cvsroot/\." \ "\." dotest basicb-9c "cat newdir/CVS/Repository" \ @@ -9368,8 +9368,7 @@ dotest toplevel-6 "${testcvs} update top-dir" \ "${PROG} [a-z]*: Updating top-dir" dotest toplevel-7 "${testcvs} update" \ -"${PROG} [a-z]*: Updating \. -${PROG} [a-z]*: Updating top-dir" +"${PROG} [a-z]*: Updating top-dir" dotest toplevel-8 "${testcvs} update -d top-dir" \ "${PROG} [a-z]*: Updating top-dir" [Remaining issues include: * Documentation (cvs.texinfo, NEWS) * Client/server. * Make a test case for the "Note 3" case? * Look into the serverpatch-6 case any more? Look into the "cvsadm" test some more? * Next steps? Ask, on one or more mailing lists, for people to try it? * And of course the predictable battle of "what should the default be?" -kingdon] Index: ChangeLog =================================================================== RCS file: /home2/cvsroot/ccvs/src/ChangeLog,v retrieving revision 1.1530 diff -c -r1.1530 ChangeLog *** ChangeLog 1998/06/04 12:46:36 1.1530 --- ChangeLog 1998/06/08 18:20:44 *************** *** 1,3 **** --- 1,10 ---- + 1998-06-08 Jim Kingdon + + * cvs.h, main.c (top_level_admin): New variable. + * parseinfo.c (parse_config): Set it. + * checkout.c (checkout_proc): Consult it. + * sanity.sh (toplevel2): New tests, for this feature. + 1998-06-04 Jim Kingdon * add.c (add): Only send "Directory" requests if we need to. Index: checkout.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/checkout.c,v retrieving revision 1.80 diff -c -r1.80 checkout.c *** checkout.c 1998/05/15 16:40:14 1.80 --- checkout.c 1998/06/07 02:48:30 *************** *** 886,892 **** build_one_dir whenever the -d command option was specified to checkout. */ ! if (! where_is_absolute) { /* It may be argued that we shouldn't set any sticky bits for the top-level repository. FIXME? */ --- 886,892 ---- build_one_dir whenever the -d command option was specified to checkout. */ ! if (! where_is_absolute && top_level_admin) { /* It may be argued that we shouldn't set any sticky bits for the top-level repository. FIXME? */ Index: cvs.h =================================================================== RCS file: /home2/cvsroot/ccvs/src/cvs.h,v retrieving revision 1.184 diff -c -r1.184 cvs.h *** cvs.h 1998/05/13 17:15:28 1.184 --- cvs.h 1998/06/07 02:43:57 *************** *** 385,390 **** --- 385,392 ---- extern int noexec; /* Don't modify disk anywhere */ extern int logoff; /* Don't write history entry */ + extern int top_level_admin; + #ifdef AUTH_SERVER_SUPPORT extern char *Pserver_Repos; /* used to check that same repos is transmitted in pserver auth and in Index: main.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/main.c,v retrieving revision 1.126 diff -c -r1.126 main.c *** main.c 1998/05/13 17:15:29 1.126 --- main.c 1998/06/07 02:46:56 *************** *** 41,46 **** --- 41,53 ---- int trace = 0; int noexec = 0; int logoff = 0; + + /* Set if we should be writing CVSADM directories at top level. At + least for now we'll make the default be on (the CVS 1.9.2, not CVS + 1.9, behavior). This probably needs to be fought over ^W^W + discussed :-). */ + int top_level_admin = 1; + mode_t cvsumask = UMASK_DFLT; char *CurDir; Index: parseinfo.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/parseinfo.c,v retrieving revision 1.28 diff -c -r1.28 parseinfo.c *** parseinfo.c 1998/03/04 22:15:38 1.28 --- parseinfo.c 1998/06/07 02:08:48 *************** *** 346,351 **** --- 346,363 ---- goto error_return; } } + else if (strcmp (line, "TopLevelAdmin") == 0) + { + if (strcmp (p, "no") == 0) + top_level_admin = 0; + else if (strcmp (p, "yes") == 0) + top_level_admin = 1; + else + { + error (0, 0, "unrecognized value '%s' for TopLevelAdmin", p); + goto error_return; + } + } else { /* We may be dealing with a keyword which was added in a Index: sanity.sh =================================================================== RCS file: /home2/cvsroot/ccvs/src/sanity.sh,v retrieving revision 1.397 diff -c -r1.397 sanity.sh *** sanity.sh 1998/06/02 16:23:27 1.397 --- sanity.sh 1998/06/08 17:48:48 *************** *** 557,563 **** tests="${tests} new newb conflicts conflicts2 conflicts3" # Checking out various places (modules, checkout -d, &c) tests="${tests} modules modules2 modules3 modules4" ! tests="${tests} cvsadm emptydir abspath toplevel" # Log messages, error messages. tests="${tests} mflag editor errmsg1 errmsg2" # Watches, binary files, history browsing, &c. --- 557,563 ---- tests="${tests} new newb conflicts conflicts2 conflicts3" # Checking out various places (modules, checkout -d, &c) tests="${tests} modules modules2 modules3 modules4" ! tests="${tests} cvsadm emptydir abspath toplevel toplevel2" # Log messages, error messages. tests="${tests} mflag editor errmsg1 errmsg2" # Watches, binary files, history browsing, &c. *************** *** 8054,8059 **** --- 8054,8154 ---- chmod +w ../1 cd .. + rm -r 1 + rm -rf ${CVSROOT_DIRNAME}/top-dir ${CVSROOT_DIRNAME}/second-dir + ;; + + toplevel2) + # Similar to toplevel, but test the case where TopLevelAdmin=no. + + # First set the TopLevelAdmin setting. + mkdir 1; cd 1 + dotest toplevel2-1a "${testcvs} -q co CVSROOT/config" \ + "U CVSROOT/config" + cd CVSROOT + echo "TopLevelAdmin=no" >config + dotest toplevel2-1b "${testcvs} -q ci -m no-top-level" \ + "Checking in config; + ${TESTDIR}/cvsroot/CVSROOT/config,v <-- config + new revision: 1\.[0-9]*; previous revision: 1\.[0-9]* + done + ${PROG} [a-z]*: Rebuilding administrative file database" + cd ../.. + rm -r 1 + + # Now set up some directories and subdirectories + mkdir 1; cd 1 + dotest toplevel2-1 "${testcvs} -q co -l ." '' + mkdir top-dir second-dir + dotest toplevel2-2 "${testcvs} add top-dir second-dir" \ + "Directory ${TESTDIR}/cvsroot/top-dir added to the repository + Directory ${TESTDIR}/cvsroot/second-dir added to the repository" + cd top-dir + + touch file1 + dotest toplevel2-3 "${testcvs} add file1" \ + "${PROG} [a-z]*: scheduling file .file1. for addition + ${PROG} [a-z]*: use .${PROG} commit. to add this file permanently" + dotest toplevel2-4 "${testcvs} -q ci -m add" \ + "RCS file: ${TESTDIR}/cvsroot/top-dir/file1,v + done + Checking in file1; + ${TESTDIR}/cvsroot/top-dir/file1,v <-- file1 + initial revision: 1\.1 + done" + cd .. + + cd second-dir + touch file2 + dotest toplevel2-3s "${testcvs} add file2" \ + "${PROG} [a-z]*: scheduling file .file2. for addition + ${PROG} [a-z]*: use .${PROG} commit. to add this file permanently" + dotest toplevel2-4s "${testcvs} -q ci -m add" \ + "RCS file: ${TESTDIR}/cvsroot/second-dir/file2,v + done + Checking in file2; + ${TESTDIR}/cvsroot/second-dir/file2,v <-- file2 + initial revision: 1\.1 + done" + + cd ../.. + rm -r 1; mkdir 1; cd 1 + dotest toplevel2-5 "${testcvs} co top-dir" \ + "${PROG} [a-z]*: Updating top-dir + U top-dir/file1" + + dotest toplevel2-6 "${testcvs} update top-dir" \ + "${PROG} [a-z]*: Updating top-dir" + dotest toplevel2-7 "${testcvs} update" \ + "${PROG} [a-z]*: Updating top-dir" + + dotest toplevel2-8 "${testcvs} update -d top-dir" \ + "${PROG} [a-z]*: Updating top-dir" + # Contrast this with toplevel-9, which has TopLevelAdmin=yes. + dotest toplevel2-9 "${testcvs} update -d" \ + "${PROG} [a-z]*: Updating top-dir" + + cd .. + rm -r 1; mkdir 1; cd 1 + dotest toplevel2-10 "${testcvs} co top-dir" \ + "${PROG} [a-z]*: Updating top-dir + U top-dir/file1" + # This tests more or less the same thing, in a particularly + # "real life" example. With TopLevelAdmin=yes, this command + # would give us second-dir and CVSROOT directories too. + dotest toplevel2-11 "${testcvs} -q update -d" "" + + dotest toplevel2-cleanup-1 "${testcvs} -q co CVSROOT/config" \ + "U CVSROOT/config" + cd CVSROOT + echo "# empty file" >config + dotest toplevel2-cleanup-2 "${testcvs} -q ci -m toplevel2-cleanup" \ + "Checking in config; + ${TESTDIR}/cvsroot/CVSROOT/config,v <-- config + new revision: 1\.[0-9]*; previous revision: 1\.[0-9]* + done + ${PROG} [a-z]*: Rebuilding administrative file database" + cd ../.. rm -r 1 rm -rf ${CVSROOT_DIRNAME}/top-dir ${CVSROOT_DIRNAME}/second-dir ;;