summaryrefslogtreecommitdiff
path: root/usr.bin/cvs
diff options
context:
space:
mode:
authorJean-Francois Brousseau <jfb@cvs.openbsd.org>2004-08-12 18:36:40 +0000
committerJean-Francois Brousseau <jfb@cvs.openbsd.org>2004-08-12 18:36:40 +0000
commit297866f95cb87282a852bc9f3a0f9efe1bf82200 (patch)
treeee10dfdc1bb7592c6d17e7b6cd08ed8a340a5e25 /usr.bin/cvs
parent200842c21bad72a1c2c6474aa9fa5c76c291bc98 (diff)
Implement cvs_file_getspec() so we can finally deal with explicit file
arguments on the command-line, and fix a bunch of minor issues
Diffstat (limited to 'usr.bin/cvs')
-rw-r--r--usr.bin/cvs/file.c135
1 files changed, 92 insertions, 43 deletions
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index 0143e3a7657..b76c7b13891 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,16 +1,16 @@
-/* $OpenBSD: file.c,v 1.25 2004/08/10 14:23:57 jfb Exp $ */
+/* $OpenBSD: file.c,v 1.26 2004/08/12 18:36:39 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
- * All rights reserved.
+ * All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
@@ -21,7 +21,7 @@
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
@@ -126,7 +126,7 @@ cvs_file_init(void)
/* standard patterns to ignore */
for (i = 0; i < (int)(sizeof(cvs_ign_std)/sizeof(char *)); i++)
- cvs_file_ignore(cvs_ign_std[i]);
+ cvs_file_ignore(cvs_ign_std[i]);
/* read the cvsignore file in the user's home directory, if any */
pwd = getpwuid(getuid());
@@ -227,6 +227,8 @@ cvs_file_chkign(const char *file)
* cvs_file_create()
*
* Create a new file whose path is specified in <path> and of type <type>.
+ * If the type is DT_DIR, the CVS administrative repository and files will be
+ * created.
* Returns the created file on success, or NULL on failure.
*/
@@ -239,14 +241,17 @@ cvs_file_create(const char *path, u_int type, mode_t mode)
cfp = cvs_file_alloc(path, type);
if (cfp == NULL)
return (NULL);
+
cfp->cf_type = type;
cfp->cf_mode = mode;
+ cfp->cf_ddat->cd_root = cvsroot_get(path);
if (type == DT_DIR) {
- if (mkdir(path, mode) == -1) {
+ if ((mkdir(path, mode) == -1) || (cvs_mkadmin(cfp, mode) < 0)) {
cvs_file_free(cfp);
return (NULL);
}
+
}
else {
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, mode);
@@ -296,8 +301,44 @@ cvs_file_get(const char *path, int flags)
CVSFILE*
cvs_file_getspec(char **fspec, int fsn, int flags)
{
- /* XXX implement me */
- return (NULL);
+ int i;
+ char *sp, *np, pcopy[MAXPATHLEN];
+ CVSFILE *base, *cf, *nf;
+
+ base = cvs_file_get(".", 0);
+ if (base == NULL)
+ return (NULL);
+
+ for (i = 0; i < fsn; i++) {
+ strlcpy(pcopy, fspec[i], sizeof(pcopy));
+ cf = base;
+ sp = pcopy;
+
+ do {
+ np = strchr(sp, '/');
+ if (np != NULL)
+ *np = '\0';
+ nf = cvs_file_find(cf, sp);
+ if (nf == NULL) {
+ nf = cvs_file_lget(pcopy, 0, cf);
+ if (nf == NULL) {
+ cvs_file_free(base);
+ return (NULL);
+ }
+
+ cvs_file_attach(cf, nf);
+ }
+
+ if (np != NULL) {
+ *np = '/';
+ sp = np + 1;
+ }
+
+ cf = nf;
+ } while (np != NULL);
+ }
+
+ return (base);
}
@@ -405,29 +446,37 @@ cvs_file_getdir(CVSFILE *cf, int flags)
TAILQ_INIT(&dirs);
cdp = cf->cf_ddat;
- cdp->cd_root = cvsroot_get(cf->cf_path);
- if (cdp->cd_root == NULL) {
- cvs_file_freedir(cdp);
- return (-1);
- }
+ if (cf->cf_cvstat != CVS_FST_UNKNOWN) {
+ cdp->cd_root = cvsroot_get(cf->cf_path);
+ if (cdp->cd_root == NULL) {
+ cvs_file_freedir(cdp);
+ return (-1);
+ }
- if (flags & CF_MKADMIN)
- cvs_mkadmin(cf, 0755);
-
- /* if the CVS administrative directory exists, load the info */
- snprintf(pbuf, sizeof(pbuf), "%s/" CVS_PATH_CVSDIR, cf->cf_path);
- if ((stat(pbuf, &st) == 0) && S_ISDIR(st.st_mode)) {
- if (cvs_readrepo(cf->cf_path, pbuf, sizeof(pbuf)) == 0) {
- cdp->cd_repo = strdup(pbuf);
- if (cdp->cd_repo == NULL) {
- free(cdp);
- return (-1);
+ if (flags & CF_MKADMIN)
+ cvs_mkadmin(cf, 0755);
+
+ /* if the CVS administrative directory exists, load the info */
+ snprintf(pbuf, sizeof(pbuf), "%s/" CVS_PATH_CVSDIR,
+ cf->cf_path);
+ if ((stat(pbuf, &st) == 0) && S_ISDIR(st.st_mode)) {
+ if (cvs_readrepo(cf->cf_path, pbuf,
+ sizeof(pbuf)) == 0) {
+ cdp->cd_repo = strdup(pbuf);
+ if (cdp->cd_repo == NULL) {
+ free(cdp);
+ return (-1);
+ }
}
+
+ cdp->cd_ent = cvs_ent_open(cf->cf_path, O_RDWR);
}
- cdp->cd_ent = cvs_ent_open(cf->cf_path, O_RDWR);
}
+ if (!(flags & CF_RECURSE) || (cf->cf_cvstat == CVS_FST_UNKNOWN))
+ return (0);
+
fd = open(cf->cf_path, O_RDONLY);
if (fd == -1) {
cvs_log(LP_ERRNO, "failed to open `%s'", cf->cf_path);
@@ -460,12 +509,12 @@ cvs_file_getdir(CVSFILE *cf, int flags)
cf->cf_path, ent->d_name);
cfp = cvs_file_lget(pbuf, flags, cf);
if (cfp != NULL) {
- if (cfp->cf_type == DT_DIR) {
- TAILQ_INSERT_HEAD(&dirs, cfp, cf_list);
+ if (cfp->cf_type == DT_DIR) {
+ TAILQ_INSERT_TAIL(&dirs, cfp, cf_list);
ndirs++;
}
else {
- TAILQ_INSERT_HEAD(&(cdp->cd_files), cfp,
+ TAILQ_INSERT_TAIL(&(cdp->cd_files), cfp,
cf_list);
cdp->cd_nfiles++;
}
@@ -477,12 +526,15 @@ cvs_file_getdir(CVSFILE *cf, int flags)
cvs_file_sort(&(cdp->cd_files), cdp->cd_nfiles);
cvs_file_sort(&dirs, ndirs);
}
- TAILQ_FOREACH(cfp, &dirs, cf_list)
+
+ while (!TAILQ_EMPTY(&dirs)) {
+ cfp = TAILQ_FIRST(&dirs);
+ TAILQ_REMOVE(&dirs, cfp, cf_list);
TAILQ_INSERT_TAIL(&(cdp->cd_files), cfp, cf_list);
+ }
cdp->cd_nfiles += ndirs;
(void)close(fd);
- cf->cf_ddat = cdp;
return (0);
}
@@ -720,9 +772,10 @@ cvs_file_lget(const char *path, int flags, CVSFILE *parent)
ent = cvs_ent_get(CVS_DIR_ENTRIES(parent), cfp->cf_name);
}
- if (ent == NULL)
+ if (ent == NULL) {
cfp->cf_cvstat = (cwd == 1) ?
CVS_FST_UPTODATE : CVS_FST_UNKNOWN;
+ }
else {
/* always show directories as up-to-date */
if (ent->ce_type == CVS_ENT_DIR)
@@ -750,13 +803,9 @@ cvs_file_lget(const char *path, int flags, CVSFILE *parent)
}
}
- if ((cfp->cf_type == DT_DIR) && ((flags & CF_RECURSE) || cwd)) {
- if ((flags & CF_KNOWN) && (cfp->cf_cvstat == CVS_FST_UNKNOWN)) {
- }
- else if (cvs_file_getdir(cfp, flags) < 0) {
- cvs_file_free(cfp);
- return (NULL);
- }
+ if ((cfp->cf_type == DT_DIR) && (cvs_file_getdir(cfp, flags) < 0)) {
+ cvs_file_free(cfp);
+ return (NULL);
}
return (cfp);