summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Lai <ray@cvs.openbsd.org>2006-03-14 03:33:31 +0000
committerRay Lai <ray@cvs.openbsd.org>2006-03-14 03:33:31 +0000
commit60bcb76b5082163690969293bc23050d425fd0d2 (patch)
tree0b002f2284034955b28a4864da00f78557f16df1
parent96f5855fa4eb93ddc3f1f3ff54da6154656c73de (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/Makefile31
-rw-r--r--usr.bin/rcs/ci.c148
-rw-r--r--usr.bin/rcs/rcsprog.c3
-rw-r--r--usr.bin/rcs/rcsprog.h3
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 */