[Various notes and disclaimers: * Missing any code for "cvs rm" on a directory. * Haven't tested this. It does compile but I haven't run it. Would want a variety of sanity.sh test cases, of course. * Need to think harder about how this interacts with -d and -P and so on. And about compatibility in general (maybe all the new functionality is enabled by a configuration setting in CVSROOT/config? That kind of issue). * For now at least, I'm treating this as a separate issue from whether "cvs add" on a directory is immediate or waits for a commit. Might be good to tackle the two at the same time, since they aren't completely separate (and dealing with the compatibility questions all at once might be easier). * Probably want to think at least a bit about "_directory" versus "directory" as the name of the state. -kingdon] Index: ChangeLog =================================================================== RCS file: /home2/cvsroot/ccvs/src/ChangeLog,v retrieving revision 1.1672 diff -c -r1.1672 ChangeLog *** ChangeLog 1998/12/19 04:52:40 1.1672 --- ChangeLog 1998/12/20 18:40:31 *************** *** 1,3 **** --- 1,14 ---- + 1998-12-20 Jim Kingdon + + * rcs.c, cvs.h (RCS_checkin): New flag RCS_FLAGS_DIRECTORY, lets + us set the state to "directory". + * rcs.c, rcs.h (RCS_isdir): New function, to get whether state is + "directory". + * add.c (add_directory): Check in a directory revision when we add + a directory. + * update.c (update_dirent_proc): Don't create a new directory if + there is no directory revision. + 1998-12-16 Jim Meyering * rcs.c (RCS_getdate): Handle the case in which a file is first Index: add.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/add.c,v retrieving revision 1.69 diff -c -r1.69 add.c *** add.c 1998/09/01 13:54:40 1.69 --- add.c 1998/12/20 18:44:51 *************** *** 24,29 **** --- 24,30 ---- * file to be resurrected. */ + #include #include "cvs.h" #include "savecwd.h" #include "fileattr.h" *************** *** 700,705 **** --- 701,738 ---- #else Create_Admin (".", finfo->fullname, rcsdir, tag, date, nonbranch, 0); #endif + + { + RCSNode *rcsnode; + int status; + + /* Even if the directory existed, go ahead and check in a + directory revision to the dir,v file, to patch it up in case + the directory was created with an old version of CVS. */ + rcsnode = RCS_parse (finfo->file, finfo->repository); + if (rcsnode == NULL) + { + error (0, 0, "cannot parse RCS file for %s", finfo->fullname); + goto rcsdone; + } + + /* FIXME: The case where tag != NULL is (I think) unhandled. I + think we need to call RCS_getversion or some such to get a + numeric revision. */ + assert (tag == NULL); + + status = RCS_checkin (rcsnode, NULL, message, tag, + RCS_FLAGS_DIRECTORY); + if (status < 0) + error (0, errno, "cannot checkin directory revision"); + if (status <= 0) + goto rcsdone; + + rcsdone: + if (rcsnode != NULL) + freercsnode (&rcsnode); + } + if (tag) free (tag); if (date) Index: cvs.h =================================================================== RCS file: /home2/cvsroot/ccvs/src/cvs.h,v retrieving revision 1.194 diff -c -r1.194 cvs.h *** cvs.h 1998/10/21 17:09:41 1.194 --- cvs.h 1998/12/20 18:02:25 *************** *** 415,420 **** --- 415,421 ---- #define RCS_FLAGS_QUIET 4 #define RCS_FLAGS_MODTIME 8 #define RCS_FLAGS_KEEPFILE 16 + #define RCS_FLAGS_DIRECTORY 32 extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile, char *opts, char *options, Index: rcs.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/rcs.c,v retrieving revision 1.209 diff -c -r1.209 rcs.c *** rcs.c 1998/12/19 04:47:33 1.209 --- rcs.c 1998/12/20 18:03:03 *************** *** 3634,3639 **** --- 3634,3660 ---- return (version->dead); } + /* Return true if RCS revision with numeric revision TAG is a + directory revision. */ + int + RCS_isdir (rcs, rev) + RCSNode *rcs; + const char *rev; + { + Node *p; + RCSVers *version; + + if (rcs->flags & PARTIAL) + RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL); + + p = findnode (rcs->versions, rev); + if (p == NULL) + return (0); + + version = (RCSVers *) p->data; + return (STREQ (version->state, "directory")); + } + /* Return the RCS keyword expansion mode. For example "b" for binary. Returns a pointer into storage which is allocated and freed along with the rest of the RCS information; the caller should not modify this *************** *** 5068,5073 **** --- 5089,5095 ---- /* Check in to RCSFILE with revision REV (which must be greater than the largest revision) and message MESSAGE (which is checked for legality). If FLAGS & RCS_FLAGS_DEAD, check in a dead revision. + If FLAGS & RCS_FLAGS_DIRECTORY, check in a directory revision. If FLAGS & RCS_FLAGS_QUIET, tell ci to be quiet. If FLAGS & RCS_FLAGS_MODTIME, use the working file's modification time for the checkin time. WORKFILE is the working file to check in from, or *************** *** 5166,5171 **** --- 5188,5195 ---- delta->state = xstrdup (RCSDEAD); delta->dead = 1; } + else if (flags & RCS_FLAGS_DIRECTORY) + delta->state = xstrdup ("directory"); else delta->state = xstrdup ("Exp"); Index: rcs.h =================================================================== RCS file: /home2/cvsroot/ccvs/src/rcs.h,v retrieving revision 1.52 diff -c -r1.52 rcs.h *** rcs.h 1998/08/26 17:22:30 1.52 --- rcs.h 1998/12/20 18:04:18 *************** *** 211,216 **** --- 211,217 ---- char *RCS_branch_head PROTO ((RCSNode *rcs, char *rev)); int RCS_isdead PROTO((RCSNode *, const char *)); + int RCS_isdir PROTO ((RCSNode *, const char *)); char *RCS_getexpand PROTO ((RCSNode *)); int RCS_checkout PROTO ((RCSNode *, char *, char *, char *, char *, char *, RCSCHECKOUTPROC, void *)); Index: update.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/update.c,v retrieving revision 1.162 diff -c -r1.162 update.c *** update.c 1998/11/12 20:24:45 1.162 --- update.c 1998/12/20 18:43:22 *************** *** 865,873 **** --- 865,894 ---- if (!isdir (dir)) { + RCSNode *rcsnode; + char *rev; + /* if we aren't building dirs, blow it off */ if (!update_build_dirs) return (R_SKIP_ALL); + + /* Now, if there is an RCS file for this directory, and it + says that the relevant revision is not a directory + revision, then skip it. If there is no RCS file, the + repository was written by an old version of CVS; so go + ahead and create it like we always have. */ + rcsnode = RCS_parse (dir, repository); + if (rcsnode != NULL) + { + int forget_it = 0; + + rev = RCS_getversion (rcsnode, tag, date, force_tag_match, + (int *) NULL); + forget_it = !RCS_isdir (rcsnode, rev); + freercsnode (&rcsnode); + if (forget_it) + return R_SKIP_ALL; + } /* Various CVS administrators are in the habit of removing the repository directory for things they don't want any