diff options
author | Joris Vink <joris@cvs.openbsd.org> | 2005-12-03 01:02:10 +0000 |
---|---|---|
committer | Joris Vink <joris@cvs.openbsd.org> | 2005-12-03 01:02:10 +0000 |
commit | ef47fbf93d2302d521921cce5f98a093b4779e9f (patch) | |
tree | 50d76a77cc19c09cea910a3890611cb290e63bab /usr.bin/cvs/update.c | |
parent | 1c6cd252eaeaeedbd87c69d5843ae9550b20ee91 (diff) |
add very basic support for the following stuff:
- checkout in local mode (example: /cvs)
- update in local and server mode (example: /cvs and user@host:/cvs)
- import in local and server mode (example: /cvs and user@host:/cvs)
what remains to be done:
- not all options are supported yet, and update cannot pick up newly
added files yet. these things are pending and will be commited
real soon.
- checkout only works locally right now.
- fix rcs parsing code so that we don't fucking hog 100% cpu
on really BIG BIG BIG ass trees.
mainly tested by pedro@ and myself, thanks a lot pedro!
"go for it" niallo@
Diffstat (limited to 'usr.bin/cvs/update.c')
-rw-r--r-- | usr.bin/cvs/update.c | 128 |
1 files changed, 117 insertions, 11 deletions
diff --git a/usr.bin/cvs/update.c b/usr.bin/cvs/update.c index 372ee452f15..62f4cff1c66 100644 --- a/usr.bin/cvs/update.c +++ b/usr.bin/cvs/update.c @@ -1,4 +1,4 @@ -/* $OpenBSD: update.c,v 1.44 2005/08/08 11:37:41 xsa Exp $ */ +/* $OpenBSD: update.c,v 1.45 2005/12/03 01:02:09 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -36,14 +36,13 @@ #include "cvs.h" #include "log.h" #include "proto.h" - +#include "diff.h" static int cvs_update_init(struct cvs_cmd *, int, char **, int *); static int cvs_update_pre_exec(struct cvsroot *); static int cvs_update_remote(CVSFILE *, void *); static int cvs_update_local(CVSFILE *, void *); - struct cvs_cmd cvs_cmd_update = { CVS_OP_UPDATE, CVS_REQ_UPDATE, "update", { "up", "upd" }, @@ -220,13 +219,20 @@ cvs_update_remote(CVSFILE *cf, void *arg) static int cvs_update_local(CVSFILE *cf, void *arg) { - int ret; + int ret, islocal, revdiff; char fpath[MAXPATHLEN], rcspath[MAXPATHLEN]; + char *repo; RCSFILE *rf; + RCSNUM *frev; + BUF *fbuf; + struct cvsroot *root; - ret = 0; + revdiff = ret = 0; rf = NULL; + islocal = (cvs_cmdop != CVS_OP_SERVER); + root = CVS_DIR_ROOT(cf); + repo = CVS_DIR_REPO(cf); cvs_file_getpath(cf, fpath, sizeof(fpath)); if (cf->cf_cvstat == CVS_FST_UNKNOWN) { @@ -235,20 +241,120 @@ cvs_update_local(CVSFILE *cf, void *arg) } if (cf->cf_type == DT_DIR) { - cvs_log(LP_NOTICE, "Updating %s", fpath); + if (verbosity > 1) + cvs_log(LP_NOTICE, "Updating %s", fpath); + return (CVS_EX_OK); } if (cvs_rcs_getpath(cf, rcspath, sizeof(rcspath)) == NULL) return (CVS_EX_DATA); - rf = rcs_open(rcspath, RCS_RDWR); - if (rf == NULL) { - printf("failed here?\n"); + /* + * Only open the RCS file for files that have not been added. + */ + if (cf->cf_cvstat != CVS_FST_ADDED) { + rf = rcs_open(rcspath, RCS_READ); + + /* + * If there is no RCS file available in the repository + * directory that matches this file, it's gone. + * XXX: so what about the Attic? + */ + if (rf == NULL) { + cvs_log(LP_WARN, "%s is no longer in the repository", + fpath); + if (cvs_checkout_rev(NULL, NULL, cf, fpath, + islocal, CHECKOUT_REV_REMOVED) < 0) + return (CVS_EX_FILE); + return (CVS_EX_OK); + } + } + + /* set keyword expansion */ + /* XXX look at cf->cf_opts as well for this */ + if (rcs_kwexp_set(rf, kflag) < 0) { + if (rf != NULL) + rcs_close(rf); return (CVS_EX_DATA); } - rcs_close(rf); + /* fill in the correct revision */ + if (rev != NULL) { + if ((frev = rcsnum_parse(rev)) == NULL) { + if (rf != NULL) + rcs_close(rf); + return (CVS_EX_DATA); + } + } else { + frev = rf->rf_head; + } - return (ret); + /* + * Compare the headrevision with the revision we currently have. + */ + if (rf != NULL && cf->cf_lrev != NULL) + revdiff = rcsnum_cmp(cf->cf_lrev, frev, 0); + + switch (cf->cf_cvstat) { + case CVS_FST_MODIFIED: + /* + * If the file has been modified but there is a newer version + * available, we try to merge it into the existing changes. + */ + if (revdiff == 1) { + fbuf = cvs_diff3(rf, fpath, cf->cf_lrev, frev); + if (fbuf == NULL) { + cvs_log(LP_ERR, "merge failed"); + break; + } + + /* + * Please note fbuf will be free'd in cvs_checkout_rev + */ + if (cvs_checkout_rev(rf, frev, cf, fpath, islocal, + CHECKOUT_REV_MERGED, fbuf) != -1) { + cvs_printf("%c %s\n", + (diff3_conflicts > 0) ? 'C' : 'M', + fpath); + if (diff3_conflicts > 0) + cf->cf_cvstat = CVS_FST_CONFLICT; + } + } else { + cvs_printf("M %s\n", fpath); + } + break; + case CVS_FST_ADDED: + cvs_printf("A %s\n", fpath); + break; + case CVS_FST_REMOVED: + cvs_printf("R %s\n", fpath); + break; + case CVS_FST_CONFLICT: + cvs_printf("C %s\n", fpath); + break; + case CVS_FST_LOST: + if (cvs_checkout_rev(rf, frev, cf, fpath, islocal, + CHECKOUT_REV_CREATED) != -1) { + cf->cf_cvstat = CVS_FST_UPTODATE; + cvs_printf("U %s\n", fpath); + } + break; + case CVS_FST_UPTODATE: + if (revdiff == 1) { + if (cvs_checkout_rev(rf, frev, cf, fpath, islocal, + CHECKOUT_REV_CREATED) != -1) + cvs_printf("P %s\n", fpath); + } + break; + default: + break; + } + + if ((frev != NULL) && (frev != rf->rf_head)) + rcsnum_free(frev); + if (rf != NULL) + rcs_close(rf); + + return (CVS_EX_OK); } |