diff options
-rw-r--r-- | usr.bin/cvs/cvs.h | 24 | ||||
-rw-r--r-- | usr.bin/cvs/entries.c | 86 | ||||
-rw-r--r-- | usr.bin/cvs/file.c | 82 |
3 files changed, 152 insertions, 40 deletions
diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h index a49688203a5..0233f7fe2c4 100644 --- a/usr.bin/cvs/cvs.h +++ b/usr.bin/cvs/cvs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cvs.h,v 1.7 2004/07/23 05:40:32 jfb Exp $ */ +/* $OpenBSD: cvs.h,v 1.8 2004/07/25 03:18:53 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -28,7 +28,7 @@ #define CVS_H #include <sys/param.h> - +#include <stdio.h> #include "rcs.h" #define CVS_VERSION "OpenCVS 0.1" @@ -46,6 +46,7 @@ /* operations */ +#define CVS_OP_ANY 0 /* all operations */ #define CVS_OP_ADD 1 #define CVS_OP_ANNOTATE 2 #define CVS_OP_COMMIT 3 @@ -240,6 +241,7 @@ struct cvsroot { #define CF_IGNORE 0x02 /* apply regular ignore rules */ #define CF_RECURSE 0x04 /* recurse on directory operations */ #define CF_SORT 0x08 /* all files are sorted alphabetically */ +#define CF_KNOWN 0x10 /* only recurse in directories known to CVS */ /* @@ -249,18 +251,28 @@ struct cvsroot { * points back to the parent node in the directory tree structure (it is * NULL if the directory is at the wd of the command). * + * The <cf_cvstat> field gives the file's status with regards to the CVS + * repository. The file can be in any one of the CVS_FST_* states. * If the file's type is DT_DIR, then the <cf_ddat> pointer will point to * a cvs_dir structure containing data specific to the directory (such as * the contents of the directory's CVS/Entries, CVS/Root, etc.). */ +#define CVS_FST_UNKNOWN 0 +#define CVS_FST_UPTODATE 1 +#define CVS_FST_MODIFIED 2 +#define CVS_FST_ADDED 3 +#define CVS_FST_REMOVED 4 +#define CVS_FST_CONFLICT 5 + struct cvs_file { char *cf_path; struct cvs_file *cf_parent; /* parent directory (NULL if none) */ char *cf_name; - u_int cf_type; /* uses values from dirent.h */ - struct stat *cf_stat; - struct cvs_dir *cf_ddat; /* only for directories */ + u_int16_t cf_cvstat; /* cvs status of the file */ + u_int16_t cf_type; /* uses values from dirent.h */ + struct stat *cf_stat; /* only available with CF_STAT flag */ + struct cvs_dir *cf_ddat; /* only for directories */ LIST_ENTRY(cvs_file) cf_list; }; @@ -401,6 +413,8 @@ int cvs_ent_addln (CVSENTRIES *, const char *); int cvs_ent_remove (CVSENTRIES *, const char *); struct cvs_ent* cvs_ent_parse (const char *); void cvs_ent_close (CVSENTRIES *); +void cvs_ent_free (struct cvs_ent *); +struct cvs_ent* cvs_ent_getent (const char *); /* history API */ CVSHIST* cvs_hist_open (const char *); diff --git a/usr.bin/cvs/entries.c b/usr.bin/cvs/entries.c index 967373eeb91..40f9db3bdd1 100644 --- a/usr.bin/cvs/entries.c +++ b/usr.bin/cvs/entries.c @@ -1,4 +1,4 @@ -/* $OpenBSD: entries.c,v 1.4 2004/07/14 19:03:00 jfb Exp $ */ +/* $OpenBSD: entries.c,v 1.5 2004/07/25 03:18:53 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -90,6 +90,8 @@ cvs_ent_open(const char *dir, int flags) (void)fclose(fp); return (NULL); } + memset(ep, 0, sizeof(*ep)); + ep->cef_path = strdup(dir); if (ep->cef_path == NULL) { cvs_log(LP_ERRNO, "failed to copy Entries path"); @@ -125,12 +127,26 @@ cvs_ent_open(const char *dir, int flags) /* * cvs_ent_close() * - * Close the Entries file <ep>. + * Close the Entries file <ep> and free all data. Any reference to entries + * structure within that file become invalid. */ void cvs_ent_close(CVSENTRIES *ep) { + struct cvs_ent *ent; + + if (ep->cef_file != NULL) + (void)fclose(ep); + if (ep->cef_path != NULL) + free(ep->cef_path); + + while (!TAILQ_EMPTY(&(ep->cef_ent))) { + ent = TAILQ_FIRST(&(ep->cef_ent)); + TAILQ_REMOVE(&(ep->cef_ent), ent, ce_list); + cvs_ent_free(ent); + } + free(ep); } @@ -228,12 +244,11 @@ cvs_ent_get(CVSENTRIES *ef, const char *file) struct cvs_ent* cvs_ent_next(CVSENTRIES *ef) { - if (ef->cef_cur == NULL) { + if (ef->cef_cur == NULL) ef->cef_cur = TAILQ_FIRST(&(ef->cef_ent)); - return (ef->cef_cur); - } - - return TAILQ_NEXT(ef->cef_cur, ce_list); + else + ef->cef_cur = TAILQ_NEXT(ef->cef_cur, ce_list); + return (ef->cef_cur); } @@ -256,6 +271,7 @@ cvs_ent_parse(const char *entry) cvs_log(LP_ERRNO, "failed to allocate CVS entry"); return (NULL); } + memset(entp, 0, sizeof(*entp)); entp->ce_rev = rcsnum_alloc(); if (entp->ce_rev == NULL) { @@ -265,14 +281,13 @@ cvs_ent_parse(const char *entry) entp->ce_line = strdup(entry); if (entp->ce_line == NULL) { - free(entp); + cvs_ent_free(entp); return (NULL); } entp->ce_buf = strdup(entry); if (entp->ce_buf == NULL) { - free(entp->ce_line); - free(entp); + cvs_ent_free(entp); return (NULL); } sp = entp->ce_buf; @@ -310,3 +325,54 @@ cvs_ent_parse(const char *entry) return (entp); } + + +/* + * cvs_ent_free() + * + * Free a single CVS entries structure. + */ + +void +cvs_ent_free(struct cvs_ent *ent) +{ + if (ent->ce_rev != NULL) + rcsnum_free(ent->ce_rev); + if (ent->ce_line != NULL) + free(ent->ce_line); + if (ent->ce_buf != NULL) + free(ent->ce_buf); + free(ent); +} + + +/* + * cvs_ent_getent() + * + * Get a single entry from the CVS/Entries file of the basename portion of + * path <path> and return that entry. That entry must later be freed using + * cvs_ent_free(). + */ + +struct cvs_ent* +cvs_ent_getent(const char *path) +{ + char base[MAXPATHLEN], file[MAXPATHLEN]; + CVSENTRIES *entf; + struct cvs_ent *ep; + + cvs_splitpath(path, base, sizeof(base), file, sizeof(file)); + + entf = cvs_ent_open(base, O_RDONLY); + if (entf == NULL) + return (NULL); + + ep = cvs_ent_get(entf, file); + if (ep != NULL) { + /* take it out of the queue so it doesn't get freed */ + TAILQ_REMOVE(&(entf->cef_ent), ep, ce_list); + } + + cvs_ent_close(entf); + return (ep); +} diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c index 07df1697b16..7ac68e4642a 100644 --- a/usr.bin/cvs/file.c +++ b/usr.bin/cvs/file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file.c,v 1.3 2004/07/23 05:40:32 jfb Exp $ */ +/* $OpenBSD: file.c,v 1.4 2004/07/25 03:18:52 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -87,6 +87,9 @@ static const char *cvs_ign_std[] = { }; +static RCSNUM *cvs_addedrev; + + TAILQ_HEAD(, cvs_ignpat) cvs_ign_pats; @@ -113,6 +116,9 @@ cvs_file_init(void) TAILQ_INIT(&cvs_ign_pats); + cvs_addedrev = rcsnum_alloc(); + rcsnum_aton("0", NULL, cvs_addedrev); + /* standard patterns to ignore */ for (i = 0; i < sizeof(cvs_ign_std)/sizeof(char *); i++) cvs_file_ignore(cvs_ign_std[i]); @@ -274,6 +280,15 @@ cvs_file_getv(const char *dir, int *nfiles, int recurse) * * Load a cvs_file structure with all the information pertaining to the file * <path>. + * The <flags> parameter specifies various flags that alter the behaviour of + * the function. The CF_STAT flag is used to keep stat information of the + * file in the structure after it is used (it is lost otherwise). The + * CF_RECURSE flag causes the function to recursively load subdirectories + * when <path> is a directory. The CF_SORT flag causes the files to be + * sorted in alphabetical order upon loading. + * The special case of "." as a path specification generates recursion for + * a single level and is equivalent to calling cvs_file_get() on all files + * of that directory. * Returns a pointer to the cvs file structure, which must later be freed * with cvs_file_free(). */ @@ -281,14 +296,21 @@ cvs_file_getv(const char *dir, int *nfiles, int recurse) struct cvs_file* cvs_file_get(const char *path, int flags) { + int cwd; size_t dlen; struct stat st; struct cvs_file *cfp; + struct cvs_ent *ent; printf("cvs_file_get(%s)\n", path); + if (strcmp(path, ".") == 0) + cwd = 1; + else + cwd = 0; + if (stat(path, &st) == -1) { - cvs_log(LP_ERRNO, "failed to stat file"); + cvs_log(LP_ERRNO, "failed to stat %s", path); return (NULL); } @@ -299,8 +321,22 @@ cvs_file_get(const char *path, int flags) } memset(cfp, 0, sizeof(*cfp)); + ent = cvs_ent_getent(path); + if (ent == NULL) + cfp->cf_cvstat = (cwd == 1) ? + CVS_FST_UPTODATE : CVS_FST_UNKNOWN; + else { + if (rcsnum_cmp(ent->ce_rev, cvs_addedrev, 2) == 0) + cfp->cf_cvstat = CVS_FST_ADDED; + else + cfp->cf_cvstat = CVS_FST_UPTODATE; + + cvs_ent_free(ent); + } + cfp->cf_path = strdup(path); if (cfp->cf_path == NULL) { + cvs_log(LP_ERRNO, "failed to allocate file path"); free(cfp); return (NULL); } @@ -313,11 +349,15 @@ cvs_file_get(const char *path, int flags) /* convert from stat mode to dirent values */ cfp->cf_type = IFTODT(st.st_mode); - if (cfp->cf_type == DT_DIR) { - cfp->cf_ddat = cvs_file_getdir(cfp, flags); - if (cfp->cf_ddat == NULL) { - cvs_file_free(cfp); - return (NULL); + if ((cfp->cf_type == DT_DIR) && ((flags & CF_RECURSE) || cwd)) { + if ((flags & CF_KNOWN) && (cfp->cf_cvstat == CVS_FST_UNKNOWN)) + cfp->cf_ddat = NULL; + else { + cfp->cf_ddat = cvs_file_getdir(cfp, flags); + if (cfp->cf_ddat == NULL) { + cvs_file_free(cfp); + return (NULL); + } } } @@ -361,15 +401,12 @@ cvs_file_getdir(struct cvs_file *cf, int flags) memset(cdp, 0, sizeof(*cdp)); LIST_INIT(&(cdp->cd_files)); - if (cvs_readrepo(cf->cf_path, pbuf, sizeof(pbuf)) < 0) { - free(cdp); - return (NULL); - } - - cdp->cd_repo = strdup(pbuf); - if (cdp->cd_repo == NULL) { - free(cdp); - return (NULL); + if (cvs_readrepo(cf->cf_path, pbuf, sizeof(pbuf)) == 0) { + cdp->cd_repo = strdup(pbuf); + if (cdp->cd_repo == NULL) { + free(cdp); + return (NULL); + } } cdp->cd_root = cvsroot_get(cf->cf_path); @@ -403,8 +440,10 @@ cvs_file_getdir(struct cvs_file *cf, int flags) snprintf(pbuf, sizeof(pbuf), "%s/%s", cf->cf_path, ent->d_name); cfp = cvs_file_get(pbuf, flags); - - LIST_INSERT_HEAD(&(cdp->cd_files), cfp, cf_list); + if (cfp != NULL) { + cfp->cf_parent = cf; + LIST_INSERT_HEAD(&(cdp->cd_files), cfp, cf_list); + } } if (flags & CF_SORT) @@ -477,7 +516,6 @@ cvs_file_sort(struct cvs_flist *flp) i = 0; LIST_FOREACH(cf, flp, cf_list) { - printf("adding `%s'\n", cf->cf_path); cfvec[i++] = cf; if (i == sizeof(cfvec)/sizeof(struct cvs_file *)) { cvs_log(LP_WARN, "too many files to sort"); @@ -494,13 +532,7 @@ cvs_file_sort(struct cvs_flist *flp) LIST_INIT(flp); nb = (size_t)i; - printf("Before: \n"); - for (i = 0; i < (int)nb; i++) - printf("[%d] = `%s'\n", i, cfvec[i]->cf_name); heapsort(cfvec, nb, sizeof(cf), cvs_file_cmp); - printf("===================================\nAfter: \n"); - for (i = 0; i < (int)nb; i++) - printf("[%d] = `%s'\n", i, cfvec[i]->cf_name); /* rebuild the list from the bottom up */ for (i = (int)nb - 1; i >= 0; i--) |