summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src')
-rw-r--r--contrib/cvs/src/NOTES60
-rw-r--r--contrib/cvs/src/README-rm-add31
-rw-r--r--contrib/cvs/src/commit.c8
-rw-r--r--contrib/cvs/src/cvs.h11
-rw-r--r--contrib/cvs/src/diff.c6
-rw-r--r--contrib/cvs/src/import.c2
-rw-r--r--contrib/cvs/src/lock.c7
-rw-r--r--contrib/cvs/src/logmsg.c67
-rw-r--r--contrib/cvs/src/main.c93
-rw-r--r--contrib/cvs/src/mkmodules.c17
-rw-r--r--contrib/cvs/src/rcs.c170
-rw-r--r--contrib/cvs/src/rcs.h3
-rw-r--r--contrib/cvs/src/recurse.c9
-rw-r--r--contrib/cvs/src/server.c38
-rw-r--r--contrib/cvs/src/update.c2
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;
OpenPOWER on IntegriCloud