diff options
author | Ray Lai <ray@cvs.openbsd.org> | 2006-03-14 03:33:31 +0000 |
---|---|---|
committer | Ray Lai <ray@cvs.openbsd.org> | 2006-03-14 03:33:31 +0000 |
commit | 60bcb76b5082163690969293bc23050d425fd0d2 (patch) | |
tree | 0b002f2284034955b28a4864da00f78557f16df1 | |
parent | 96f5855fa4eb93ddc3f1f3ff54da6154656c73de (diff) |
ci currently doesn't parse the -x flag at all, defaulting to ",v/" every
time. I rewrote checkin_choose_rcsfile() to handle it using these rules:
- If a directory structure is given (ci -x,abcd dir/dir2/file) then all
RCS files are under dir/dir2.
- If the RCS/ directory exists, use it. Otherwise use current directory.
- If the -x flag is specified, use those slash-separated extensions.
Otherwise, use the default (",v/").
- Look in the rcs directory (RCS/ or current directory) for a file
with a matching extension, for each extension. Each extension is
tried in order. If a file exists, it is used. If no file exists
with any extension, the first one is used.
- The empty extension is treated as no extension, because I can't
figure out what its special meaning is.
It sounds complicated, and the code is kinda complicated as well, but it
makes sense if you think about it.
ok niallo
-rw-r--r-- | regress/usr.bin/rcs/Makefile | 31 | ||||
-rw-r--r-- | usr.bin/rcs/ci.c | 148 | ||||
-rw-r--r-- | usr.bin/rcs/rcsprog.c | 3 | ||||
-rw-r--r-- | usr.bin/rcs/rcsprog.h | 3 |
4 files changed, 136 insertions, 49 deletions
diff --git a/regress/usr.bin/rcs/Makefile b/regress/usr.bin/rcs/Makefile index 09d2ce6fc2a..8dd0dd50ec5 100644 --- a/regress/usr.bin/rcs/Makefile +++ b/regress/usr.bin/rcs/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.3 2006/03/14 01:51:35 ray Exp $ +# $OpenBSD: Makefile,v 1.4 2006/03/14 03:33:30 ray Exp $ # Regression tests by Niall O'Higgins <niallo@openbsd.org>. # ksh -> Makefile by Ray Lai <ray@cyth.net>. @@ -9,7 +9,7 @@ RCS?= rcs RCSDIFF?= rcsdiff RCSMERGE?= rcsmerge -CLEANFILES= blah.c blah.c,v test test,v +CLEANFILES= blah.c blah.c,v test test,v RCS # XXX - These may need to be done in order. (At least start with # test-ci-initial.) @@ -22,7 +22,7 @@ REGRESS_TARGETS+=test-rcsdiff-rflag test-rcs-mflag test-rcs-mflag2 REGRESS_TARGETS+=test-co-RCSINIT test-ci-nflag test-ci-Nflag REGRESS_TARGETS+=test-ci-sflag test-co-lflag2 test-rcsdiff #REGRESS_TARGETS+=test-rcsmerge -REGRESS_TARGETS+=test-ci-dflag test-comma +REGRESS_TARGETS+=test-ci-dflag test-ci-xflag test-comma test-ci-initial: clean @echo 'this is a test file' > test @@ -185,6 +185,28 @@ test-ci-dflag: @${CI} -q -d'2037-01-12 04:00:00+00' -m'dated revision' -l test @grep -q 'dated revision' test,v +test-ci-xflag: + @mkdir -p RCS + @rm -rf RCS/file* + @touch file + @echo . | ${CI} -x,abcd/,v file + @test -e RCS/file,abcd + @test ! -e RCS/file,v + + @mv -f RCS/file,abcd RCS/file,v + @${CO} -l file + @echo revision >> file + @echo . | ${CI} -x,abcd/,v/xyz file + @test ! -e RCS/file,abcd + @fgrep -q revision RCS/file,v + @test ! -e RCS/filexyz + + @# XXX - Coming soon + @#touch file + @#echo more >> file + @#${CI} -x file + @#fgrep -q more RCS/file + test-comma: @rm -rf RCS @mkdir -p RCS @@ -193,4 +215,7 @@ test-comma: @test -e RCS/file,notext,v @test ! -e RCS/file,v +clean: + @rm -rf ${CLEANFILES} + .include <bsd.regress.mk> diff --git a/usr.bin/rcs/ci.c b/usr.bin/rcs/ci.c index d3028ba23fa..ad2e9f88323 100644 --- a/usr.bin/rcs/ci.c +++ b/usr.bin/rcs/ci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ci.c,v 1.115 2006/03/11 22:44:11 niallo Exp $ */ +/* $OpenBSD: ci.c,v 1.116 2006/03/14 03:33:30 ray Exp $ */ /* * Copyright (c) 2005, 2006 Niall O'Higgins <niallo@openbsd.org> * All rights reserved. @@ -840,64 +840,126 @@ checkin_mtimedate(struct checkin_params *pb) /* * checkin_choose_rcsfile() * - * Given a relative filename, decide where the corresponding ,v file - * should be. + * Given a relative filename, decide where the corresponding RCS file + * should be. Tries each extension until a file is found. If no file + * was found, returns a path with the first extension. * * Returns pointer to a char array on success, NULL on failure. */ static char * checkin_choose_rcsfile(const char *filename) { - char name[MAXPATHLEN], *basepath; - const char *ptr; - size_t len; struct stat sb; + char *ext, name[MAXPATHLEN], *next, *ptr, rcsdir[MAXPATHLEN], + *ret, *suffixes, rcspath[MAXPATHLEN]; - basepath = xmalloc(MAXPATHLEN); - basepath[0] = '\0'; - if (strchr(filename, '/') == NULL) { - strlcat(basepath, RCSDIR"/", MAXPATHLEN); - if ((stat(basepath, &sb) == 0) && (sb.st_mode & S_IFDIR)) { - /* <path>/RCS/<filename>,v */ - strlcat(basepath, filename, MAXPATHLEN); - strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN); - } else { - /* <path>/<filename>,v */ - strlcpy(basepath, filename, MAXPATHLEN); - strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN); - } + /* If -x flag was not given, use default. */ + if (rcs_suffixes == NULL) + rcs_suffixes = RCS_DEFAULT_SUFFIX; + + /* + * If `filename' contains a directory, `rcspath' contains that + * directory, including a trailing slash. Otherwise `rcspath' + * contains an empty string. + */ + if (strlcpy(rcspath, filename, sizeof(rcspath)) >= sizeof(rcspath)) + return (NULL); + /* If `/' is found, end string after `/'. */ + if ((ptr = strrchr(rcspath, '/')) != NULL) + *(++ptr) = '\0'; + else + rcspath[0] = '\0'; + + /* Append RCS/ to `rcspath' if it exists. */ + if (strlcpy(rcsdir, rcspath, sizeof(rcsdir)) >= sizeof(rcsdir) || + strlcat(rcsdir, RCSDIR, sizeof(rcsdir)) >= sizeof(rcsdir)) + return (NULL); + if ((stat(rcsdir, &sb) == 0) && (sb.st_mode & S_IFDIR)) + if (strlcpy(rcspath, rcsdir, sizeof(rcspath)) >= sizeof(rcspath) || + strlcat(rcspath, "/", sizeof(rcspath)) >= sizeof(rcspath)) + return (NULL); + + /* Name of file without path. */ + if ((ptr = strrchr(filename, '/')) == NULL) { + if (strlcpy(name, filename, sizeof(name)) >= sizeof(name)) + return (NULL); } else { - ptr = filename; - /* Walk backwards till we find the base directory */ - len = strlen(filename); - ptr += len + 1; - while (filename[len] != '/') { - len--; - ptr--; + /* Skip `/'. */ + if (strlcpy(name, ptr + 1, sizeof(name)) >= sizeof(name)) + return (NULL); + } + + /* Name of RCS file without an extension. */ + if (strlcat(rcspath, name, sizeof(rcspath)) >= sizeof(rcspath)) + return (NULL); + + /* + * If only the empty suffix was given, use existing rcspath. + * This ensures that there is at least one suffix for strsep(). + */ + if (strcmp(rcs_suffixes, "") == 0) { + if ((ret = strdup(rcspath)) == NULL); + fatal("out of memory"); + return (ret); + } + + /* + * Cycle through slash-separated `rcs_suffixes', appending each + * extension to `rcspath' and testing if the file exists. If it + * does, return that string. Otherwise return path with first + * extension. + */ + if ((suffixes = strdup(rcs_suffixes)) == NULL) + fatal("out of memory"); + for (ret = NULL, next = suffixes; (ext = strsep(&next, "/")) != NULL;) { + char fpath[MAXPATHLEN]; + + /* Construct RCS file path. */ + if (strlcpy(fpath, rcspath, sizeof(fpath)) >= sizeof(fpath) || + strlcat(fpath, ext, sizeof(fpath)) >= sizeof(fpath)) { + xfree(suffixes); + return (NULL); + } + + /* Don't use `filename' as RCS file. */ + if (strcmp(fpath, filename) == 0) + continue; + + if (stat(fpath, &sb) == 0) { + if ((ret = strdup(fpath)) == NULL) + fatal("out of memory"); + break; } + } + xfree(suffixes); + + /* + * If `ret' is still NULL no RCS file with any extension exists + * so we use the first extension. + */ + if (ret == NULL) { /* - * Need two bytes extra for trailing slash and - * NUL-termination. + * XXX - We shouldn't need to do strsep again, + * suffixes should now be NUL separated. */ - len += 2; - if (len > MAXPATHLEN) { - xfree(basepath); + if ((suffixes = strdup(rcs_suffixes)) == NULL) + fatal("out of memory"); + next = suffixes; + /* Get first extension again. */ + if ((ext = strsep(&next, "/")) == NULL) { + xfree(suffixes); return (NULL); } - strlcpy(basepath, filename, len); - strlcpy(name, ptr, MAXPATHLEN); - strlcat(basepath, RCSDIR"/", MAXPATHLEN); - if ((stat(basepath, &sb) == 0) && (sb.st_mode & S_IFDIR)) { - /* <path>/RCS/<filename>,v */ - strlcat(basepath, name, MAXPATHLEN); - strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN); - } else { - /* <path>/<filename>,v */ - strlcpy(basepath, filename, MAXPATHLEN); - strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN); + if (strlcat(rcspath, ext, sizeof(rcspath)) >= sizeof(rcspath)) { + xfree(suffixes); + return (NULL); } + if ((ret = strdup(rcspath)) == NULL) + fatal("out of memory"); + xfree(suffixes); } - return (basepath); + + return (ret); } /* diff --git a/usr.bin/rcs/rcsprog.c b/usr.bin/rcs/rcsprog.c index 295522d1d04..bea11281c5e 100644 --- a/usr.bin/rcs/rcsprog.c +++ b/usr.bin/rcs/rcsprog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsprog.c,v 1.71 2006/03/14 01:51:35 ray Exp $ */ +/* $OpenBSD: rcsprog.c,v 1.72 2006/03/14 03:33:30 ray Exp $ */ /* * Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -29,7 +29,6 @@ #include "rcsprog.h" #define RCS_CMD_MAXARG 128 -#define RCS_DEFAULT_SUFFIX ",v/" #define RCSPROG_OPTSTRING "A:a:b::c:e::hik:Lm:Mn:N:qt::TUVx:z:" #define DESC_PROMPT "enter description, terminated with single '.' " \ diff --git a/usr.bin/rcs/rcsprog.h b/usr.bin/rcs/rcsprog.h index 67da6bfa377..e7045e470fb 100644 --- a/usr.bin/rcs/rcsprog.h +++ b/usr.bin/rcs/rcsprog.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsprog.h,v 1.36 2006/03/08 20:19:39 joris Exp $ */ +/* $OpenBSD: rcsprog.h,v 1.37 2006/03/14 03:33:30 ray Exp $ */ /* * Copyright (c) 2005 Joris Vink <joris@openbsd.org> * All rights reserved. @@ -32,6 +32,7 @@ #include "worklist.h" #include "xmalloc.h" +#define RCS_DEFAULT_SUFFIX ",v/" #define RCS_TMPDIR_DEFAULT "/tmp" /* flags specific to ci.c */ |