summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2005-06-14 15:27:32 +0000
committerJoris Vink <joris@cvs.openbsd.org>2005-06-14 15:27:32 +0000
commit9c7eda0365b7c23520fbc684ef785dffd90ab524 (patch)
treef92e78c7d21e45825946721553c2ebe18f7b6f4f
parent15ca9651efc74c158bdbd509b206196cde48c2e3 (diff)
finish pruning support, this has been sitting
in my tree since c2k5 ok xsa@
-rw-r--r--usr.bin/cvs/cmd.c8
-rw-r--r--usr.bin/cvs/file.c67
-rw-r--r--usr.bin/cvs/file.h4
3 files changed, 74 insertions, 5 deletions
diff --git a/usr.bin/cvs/cmd.c b/usr.bin/cvs/cmd.c
index afe06dbda8d..d3cb95245bd 100644
--- a/usr.bin/cvs/cmd.c
+++ b/usr.bin/cvs/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.25 2005/06/13 13:02:18 xsa Exp $ */
+/* $OpenBSD: cmd.c,v 1.26 2005/06/14 15:27:31 joris Exp $ */
/*
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
* All rights reserved.
@@ -155,6 +155,7 @@ cvs_startcmd(struct cvs_cmd *cmd, int argc, char **argv)
int ret;
struct cvsroot *root;
int (*ex_hdlr)(CVSFILE *, void *);
+ char fpath[MAXPATHLEN];
/* if the command requested is the server one, just call the
* cvs_server() function to handle it, and return after it.
@@ -203,6 +204,8 @@ cvs_startcmd(struct cvs_cmd *cmd, int argc, char **argv)
if (cvs_files == NULL)
return (CVS_EX_DATA);
+ cvs_file_getpath(cvs_files, fpath, sizeof(fpath));
+
if (cmd->cmd_post_exec != NULL) {
if ((ret = cmd->cmd_post_exec(root)) != 0)
return (ret);
@@ -229,6 +232,9 @@ cvs_startcmd(struct cvs_cmd *cmd, int argc, char **argv)
if (cmd->cmd_cleanup != NULL)
(*cmd->cmd_cleanup)();
+ if (cmd->cmd_flags & CVS_CMD_PRUNEDIRS)
+ cvs_file_prune(fpath);
+
if (root->cr_method != CVS_METHOD_LOCAL)
cvs_disconnect(root);
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index 44d831ae5bb..d12d6eddef0 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.87 2005/06/09 01:45:45 joris Exp $ */
+/* $OpenBSD: file.c,v 1.88 2005/06/14 15:27:31 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -116,7 +116,6 @@ static CVSFILE* cvs_file_alloc (const char *, u_int);
static CVSFILE* cvs_file_lget (const char *, int, CVSFILE *, struct cvs_ent *);
-
/*
* cvs_file_init()
*
@@ -1153,3 +1152,67 @@ cvs_file_cmpname(const char *name1, const char *name2)
return (cvs_nocase == 0) ? (strcmp(name1, name2)) :
(strcasecmp(name1, name2));
}
+
+/*
+ * remove a directory if it does not contain
+ * any files other than the CVS/ administrative files.
+ */
+int
+cvs_file_prune(char *path)
+{
+ DIR *dirp;
+ int l, pwd, empty;
+ struct dirent *dp;
+ char fpath[MAXPATHLEN];
+ CVSENTRIES *entf;
+
+ pwd = (!strcmp(path, "."));
+
+ if ((dirp = opendir(path)) == NULL) {
+ cvs_log(LP_ERRNO, "failed to open `%s'", fpath);
+ return (-1);
+ }
+
+ empty = 0;
+ entf = cvs_ent_open(path, O_RDWR);
+
+ while ((dp = readdir(dirp)) != NULL) {
+ if (!strcmp(dp->d_name, ".") ||
+ !strcmp(dp->d_name, "..") ||
+ !strcmp(dp->d_name, CVS_PATH_CVSDIR))
+ continue;
+
+ empty++;
+ if (dp->d_type == DT_DIR) {
+ l = snprintf(fpath, sizeof(fpath), "%s%s%s",
+ (pwd) ? "" : path, (pwd) ? "" : "/", dp->d_name);
+ if (l == -1 || l >= (int)sizeof(fpath)) {
+ errno = ENAMETOOLONG;
+ cvs_log(LP_ERRNO, "%s", fpath);
+ continue;
+ }
+
+ if (cvs_file_prune(fpath)) {
+ empty--;
+ if (entf)
+ cvs_ent_remove(entf, fpath);
+ } else {
+ empty++;
+ }
+ }
+ }
+
+ closedir(dirp);
+ if (entf)
+ cvs_ent_close(entf);
+
+ empty = (empty == 0);
+ if (empty) {
+ if (cvs_remove_dir(path) < 0) {
+ cvs_log(LP_ERR, "failed to prune `%s'", path);
+ empty = 0;
+ }
+ }
+
+ return (empty);
+}
diff --git a/usr.bin/cvs/file.h b/usr.bin/cvs/file.h
index 7e2a3d199c0..38bd550e147 100644
--- a/usr.bin/cvs/file.h
+++ b/usr.bin/cvs/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.20 2005/05/24 04:12:25 jfb Exp $ */
+/* $OpenBSD: file.h,v 1.21 2005/06/14 15:27:31 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -144,6 +144,6 @@ CVSFILE* cvs_file_load (const char *, int);
CVSFILE* cvs_file_find (CVSFILE *, const char *);
char* cvs_file_getpath (CVSFILE *, char *, size_t);
void cvs_file_free (CVSFILE *);
-
+int cvs_file_prune (char *);
#endif /* FILE_H */