summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/cvs/rcs.c31
-rw-r--r--usr.bin/cvs/rcs.h5
-rw-r--r--usr.bin/rcs/ci.c75
-rw-r--r--usr.bin/rcs/co.c161
-rw-r--r--usr.bin/rcs/rcsclean.c8
-rw-r--r--usr.bin/rcs/rcsprog.h5
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 */