[When I first looked at this, I wrote "Seems like a potentially good idea". I haven't examined it with a fine-toothed comb however. There are some PATH_MAX's which need nuking. I just took a quick glance, and I'm not very clear at all about what these patches do. So if nothing else they need better documentation. -kingdon] From: Simon Liddington Subject: New patch to fix global -d option To: bug-cvs@prep.ai.mit.edu Date: Wed, 8 Jan 1997 16:37:46 +0000 (GMT) Hi CVS person, again! DO NOT use the last patch I sent in the email with the following details: >From sjl96v Mon Jan 6 20:48:28 1997 Subject: patch to fix global -d option To: bug-cvs@prep.ai.mit.edu Date: Mon, 6 Jan 1997 20:48:28 +0000 (GMT) Reply-To: sjl96v@ecs.soton.ac.uk Please excuse my incompetance! but i have just found out that it is broken for checkout and probably some other commands as well. So, here is a new patch which should be used on a clean version 1.9 source tree. The text below here is the same as i sent last time to describe what i have done, and below that is the new patch. Here is a patch which fixes the problem with the global -d option when the CVS\Root files specify a non-existent repository. It also rewrites the CVS\Repository files if these were written with absolute paths. The comments in the code said we may wish this overwriting of admin files to happen in all directories recursed into but the code only did the directory that cvs was called from. This patch implements the more desirable rewriting in all recursed directories. Problems can occur for client/server cvs if the CVS\Repository files are written with absolute paths. Therefore i changed the default in options.h.in for RELATIVE_REPOS to use relative repository files. It has been reported that relative repository files don't work with client/server but it does in my experience and I cannot see any reason why it should not work ok. This problem is because the admin files are rewritten at the client end and may not have been rewritten by the time the server uses them (especially if the server is the faster machine, as is often the case :-) ). Relative repository files do not need rewritting and so fix the problem. I am running cvs on a pentium running Linux 2.0.18. I hope this is useful to you. Simon Liddington Here's the context diff file, patch should be run from the base CVS-1.9 directory to apply it. diff -r -c -x .orig -x .new ./BUGS ../cvs-1.9.new/BUGS *** ./BUGS Tue Oct 1 01:49:39 1996 --- ../cvs-1.9.new/BUGS Mon Jan 6 16:35:35 1997 *************** *** 55,60 **** --- 55,71 ---- * Defining RELATIVE_REPOS is said to not work with client/server CVS. + From: sjl96v@ecs.soton.ac.uk (Simon Liddington) + Since making global -d option override and rewrite the admin files + it is better to use relative repository files if you are using + client/server support. This is because the admin files are + rewritten at the client and may not have been rewritten by the time + server uses them (especially if the server is the faster machine, + as is often the case :-) ). + It has been reported that relative repository files don't work with + client/server but it does in my experience and I cannot see any + reason why it should not work ok. + * From: "Charles M. Hannum" To: info-cvs@prep.ai.mit.edu Subject: Still one more bug diff -r -c -x .orig -x .new ./ChangeLog ../cvs-1.9.new/ChangeLog *** ./ChangeLog Wed Oct 2 07:03:33 1996 --- ../cvs-1.9.new/ChangeLog Mon Jan 6 17:26:20 1997 *************** *** 1,3 **** --- 1,13 ---- + Mon Jan 6 17:14:56 1997 Simon Liddington + + * NEWS : Fixes to use of global -d option to override + CVS\Root files and CVS\Repository files if it contains + absolute path names. + + * BUGS : RELATIVE_REPOS works for me with client/server CVS, + and works better when using the global -d option to override + CVS\Root files. + Tue Oct 1 14:32:44 1996 Jim Kingdon * NEWS, README: Revert changes regarding -D, -g, and A4. They diff -r -c -x .orig -x .new ./NEWS ../cvs-1.9.new/NEWS *** ./NEWS Wed Oct 2 07:03:34 1996 --- ../cvs-1.9.new/NEWS Mon Jan 6 16:39:16 1997 *************** *** 1,3 **** --- 1,14 ---- + Changes since 1.9: + + * Fixed use of global -d option to override the cvsroot setting stored + in the CVS/Root file in each working directory when the CVS\Root file + specifies a non-existent directory. If the CVS\Repository files do not + use relative paths then these will need to be overwritten too and this + is fixed. It now overwrites these files in all directories that are + recursed into. For Client/Server the use of relative path names is + recommended when using the -d option and so the default has been changed + to this. + Changes since 1.8: * Windows NT client should now work on Windows 95 as well. diff -r -c -x .orig -x .new ./src/ChangeLog ../cvs-1.9.new/src/ChangeLog *** ./src/ChangeLog Fri Oct 4 21:03:06 1996 --- ../cvs-1.9.new/src/ChangeLog Mon Jan 6 16:24:36 1997 *************** *** 1,3 **** --- 1,51 ---- + Mon Jan 6 15:28:33 1997 Simon Liddington + + * repos.c (Create_Repository) : Added Create_Repository function along + lines of Create_Root in root.c. The code in it is basically moved from + Create_Admin. This allows this code to be reused when overwriting + repository files which don't have relative paths in them. This is + needed when the -d option is used to overwrite the CVS\Root directory. + + * root.c (Name_Root) : should not check that the repository + exists as we still want a valid return value when the CVS\Root file is + being overriden by the -d option. Therefore this check is moved to + main in main.c. + (Create_Root) : added updatedir to parameter list so that errors can + be reported better. + + * create_adm.c (Create_Admin) : added updatedir parameter to + Create_Root call. Used new Create_Repository function. + + * cvs.h : Added overrideroot global flag which is true when the + CVS\Root files are being overridden (and overwritten) due to the + global -d optin being used. + (Create_Root) : added updatedir to parameter list. + (Create_Repository) : added this new function. + + * options.h.in (RELATIVE_REPOS) : changed to use relative Repository + files. Since making global -d option override and rewrite the admin + files it is better to use relative repository files if you are using + client/server support. This is because the admin files are + rewritten at the client and may not have been rewritten by the time + server uses them (especially if the server is the faster machine, + as is often the case :-) ). + It has been reported in BUGS that relative repository files don't work + with client/server but it does in my experience and I cannot see any + reason why it should not work ok. + + * main.c (main) : fixed problem of using global -d option if CVS\Root + has non-existent repository in it. Had to move this check from + Name_Root to here and bypass it if -d option had been used. + -d option sets a global now so that all directories recursed into + have their admin files corrected, not just the one we are called from. + + * recurse.c (do_recursion) : If global -d option has been used then + we need to overwrite the CVS\Root file (and also the CVS\Repository + file if it did not use a relative path). Previous comments in the + said that we might want to do this in all directories that we recurse + into but the code did not. Now it does, by doing it during the + recursion. + Fri Oct 4 15:11:46 1996 Jim Kingdon * server.c (server_cleanup): Temporarily clear noexec when calling diff -r -c -x .orig -x .new ./src/create_adm.c ../cvs-1.9.new/src/create_adm.c *** ./src/create_adm.c Thu Jun 6 17:18:55 1996 --- ../cvs-1.9.new/src/create_adm.c Fri Dec 20 15:59:16 1996 *************** *** 24,30 **** char *date; { FILE *fout; - char *cp; char tmp[PATH_MAX]; #ifdef SERVER_SUPPORT --- 24,29 ---- *************** *** 53,104 **** /* record the current cvs root for later use */ ! Create_Root (dir, CVSroot_original); ! if (dir != NULL) ! (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP); ! else ! (void) strcpy (tmp, CVSADM_REP); ! fout = CVS_FOPEN (tmp, "w+"); ! if (fout == NULL) ! { ! if (update_dir[0] == '\0') ! error (1, errno, "cannot open %s", tmp); ! else ! error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP); ! } ! cp = repository; ! strip_path (cp); ! ! #ifdef RELATIVE_REPOS ! /* ! * If the Repository file is to hold a relative path, try to strip off ! * the leading CVSroot argument. ! */ ! if (CVSroot_directory != NULL) ! { ! char path[PATH_MAX]; ! ! (void) sprintf (path, "%s/", CVSroot_directory); ! if (strncmp (repository, path, strlen (path)) == 0) ! cp = repository + strlen (path); ! } ! #endif ! ! if (fprintf (fout, "%s\n", cp) < 0) ! { ! if (update_dir[0] == '\0') ! error (1, errno, "write to %s failed", tmp); ! else ! error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP); ! } ! if (fclose (fout) == EOF) ! { ! if (update_dir[0] == '\0') ! error (1, errno, "cannot close %s", tmp); ! else ! error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP); ! } ! /* now, do the Entries file */ if (dir != NULL) (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT); --- 52,61 ---- /* record the current cvs root for later use */ ! Create_Root (dir, update_dir, CVSroot_original); ! ! Create_Repository (dir, update_dir, repository); ! /* now, do the Entries file */ if (dir != NULL) (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT); *************** *** 136,140 **** (server_active) ? 'S' : ' '); } #endif - } --- 93,96 ---- diff -r -c -x .orig -x .new ./src/cvs.h ../cvs-1.9.new/src/cvs.h *** ./src/cvs.h Wed Oct 2 07:03:59 1996 --- ../cvs-1.9.new/src/cvs.h Thu Dec 19 16:04:03 1996 *************** *** 356,361 **** --- 356,362 ---- extern int trace; /* Show all commands */ extern int noexec; /* Don't modify disk anywhere */ extern int logoff; /* Don't write history entry */ + extern int overrideroot; /* Override the root directory with -d option */ extern char hostname[]; *************** *** 395,401 **** char *Name_Root PROTO((char *dir, char *update_dir)); int parse_cvsroot PROTO((char *CVSroot)); void set_local_cvsroot PROTO((char *dir)); ! void Create_Root PROTO((char *dir, char *rootdir)); int same_directories PROTO((char *dir1, char *dir2)); char *Short_Repository PROTO((char *repository)); char *gca PROTO((char *rev1, char *rev2)); --- 396,403 ---- char *Name_Root PROTO((char *dir, char *update_dir)); int parse_cvsroot PROTO((char *CVSroot)); void set_local_cvsroot PROTO((char *dir)); ! void Create_Root PROTO((char *dir, char *updatedir, char *rootdir)); ! void Create_Repository PROTO((char *dir, char *updatedir, char *repository)); int same_directories PROTO((char *dir1, char *dir2)); char *Short_Repository PROTO((char *repository)); char *gca PROTO((char *rev1, char *rev2)); diff -r -c -x .orig -x .new ./src/main.c ../cvs-1.9.new/src/main.c *** ./src/main.c Wed Oct 2 07:04:02 1996 --- ../cvs-1.9.new/src/main.c Wed Jan 8 15:32:11 1997 *************** *** 41,46 **** --- 41,47 ---- int trace = FALSE; int noexec = FALSE; int logoff = FALSE; + int overrideroot = FALSE; mode_t cvsumask = UMASK_DFLT; char *CurDir; *************** *** 322,328 **** /* `getopt_long' stores the option index here, but right now we don't use it. */ int option_index = 0; - int need_to_create_root = 0; error_set_cleanup (error_cleanup); --- 323,328 ---- *************** *** 609,619 **** #else if (strcmp (command_name, "import") != 0) CVSADM_Root = Name_Root((char *) NULL, (char *) NULL); ! #endif if (CVSADM_Root != NULL) { if (CVSroot == NULL || !cvs_update_env) { CVSroot = CVSADM_Root; cvs_update_env = 1; /* need to update environment */ } --- 609,634 ---- #else if (strcmp (command_name, "import") != 0) CVSADM_Root = Name_Root((char *) NULL, (char *) NULL); ! if (CVSADM_Root != NULL) { if (CVSroot == NULL || !cvs_update_env) { + /* this check was in Name_Root() in root.c but this causes problems when + -d is used to override the CVS/Root files */ + #ifdef CLIENT_SUPPORT + if ((strchr (CVSADM_Root, ':') == NULL) && !isdir (CVSADM_Root)) + #else /* ! CLIENT_SUPPORT */ + if (!isdir (CVSADM_Root)) + #endif /* CLIENT_SUPPORT */ + { + error (0, 0, + "ignoring %s in current directory because it specifies a non-existent repository %s", + CVSADM_ROOT, CVSADM_Root); + CVSADM_Root = NULL; + } + + #endif CVSroot = CVSADM_Root; cvs_update_env = 1; /* need to update environment */ } *************** *** 625,631 **** #ifdef CLIENT_SUPPORT !getenv ("CVS_IGNORE_REMOTE_ROOT") && #endif ! strcmp (CVSroot, CVSADM_Root) != 0) { /* Once we have verified that this root is usable, we will want to write it into CVS/Root. --- 640,646 ---- #ifdef CLIENT_SUPPORT !getenv ("CVS_IGNORE_REMOTE_ROOT") && #endif ! TRUE) { /* Once we have verified that this root is usable, we will want to write it into CVS/Root. *************** *** 647,653 **** (strcmp (command_name, "release") != 0) && (strcmp (command_name, "rtag") != 0)) #endif ! need_to_create_root = 1; } } --- 662,668 ---- (strcmp (command_name, "release") != 0) && (strcmp (command_name, "rtag") != 0)) #endif ! overrideroot = TRUE; } } *************** *** 842,855 **** } /* end of stuff that gets done if the user DOESN'T ask for help */ err = (*(cm->func)) (argc, argv); - - if (need_to_create_root) - { - /* Update the CVS/Root file. We might want to do this in - all directories that we recurse into, but currently we - don't. */ - Create_Root (NULL, CVSroot); - } Lock_Cleanup (); --- 857,862 ---- diff -r -c -x .orig -x .new ./src/options.h.in ../cvs-1.9.new/src/options.h.in *** ./src/options.h.in Wed Jan 8 16:08:31 1997 --- ../cvs-1.9.new/src/options.h.in Mon Jan 6 18:03:47 1997 *************** *** 182,190 **** * one can change the physical location of the master source * repository, change one's CVSROOT environment variable, and CVS will * work without problems. I recommend using full-paths. */ #ifndef RELATIVE_REPOS ! /* #define RELATIVE_REPOS */ #endif /* --- 182,200 ---- * one can change the physical location of the master source * repository, change one's CVSROOT environment variable, and CVS will * work without problems. I recommend using full-paths. + * + * Since making global -d option override and rewrite the admin files + * it is better to use relative repository files if you are using + * client/server support. This is because the admin files are + * rewritten at the client and may not have been rewritten by the time + * server uses them (especially if the server is the faster machine, + * as is often the case :-) ). + * It has been reported that relative repository files don't work with + * client/server but it does in my experience and I cannot see any + * reason why it should not work ok. */ #ifndef RELATIVE_REPOS ! #define RELATIVE_REPOS #endif /* diff -r -c -x .orig -x .new ./src/recurse.c ../cvs-1.9.new/src/recurse.c *** ./src/recurse.c Wed Jan 8 16:08:31 1997 --- ../cvs-1.9.new/src/recurse.c Mon Jan 6 18:03:48 1997 *************** *** 369,374 **** --- 369,408 ---- if (dirlist != NULL && filelist == NULL) dodoneproc = 0; + if (overrideroot) + { + /* Update the CVS/Root file. We might want to do this in + all directories that we recurse into, and now we do */ + /* First correct the repository file if it was created with an absolute path in it + which is incorrect */ + char *readrep = Name_Repository ((char *) NULL, update_dir); + if (strncmp(readrep,CVSroot_directory,strlen(CVSroot_directory))!=0) + { + char path[PATH_MAX]; + /* We need to send a repository directory with the correct root so + read the root from the CVS/Root file and remove it from the beginning of + the repository directory we read from CVS\Repository just now and add the + correct root to it and then recreate the CVS\Repository file using it */ + char *readroot = Name_Root ((char *) NULL, update_dir); + + (void) sprintf (path, "%s/", readroot); + if (strncmp (readrep, path, strlen (path)) == 0) + readrep = readrep + strlen (path); + else + { + error (1, 0, "CVS/Root and CVS/Repository are contradictory in %s\n", update_dir); + } + (void) sprintf (path, "%s/%s", CVSroot_directory, readrep); + + Create_Repository ((char *) NULL, update_dir, path); + /* reset the repository directory */ + if (repository) + repository = Name_Repository ((char *) NULL, update_dir); + + } + Create_Root ((char *) NULL, update_dir, CVSroot_original); + } + /* * If filelist or dirlist is already set, we don't look again. Otherwise, * find the files and directories diff -r -c -x .orig -x .new ./src/repos.c ../cvs-1.9.new/src/repos.c *** ./src/repos.c Tue Jul 23 16:13:28 1996 --- ../cvs-1.9.new/src/repos.c Fri Dec 20 12:07:16 1996 *************** *** 132,134 **** --- 132,196 ---- else return (repository); } + + /* + * Write the CVS/Repository file + */ + void + Create_Repository (dir, updatedir, repository) + char *dir; + char *updatedir; + char *repository; + { + char *cp; + FILE *fout; + char tmp[PATH_MAX]; + + if (noexec) + return; + + if (dir != NULL) + (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP); + else + (void) strcpy (tmp, CVSADM_REP); + fout = CVS_FOPEN (tmp, "w+"); + if (fout == NULL) + { + if (updatedir[0] == '\0') + error (1, errno, "cannot open %s", tmp); + else + error (1, errno, "cannot open %s/%s", updatedir, CVSADM_REP); + } + cp = repository; + strip_path (cp); + + #ifdef RELATIVE_REPOS + /* + * If the Repository file is to hold a relative path, try to strip off + * the leading CVSroot argument. + */ + if (CVSroot_directory != NULL) + { + char path[PATH_MAX]; + + (void) sprintf (path, "%s/", CVSroot_directory); + if (strncmp (repository, path, strlen (path)) == 0) + cp = repository + strlen (path); + } + #endif + + if (fprintf (fout, "%s\n", cp) < 0) + { + if (updatedir[0] == '\0') + error (1, errno, "write to %s failed", tmp); + else + error (1, errno, "write to %s/%s failed", updatedir, CVSADM_REP); + } + if (fclose (fout) == EOF) + { + if (updatedir[0] == '\0') + error (1, errno, "cannot close %s", tmp); + else + error (1, errno, "cannot close %s/%s", updatedir, CVSADM_REP); + } + } diff -r -c -x .orig -x .new ./src/root.c ../cvs-1.9.new/src/root.c *** ./src/root.c Thu Sep 5 20:16:07 1996 --- ../cvs-1.9.new/src/root.c Mon Jan 6 14:46:59 1997 *************** *** 98,116 **** return (NULL); } - #ifdef CLIENT_SUPPORT - if ((strchr (root, ':') == NULL) && !isdir (root)) - #else /* ! CLIENT_SUPPORT */ - if (!isdir (root)) - #endif /* CLIENT_SUPPORT */ - { - error (0, 0, "in directory %s:", xupdate_dir); - error (0, 0, - "ignoring %s because it specifies a non-existent repository %s", - CVSADM_ROOT, root); - return (NULL); - } - /* allocate space to return and fill it in */ strip_path (root); ret = xstrdup (root); --- 98,103 ---- *************** *** 150,157 **** * future work. */ void ! Create_Root (dir, rootdir) char *dir; char *rootdir; { FILE *fout; --- 137,145 ---- * future work. */ void ! Create_Root (dir, updatedir, rootdir) char *dir; + char *updatedir; char *rootdir; { FILE *fout; *************** *** 169,178 **** else (void) strcpy (tmp, CVSADM_ROOT); fout = open_file (tmp, "w+"); ! if (fprintf (fout, "%s\n", rootdir) < 0) ! error (1, errno, "write to %s failed", tmp); ! if (fclose (fout) == EOF) ! error (1, errno, "cannot close %s", tmp); } } --- 157,183 ---- else (void) strcpy (tmp, CVSADM_ROOT); fout = open_file (tmp, "w+"); ! if (fout == NULL) ! { ! if (updatedir[0] == '\0') ! error (1, errno, "cannot open %s", tmp); ! else ! error (1, errno, "cannot open %s/%s", updatedir, CVSADM_ENT); ! } ! if (fprintf (fout, "%s\n", rootdir) < 0) ! { ! if (updatedir[0] == '\0') ! error (1, errno, "write to %s failed", tmp); ! else ! error (1, errno, "write to %s/%s failed", updatedir, CVSADM_ENT); ! } ! if (fclose (fout) == EOF) ! { ! if (updatedir[0] == '\0') ! error (1, errno, "cannot close %s", tmp); ! else ! error (1, errno, "cannot close %s/%s", updatedir, CVSADM_ENT); ! } } } diff -r -c -x .orig -x .new ./src/update.c ../cvs-1.9.new/src/update.c *** ./src/update.c Wed Oct 2 07:04:09 1996 --- ../cvs-1.9.new/src/update.c Mon Jan 6 15:08:19 1997 *************** *** 696,702 **** { /* If there is no CVS/Root file, add one */ if (!isfile (CVSADM_ROOT)) ! Create_Root ((char *) NULL, CVSroot_original); } return (err); --- 696,702 ---- { /* If there is no CVS/Root file, add one */ if (!isfile (CVSADM_ROOT)) ! Create_Root ((char *) NULL, "\0" ,CVSroot_original); } return (err);