summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2006-06-01 20:00:53 +0000
committerJoris Vink <joris@cvs.openbsd.org>2006-06-01 20:00:53 +0000
commit91b2539f3bccc40a19757de24447e2354b98f1dd (patch)
tree39012707a6d654af0794262dc74b337a2dd43f2a
parent43c990ab0f3db918c8ea3707f821a4667127e554 (diff)
major rewrite of some rcs parsing stuff:
- rework rcs_getrev() to correctly support branches - rework rcs_translate_tag() to correctly translate given symbols or branches into their matching revisions - rework rcs_rev_add() to correctly update its 'next' pointers and insert the new revision in the correct place on the list. - rework rcs_head_get() to return the latest revision on the default branch if it has been set or the normal HEAD revision otherwise. - no longer access the rf_head member of the RCSFILE struct manually, use the rcs_head_get() function which correctly returns the HEAD revision, there might be a default branch that has to be used. - for now, when commiting a new revision reset the default branch.
-rw-r--r--usr.bin/cvs/add.c9
-rw-r--r--usr.bin/cvs/commit.c9
-rw-r--r--usr.bin/cvs/file.c5
-rw-r--r--usr.bin/cvs/rcs.c281
-rw-r--r--usr.bin/cvs/rcs.h4
-rw-r--r--usr.bin/cvs/status.c5
6 files changed, 155 insertions, 158 deletions
diff --git a/usr.bin/cvs/add.c b/usr.bin/cvs/add.c
index cef95503659..4cea0ab5246 100644
--- a/usr.bin/cvs/add.c
+++ b/usr.bin/cvs/add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: add.c,v 1.51 2006/05/30 21:32:52 joris Exp $ */
+/* $OpenBSD: add.c,v 1.52 2006/06/01 20:00:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -175,10 +175,12 @@ add_file(struct cvs_file *cf)
BUF *b;
int added, l, stop;
char *entry, revbuf[16], tbuf[32];
+ RCSNUM *head;
CVSENTRIES *entlist;
if (cf->file_rcs != NULL)
- rcsnum_tostr(cf->file_rcs->rf_head, revbuf, sizeof(revbuf));
+ rcsnum_tostr(rcs_head_get(cf->file_rcs),
+ revbuf, sizeof(revbuf));
added = stop = 0;
switch (cf->file_status) {
@@ -216,7 +218,8 @@ add_file(struct cvs_file *cf)
xfree(entry);
- b = rcs_getrev(cf->file_rcs, cf->file_rcs->rf_head);
+ head = rcs_head_get(cf->file_rcs);
+ b = rcs_getrev(cf->file_rcs, head);
if (b == NULL)
fatal("cvs_add_local: failed to get HEAD");
diff --git a/usr.bin/cvs/commit.c b/usr.bin/cvs/commit.c
index ecbf62ab1f6..4a4bb408428 100644
--- a/usr.bin/cvs/commit.c
+++ b/usr.bin/cvs/commit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: commit.c,v 1.67 2006/05/31 23:27:38 joris Exp $ */
+/* $OpenBSD: commit.c,v 1.68 2006/06/01 20:00:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -165,7 +165,7 @@ cvs_commit_local(struct cvs_file *cf)
if (cf->file_status == FILE_MODIFIED ||
cf->file_status == FILE_REMOVED || (cf->file_status == FILE_ADDED
&& cf->file_rcs != NULL && cf->file_rcs->rf_dead == 1))
- rcsnum_tostr(cf->file_rcs->rf_head, rbuf, sizeof(rbuf));
+ rcsnum_tostr(rcs_head_get(cf->file_rcs), rbuf, sizeof(rbuf));
else
strlcpy(rbuf, "Non-existent", sizeof(rbuf));
@@ -260,6 +260,11 @@ cvs_commit_local(struct cvs_file *cf)
fatal("cvs_commit_local: failed to set state");
}
+ if (cf->file_rcs->rf_branch != NULL) {
+ rcsnum_free(cf->file_rcs->rf_branch);
+ cf->file_rcs->rf_branch = NULL;
+ }
+
rcs_write(cf->file_rcs);
if (cf->file_status == FILE_REMOVED) {
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index 0c2e90a9450..1ff07bbe332 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.155 2006/05/31 01:26:22 joris Exp $ */
+/* $OpenBSD: file.c,v 1.156 2006/06/01 20:00:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -607,6 +607,7 @@ cvs_file_classify(struct cvs_file *cf, const char *tag, int loud)
case CVS_OP_COMMIT:
rflags = RCS_WRITE;
break;
+ case CVS_OP_IMPORT:
case CVS_OP_LOG:
rflags |= RCS_PARSE_FULLY;
break;
@@ -642,7 +643,7 @@ cvs_file_classify(struct cvs_file *cf, const char *tag, int loud)
if (tag != NULL && cf->file_rcs != NULL)
cf->file_rcsrev = rcs_translate_tag(tag, cf->file_rcs);
else if (cf->file_rcs != NULL)
- cf->file_rcsrev = cf->file_rcs->rf_head;
+ cf->file_rcsrev = rcs_head_get(cf->file_rcs);
else
cf->file_rcsrev = NULL;
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c
index dc0be399bee..b54157d744d 100644
--- a/usr.bin/cvs/rcs.c
+++ b/usr.bin/cvs/rcs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcs.c,v 1.179 2006/05/31 22:25:59 joris Exp $ */
+/* $OpenBSD: rcs.c,v 1.180 2006/06/01 20:00:52 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -591,9 +591,16 @@ out:
*
* Retrieve the revision number of the head revision for the RCS file <file>.
*/
-const RCSNUM *
+RCSNUM *
rcs_head_get(RCSFILE *file)
{
+ char br[16];
+
+ if (file->rf_branch != NULL) {
+ rcsnum_tostr(file->rf_branch, br, sizeof(br));
+ return (rcs_translate_tag(br, file));
+ }
+
return (file->rf_head);
}
@@ -1061,7 +1068,8 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
lineno = (int)strtol((lp->l_line + 1), &ep, 10);
if (lineno > dlines->l_nblines || lineno < 0 ||
*ep != ' ')
- fatal("invalid line specification in RCS patch");
+ fatal("invalid line specification in RCS patch: %s",
+ ep);
ep++;
nbln = (int)strtol(ep, &ep, 10);
if (nbln < 0 || *ep != '\0')
@@ -1140,139 +1148,109 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
BUF*
rcs_getrev(RCSFILE *rfp, RCSNUM *frev)
{
- u_int i, numlen;
- int isbranch, lookonbranch, found;
- size_t len;
- void *bp;
- RCSNUM *crev, *rev, *brev;
- BUF *rbuf;
- struct rcs_delta *rdp = NULL;
- struct rcs_branch *rb;
-
- if (rfp->rf_head == NULL)
- return (NULL);
-
- if (frev == RCS_HEAD_REV)
- rev = rfp->rf_head;
- else
- rev = frev;
+ size_t i;
+ int done, nextroot, found;
+ BUF *rcsbuf;
+ RCSNUM *tnum, *bnum;
+ struct rcs_branch *brp;
+ struct rcs_delta *hrdp, *trdp, *rdp;
+ char *data;
- /* XXX rcsnum_cmp() */
- for (i = 0; i < rfp->rf_head->rn_len; i++) {
- if (rfp->rf_head->rn_id[i] < rev->rn_id[i]) {
- rcs_errno = RCS_ERR_NOENT;
- return (NULL);
- }
- }
+ if ((hrdp = rcs_findrev(rfp, rfp->rf_head)) == NULL)
+ fatal("rcs_getrev: no HEAD revision");
- /* No matter what, we're going to need up the the description parsed */
- rcs_parse_desc(rfp, NULL);
+ tnum = frev;
+ rcs_parse_deltatexts(rfp, hrdp->rd_num);
- rdp = rcs_findrev(rfp, rfp->rf_head);
- if (rdp == NULL) {
- cvs_log(LP_ERR, "failed to get RCS HEAD revision");
- return (NULL);
+ /* revision on branch, get the branch root */
+ nextroot = 2;
+ if (RCSNUM_ISBRANCHREV(tnum)) {
+ bnum = rcsnum_alloc();
+ rcsnum_cpy(tnum, bnum, nextroot);
+ } else {
+ bnum = tnum;
}
- if (rdp->rd_tlen == 0)
- rcs_parse_deltatexts(rfp, rfp->rf_head);
+ rcsbuf = cvs_buf_alloc(hrdp->rd_tlen, BUF_AUTOEXT);
+ cvs_buf_append(rcsbuf, hrdp->rd_text, hrdp->rd_tlen);
- len = rdp->rd_tlen;
- if (len == 0) {
- rbuf = cvs_buf_alloc(1, 0);
- cvs_buf_empty(rbuf);
- return (rbuf);
- }
+ done = 0;
- rbuf = cvs_buf_alloc(len, BUF_AUTOEXT);
- cvs_buf_append(rbuf, rdp->rd_text, len);
+ rdp = hrdp;
+ if (!rcsnum_differ(rdp->rd_num, bnum))
+ goto next;
- isbranch = 0;
- brev = NULL;
+ if ((rdp = rcs_findrev(rfp, hrdp->rd_next)) == NULL)
+ return (rcsbuf);
- /*
- * If a branch was passed, get the latest revision on it.
- */
- if (RCSNUM_ISBRANCH(rev)) {
- brev = rev;
- rdp = rcs_findrev(rfp, rev);
- if (rdp == NULL)
- return (NULL);
+again:
+ for (;;) {
+ if (rdp->rd_next->rn_len != 0) {
+ trdp = rcs_findrev(rfp, rdp->rd_next);
+ if (trdp == NULL)
+ fatal("failed to grab next revision");
+ }
- rev = rdp->rd_num;
- } else {
- if (RCSNUM_ISBRANCHREV(rev)) {
- brev = rcsnum_revtobr(rev);
- isbranch = 1;
+ if (rdp->rd_tlen == 0) {
+ rcs_parse_deltatexts(rfp, rdp->rd_num);
+ if (rdp->rd_tlen == 0) {
+ if (!rcsnum_differ(rdp->rd_num, bnum))
+ break;
+ rdp = trdp;
+ continue;
+ }
}
- }
- lookonbranch = 0;
- crev = NULL;
+ cvs_buf_putc(rcsbuf, '\0');
+ data = cvs_buf_release(rcsbuf);
- /* Apply patches backwards to get the right version.
- */
- do {
- found = 0;
-
- if (rcsnum_cmp(rfp->rf_head, rev, 0) == 0)
+ rcsbuf = cvs_patchfile(data, rdp->rd_text, rcs_patch_lines);
+ if (rcsbuf == NULL)
+ fatal("rcs_getrev: failed to apply rcsdiff");
+ xfree(data);
+
+ if (!rcsnum_differ(rdp->rd_num, bnum))
break;
- if (isbranch == 1 && rdp->rd_num->rn_len < rev->rn_len &&
- !TAILQ_EMPTY(&(rdp->rd_branches)))
- lookonbranch = 1;
+ rdp = trdp;
+ }
- if (isbranch && lookonbranch == 1) {
- lookonbranch = 0;
- TAILQ_FOREACH(rb, &(rdp->rd_branches), rb_list) {
- /* XXX rcsnum_cmp() is totally broken for
- * this purpose.
- */
- numlen = MIN(brev->rn_len, rb->rb_num->rn_len);
- for (i = 0; i < numlen; i++) {
- if (rb->rb_num->rn_id[i] !=
- brev->rn_id[i])
- break;
- }
+next:
+ if (!rcsnum_differ(rdp->rd_num, frev))
+ done = 1;
- if (i == numlen) {
- crev = rb->rb_num;
- found = 1;
+ if (RCSNUM_ISBRANCHREV(frev) && done != 1) {
+ nextroot += 2;
+ rcsnum_cpy(frev, bnum, nextroot);
+
+ TAILQ_FOREACH(brp, &(rdp->rd_branches), rb_list) {
+ found = 1;
+ for (i = 0; i < nextroot - 1; i++) {
+ if (brp->rb_num->rn_id[i] != bnum->rn_id[i]) {
+ found = 0;
break;
}
}
- if (found == 0)
- crev = rdp->rd_next;
- } else {
- crev = rdp->rd_next;
- }
- rdp = rcs_findrev(rfp, crev);
- if (rdp == NULL) {
- cvs_buf_free(rbuf);
- return (NULL);
+ /* XXX */
+ if (found == 0)
+ fatal("no matching branch on list");
+ break;
}
- cvs_buf_putc(rbuf, '\0');
-
- /* check if we have parsed this rev's deltatext */
- if (rdp->rd_tlen == 0)
- rcs_parse_deltatexts(rfp, rdp->rd_num);
+ if (brp == NULL)
+ fatal("expected branch not found on branch list");
- bp = cvs_buf_release(rbuf);
- rbuf = cvs_patchfile((char *)bp, (char *)rdp->rd_text,
- rcs_patch_lines);
- xfree(bp);
+ if ((rdp = rcs_findrev(rfp, brp->rb_num)) == NULL)
+ fatal("rcs_getrev: failed to get delta for target rev");
- if (rbuf == NULL)
- break;
- } while (rcsnum_cmp(crev, rev, 0) != 0);
+ goto again;
+ }
- if (cvs_buf_getc(rbuf, cvs_buf_len(rbuf)-1) != '\n' &&
- rbuf != NULL)
- cvs_buf_putc(rbuf, '\n');
+ if (bnum != tnum)
+ rcsnum_free(bnum);
- return (rbuf);
+ return (rcsbuf);
}
/*
@@ -1294,6 +1272,7 @@ rcs_rev_add(RCSFILE *rf, RCSNUM *rev, const char *msg, time_t date,
{
time_t now;
struct passwd *pw;
+ struct rcs_branch *brp;
struct rcs_delta *ordp, *rdp;
if (rev == RCS_HEAD_REV) {
@@ -1324,13 +1303,6 @@ rcs_rev_add(RCSFILE *rf, RCSNUM *rev, const char *msg, time_t date,
rdp->rd_next = rcsnum_alloc();
- if (!(rf->rf_flags & RCS_CREATE)) {
- /* next should point to the previous HEAD */
- ordp = TAILQ_FIRST(&(rf->rf_delta));
- rcsnum_cpy(ordp->rd_num, rdp->rd_next, 0);
- }
-
-
if (username == NULL)
username = pw->pw_name;
@@ -1344,9 +1316,27 @@ rcs_rev_add(RCSFILE *rf, RCSNUM *rev, const char *msg, time_t date,
time(&now);
gmtime_r(&now, &(rdp->rd_date));
- TAILQ_INSERT_HEAD(&(rf->rf_delta), rdp, rd_list);
+ if (RCSNUM_ISBRANCHREV(rev))
+ TAILQ_INSERT_TAIL(&(rf->rf_delta), rdp, rd_list);
+ else
+ TAILQ_INSERT_HEAD(&(rf->rf_delta), rdp, rd_list);
rf->rf_ndelta++;
+ if (!(rf->rf_flags & RCS_CREATE)) {
+ if (RCSNUM_ISBRANCHREV(rev)) {
+ brp = xmalloc(sizeof(*brp));
+ brp->rb_num = rcsnum_alloc();
+ rcsnum_cpy(rdp->rd_num, brp->rb_num, 0);
+ TAILQ_INSERT_TAIL(&(rdp->rd_branches), brp, rb_list);
+
+ ordp = TAILQ_PREV(rdp, cvs_tqh, rd_list);
+ rcsnum_cpy(rdp->rd_num, ordp->rd_next, 0);
+ } else {
+ ordp = TAILQ_NEXT(rdp, rd_list);
+ rcsnum_cpy(ordp->rd_num, rdp->rd_next, 0);
+ }
+ }
+
/* not synced anymore */
rf->rf_flags &= ~RCS_SYNCED;
@@ -1619,6 +1609,7 @@ rcs_parse_deltas(RCSFILE *rfp, RCSNUM *rev)
if (rcsnum_cmp(enddelta->rd_num, rev, 0) == 0)
break;
}
+
if (ret == 0) {
rfp->rf_flags |= PARSED_DELTAS;
break;
@@ -1746,6 +1737,9 @@ rcs_parse_admin(RCSFILE *rfp)
int tok, ntok, hmask;
struct rcs_key *rk;
+ rfp->rf_head = NULL;
+ rfp->rf_branch = NULL;
+
/* hmask is a mask of the headers already encountered */
hmask = 0;
for (;;) {
@@ -2951,60 +2945,53 @@ RCSNUM *
rcs_translate_tag(const char *revstr, RCSFILE *rfp)
{
size_t i;
+ int nextroot;
RCSNUM *rev, *brev;
struct rcs_branch *brp;
struct rcs_delta *rdp, *brdp;
- char foo[16];
+ char revision[16];
rev = rcs_sym_getrev(rfp, revstr);
if (rev == NULL) {
if ((rev = rcsnum_parse(revstr)) == NULL)
- fatal("%s is an invalid revision/symbol", revstr);
+ fatal("tag %s does not exist (0)", revstr);
}
if (RCSNUM_ISBRANCH(rev)) {
brev = rcsnum_alloc();
- rcsnum_cpy(rev, brev, 2);
+ rcsnum_cpy(rev, brev, rev->rn_len - 1);
+ } else {
+ brev = rev;
+ }
- if ((rdp = rcs_findrev(rfp, brev)) == NULL)
- fatal("rcs_translate_tag: cannot find branch root "
- "for '%s'", revstr);
+ if ((rdp = rcs_findrev(rfp, brev)) == NULL)
+ fatal("tag %s does not exist (1)", revstr);
+ if (RCSNUM_ISBRANCH(rev)) {
TAILQ_FOREACH(brp, &(rdp->rd_branches), rb_list) {
- if (brp->rb_num->rn_len < 4)
- fatal("rcs_translate_tag: bad branch "
- "revision on list");
-
for (i = 0; i < rev->rn_len; i++) {
- if (rev->rn_id[i] != brp->rb_num->rn_id[i])
- continue;
+ if (brp->rb_num->rn_id[i] != rev->rn_id[i])
+ break;
}
- rcsnum_tostr(brp->rb_num, foo, sizeof(foo));
+ if (i != rev->rn_len)
+ continue;
+
break;
}
- if (brp == NULL) {
- if (cvs_cmdop == CVS_OP_IMPORT)
- return (NULL);
- rcsnum_cpy(rdp->rd_num, rev, 0);
- return (rev);
- }
+ if (brp == NULL)
+ return (NULL);
- if ((rdp = rcs_findrev(rfp, brp->rb_num)) == NULL) {
- rcsnum_tostr(brp->rb_num, foo, sizeof(foo));
- fatal("rcs_translate_tag: cannot find branch rev %s",
- foo);
- }
+ if ((rdp = rcs_findrev(rfp, brp->rb_num)) == NULL)
+ fatal("tag %s does not exist (3)", revstr);
- brdp = rdp;
- while (brdp->rd_next->rn_len != 0) {
- brdp = rcs_findrev(rfp, brdp->rd_next);
- if (brdp == NULL)
- fatal("rcs_translate_tag: next is NULL");
+ while (rdp->rd_next->rn_len != 0) {
+ if ((rdp = rcs_findrev(rfp, rdp->rd_next)) == NULL)
+ fatal("tag %s does not exist (4)", revstr);
}
- rcsnum_cpy(brdp->rd_num, rev, 0);
+ rcsnum_cpy(rdp->rd_num, rev, 0);
}
return (rev);
diff --git a/usr.bin/cvs/rcs.h b/usr.bin/cvs/rcs.h
index a69a4877072..c267536a4c1 100644
--- a/usr.bin/cvs/rcs.h
+++ b/usr.bin/cvs/rcs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcs.h,v 1.67 2006/05/31 18:26:14 joris Exp $ */
+/* $OpenBSD: rcs.h,v 1.68 2006/06/01 20:00:52 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -219,7 +219,7 @@ extern int rcs_errno;
RCSFILE *rcs_open(const char *, int, int, ...);
void rcs_close(RCSFILE *);
-const RCSNUM *rcs_head_get(RCSFILE *);
+RCSNUM *rcs_head_get(RCSFILE *);
int rcs_head_set(RCSFILE *, RCSNUM *);
const RCSNUM *rcs_branch_get(RCSFILE *);
int rcs_branch_set(RCSFILE *, const RCSNUM *);
diff --git a/usr.bin/cvs/status.c b/usr.bin/cvs/status.c
index 737f9b082ea..74031556617 100644
--- a/usr.bin/cvs/status.c
+++ b/usr.bin/cvs/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.61 2006/05/30 21:32:52 joris Exp $ */
+/* $OpenBSD: status.c,v 1.62 2006/06/01 20:00:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -155,7 +155,8 @@ cvs_status_local(struct cvs_file *cf)
if (len >= sizeof(buf))
fatal("cvs_status_local: truncation");
} else {
- rcsnum_tostr(cf->file_rcs->rf_head, revbuf, sizeof(revbuf));
+ rcsnum_tostr(rcs_head_get(cf->file_rcs),
+ revbuf, sizeof(revbuf));
l = snprintf(buf, sizeof(buf), "%s\t%s", revbuf,
cf->file_rpath);
if (l == -1 || l >= (int)sizeof(buf))