From 9c7eda0365b7c23520fbc684ef785dffd90ab524 Mon Sep 17 00:00:00 2001 From: Joris Vink Date: Tue, 14 Jun 2005 15:27:32 +0000 Subject: finish pruning support, this has been sitting in my tree since c2k5 ok xsa@ --- usr.bin/cvs/cmd.c | 8 ++++++- usr.bin/cvs/file.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- usr.bin/cvs/file.h | 4 ++-- 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 * 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 * 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 * 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 */ -- cgit v1.2.3