diff options
Diffstat (limited to 'contrib/cvs/src')
-rw-r--r-- | contrib/cvs/src/NOTES | 60 | ||||
-rw-r--r-- | contrib/cvs/src/README-rm-add | 31 | ||||
-rw-r--r-- | contrib/cvs/src/commit.c | 8 | ||||
-rw-r--r-- | contrib/cvs/src/cvs.h | 11 | ||||
-rw-r--r-- | contrib/cvs/src/diff.c | 6 | ||||
-rw-r--r-- | contrib/cvs/src/import.c | 2 | ||||
-rw-r--r-- | contrib/cvs/src/lock.c | 7 | ||||
-rw-r--r-- | contrib/cvs/src/logmsg.c | 67 | ||||
-rw-r--r-- | contrib/cvs/src/main.c | 93 | ||||
-rw-r--r-- | contrib/cvs/src/mkmodules.c | 17 | ||||
-rw-r--r-- | contrib/cvs/src/rcs.c | 170 | ||||
-rw-r--r-- | contrib/cvs/src/rcs.h | 3 | ||||
-rw-r--r-- | contrib/cvs/src/recurse.c | 9 | ||||
-rw-r--r-- | contrib/cvs/src/server.c | 38 | ||||
-rw-r--r-- | contrib/cvs/src/update.c | 2 |
15 files changed, 350 insertions, 174 deletions
diff --git a/contrib/cvs/src/NOTES b/contrib/cvs/src/NOTES deleted file mode 100644 index 646ebdf..0000000 --- a/contrib/cvs/src/NOTES +++ /dev/null @@ -1,60 +0,0 @@ -wishlist - Tue Nov 2 15:22:58 PST 1993 - -* bcopy -> memcpy & friends. - ** done 12/18/93 - -* remove static buffers. -* replace list & node cache with recursive obstacks, (xmalloc, - getnode, getlist) -* check all io functions for error return codes. also check all - system calls. -* error check mkdir. - ---- -Old notes... - -* All sizing limits are gone. The rest of these items were incidental - in that effort. - -* login name from history was duplicated. taught existing routine to - cache and use that instead. Also add routines to cache uid, pid, - etc. - -* ign strings were never freed. Now they are. - -* there was a printf("... %s ...", cp) vs *cp bug in history.c. Now - fixed. - -* The environment variables TMPDIR, HOME, and LOGNAME were not - honored. Now they are. - -* extra line inserted by do_editor() is gone. Then obviated. Editor - is now called exactly once per checkin. - -* revised editor behaviour. Never use /dev/tty. If the editor - session fails, we haven't yet done anything. Therefor the user can - safely rerun cvs and we should just fail. Also use the editor for - initial log messages on added files. Also omit the confirmation - when adding directories. Adding directories will require an - explicit "commit" step soon. Make it possible to prevent null login - messages using #define REQUIRE_LOG_MESSAGES - -* prototypes for all callbacks. - -* all callbacks get ref pointers. - -* do_recursion/start_recursion now use recusion_frame's rather than a - list of a lot of pointers and global variables. - -* corrected types on status_dirproc(). - -* CONFIRM_DIRECTORY_ADDS - -* re_comp was innappropriate in a few places. I've eliminated it. - -* FORCE_MESSAGE_ON_ADD - -* So I built a regression test. Let's call it a sanity check to be - less ambitious. It exposed that cvs is difficult to call from - scripts. - diff --git a/contrib/cvs/src/README-rm-add b/contrib/cvs/src/README-rm-add deleted file mode 100644 index 87fd7c6..0000000 --- a/contrib/cvs/src/README-rm-add +++ /dev/null @@ -1,31 +0,0 @@ -WHAT THE "DEATH SUPPORT" FEATURES DO: - -(Some of the death support stuff is documented in the main manual, but -this file is for stuff which noone has gotten around to adding to the -main manual yet). - -CVS with death support can record when a file is active, or alive, and -when it is removed, or dead. With this facility you can record the -history of a file, including the fact that at some point in its life -the file was removed and then later added. - -Files can now be added or removed in a branch and later merged -into the trunk. - - cvs update -A - touch a b c - cvs add a b c ; cvs ci -m "added" a b c - cvs tag -b branchtag - cvs update -r branchtag - touch d ; cvs add d - rm a ; cvs rm a - cvs ci -m "added d, removed a" - cvs update -A - cvs update -jbranchtag - -Added and removed files may also be merged between branches. - -Files removed in the trunk may be merged into branches. - -Files added on the trunk are a special case. They cannot be merged -into a branch. Instead, simply branch the file by hand. diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c index a7fec5f..71b491f 100644 --- a/contrib/cvs/src/commit.c +++ b/contrib/cvs/src/commit.c @@ -505,7 +505,7 @@ commit (argc, argv) /* Run the user-defined script to verify/check information in *the log message */ - do_verify (message, (char *)NULL); + do_verify (&message, (char *)NULL); /* We always send some sort of message, even if empty. */ /* FIXME: is that true? There seems to be some code in do_editor @@ -1178,7 +1178,7 @@ commit_fileproc (callerdat, finfo) got_message = 1; if (use_editor) do_editor (finfo->update_dir, &message, finfo->repository, ulist); - do_verify (message, finfo->repository); + do_verify (&message, finfo->repository); } p = findnode (cilist, finfo->file); @@ -1468,7 +1468,7 @@ commit_direntproc (callerdat, dir, repos, update_dir, entries) got_message = 1; if (use_editor) do_editor (update_dir, &message, real_repos, ulist); - do_verify (message, real_repos); + do_verify (&message, real_repos); free (real_repos); return (R_PROCESS); } @@ -2059,6 +2059,8 @@ internal error: `%s' didn't move out of the attic", char *head; char *magicrev; + fixbranch(rcsfile, sbranch); + head = RCS_getversion (rcsfile, NULL, NULL, 0, (int *) NULL); magicrev = RCS_magicrev (rcsfile, head); diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h index 5d735f1..7b50497 100644 --- a/contrib/cvs/src/cvs.h +++ b/contrib/cvs/src/cvs.h @@ -187,6 +187,7 @@ extern int errno; #define CVSROOTADM_WRITERS "writers" #define CVSROOTADM_PASSWD "passwd" #define CVSROOTADM_CONFIG "config" +#define CVSROOTADM_OPTIONS "options" #define CVSNULLREPOS "Emptydir" /* an empty directory */ @@ -256,6 +257,8 @@ extern int errno; #define CVSREAD_ENV "CVSREAD" /* make files read-only */ #define CVSREAD_DFLT 0 /* writable files by default */ +#define CVSREADONLYFS_ENV "CVSREADONLYFS" /* repository is read-only */ + #define TMPDIR_ENV "TMPDIR" /* Temporary directory */ /* #define TMPDIR_DFLT Set by options.h */ @@ -363,6 +366,7 @@ extern int really_quiet, quiet; extern int use_editor; extern int cvswrite; extern mode_t cvsumask; +extern char *RCS_citag; /* Access method specified in CVSroot. */ typedef enum { @@ -383,6 +387,7 @@ extern char *emptydir_name PROTO ((void)); extern int trace; /* Show all commands */ extern int noexec; /* Don't modify disk anywhere */ +extern int readonlyfs; /* fail on all write locks; succeed all read locks */ extern int logoff; /* Don't write history entry */ #ifdef AUTH_SERVER_SUPPORT @@ -468,6 +473,7 @@ int isabsolute PROTO((const char *filename)); char *last_component PROTO((char *path)); char *get_homedir PROTO ((void)); char *cvs_temp_name PROTO ((void)); +void parseopts PROTO ((const char *root)); int numdots PROTO((const char *s)); char *increment_revnum PROTO ((const char *)); @@ -555,7 +561,7 @@ void Update_Logfile PROTO((char *repository, char *xmessage, FILE * xlogfp, void do_editor PROTO((char *dir, char **messagep, char *repository, List * changes)); -void do_verify PROTO((char *message, char *repository)); +void do_verify PROTO((char **messagep, char *repository)); typedef int (*CALLBACKPROC) PROTO((int *pargc, char *argv[], char *where, char *mwhere, char *mfile, int shorten, int local_specified, @@ -794,9 +800,6 @@ void wrap_fromcvs_process_file PROTO ((const char *fileName)); void wrap_add_file PROTO((const char *file,int temp)); void wrap_add PROTO((char *line,int temp)); void wrap_send PROTO ((void)); -#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) -void wrap_unparse_rcs_options PROTO ((char **, int)); -#endif /* SERVER_SUPPORT || CLIENT_SUPPORT */ /* Pathname expansion */ char *expand_path PROTO((char *name, char *file, int line)); diff --git a/contrib/cvs/src/diff.c b/contrib/cvs/src/diff.c index a894c5b..4690ed8 100644 --- a/contrib/cvs/src/diff.c +++ b/contrib/cvs/src/diff.c @@ -434,14 +434,16 @@ diff_fileproc (callerdat, finfo) exists = 0; /* special handling for TAG_HEAD */ if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0) - exists = vers->vn_rcs != NULL; + exists = (vers->vn_rcs != NULL && /* XXX ? */ + !RCS_isdead (vers->srcfile, vers->vn_rcs)); /*XXX*/ else { Vers_TS *xvers; xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0); - exists = xvers->vn_rcs != NULL; + exists = (vers->vn_rcs != NULL && + !RCS_isdead (vers->srcfile, vers->vn_rcs)); /*XXX*/ freevers_ts (&xvers); } if (exists) diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c index 0a2af7f..11fc99d 100644 --- a/contrib/cvs/src/import.c +++ b/contrib/cvs/src/import.c @@ -194,7 +194,7 @@ import (argc, argv) do_editor ((char *) NULL, &message, repository, (List *) NULL); } - do_verify (message, repository); + do_verify (&message, repository); msglen = message == NULL ? 0 : strlen (message); if (msglen == 0 || message[msglen - 1] != '\n') { diff --git a/contrib/cvs/src/lock.c b/contrib/cvs/src/lock.c index be2dd1c..0d5cef6 100644 --- a/contrib/cvs/src/lock.c +++ b/contrib/cvs/src/lock.c @@ -243,7 +243,7 @@ Reader_Lock (xrepository) FILE *fp; char *tmp; - if (noexec) + if (noexec || readonlyfs) return (0); /* we only do one directory at a time for read locks! */ @@ -319,6 +319,11 @@ Writer_Lock (list) if (noexec) return (0); + if (readonlyfs) { + error (0, 0, "write lock failed - read-only repository"); + return (1); + } + /* We only know how to do one list at a time */ if (locklist != (List *) NULL) { diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c index 67194be..e471341 100644 --- a/contrib/cvs/src/logmsg.c +++ b/contrib/cvs/src/logmsg.c @@ -385,14 +385,20 @@ do_editor (dir, messagep, repository, changes) independant of the running of an editor for getting a message. */ void -do_verify (message, repository) - char *message; +do_verify (messagep, repository) + char **messagep; char *repository; { FILE *fp; char *fname; int retcode = 0; + char *line; + int line_length; + size_t line_chars_allocated; + char *p; + struct stat stbuf; + #ifdef CLIENT_SUPPORT if (client_active) /* The verification will happen on the server. */ @@ -406,7 +412,7 @@ do_verify (message, repository) /* If there's no message, then we have nothing to verify. Can this case happen? And if so why would we print a message? */ - if (message == NULL) + if (*messagep == NULL) { cvs_output ("No message to verify\n", 0); return; @@ -422,9 +428,9 @@ do_verify (message, repository) error (1, errno, "cannot create temporary file %s", fname); else { - fprintf (fp, "%s", message); - if ((message)[0] == '\0' || - (message)[strlen (message) - 1] != '\n') + fprintf (fp, "%s", *messagep); + if ((*messagep)[0] == '\0' || + (*messagep)[strlen (*messagep) - 1] != '\n') (void) fprintf (fp, "%s", "\n"); if (fclose (fp) == EOF) error (1, errno, "%s", fname); @@ -450,13 +456,62 @@ do_verify (message, repository) error (1, retcode == -1 ? errno : 0, "Message verification failed"); + } + + /* put the entire message back into the *messagep variable */ + + fp = open_file (fname, "r"); + if (fp == NULL) + { + error (1, errno, "cannot open temporary file %s", fname); + return; + } + + if (*messagep) + free (*messagep); + + if ( CVS_STAT (fname, &stbuf) != 0) + error (1, errno, "cannot find size of temp file %s", fname); + + if (stbuf.st_size == 0) + *messagep = NULL; + else + { + /* On NT, we might read less than st_size bytes, but we won't + read more. So this works. */ + *messagep = (char *) xmalloc (stbuf.st_size + 1); + *messagep[0] = '\0'; + } + + line = NULL; + line_chars_allocated = 0; + + if (*messagep) + { + p = *messagep; + while (1) + { + line_length = getline (&line, &line_chars_allocated, fp); + if (line_length == -1) + { + if (ferror (fp)) + error (0, errno, "warning: cannot read %s", fname); + break; + } + if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0) + continue; + (void) strcpy (p, line); + p += line_length; } } + if (fclose (fp) < 0) + error (0, errno, "warning: cannot close %s", fname); /* Delete the temp file */ unlink_file (fname); free (fname); + } } } diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c index 2397d7e..b2d1677 100644 --- a/contrib/cvs/src/main.c +++ b/contrib/cvs/src/main.c @@ -40,6 +40,7 @@ int really_quiet = 0; int quiet = 0; int trace = 0; int noexec = 0; +int readonlyfs = 0; int logoff = 0; mode_t cvsumask = UMASK_DFLT; @@ -212,6 +213,7 @@ static const char *const opt_usage[] = " -l Turn history logging off.\n", " -n Do not execute anything that will change the disk.\n", " -t Show trace of program execution -- try with -n.\n", + " -R Assume repository is read-only, such as CDROM\n", " -v CVS version and copyright.\n", " -b bindir Find RCS programs in 'bindir'.\n", " -T tmpdir Use 'tmpdir' for temporary files.\n", @@ -444,6 +446,10 @@ main (argc, argv) } if (getenv (CVSREAD_ENV) != NULL) cvswrite = 0; + if (getenv (CVSREADONLYFS_ENV) != NULL) { + readonlyfs = 1; + logoff = 1; + } /* Set this to 0 to force getopt initialization. getopt() sets this to 1 internally. */ @@ -473,7 +479,7 @@ main (argc, argv) opterr = 1; while ((c = getopt_long - (argc, argv, "+Qqrwtnlvb:T:e:d:Hfz:s:xa", long_options, &option_index)) + (argc, argv, "+QqrwtnRlvb:T:e:d:Hfz:s:xa", long_options, &option_index)) != EOF) { switch (c) @@ -509,6 +515,10 @@ main (argc, argv) case 't': trace = 1; break; + case 'R': + readonlyfs = 1; + logoff = 1; + break; case 'n': noexec = 1; case 'l': /* Fall through */ @@ -811,13 +821,14 @@ Copyright (c) 1989-1997 Brian Berliner, david d `zoo' zuhn, \n\ } (void) strcat (path, "/"); (void) strcat (path, CVSROOTADM_HISTORY); - if (isfile (path) && !isaccessible (path, R_OK | W_OK)) + if (readonlyfs == 0 && isfile (path) && !isaccessible (path, R_OK | W_OK)) { save_errno = errno; error (0, 0, "Sorry, you don't have read/write access to the history file"); error (1, save_errno, "%s", path); } free (path); + parseopts(CVSroot_directory); } #ifdef HAVE_PUTENV @@ -863,6 +874,12 @@ Copyright (c) 1989-1997 Brian Berliner, david d `zoo' zuhn, \n\ (void) putenv (env); /* do not free env, as putenv has control of it */ } + { + char *env; + env = xmalloc (sizeof "CVS_PID=" + 32); /* XXX pid < 10^32 */ + (void) sprintf (env, "CVS_PID=%ld", (long) getpid ()); + (void) putenv (env); + } #endif #ifndef DONT_USE_SIGNALS @@ -1000,3 +1017,75 @@ usage (cpp) (void) fprintf (stderr, *cpp); error_exit (); } + +void +parseopts(root) + const char *root; +{ + char path[PATH_MAX]; + int save_errno; + char buf[1024]; + const char *p; + char *q; + FILE *fp; + + if (root == NULL) { + printf("no CVSROOT in parseopts\n"); + return; + } + p = strchr (root, ':'); + if (p) + p++; + else + p = root; + if (p == NULL) { + printf("mangled CVSROOT in parseopts\n"); + return; + } + (void) sprintf (path, "%s/%s/%s", p, CVSROOTADM, CVSROOTADM_OPTIONS); + if ((fp = fopen(path, "r")) != NULL) { + while (fgets(buf, sizeof buf, fp) != NULL) { + if (buf[0] == '#') + continue; + q = strrchr(buf, '\n'); + if (q) + *q = '\0'; + + if (!strncmp(buf, "tag=", 4)) { + char *what; + char *rcs_localid; + + rcs_localid = buf + 4; + RCS_setlocalid(rcs_localid); + what = malloc(sizeof("RCSLOCALID") + 2 + strlen(rcs_localid)); + if (what == NULL) { + printf("no memory for local tag\n"); + return; + } + sprintf(what, "RCSLOCALID=%s", rcs_localid); + putenv(what); + } + if (!strncmp(buf, "tagexpand=", 10)) { + char *what; + char *rcs_incexc; + + rcs_incexc = buf + 10; + RCS_setincexc(rcs_incexc); + what = malloc(sizeof("RCSINCEXC") + 2 + strlen(rcs_incexc)); + if (what == NULL) { + printf("no memory for tag expand mode\n"); + return; + } + sprintf(what, "RCSINCEXC=%s", rcs_incexc); + putenv(what); + } + /* + * OpenBSD has a "umask=" and "dlimit=" command, we silently + * ignore them here since they are not much use to us. cvsumask + * defaults to 002 already, and the dlimit (data size limit) + * should really be handled elsewhere. + */ + } + fclose(fp); + } +} diff --git a/contrib/cvs/src/mkmodules.c b/contrib/cvs/src/mkmodules.c index dab5b3f..3c63433 100644 --- a/contrib/cvs/src/mkmodules.c +++ b/contrib/cvs/src/mkmodules.c @@ -204,15 +204,15 @@ static const char *const checkoutlist_contents[] = { }; static const char *const cvswrappers_contents[] = { - "# This file affects handling of files based on their names.\n", + "# This file describes wrappers and other binary files to CVS.\n", "#\n", - "# The -t/-f options allow one to treat directories of files\n", - "# as a single file, or to transform a file in other ways on\n", - "# its way in and out of CVS.\n", + "# Wrappers are the concept where directories of files are to be\n", + "# treated as a single file. The intended use is to wrap up a wrapper\n", + "# into a single tar such that the tar archive can be treated as a\n", + "# single binary file in CVS.\n", "#\n", - "# The -m option specifies whether CVS attempts to merge files.\n", - "#\n", - "# The -k option specifies keyword expansion (e.g. -kb for binary).\n", + "# To solve the problem effectively, it was also necessary to be able to\n", + "# prevent rcsmerge from merging these files.\n", "#\n", "# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)\n", "#\n", @@ -222,11 +222,10 @@ static const char *const cvswrappers_contents[] = { "# -f from cvs filter value: path to filter\n", "# -t to cvs filter value: path to filter\n", "# -m update methodology value: MERGE or COPY\n", - "# -k expansion mode value: b, o, kkv, &c\n", "#\n", "# and value is a single-quote delimited value.\n", + "#\n", "# For example:\n", - "#*.gif -k 'b'\n", NULL }; diff --git a/contrib/cvs/src/rcs.c b/contrib/cvs/src/rcs.c index c134d67..3400027 100644 --- a/contrib/cvs/src/rcs.c +++ b/contrib/cvs/src/rcs.c @@ -61,6 +61,8 @@ static FILE *rcs_internal_lockfile PROTO ((char *)); static void rcs_internal_unlockfile PROTO ((FILE *, char *)); static char *rcs_lockfilename PROTO ((char *)); +static char * getfullCVSname PROTO ((char *, char **)); + /* * We don't want to use isspace() from the C library because: * @@ -1463,13 +1465,25 @@ RCS_magicrev (rcs, rev) char *rev; { int rev_num; - char *xrev, *test_branch; + char *xrev, *test_branch, *local_branch_num; xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */ check_rev = xrev; + local_branch_num = getenv("CVS_LOCAL_BRANCH_NUM"); + if (local_branch_num) + { + rev_num = atoi(local_branch_num); + if (rev_num < 2) + rev_num = 2; + else + rev_num &= ~1; + } + else + rev_num = 2; + /* only look at even numbered branches */ - for (rev_num = 2; ; rev_num += 2) + for ( ; ; rev_num += 2) { /* see if the physical branch exists */ (void) sprintf (xrev, "%s.%d", rev, rev_num); @@ -2322,27 +2336,31 @@ struct rcs_keyword { const char *string; size_t len; + int expandit; }; #define KEYWORD_INIT(s) (s), sizeof (s) - 1 -static const struct rcs_keyword keywords[] = +static struct rcs_keyword keywords[] = { - { KEYWORD_INIT ("Author") }, - { KEYWORD_INIT ("Date") }, - { KEYWORD_INIT ("Header") }, - { KEYWORD_INIT ("Id") }, - { KEYWORD_INIT ("Locker") }, - { KEYWORD_INIT ("Log") }, - { KEYWORD_INIT ("Name") }, - { KEYWORD_INIT ("RCSfile") }, - { KEYWORD_INIT ("Revision") }, - { KEYWORD_INIT ("Source") }, - { KEYWORD_INIT ("State") }, - { NULL, 0 } + { KEYWORD_INIT ("Author"), 1 }, + { KEYWORD_INIT ("Date"), 1 }, + { KEYWORD_INIT ("CVSHeader"), 1 }, + { KEYWORD_INIT ("Header"), 1 }, + { KEYWORD_INIT ("Id"), 1 }, + { KEYWORD_INIT ("Locker"), 1 }, + { KEYWORD_INIT ("Log"), 1 }, + { KEYWORD_INIT ("Name"), 1 }, + { KEYWORD_INIT ("RCSfile"), 1 }, + { KEYWORD_INIT ("Revision"), 1 }, + { KEYWORD_INIT ("Source"), 1 }, + { KEYWORD_INIT ("State"), 1 }, + { NULL, 0, 0 }, + { NULL, 0, 0 } }; enum keyword { KEYWORD_AUTHOR = 0, KEYWORD_DATE, + KEYWORD_CVSHEADER, KEYWORD_HEADER, KEYWORD_ID, KEYWORD_LOCKER, @@ -2351,8 +2369,10 @@ enum keyword KEYWORD_RCSFILE, KEYWORD_REVISION, KEYWORD_SOURCE, - KEYWORD_STATE + KEYWORD_STATE, + KEYWORD_LOCALID }; +enum keyword keyword_local = KEYWORD_ID; /* Convert an RCS date string into a readable string. This is like the RCS date2str function. */ @@ -2530,7 +2550,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) slen = s - srch; for (keyword = keywords; keyword->string != NULL; keyword++) { - if (keyword->len == slen + if (keyword->expandit + && keyword->len == slen && strncmp (keyword->string, srch, slen) == 0) { break; @@ -2577,15 +2598,25 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) free_value = 1; break; + case KEYWORD_CVSHEADER: case KEYWORD_HEADER: case KEYWORD_ID: + case KEYWORD_LOCALID: { char *path; int free_path; char *date; + char *old_path; - if (kw == KEYWORD_HEADER) + old_path = NULL; + if (kw == KEYWORD_HEADER || + (kw == KEYWORD_LOCALID && + keyword_local == KEYWORD_HEADER)) path = rcs->path; + else if (kw == KEYWORD_CVSHEADER || + (kw == KEYWORD_LOCALID && + keyword_local == KEYWORD_CVSHEADER)) + path = getfullCVSname(rcs->path, &old_path); else path = last_component (rcs->path); path = escape_keyword_value (path, &free_path); @@ -2605,6 +2636,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) locker != NULL ? locker : ""); if (free_path) free (path); + if (old_path) + free (old_path); free (date); free_value = 1; } @@ -6689,3 +6722,104 @@ make_file_label (path, rev, rcs) return label; } +void +RCS_setlocalid (arg) + const char *arg; +{ + char *copy, *next, *key; + + copy = xstrdup(arg); + next = copy; + key = strtok(next, "="); + + keywords[KEYWORD_LOCALID].string = xstrdup(key); + keywords[KEYWORD_LOCALID].len = strlen(key); + keywords[KEYWORD_LOCALID].expandit = 1; + + /* options? */ + while (key = strtok(NULL, ",")) { + if (!strcmp(key, keywords[KEYWORD_ID].string)) + keyword_local = KEYWORD_ID; + else if (!strcmp(key, keywords[KEYWORD_HEADER].string)) + keyword_local = KEYWORD_HEADER; + else if (!strcmp(key, keywords[KEYWORD_CVSHEADER].string)) + keyword_local = KEYWORD_CVSHEADER; + else + error(1, 0, "Unknown LocalId mode: %s", key); + } + free(copy); +} + +void +RCS_setincexc (arg) + const char *arg; +{ + char *key; + char *copy, *next; + int include = 0; + struct rcs_keyword *keyword; + + copy = xstrdup(arg); + next = copy; + switch (*next++) { + case 'e': + include = 0; + break; + case 'i': + include = 1; + break; + default: + free(copy); + return; + } + + if (include) + for (keyword = keywords; keyword->string != NULL; keyword++) + { + keyword->expandit = 0; + } + + key = strtok(next, ","); + while (key) { + for (keyword = keywords; keyword->string != NULL; keyword++) { + if (strcmp (keyword->string, key) == 0) + keyword->expandit = include; + } + key = strtok(NULL, ","); + } + free(copy); + return; +} + +#define ATTIC "/" CVSATTIC +static char * +getfullCVSname(CVSname, pathstore) + char *CVSname, **pathstore; +{ + if (CVSroot_directory) { + int rootlen; + char *c = NULL; + int alen = sizeof(ATTIC) - 1; + + *pathstore = xstrdup(CVSname); + if ((c = strrchr(*pathstore, '/')) != NULL) { + if (c - *pathstore >= alen) { + if (!strncmp(c - alen, ATTIC, alen)) { + while (*c != '\0') { + *(c - alen) = *c; + c++; + } + *(c - alen) = '\0'; + } + } + } + + rootlen = strlen(CVSroot_directory); + if (!strncmp(*pathstore, CVSroot_directory, rootlen) && + (*pathstore)[rootlen] == '/') + CVSname = (*pathstore + rootlen + 1); + else + CVSname = (*pathstore); + } + return CVSname; +} diff --git a/contrib/cvs/src/rcs.h b/contrib/cvs/src/rcs.h index d0f47bb..60c4f3f 100644 --- a/contrib/cvs/src/rcs.h +++ b/contrib/cvs/src/rcs.h @@ -215,6 +215,9 @@ char *RCS_getaccess PROTO ((RCSNode *)); void RCS_rewrite PROTO ((RCSNode *, Deltatext *, char *)); int rcs_change_text PROTO ((const char *, char *, size_t, const char *, size_t, char **, size_t *)); +void RCS_setincexc PROTO ((const char *arg)); + +void RCS_setlocalid PROTO ((const char *arg)); char *make_file_label PROTO ((char *, char *, RCSNode *)); /* From import.c. */ diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c index d2fae6f..25b5b71 100644 --- a/contrib/cvs/src/recurse.c +++ b/contrib/cvs/src/recurse.c @@ -790,6 +790,7 @@ but CVS uses %s for its own purposes; skipping %s directory", repository = srepository; } +#if 0 /* Put back update_dir. I think this is the same as just setting update_dir back to saved_update_dir, but there are a few cases I'm not sure about (in particular, if DIR is "." and update_dir is @@ -800,6 +801,14 @@ but CVS uses %s for its own purposes; skipping %s directory", else update_dir[0] = '\0'; free (saved_update_dir); +#else + /* The above code is cactus!!! - it doesn't handle descending + multiple directories at once! ie: it recurses down several + dirs and then back up one. This breaks 'diff', 'update', + 'commit', etc. */ + free (update_dir); + update_dir = saved_update_dir; +#endif return (err); } diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c index a833415..509be56 100644 --- a/contrib/cvs/src/server.c +++ b/contrib/cvs/src/server.c @@ -599,7 +599,7 @@ serve_root (arg) } (void) strcat (path, "/"); (void) strcat (path, CVSROOTADM_HISTORY); - if (isfile (path) && !isaccessible (path, R_OK | W_OK)) + if (readonlyfs == 0 && isfile (path) && !isaccessible (path, R_OK | W_OK)) { save_errno = errno; pending_error_text = malloc (80 + strlen (path)); @@ -621,6 +621,7 @@ Sorry, you don't have read/write access to the history file %s", path); (void) putenv (env); /* do not free env, as putenv has control of it */ #endif + parseopts(CVSroot_directory); } static int max_dotdot_limit = 0; @@ -3780,38 +3781,6 @@ serve_gzip_stream (arg) buf_from_net->memory_error); } -/* Tell the client about RCS options set in CVSROOT/cvswrappers. */ -static void -serve_wrapper_sendme_rcs_options (arg) - char *arg; -{ - /* Actually, this is kind of sdrawkcab-ssa: the client wants - * verbatim lines from a cvswrappers file, but the server has - * already parsed the cvswrappers file into the wrap_list struct. - * Therefore, the server loops over wrap_list, unparsing each - * entry before sending it. - */ - char *wrapper_line = NULL; - - wrap_setup (); - - for (wrap_unparse_rcs_options (&wrapper_line, 1); - wrapper_line; - wrap_unparse_rcs_options (&wrapper_line, 0)) - { - buf_output0 (buf_to_net, "Wrapper-rcsOption "); - buf_output0 (buf_to_net, wrapper_line); - buf_output0 (buf_to_net, "\012");; - free (wrapper_line); - } - - buf_output0 (buf_to_net, "ok\012"); - - /* The client is waiting for us, so we better send the data now. */ - buf_flush (buf_to_net, 1); -} - - static void serve_ignore (arg) char *arg; @@ -4081,9 +4050,6 @@ struct request requests[] = REQ_LINE("Argumentx", serve_argumentx, rq_essential), REQ_LINE("Global_option", serve_global_option, rq_optional), REQ_LINE("Gzip-stream", serve_gzip_stream, rq_optional), - REQ_LINE("wrapper-sendme-rcsOptions", - serve_wrapper_sendme_rcs_options, - rq_optional), REQ_LINE("Set", serve_set, rq_optional), #ifdef ENCRYPTION # ifdef HAVE_KERBEROS diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c index 48bed3b..2aa3032 100644 --- a/contrib/cvs/src/update.c +++ b/contrib/cvs/src/update.c @@ -490,7 +490,7 @@ update_fileproc (callerdat, finfo) && tag != NULL && finfo->rcs != NULL) { - char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL); + char *rev = RCS_getversion (finfo->rcs, tag, date, 1, NULL); if (rev != NULL && !RCS_nodeisbranch (finfo->rcs, tag)) nonbranch = 1; |