diff options
-rw-r--r-- | usr.bin/cvs/rcs.c | 31 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.h | 5 | ||||
-rw-r--r-- | usr.bin/rcs/ci.c | 75 | ||||
-rw-r--r-- | usr.bin/rcs/co.c | 161 | ||||
-rw-r--r-- | usr.bin/rcs/rcsclean.c | 8 | ||||
-rw-r--r-- | usr.bin/rcs/rcsprog.h | 5 |
6 files changed, 170 insertions, 115 deletions
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index a26bca40168..d890e732f21 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.108 2005/12/03 15:31:53 joris Exp $ */ +/* $OpenBSD: rcs.c,v 1.109 2005/12/08 18:56:10 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -308,6 +308,8 @@ rcs_open(const char *path, int flags, ...) RCSFILE *rfp; struct stat st; va_list vap; + struct rcs_delta *rdp; + struct rcs_lock *lkr; fmode = 0; flags &= 0xffff; /* ditch any internal flags */ @@ -358,6 +360,20 @@ rcs_open(const char *path, int flags, ...) return (NULL); } + /* fill in rd_locker */ + TAILQ_FOREACH(lkr, &(rfp->rf_locks), rl_list) { + if ((rdp = rcs_findrev(rfp, lkr->rl_num)) == NULL) { + rcs_close(rfp); + return (NULL); + } + + rdp->rd_locker = strdup(lkr->rl_name); + if (rdp->rd_locker == NULL) { + rcs_close(rfp); + return (NULL); + } + } + return (rfp); } @@ -993,7 +1009,8 @@ rcs_lock_add(RCSFILE *file, const char *user, RCSNUM *rev) /* first look for duplication */ TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list) { - if (strcmp(lkp->rl_name, user) == 0) { + if ((strcmp(lkp->rl_name, user) == 0) && + (rcsnum_cmp(rev, lkp->rl_num, 0) == 0)) { rcs_errno = RCS_ERR_DUPENT; return (-1); } @@ -1036,13 +1053,15 @@ rcs_lock_add(RCSFILE *file, const char *user, RCSNUM *rev) * Returns 0 on success, or -1 on failure. */ int -rcs_lock_remove(RCSFILE *file, const RCSNUM *rev) +rcs_lock_remove(RCSFILE *file, const char *user, RCSNUM *rev) { struct rcs_lock *lkp; - TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list) - if (rcsnum_cmp(lkp->rl_num, rev, 0) == 0) + TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list) { + if ((strcmp(lkp->rl_name, user) == 0) && + (rcsnum_cmp(lkp->rl_num, rev, 0) == 0)) break; + } if (lkp == NULL) { rcs_errno = RCS_ERR_NOENT; @@ -2465,6 +2484,8 @@ rcs_freedelta(struct rcs_delta *rdp) if (rdp->rd_author != NULL) free(rdp->rd_author); + if (rdp->rd_locker != NULL) + free(rdp->rd_locker); if (rdp->rd_state != NULL) free(rdp->rd_state); if (rdp->rd_log != NULL) diff --git a/usr.bin/cvs/rcs.h b/usr.bin/cvs/rcs.h index 06faa90602e..e4335181fcf 100644 --- a/usr.bin/cvs/rcs.h +++ b/usr.bin/cvs/rcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.h,v 1.41 2005/12/03 15:31:53 joris Exp $ */ +/* $OpenBSD: rcs.h,v 1.42 2005/12/08 18:56:10 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -155,6 +155,7 @@ struct rcs_delta { char *rd_author; char *rd_state; char *rd_log; + char *rd_locker; u_char *rd_text; size_t rd_tlen; @@ -206,7 +207,7 @@ int rcs_sym_check(const char *); int rcs_lock_getmode(RCSFILE *); int rcs_lock_setmode(RCSFILE *, int); int rcs_lock_add(RCSFILE *, const char *, RCSNUM *); -int rcs_lock_remove(RCSFILE *, const RCSNUM *); +int rcs_lock_remove(RCSFILE *, const char *, RCSNUM *); BUF *rcs_getrev(RCSFILE *, RCSNUM *); int rcs_deltatext_set(RCSFILE *, RCSNUM *, const char *); const char *rcs_desc_get(RCSFILE *); diff --git a/usr.bin/rcs/ci.c b/usr.bin/rcs/ci.c index 705bcc79ef7..c7184f38cf8 100644 --- a/usr.bin/rcs/ci.c +++ b/usr.bin/rcs/ci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ci.c,v 1.81 2005/12/03 17:11:58 niallo Exp $ */ +/* $OpenBSD: ci.c,v 1.82 2005/12/08 18:56:10 joris Exp $ */ /* * Copyright (c) 2005 Niall O'Higgins <niallo@openbsd.org> * All rights reserved. @@ -59,6 +59,7 @@ struct checkin_params { RCSFILE *file; RCSNUM *frev, *newrev; char fpath[MAXPATHLEN], *rcs_msg, *username, *deltatext, *filename; + char *author; const char *symbol, *state, *description; }; @@ -100,7 +101,7 @@ checkin_main(int argc, char **argv) pb.date = DATE_NOW; pb.file = NULL; - pb.rcs_msg = pb.username = NULL; + pb.rcs_msg = pb.username = pb.author = NULL; pb.state = pb.symbol = pb.description = NULL; pb.newrev = NULL; pb.fmode = pb.flags = status = 0; @@ -207,7 +208,10 @@ checkin_main(int argc, char **argv) printf("%s\n", rcs_version); exit(0); case 'w': - pb.username = rcs_optarg; + if ((pb.author = strdup(rcs_optarg)) == NULL) { + cvs_log(LP_ERRNO, "out of memory"); + exit(1); + } break; case 'x': rcs_suffixes = rcs_optarg; @@ -227,7 +231,7 @@ checkin_main(int argc, char **argv) exit(1); } - if ((pb.username == NULL) && (pb.username = getlogin()) == NULL) { + if ((pb.username = getlogin()) == NULL) { cvs_log(LP_ERRNO, "failed to get username"); exit(1); } @@ -444,9 +448,20 @@ checkin_update(struct checkin_params *pb) char *filec, numb1[64], numb2[64]; BUF *bp; + /* + * XXX this is wrong, we need to get the revision the user + * has the lock for. So we can decide if we want to create a + * branch or not. (if it's not current HEAD we need to branch). + */ pb->frev = pb->file->rf_head; - /* If revision passed on command line is less than HEAD, bail. */ + if (checkin_checklock(pb) < 0) + return (-1); + + /* If revision passed on command line is less than HEAD, bail. + * XXX only applies to ci -r1.2 foo for example if HEAD is > 1.2 and + * there is no lock set for the user. + */ if ((pb->newrev != NULL) && (rcsnum_cmp(pb->newrev, pb->frev, 0) > 0)) { cvs_log(LP_ERR, @@ -458,9 +473,6 @@ checkin_update(struct checkin_params *pb) return (-1); } - if (checkin_checklock(pb) < 0) - return (-1); - /* Load file contents */ if ((bp = cvs_buf_load(pb->filename, BUF_AUTOEXT)) == NULL) { cvs_log(LP_ERR, "failed to load '%s'", pb->filename); @@ -491,9 +503,12 @@ checkin_update(struct checkin_params *pb) if (pb->flags & INTERACTIVE) pb->rcs_msg = checkin_getlogmsg(pb->frev, pb->newrev); - if (rcs_lock_remove(pb->file, pb->frev) < 0) { + if (rcs_lock_remove(pb->file, pb->username, pb->frev) < 0) { if (rcs_errno != RCS_ERR_NOENT) - cvs_log(LP_WARN, "failed to remove lock"); + cvs_log(LP_WARN, "failed to remove lock"); + else if (!(pb->flags & CO_LOCK)) + cvs_log(LP_WARN, "previous revision was not locked; " + "ignoring -l option"); } /* Current head revision gets the RCS patch as rd_text */ @@ -514,7 +529,7 @@ checkin_update(struct checkin_params *pb) /* Now add our new revision */ if (rcs_rev_add(pb->file, (pb->newrev == NULL ? RCS_HEAD_REV : pb->newrev), - pb->rcs_msg, pb->date, pb->username) != 0) { + pb->rcs_msg, pb->date, pb->author) != 0) { cvs_log(LP_ERR, "failed to add new revision"); return (-1); } @@ -551,7 +566,7 @@ checkin_update(struct checkin_params *pb) if (((pb->flags & CO_LOCK) || (pb->flags & CO_UNLOCK)) && !(pb->flags & CI_DEFAULT)) checkout_rev(pb->file, pb->newrev, pb->filename, pb->flags, - pb->username); + pb->username, pb->author, NULL); /* File will NOW be synced */ rcs_close(pb->file); @@ -613,7 +628,7 @@ checkin_init(struct checkin_params *pb) rcs_desc_set(pb->file, rcs_desc); /* Now add our new revision */ - if (rcs_rev_add(pb->file, RCS_HEAD_REV, LOG_INIT, -1, pb->username) != 0) { + if (rcs_rev_add(pb->file, RCS_HEAD_REV, LOG_INIT, -1, pb->author) != 0) { cvs_log(LP_ERR, "failed to add new revision"); return (-1); } @@ -647,7 +662,7 @@ checkin_init(struct checkin_params *pb) if (((pb->flags & CO_LOCK) || (pb->flags & CO_UNLOCK)) && !(pb->flags & CI_DEFAULT)) checkout_rev(pb->file, pb->newrev, pb->filename, pb->flags, - pb->username); + pb->username, pb->author, NULL); /* File will NOW be synced */ rcs_close(pb->file); @@ -707,8 +722,8 @@ checkin_revert(struct checkin_params *pb) (void)unlink(pb->filename); if ((pb->flags & CO_LOCK) || (pb->flags & CO_UNLOCK)) checkout_rev(pb->file, pb->frev, pb->filename, - pb->flags, pb->username); - rcs_lock_remove(pb->file, pb->frev); + pb->flags, pb->username, pb->author, NULL); + rcs_lock_remove(pb->file, pb->username, pb->frev); rcs_close(pb->file); if (verbose == 1) printf("done\n"); @@ -723,29 +738,19 @@ checkin_revert(struct checkin_params *pb) static int checkin_checklock(struct checkin_params *pb) { - int found = 0, notlocked = 1; + int notlocked = 1; struct rcs_lock *lkp; - if (!TAILQ_EMPTY(&(pb->file->rf_locks))) { - TAILQ_FOREACH(lkp, &(pb->file->rf_locks), rl_list) { - if (!strcmp(lkp->rl_name, pb->username)) - notlocked = 0; - - if ((!strcmp(lkp->rl_name, pb->username)) && - (!rcsnum_cmp(lkp->rl_num, pb->frev, 0))) { - found = 1; - return (0); - } - } + TAILQ_FOREACH(lkp, &(pb->file->rf_locks), rl_list) { + if ((!strcmp(lkp->rl_name, pb->username)) && + (!rcsnum_cmp(lkp->rl_num, pb->frev, 0))) + return (0); } - if ((found == 0) && (notlocked == 1)) { - cvs_log(LP_ERR, - "%s: no lock set by %s", pb->file->rf_path, pb->username); - rcs_close(pb->file); - return (-1); - } - return (0); + cvs_log(LP_ERR, + "%s: no lock set by %s", pb->file->rf_path, pb->username); + rcs_close(pb->file); + return (-1); } /* diff --git a/usr.bin/rcs/co.c b/usr.bin/rcs/co.c index 76eba7eafcc..1a625b2801d 100644 --- a/usr.bin/rcs/co.c +++ b/usr.bin/rcs/co.c @@ -1,4 +1,4 @@ -/* $OpenBSD: co.c,v 1.43 2005/12/05 19:46:24 xsa Exp $ */ +/* $OpenBSD: co.c,v 1.44 2005/12/08 18:56:10 joris Exp $ */ /* * Copyright (c) 2005 Joris Vink <joris@openbsd.org> * All rights reserved. @@ -38,8 +38,6 @@ #define CO_OPTSTRING "f::k:l::M::p::q::r::s:Tu::Vw::x:" -static int checkout_state(RCSFILE *, RCSNUM *, const char *, int, - const char *, const char *); static void checkout_err_nobranch(RCSFILE *, const char *, const char *, const char *, int); @@ -50,7 +48,7 @@ checkout_main(int argc, char **argv) RCSNUM *frev, *rev; RCSFILE *file; char fpath[MAXPATHLEN], buf[16]; - char *username; + char *author, *username; const char *state; struct rcs_delta *rdp; time_t rcs_mtime = -1; @@ -59,7 +57,8 @@ checkout_main(int argc, char **argv) kflag = RCS_KWEXP_ERR; rev = RCS_HEAD_REV; frev = NULL; - state = username = NULL; + state = NULL; + author = NULL; while ((ch = rcs_getopt(argc, argv, CO_OPTSTRING)) != -1) { switch (ch) { @@ -113,7 +112,18 @@ checkout_main(int argc, char **argv) printf("%s\n", rcs_version); exit(0); case 'w': - username = rcs_optarg; + /* if no argument, assume current user */ + if (rcs_optarg == NULL) { + if ((author = getlogin()) == NULL) { + cvs_log(LP_ERRNO, + "could not get login"); + exit(1); + } + } else if ((author = strdup(rcs_optarg)) == NULL) { + cvs_log(LP_ERRNO, "out of memory"); + exit(1); + } + flags |= CO_AUTHOR; break; case 'x': @@ -134,7 +144,7 @@ checkout_main(int argc, char **argv) exit (1); } - if ((username == NULL) && ((username = getlogin()) == NULL)) { + if ((username = getlogin()) == NULL) { cvs_log(LP_ERRNO, "failed to get username"); exit (1); } @@ -166,32 +176,10 @@ checkout_main(int argc, char **argv) else frev = rev; - rcsnum_tostr(frev, buf, sizeof(buf)); - - if ((rdp = rcs_findrev(file, frev)) == NULL) - return (-1); - - if (((flags & CO_STATE) && - (strcmp(rdp->rd_state, state) != 0)) || - ((flags & CO_AUTHOR) && - (strcmp(rdp->rd_author, username) != 0))) { - checkout_err_nobranch(file, username, NULL, state, - flags); - return (-1); - } - - if (flags & CO_STATE) { - if (checkout_state(file, frev, argv[i], flags, - username, state) < 0) { + if (checkout_rev(file, frev, argv[i], flags, + username, author, state) < 0) { rcs_close(file); continue; - } - } else { - if (checkout_rev(file, frev, argv[i], flags, - username) < 0) { - rcs_close(file); - continue; - } } rcs_close(file); @@ -219,48 +207,103 @@ checkout_usage(void) * Checkout revision <rev> from RCSFILE <file>, writing it to the path <dst> * Currenly recognised <flags> are CO_LOCK, CO_UNLOCK and CO_REVDATE. * + * Looks up revision based upon <lockname>, <author>, <state> + * * Returns 0 on success, -1 on failure. */ int checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags, - const char *username) + const char *lockname, const char *author, const char *state) { + BUF *bp; + int lcount; char buf[16], yn; mode_t mode = 0444; - BUF *bp; struct stat st; - char *content; + struct rcs_delta *rdp; + struct rcs_lock *lkp; + char *content, msg[128]; /* Check out the latest revision if <frev> is greater than HEAD */ if (rcsnum_cmp(frev, file->rf_head, 0) == -1) frev = file->rf_head; + lcount = 0; + TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list) { + if (!strcmp(lkp->rl_name, lockname)) + lcount++; + } + + /* + * If the user didn't specify any revision, we cycle through + * revisions to lookup the first one that matches what he specified. + * + * If we cannot find one, we return an error. + */ + rdp = NULL; + if (frev == file->rf_head) { + if (lcount > 1) { + cvs_log(LP_WARN, + "multiple revisions locked by %s; " + "please specify one", lockname); + return (-1); + } + + TAILQ_FOREACH(rdp, &file->rf_delta, rd_list) { + if ((author != NULL) && + (strcmp(rdp->rd_author, author))) + continue; + if ((state != NULL) && + (strcmp(rdp->rd_state, state))) + continue; + + frev = rdp->rd_num; + break; + } + } else { + rdp = rcs_findrev(file, frev); + } + + if (rdp == NULL) { + checkout_err_nobranch(file, author, NULL, state, flags); + return (-1); + } + rcsnum_tostr(frev, buf, sizeof(buf)); + if (rdp->rd_locker != NULL) { + if (strcmp(lockname, rdp->rd_locker)) { + strlcpy(msg, "Revision %s is already locked by %s; ", + sizeof(msg)); + if (flags & CO_UNLOCK) + strlcat(msg, "use co -r or rcs -u", sizeof(msg)); + cvs_log(LP_ERR, msg, buf, rdp->rd_locker); + return (-1); + } + } + if (verbose == 1) printf("revision %s", buf); + if ((bp = rcs_getrev(file, frev)) == NULL) { cvs_log(LP_ERR, "cannot find revision `%s'", buf); return (-1); } if (flags & CO_LOCK) { - if ((username != NULL) - && (rcs_lock_add(file, username, frev) < 0)) { - if ((rcs_errno != RCS_ERR_DUPENT) && (verbose == 1)) - cvs_log(LP_ERR, "failed to lock '%s'", buf); + if ((lockname != NULL) + && (rcs_lock_add(file, lockname, frev) < 0)) { + if (rcs_errno != RCS_ERR_DUPENT) + return (-1); } mode = 0644; if (verbose == 1) printf(" (locked)"); } else if (flags & CO_UNLOCK) { - if (rcs_lock_remove(file, frev) < 0) { - if (rcs_errno != RCS_ERR_NOENT) - cvs_log(LP_ERR, - "failed to remove lock '%s'", buf); - } + if (rcs_lock_remove(file, lockname, frev) < 0) + return (-1); mode = 0444; if (verbose == 1) @@ -270,6 +313,12 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags, if (verbose == 1) printf("\n"); + if (flags & CO_LOCK) { + lcount++; + if (lcount > 1) + cvs_log(LP_WARN, "You now have %d locks.", lcount); + } + if ((pipeout == 0) && (stat(dst, &st) == 0) && !(flags & FORCE)) { if (st.st_mode & S_IWUSR) { yn = 0; @@ -325,32 +374,6 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags, } /* - * checkout_state() - * - * Search from supplied revision backwards until we find one - * with state <state> and check that out. - * - * Returns 0 on success, -1 on checkout_rev failure. - */ -static int -checkout_state(RCSFILE *file, RCSNUM *rev, const char *dst, int flags, - const char *username, const char *state) -{ - const char *tstate; - - if (rev == NULL) - return (-1); - else { - if (((tstate = rcs_state_get(file, rev)) != NULL) - && (strcmp(state, tstate) == 0)) - return (checkout_rev(file, rev, dst, flags, username)); - else - rev = rcsnum_dec(rev); - return (checkout_state(file, rev, dst, flags, username, state)); - } -} - -/* * checkout_err_nobranch() * * XXX - should handle the dates too. diff --git a/usr.bin/rcs/rcsclean.c b/usr.bin/rcs/rcsclean.c index e03c930cd6c..661431925a2 100644 --- a/usr.bin/rcs/rcsclean.c +++ b/usr.bin/rcs/rcsclean.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsclean.c,v 1.18 2005/11/28 14:43:59 xsa Exp $ */ +/* $OpenBSD: rcsclean.c,v 1.19 2005/12/08 18:56:10 joris Exp $ */ /* * Copyright (c) 2005 Joris Vink <joris@openbsd.org> * All rights reserved. @@ -43,6 +43,7 @@ static int nflag = 0; static int kflag = RCS_KWEXP_ERR; static int uflag = 0; static int flags = 0; +static char *locker = NULL; int rcsclean_main(int argc, char **argv) @@ -97,6 +98,9 @@ rcsclean_main(int argc, char **argv) argc -= rcs_optind; argv += rcs_optind; + if ((locker = getlogin()) == NULL) + exit(1); + if (argc == 0) { if ((dirp = opendir(".")) == NULL) { cvs_log(LP_ERRNO, "failed to open directory '.'"); @@ -196,7 +200,7 @@ rcsclean_file(char *fname, RCSNUM *rev) rcsnum_tostr(frev, numb, sizeof(numb)), fpath); } - (void)rcs_lock_remove(file, frev); + (void)rcs_lock_remove(file, locker, frev); } if (TAILQ_EMPTY(&(file->rf_locks))) { diff --git a/usr.bin/rcs/rcsprog.h b/usr.bin/rcs/rcsprog.h index 25539242ca9..24e8d3f1e6f 100644 --- a/usr.bin/rcs/rcsprog.h +++ b/usr.bin/rcs/rcsprog.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsprog.h,v 1.29 2005/12/06 10:29:12 xsa Exp $ */ +/* $OpenBSD: rcsprog.h,v 1.30 2005/12/08 18:56:10 joris Exp $ */ /* * Copyright (c) 2005 Joris Vink <joris@openbsd.org> * All rights reserved. @@ -67,7 +67,8 @@ void checkin_usage(void); /* co.c */ int checkout_main(int, char **); -int checkout_rev(RCSFILE *, RCSNUM *, const char *, int, const char *); +int checkout_rev(RCSFILE *, RCSNUM *, const char *, int, const char *, + const char *, const char *); void checkout_usage(void); /* ident.c */ |