As promised, I've now finally (sorry for the delay) started to work-off
my larger CVS patch set for OpenPKG which you can find in original under
http://cvs.openpkg.org/openpkg-src/cvs/cvs.patch.rse
The first result is a completely worked-off "importinfo" and "admininfo"
patch against the latest CVS HEAD version of CVS which you can find
under http://www.engelschall.com/~rse/cvs/cvs.patch-info.diff and in the
attachment to this email.
The patch adds two still missing and very important auditing hook
facilities to CVS: "CVSROOT/importinfo" for auditing "cvs import"
operations and "CVSROOT/admininfo" for auditing "cvs admin" operations.
I was prompted to implement these some years ago when I wrote OSSP
Shiela (see http://www.ossp.org/pkg/tool/shiela/ for details) and had
to recognize that it still could be circumvented by the two remaining
repository-destructive operations "cvs import" and "cvs admin".
The patch was adjusted in style (including C89) to now hopefully fully
conform to the CVS coding style, and extended with documentation and
full test suite additions. It also includes some of the feedback you
already gave to Wu Yongwei. It should be now ready for final inclusion
into the CVSHome.org CVS sources and become part of the next major CVS
release.
Please review the patch in detail and give me feedback. If everything is
fine, please commit it to the CVS HEAD of CVS and let us proceed to the
next possible contributions derived from my OpenPKG CVS patch set.
Yours,
Ralf S. Engelschall
[EMAIL PROTECTED]
www.engelschall.com
This patch adds two still missing and very important auditing hook
facilities to CVS: "CVSROOT/importinfo" for auditing "cvs import"
operations and "CVSROOT/admininfo" for auditing "cvs admin" operations.
Index: man/cvs.1
===================================================================
RCS file: /cvs/ccvs/man/cvs.1,v
retrieving revision 1.35
diff -u -d -r1.35 cvs.1
--- man/cvs.1 19 Mar 2003 21:13:30 -0000 1.35
+++ man/cvs.1 4 Oct 2003 10:35:47 -0000
@@ -1975,6 +1975,11 @@
$CVSROOT/CVSROOT
Directory of global administrative files for repository.
.TP
+CVSROOT/importinfo,v
+Records programs for filtering
+.` "cvs import"
+requests.
+.TP
CVSROOT/commitinfo,v
Records programs for filtering
.` "cvs commit"
@@ -2017,6 +2022,11 @@
.` "cvs rtag"
operations.
.TP
+CVSROOT/admininfo,v
+Records programs for validating/logging
+.` "cvs admin"
+operations.
+.TP
MODULE/Attic
Directory for removed source files.
.TP
@@ -2108,7 +2118,7 @@
This is the process identification (aka pid) number of the
.B cvs
process. It is often useful in the programs and/or scripts
-specified by the CVSROOT/commitinfo CVSROOT/verifymsg and
+specified by the CVSROOT/importinfo CVSROOT/commitinfo CVSROOT/verifymsg and
CVSROOT/loginfo administrative files.
.TP
.SM CVS_RSH
Index: man/cvs.5
===================================================================
RCS file: /cvs/ccvs/man/cvs.5,v
retrieving revision 1.6
diff -u -d -r1.6 cvs.5
--- man/cvs.5 17 Apr 2002 19:00:20 -0000 1.6
+++ man/cvs.5 4 Oct 2003 10:35:48 -0000
@@ -15,6 +15,8 @@
.hy 0
.na
.TP
+.B $CVSROOT/CVSROOT/importinfo,v
+.TP
.B $CVSROOT/CVSROOT/commitinfo,v
.TP
.B $CVSROOT/CVSROOT/cvsignore,v
@@ -32,6 +34,8 @@
.B $CVSROOT/CVSROOT/rcsinfo,v
.TP
.B $CVSROOT/CVSROOT/taginfo,v
+.TP
+.B $CVSROOT/CVSROOT/admininfo,v
.ad b
.hy 1
.SH DESCRIPTION
@@ -59,6 +63,14 @@
(absolute, or relative to \fB$CVSROOT\fP) for the files they wish to
manage with \fBcvs\fP commands.
.SP
+You can use the `\|importinfo\|' file to define programs to execute
+whenever `\|\fBcvs import\fP\|' is about to execute. These programs are
+used for ``pre-import'' checking to verify that the imported files are
+really ready to be committed. Some uses for this check might be to turn
+off a portion (or all) of the source repository from a particular person
+or group. Or, perhaps, to verify that the imported files conform to the
+site's standards for coding practice.
+.SP
You can use the `\|commitinfo\|' file to define programs to execute
whenever `\|\fBcvs commit\fP\|' is about to execute.
These programs are used for ``pre-commit'' checking to verify that the
@@ -92,6 +104,11 @@
to a group of developers, or, perhaps, post a message to a particular
newsgroup.
.SP
+You can use the `\|admininfo\|' file to define programs to execute
+whenever `\|\fBcvs admin\fP\|' is about to execute. Some uses for this
+check might be to turn off administration access to a portion (or all)
+of the source repository for a particular person or group.
+.SP
You can use the `\|rcsinfo\|' file to define forms for log messages.
.SP
You can use the `\|editinfo\|' file to define a program to execute for
@@ -207,7 +224,7 @@
directory of the checked-out module. \fIprog\fP runs with a
single argument, the full path to the source repository for this module.
.TP
-\&\fBcommitinfo\fP, \fBloginfo\fP, \fBrcsinfo\fP, \fBeditinfo\fP
+\&\fBimportinfo, \fP\fBcommitinfo\fP, \fBloginfo\fP, \fBrcsinfo\fP, \fBeditinfo\fP,
\fBadmininfo\fP
These files all specify programs to call at different points in the
`\|\fBcvs commit\fP\|' process. They have a common structure.
Each line is a pair of fields: a regular expression, separated by
@@ -246,6 +263,12 @@
.B "filename revision" .
A non-zero exit of the filter program will cause the tag to be aborted.
.SP
+For `\|importinfo\|', the rest of the line is a command-line template to
+execute. The template can include not only a program name, but whatever
+list of arguments you wish. The vendor tag and the full path to the
+current source repository is appended to the template, followed by the
+file names of any files involved in the import.
+.SP
For `\|commitinfo\|', the rest of the line is a command-line template to
execute.
The template can include not only a program name, but whatever
@@ -263,6 +286,12 @@
list of arguments you wish.
The full path to the current log message template file is appended to the
template.
+.SP
+For `\|admininfo\|', the rest of the line is a command-line template to
+execute. The template can include not only a program name, but whatever
+list of arguments you wish. The full path to the current source
+repository is appended to the template, followed by the file names of
+any files involved in the administration operation.
.SP
You can use one of two special strings instead of a regular
expression: `\|\fBALL\fP\|' specifies a command line template that
Index: src/admin.c
===================================================================
RCS file: /cvs/ccvs/src/admin.c,v
retrieving revision 1.90
diff -u -d -r1.90 admin.c
--- src/admin.c 19 Aug 2003 13:35:15 -0000 1.90
+++ src/admin.c 4 Oct 2003 10:35:49 -0000
@@ -137,6 +137,150 @@
dat->av[dat->ac++] = newelt;
}
+static List *admininfo_dlist;
+static List *admininfo_flist;
+
+static void admininfo_dlist_delproc (Node *);
+static int admininfo_info_runproc (char *, char *, void *);
+static int admininfo_flist_runproc (Node *, void *);
+
+struct admininfo_dlist_st {
+ List *flist;
+};
+
+/* file callback function for recursive processing */
+static int
+admininfo_fileproc (void *callerdat, struct file_info *finfo)
+{
+ char *xdir;
+ Node *dnode;
+ Node *fnode;
+
+ /* determine current directory */
+ if (finfo->update_dir[0] == '\0')
+ xdir = ".";
+ else
+ xdir = finfo->update_dir;
+
+ /* find directory node in directory list */
+ if ((dnode = findnode (admininfo_dlist, xdir)) != NULL)
+ /* take already existing file list */
+ admininfo_flist = ((struct admininfo_dlist_st *)dnode->data)->flist;
+ else
+ {
+ /* create a new file list */
+ struct admininfo_dlist_st *dlist;
+
+ admininfo_flist = getlist ();
+
+ dlist = (struct admininfo_dlist_st *) xmalloc (sizeof(struct
admininfo_dlist_st));
+ dlist->flist = admininfo_flist;
+
+ dnode = getnode();
+ dnode->type = UPDATE;
+ dnode->key = xstrdup (xdir);
+ dnode->data = (char *)dlist;
+ dnode->delproc = admininfo_dlist_delproc;
+
+ (void) addnode (admininfo_dlist, dnode);
+ }
+
+ /* create new file node in file list */
+ fnode = getnode ();
+ fnode->type = UPDATE;
+ fnode->key = xstrdup (finfo->file);
+ fnode->data = NULL;
+ fnode->delproc = NULL;
+ (void) addnode (admininfo_flist, fnode);
+
+ return 0;
+}
+
+/* delete a directory list node */
+static void
+admininfo_dlist_delproc (Node *p)
+{
+ struct admininfo_dlist_st *dlist;
+
+ dlist = (struct admininfo_dlist_st *)p->data;
+ dellist (&dlist->flist);
+ free (dlist);
+ return;
+}
+
+/* file callback function for recursive processing (when done) */
+static int
+admininfo_filesdoneproc (void *callerdat, int err, char *repos, char *update_dir,
List *entries)
+{
+ Node *dnode;
+ int n;
+
+ /* find file list for update directory */
+ if ((dnode = findnode (admininfo_dlist, update_dir)) != NULL)
+ admininfo_flist = ((struct admininfo_dlist_st *)dnode->data)->flist;
+ else
+ admininfo_flist = (List *)NULL;
+ if ( (admininfo_flist == NULL)
+ || (admininfo_flist->list->next == admininfo_flist->list))
+ return err;
+
+ /* parse and execute the admininfo configuration */
+ if ((n = Parse_Info (CVSROOTADM_ADMININFO, repos,
+ admininfo_info_runproc, PIOPT_ALL, NULL)) > 0)
+ {
+ error (0, 0, "Pre-admin check failed");
+ err += n;
+ }
+
+ return err;
+}
+
+/* admininfo configuration entry callback */
+static int admininfo_info_runproc (char *repository, char *filter, void *closure)
+{
+ char *s, *cp;
+ int rv;
+
+ if (noexec || repository == NULL)
+ return;
+
+ /* if easily possible, make sure that the filter command really exists in advance
*/
+ if (filter[0] == '/') {
+ s = xstrdup (filter);
+ for (cp = s; *cp; cp++) {
+ if (isspace ((unsigned char)*cp)) {
+ *cp = '\0';
+ break;
+ }
+ }
+ if (! isfile (s)) {
+ error (0, errno, "cannot find pre-admin filter '%s'", s);
+ free (s);
+ return (1);
+ }
+ free(s);
+ }
+
+ /* construct the filter command */
+ run_setup (filter);
+ run_arg (repository);
+ walklist (admininfo_flist, admininfo_flist_runproc, NULL);
+
+ /* execute the filter command */
+ rv = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+
+ return rv;
+}
+
+/* file list callback for adding file as another program argument */
+static int
+admininfo_flist_runproc (Node *p, void *closure)
+{
+ if (p->key != NULL)
+ run_arg (p->key);
+ return 0;
+}
+
int
admin (int argc, char **argv)
{
@@ -512,6 +656,18 @@
#endif /* CLIENT_SUPPORT */
lock_tree_for_write (argc, argv, 0, W_LOCAL, 0);
+
+ /* allow `CVSROOT/admininfo' filters to check whether the `cvs admin'
+ operation is authorized for all the specified files in the repository */
+ admininfo_dlist = getlist();
+ err = start_recursion (admininfo_fileproc, admininfo_filesdoneproc,
+ (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
+ argc, argv, 0, W_LOCAL, 0, 0, (char *)NULL, 1, (char
*)NULL);
+ if (err)
+ {
+ Lock_Cleanup ();
+ error (1, 0, "correct above errors first!");
+ }
err = start_recursion
( admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
Index: src/cvs.h
===================================================================
RCS file: /cvs/ccvs/src/cvs.h,v
retrieving revision 1.270
diff -u -d -r1.270 cvs.h
--- src/cvs.h 29 Aug 2003 19:00:12 -0000 1.270
+++ src/cvs.h 4 Oct 2003 10:35:51 -0000
@@ -166,6 +166,8 @@
#define CVSROOTADM_WRITERS "writers"
#define CVSROOTADM_PASSWD "passwd"
#define CVSROOTADM_CONFIG "config"
+#define CVSROOTADM_ADMININFO "admininfo"
+#define CVSROOTADM_IMPORTINFO "importinfo"
#define CVSNULLREPOS "Emptydir" /* an empty directory */
Index: src/import.c
===================================================================
RCS file: /cvs/ccvs/src/import.c,v
retrieving revision 1.139
diff -u -d -r1.139 import.c
--- src/import.c 19 Aug 2003 13:35:15 -0000 1.139
+++ src/import.c 4 Oct 2003 10:35:53 -0000
@@ -56,6 +56,151 @@
NULL
};
+static char *importinfo_vtag;
+
+/* importinfo directory recursive descending */
+static int
+importinfo_descend (char *thisdir)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ int err = 0;
+ List *dirlist = NULL;
+
+ /* first, load up any per-directory ignore lists */
+ ign_add_file (CVSDOTIGNORE, 1);
+ wrap_add_file (CVSDOTWRAPPER, 1);
+
+ if ((dirp = CVS_OPENDIR (thisdir)) == NULL)
+ {
+ error (0, errno, "cannot open directory");
+ err++;
+ }
+ else {
+ errno = 0;
+ while ((dp = CVS_READDIR (dirp)) != NULL)
+ {
+ if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
+ goto one_more_time_boys;
+#ifdef SERVER_SUPPORT
+ if (server_active && strcmp (dp->d_name, CVSADM) == 0)
+ goto one_more_time_boys;
+#endif
+ if (ign_name (dp->d_name))
+ goto one_more_time_boys;
+ if (
+#ifdef DT_DIR
+ (dp->d_type == DT_DIR || (dp->d_type == DT_UNKNOWN && isdir
(dp->d_name)))
+#else
+ isdir (dp->d_name)
+#endif
+ && !wrap_name_has (dp->d_name, WRAP_TOCVS)
+ ) {
+ Node *n;
+ if (dirlist == NULL)
+ dirlist = getlist ();
+ n = getnode ();
+ n->key = xstrdup (dp->d_name);
+ addnode (dirlist, n);
+ }
+ else if (
+#ifdef DT_DIR
+ dp->d_type == DT_LNK || (dp->d_type == DT_UNKNOWN && islink
(dp->d_name))
+#else
+ islink (dp->d_name)
+#endif
+ )
+ {
+ err++;
+ }
+ else {
+ if (strcmp (thisdir, ".") == 0)
+ {
+ run_arg (dp->d_name);
+ }
+ else
+ {
+ char *p;
+ p = xmalloc (strlen (thisdir) +1 + strlen (dp->d_name) + 1);
+ (void) sprintf (p, "%s/%s", thisdir, dp->d_name);
+ run_arg (p);
+ free (p);
+ }
+ }
+ one_more_time_boys:
+ errno = 0;
+ }
+ if (errno != 0)
+ {
+ error (0, errno, "cannot read directory");
+ err++;
+ }
+ CVS_CLOSEDIR (dirp);
+ }
+ if (dirlist != NULL)
+ {
+ Node *head, *p;
+ head = dirlist->list;
+ for (p = head->next; p != head; p = p->next) {
+ if (strcmp (thisdir, ".") == 0)
+ {
+ err += importinfo_descend (p->key);
+ }
+ else
+ {
+ char *nextdir;
+ nextdir = xmalloc (strlen (thisdir) + 1 + strlen(p->key) + 1);
+ (void) sprintf (nextdir, "%s/%s", thisdir, p->key);
+ err += importinfo_descend (nextdir);
+ free (nextdir);
+ }
+ }
+ dellist (&dirlist);
+ }
+ return (err);
+}
+
+/* importinfo check processing callback */
+static int
+importinfo_runproc (char *repository, char *filter, void *closure)
+{
+ char *s, *cp;
+ int rv;
+
+ if (noexec || repository == NULL)
+ return;
+
+ /* if easily possible, make sure that the filter command really exists in advance
*/
+ if (filter[0] == '/') {
+ s = xstrdup (filter);
+ for (cp = s; *cp; cp++) {
+ if (isspace ((unsigned char)*cp)) {
+ *cp = '\0';
+ break;
+ }
+ }
+ if (! isfile (s)) {
+ error (0, errno, "cannot find pre-import filter '%s'", s);
+ free (s);
+ return (1);
+ }
+ free (s);
+ }
+
+ /* construct the filter command */
+ run_setup (filter);
+ run_arg (importinfo_vtag);
+ run_arg (repository);
+ rv = importinfo_descend (".");
+ if (rv > 0)
+ return rv;
+
+ /* execute the filter command */
+ rv = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
+
+ return rv;
+}
+
int
import (int argc, char **argv)
{
@@ -286,6 +431,12 @@
{
error (1, 0, "attempt to import the repository");
}
+
+ /* run administrative filter command */
+ importinfo_vtag = argv[1];
+ if (Parse_Info (CVSROOTADM_IMPORTINFO, argv[0],
+ importinfo_runproc, PIOPT_ALL, NULL) > 0)
+ error (1, 0, "Pre-import check failed");
/*
* Make all newly created directories writable. Should really use a more
Index: src/mkmodules.c
===================================================================
RCS file: /cvs/ccvs/src/mkmodules.c,v
retrieving revision 1.75
diff -u -d -r1.75 mkmodules.c
--- src/mkmodules.c 12 Sep 2003 18:54:52 -0000 1.75
+++ src/mkmodules.c 4 Oct 2003 10:35:55 -0000
@@ -120,6 +120,25 @@
NULL
};
+static const char *const importinfo_contents[] = {
+ "# The \"importinfo\" file is used to control pre-import checks.\n",
+ "# The filter on the right is invoked with the repository to check.\n",
+ "# A non-zero exit of the filter program will cause the import\n",
+ "# operation to be aborted.\n",
+ "#\n",
+ "# The first entry on a line is a regular expression which is tested\n",
+ "# against the directory that the change is being committed to, relative\n",
+ "# to the $CVSROOT. For the first match that is found, then the remainder\n",
+ "# of the line is the name of the filter to run.\n",
+ "#\n",
+ "# If the repository name does not match any of the regular expressions in
this\n",
+ "# file, the \"DEFAULT\" line is used, if it is specified.\n",
+ "#\n",
+ "# If the name \"ALL\" appears as a regular expression it is always used\n",
+ "# in addition to the first matching regex or \"DEFAULT\".\n",
+ NULL
+};
+
static const char *const commitinfo_contents[] = {
"# The \"commitinfo\" file is used to control pre-commit checks.\n",
"# The filter on the right is invoked with the repository and a list \n",
@@ -163,6 +182,25 @@
NULL
};
+static const char *const admininfo_contents[] = {
+ "# The \"admininfo\" file is used to control pre-admin checks.\n",
+ "# The filter on the right is invoked with the repository and a list \n",
+ "# of files to check. A non-zero exit of the filter program will \n",
+ "# cause the admin operation to be aborted.\n",
+ "#\n",
+ "# The first entry on a line is a regular expression which is tested\n",
+ "# against the directory that the change is being committed to, relative\n",
+ "# to the $CVSROOT. For the first match that is found, then the remainder\n",
+ "# of the line is the name of the filter to run.\n",
+ "#\n",
+ "# If the repository name does not match any of the regular expressions in
this\n",
+ "# file, the \"DEFAULT\" line is used, if it is specified.\n",
+ "#\n",
+ "# If the name \"ALL\" appears as a regular expression it is always used\n",
+ "# in addition to the first matching regex or \"DEFAULT\".\n",
+ NULL
+};
+
static const char *const checkoutlist_contents[] = {
"# The \"checkoutlist\" file is used to support additional version controlled\n",
"# administrative files in $CVSROOT/CVSROOT, such as template files.\n",
@@ -307,12 +345,18 @@
{CVSROOTADM_VERIFYMSG,
"a %s file can be used to validate log messages",
verifymsg_contents},
+ {CVSROOTADM_IMPORTINFO,
+ "a %s file can be used to configure 'cvs import' checking",
+ importinfo_contents},
{CVSROOTADM_COMMITINFO,
"a %s file can be used to configure 'cvs commit' checking",
commitinfo_contents},
{CVSROOTADM_TAGINFO,
"a %s file can be used to configure 'cvs tag' checking",
taginfo_contents},
+ {CVSROOTADM_ADMININFO,
+ "a %s file can be used to configure 'cvs admin' checking",
+ admininfo_contents},
{CVSROOTADM_IGNORE,
"a %s file can be used to specify files to ignore",
NULL},
Index: src/sanity.sh
===================================================================
RCS file: /cvs/ccvs/src/sanity.sh,v
retrieving revision 1.820
diff -u -d -r1.820 sanity.sh
--- src/sanity.sh 12 Sep 2003 18:54:52 -0000 1.820
+++ src/sanity.sh 4 Oct 2003 10:36:37 -0000
@@ -943,6 +943,8 @@
tests="${tests} head tagdate multibranch2 tag8k"
# "cvs admin", reserved checkouts.
tests="${tests} admin reserved"
+ # "cvs import" and "cvs admin" filters
+ tests="${tests} importinfo admininfo"
# Nuts and bolts of diffing/merging (diff library, &c)
tests="${tests} diffmerge1 diffmerge2"
# Release of multiple directories
@@ -10276,10 +10278,12 @@
mkdir keywordexpand; cd keywordexpand
dotest keywordexpand-1 "${testcvs} -q co CVSROOT" \
-'U CVSROOT/checkoutlist
+'U CVSROOT/admininfo
+U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
+U CVSROOT/importinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
@@ -10403,10 +10407,12 @@
############################################################
# Check out the whole repository
mkdir 1; cd 1
- dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/checkoutlist
+ dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/admininfo
+U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
+U CVSROOT/importinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
@@ -10426,10 +10432,12 @@
############################################################
# Check out CVSROOT
mkdir 1; cd 1
- dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
+ dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/admininfo
+U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
+U CVSROOT/importinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
@@ -10452,10 +10460,12 @@
mkdir 1; cd 1
dotest modules-3 "${testcvs} -q co somedir" ''
cd somedir
- dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
+ dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/admininfo
+U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
+U CVSROOT/importinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
@@ -10519,10 +10529,12 @@
cd ..
dotest modules-146 "${testcvs} -q co CVSROOT" \
-"U CVSROOT/checkoutlist
+"U CVSROOT/admininfo
+U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
+U CVSROOT/importinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
@@ -11310,10 +11322,12 @@
cd ..
dotest modules5-6 "${testcvs} -q co CVSROOT" \
-"U CVSROOT/checkoutlist
+"U CVSROOT/admininfo
+U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
+U CVSROOT/importinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
@@ -13509,6 +13523,8 @@
dotest_fail checkout_repository-2 "${testcvs} co CVSROOT" \
"${CPROG} \[checkout aborted\]: Cannot check out files into the repository itself" \
"${SPROG} checkout: Updating CVSROOT
+${CPROG} checkout: move away CVSROOT/admininfo; it is in the way
+C CVSROOT/admininfo
${CPROG} checkout: move away CVSROOT/checkoutlist; it is in the way
C CVSROOT/checkoutlist
${CPROG} checkout: move away CVSROOT/commitinfo; it is in the way
@@ -13517,6 +13533,8 @@
C CVSROOT/config
${CPROG} checkout: move away CVSROOT/cvswrappers; it is in the way
C CVSROOT/cvswrappers
+${CPROG} checkout: move away CVSROOT/importinfo; it is in the way
+C CVSROOT/importinfo
${CPROG} checkout: move away CVSROOT/loginfo; it is in the way
C CVSROOT/loginfo
${CPROG} checkout: move away CVSROOT/modules; it is in the way
@@ -22722,6 +22740,196 @@
rm -r 1
rm ${TESTDIR}/lockme
rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+ importinfo)
+ # CHECK THE "importinfo" FILTERING HOOK
+
+ # create and enter a working area
+ mkdir ${TESTDIR}/importinfo
+ cd ${TESTDIR}/importinfo
+ dotest importinfo-1 "${testcvs} -Q co . >>${LOGFILE}" ''
+
+ # create importinfo filter script
+ cat >${TESTDIR}/importinfo-filter <<EOF
+#!${TESTSHELL}
+echo "Importinfo hook: \$@"
+arg1=\$1; shift
+arg2=\$1; shift
+tag=\$1; shift
+repo=\$1; shift
+for file in \$*; do
+ if [ ! -f \$file ]; then
+ echo "imported file \"\$file\" not found"
+ exit 1
+ fi
+ if [ ".\`grep taboo \$file\`" != . ]; then
+ echo "imported file \"\$file\" contains taboo word"
+ exit 1
+ fi
+done
+exit 0
+EOF
+ chmod +x ${TESTDIR}/importinfo-filter
+
+ # hook importinfo filter script into repository
+ cd CVSROOT
+ echo "ALL ${TESTDIR}/importinfo-filter arg1 arg2" >>importinfo
+ dotest importinfo-2 "${testcvs} -q ci -m importinfo-test importinfo" \
+"Checking in importinfo;
+${CVSROOT_DIRNAME}/CVSROOT/importinfo,v <-- importinfo
+new revision: 1\.2; previous revision: 1\.1
+done
+${SPROG} commit: Rebuilding administrative file database"
+ cd ..
+
+ # create test area
+ mkdir test
+ cd test
+ mkdir dir1
+ mkdir dir2
+ mkdir dir2/dir21
+ mkdir dir2/dir22
+ mkdir dir3
+ echo "file1" >dir1/file1
+ echo "file2" >dir2/file2
+ echo "file21" >dir2/dir21/file21
+ echo "file22" >dir2/dir22/file22
+ echo "file3" >dir3/file3
+
+ # import the test area
+ dotest importinfo-3 "${testcvs} import -m importinfo-test test FOO BAR" \
+"Importinfo hook: arg1 arg2 FOO test dir1/file1 dir2/file2 dir2/dir21/file21
dir2/dir22/file22 dir3/file3
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/test/dir1
+N test/dir1/file1
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/test/dir2
+N test/dir2/file2
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/test/dir2/dir21
+N test/dir2/dir21/file21
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/test/dir2/dir22
+N test/dir2/dir22/file22
+${SPROG} import: Importing ${CVSROOT_DIRNAME}/test/dir3
+N test/dir3/file3
+
+No conflicts created by this import"
+
+ # import the test area again
+ echo "this file contains a taboo word" >dir2/dir22/file22
+ dotest_fail importinfo-4 "${testcvs} import -m importinfo-test test FOO BAR"
\
+"Importinfo hook: arg1 arg2 FOO test dir1/file1 dir2/file2 dir2/dir21/file21
dir2/dir22/file22 dir3/file3
+imported file \"dir2/dir22/file22\" contains taboo word
+${CPROG} \[import aborted\]: Pre-import check failed"
+
+ # checkpoint
+ cd ..
+ dokeep
+
+ # remove imported data
+ rm -rf ${CVSROOT_DIRNAME}/test
+
+ # remove importinfo changes
+ rm -f ${CVSROOT_DIRNAME}/CVSROOT/importinfo,v \
+ ${CVSROOT_DIRNAME}/CVSROOT/importinfo
+ dotest importinfo-cleanup-1 "${testcvs} -Q init" ''
+
+ # remove importinfo filter script
+ rm -f ${TESTDIR}/importinfo-filter
+
+ # remove working directory
+ cd ..
+ rm -rf ${TESTDIR}/importinfo
+ ;;
+
+ admininfo)
+ # CHECK THE "admininfo" FILTERING HOOK
+
+ # create and enter a working area
+ mkdir ${TESTDIR}/admininfo
+ cd ${TESTDIR}/admininfo
+ dotest admininfo-1 "${testcvs} -Q co . >>${LOGFILE}" ''
+
+ # create admininfo filter script
+ cat >${TESTDIR}/admininfo-filter <<EOF
+#!${TESTSHELL}
+echo "Admininfo hook: \$@"
+arg1=\$1; shift
+arg2=\$1; shift
+repo=\$1; shift
+for file in \$*; do
+ if [ ".\$file" = ".file2" ]; then
+ echo "administration on file \"\$file\" not allowed"
+ exit 1
+ fi
+done
+exit 0
+EOF
+ chmod +x ${TESTDIR}/admininfo-filter
+
+ # hook admininfo filter script into repository
+ cd CVSROOT
+ echo "ALL ${TESTDIR}/admininfo-filter arg1 arg2" >>admininfo
+ dotest admininfo-2 "${testcvs} -q ci -m admininfo-test admininfo" \
+"Checking in admininfo;
+${CVSROOT_DIRNAME}/CVSROOT/admininfo,v <-- admininfo
+new revision: 1\.2; previous revision: 1\.1
+done
+${SPROG} commit: Rebuilding administrative file database"
+ cd ..
+
+ # create test area
+ mkdir test
+ dotest admininfo-3 "${testcvs} -q add test" \
+"Directory ${CVSROOT_DIRNAME}/test added to the repository"
+ cd test
+ echo "file1" >file1
+ echo "file2" >file2
+ dotest admininfo-4 "${testcvs} add file1 file2" \
+"${SPROG} add: scheduling file .file1. for addition
+${SPROG} add: scheduling file .file2. for addition
+${SPROG} add: use .${SPROG} commit. to add these files permanently"
+ dotest admininfo-5 "${testcvs} -q commit -m admininfo-test" \
+"RCS file: ${CVSROOT_DIRNAME}/test/file1,v
+done
+Checking in file1;
+${CVSROOT_DIRNAME}/test/file1,v <-- file1
+initial revision: 1\.1
+done
+RCS file: ${CVSROOT_DIRNAME}/test/file2,v
+done
+Checking in file2;
+${CVSROOT_DIRNAME}/test/file2,v <-- file2
+initial revision: 1\.1
+done"
+
+ # perform administration operation on file1
+ dotest admininfo-6 "${testcvs} admin -ko file1" \
+"Admininfo hook: arg1 arg2 ${CVSROOT_DIRNAME}/test file1
+RCS file: ${CVSROOT_DIRNAME}/test/file1,v
+done"
+ dotest_fail admininfo-7 "${testcvs} admin -ko file2" \
+"Admininfo hook: arg1 arg2 ${CVSROOT_DIRNAME}/test file2
+administration on file .file2. not allowed
+${SPROG} admin: Pre-admin check failed
+${CPROG} \[admin aborted\]: correct above errors first!"
+
+ # checkpoint
+ cd ..
+ dokeep
+
+ # remove imported data
+ rm -rf ${CVSROOT_DIRNAME}/test
+
+ # remove admininfo changes
+ rm -f ${CVSROOT_DIRNAME}/CVSROOT/admininfo,v \
+ ${CVSROOT_DIRNAME}/CVSROOT/admininfo
+ dotest admininfo-cleanup-1 "${testcvs} -Q init" ''
+
+ # remove admininfo filter script
+ rm -f ${TESTDIR}/admininfo-filter
+
+ # remove working directory
+ cd ..
+ rm -rf ${TESTDIR}/admininfo
;;
diffmerge1)
_______________________________________________
Info-cvs mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/info-cvs