$Id: cvs.patch,v 1.1 2001/11/07 22:53:45 naddy Exp $ Index: src/cvs.h =================================================================== RCS file: /cvs/src/gnu/usr.bin/cvs/src/cvs.h,v retrieving revision 1.24 diff -u -r1.24 cvs.h --- src/cvs.h 28 Sep 2001 23:26:33 -0000 1.24 +++ src/cvs.h 7 Nov 2001 16:31:55 -0000 @@ -187,6 +187,7 @@ #define CVSROOTADM_WRITERS "writers" #define CVSROOTADM_PASSWD "passwd" #define CVSROOTADM_CONFIG "config" +#define CVSROOTADM_OPTIONS "options" #define CVSNULLREPOS "Emptydir" /* an empty directory */ @@ -365,7 +366,6 @@ extern int use_editor; extern int cvswrite; extern mode_t cvsumask; -extern char *RCS_citag; /* Access method specified in CVSroot. */ typedef enum { @@ -503,6 +503,7 @@ char *get_homedir PROTO ((void)); char *cvs_temp_name PROTO ((void)); FILE *cvs_temp_file PROTO ((char **filename)); +void parseopts PROTO ((const char *root)); int numdots PROTO((const char *s)); char *increment_revnum PROTO ((const char *)); Index: src/main.c =================================================================== RCS file: /cvs/src/gnu/usr.bin/cvs/src/main.c,v retrieving revision 1.37 diff -u -r1.37 main.c --- src/main.c 28 Sep 2001 23:26:33 -0000 1.37 +++ src/main.c 7 Nov 2001 19:13:52 -0000 @@ -50,7 +50,6 @@ int top_level_admin = 0; mode_t cvsumask = UMASK_DFLT; -char *RCS_citag = NULL; char *CurDir; @@ -978,6 +977,9 @@ if we didn't, then there would be no way to check in a new CVSROOT/config file to fix the broken one! */ parse_config (current_parsed_root->directory); + + /* Now is a convenient time to read CVSROOT/options */ + parseopts(current_parsed_root->directory); } #ifdef CLIENT_SUPPORT @@ -1162,4 +1164,57 @@ for (; *cpp; 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); + } + if (!strncmp(buf, "tagexpand=", 10)) { + char *what; + char *rcs_incexc; + + rcs_incexc = buf + 10; + RCS_setincexc(rcs_incexc); + } + /* Silently ignore other commands. */ + } + fclose(fp); + } } Index: src/parseinfo.c =================================================================== RCS file: /cvs/src/gnu/usr.bin/cvs/src/parseinfo.c,v retrieving revision 1.7 diff -u -r1.7 parseinfo.c --- src/parseinfo.c 28 Sep 2001 23:26:33 -0000 1.7 +++ src/parseinfo.c 7 Nov 2001 16:44:03 -0000 @@ -336,12 +336,7 @@ } } else if (strcmp (line, "tag") == 0) { - RCS_citag = strdup(p); - if (RCS_citag == NULL) { - error (0, 0, "%s: no memory for local tag '%s'", - infopath, p); - goto error_return; - } + RCS_setlocalid(p); } else if (strcmp (line, "umask") == 0) { cvsumask = (mode_t)(strtol(p, NULL, 8) & 0777); Index: src/rcs.c =================================================================== RCS file: /cvs/src/gnu/usr.bin/cvs/src/rcs.c,v retrieving revision 1.15 diff -u -r1.15 rcs.c --- src/rcs.c 28 Sep 2001 23:26:33 -0000 1.15 +++ src/rcs.c 7 Nov 2001 16:57:40 -0000 @@ -120,6 +120,8 @@ evaluates its arguments multiple times. */ #define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0) +static char * getfullCVSname PROTO ((char *, char **)); + /* * We don't want to use isspace() from the C library because: * @@ -3340,28 +3342,31 @@ { const char *string; size_t len; + int expandit; }; #define KEYWORD_INIT(s) (s), sizeof (s) - 1 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 }, - { 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, @@ -3373,6 +3378,7 @@ 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. */ @@ -3508,11 +3514,6 @@ return; } - if (RCS_citag != NULL && keywords[KEYWORD_LOCALID].string == NULL) { - keywords[KEYWORD_LOCALID].string = RCS_citag; - keywords[KEYWORD_LOCALID].len = strlen(RCS_citag); - } - /* If we are using -kkvl, dig out the locker information if any. */ locker = NULL; if (expand == KFLAG_KVL) @@ -3557,7 +3558,8 @@ 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; @@ -3604,6 +3606,7 @@ free_value = 1; break; + case KEYWORD_CVSHEADER: case KEYWORD_HEADER: case KEYWORD_ID: case KEYWORD_LOCALID: @@ -3611,9 +3614,17 @@ 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); @@ -3633,6 +3644,8 @@ locker != NULL ? locker : ""); if (free_path) free (path); + if (old_path) + free (old_path); free (date); free_value = 1; } @@ -8428,4 +8441,106 @@ } } 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 (current_parsed_root->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(current_parsed_root->directory); + if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) && + (*pathstore)[rootlen] == '/') + CVSname = (*pathstore + rootlen + 1); + else + CVSname = (*pathstore); + } + return CVSname; } Index: src/rcs.h =================================================================== RCS file: /cvs/src/gnu/usr.bin/cvs/src/rcs.h,v retrieving revision 1.1.1.15 diff -u -r1.1.1.15 rcs.h --- src/rcs.h 28 Sep 2001 22:45:39 -0000 1.1.1.15 +++ src/rcs.h 7 Nov 2001 16:58:39 -0000 @@ -240,6 +240,8 @@ void RCS_deltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *, char *, enum rcs_delta_op, 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 *)); extern int preserve_perms; Index: src/server.c =================================================================== RCS file: /cvs/src/gnu/usr.bin/cvs/src/server.c,v retrieving revision 1.26 diff -u -r1.26 server.c --- src/server.c 29 Sep 2001 00:00:39 -0000 1.26 +++ src/server.c 7 Nov 2001 17:00:10 -0000 @@ -781,6 +781,9 @@ nothing. But for rsh, we need to do it now. */ parse_config (current_parsed_root->directory); + /* Now is a good time to read CVSROOT/options too. */ + parseopts(current_parsed_root->directory); + path = malloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM) + 2);