diff options
Diffstat (limited to 'usr.bin/cvs/rcs.c')
-rw-r--r-- | usr.bin/cvs/rcs.c | 179 |
1 files changed, 122 insertions, 57 deletions
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index 62fc1b6b2c7..e7ece10e923 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.155 2006/03/29 09:16:53 ray Exp $ */ +/* $OpenBSD: rcs.c,v 1.156 2006/03/30 23:06:25 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -1169,12 +1169,14 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) BUF* rcs_getrev(RCSFILE *rfp, RCSNUM *frev) { - int res; + u_int i, numlen; + int isbranch, lookonbranch; size_t len; void *bp; - RCSNUM *crev, *rev; + RCSNUM *crev, *rev, *brev; BUF *rbuf; struct rcs_delta *rdp = NULL; + struct rcs_branch *rb; if (rfp->rf_head == NULL) return (NULL); @@ -1184,10 +1186,12 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) else rev = frev; - res = rcsnum_cmp(rfp->rf_head, rev, 0); - if (res == 1) { - rcs_errno = RCS_ERR_NOENT; - return (NULL); + /* 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); + } } /* No matter what, we're going to need up the the description parsed */ @@ -1198,8 +1202,10 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) cvs_log(LP_ERR, "failed to get RCS HEAD revision"); return (NULL); } + if (rdp->rd_tlen == 0) rcs_parse_deltatexts(rfp, rfp->rf_head); + len = rdp->rd_tlen; if (len == 0) { rbuf = cvs_buf_alloc(1, 0); @@ -1210,33 +1216,86 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) rbuf = cvs_buf_alloc(len, BUF_AUTOEXT); cvs_buf_append(rbuf, rdp->rd_text, len); - if (res != 0) { - /* Apply patches backwards to get the right version. - * This will need some rework to support sub branches. - */ - do { - crev = rdp->rd_next; - rdp = rcs_findrev(rfp, crev); - if (rdp == NULL) { - cvs_buf_free(rbuf); - return (NULL); - } - 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); - - bp = cvs_buf_release(rbuf); - rbuf = cvs_patchfile((char *)bp, (char *)rdp->rd_text, - rcs_patch_lines); - xfree(bp); - if (rbuf == NULL) - break; - } while (rcsnum_cmp(crev, rev, 0) != 0); + isbranch = 0; + brev = NULL; + + /* + * 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) + fatal("failed to translate branch to latest revision"); + + rev = rdp->rd_num; + } else { + if (RCSNUM_ISBRANCHREV(rev)) { + brev = rcsnum_revtobr(rev); + isbranch = 1; + } } + + lookonbranch = 0; + crev = NULL; + + /* Apply patches backwards to get the right version. + */ + do { + if (rcsnum_cmp(rfp->rf_head, rev, 0) == 0) + break; + + if ((isbranch == 1) && (rdp->rd_num->rn_len < rev->rn_len) && + (!TAILQ_EMPTY(&(rdp->rd_branches)))) + lookonbranch = 1; + + 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; + } + + if (i == numlen) { + crev = rb->rb_num; + break; + } + } + } else { + crev = rdp->rd_next; + } + + rdp = rcs_findrev(rfp, crev); + if (rdp == NULL) { + cvs_buf_free(rbuf); + return (NULL); + } + + 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); + + bp = cvs_buf_release(rbuf); + rbuf = cvs_patchfile((char *)bp, (char *)rdp->rd_text, + rcs_patch_lines); + xfree(bp); + + if (rbuf == NULL) + break; + } while (rcsnum_cmp(crev, rev, 0) != 0); + if (cvs_buf_getc(rbuf, cvs_buf_len(rbuf)-1) != '\n' && rbuf != NULL) cvs_buf_putc(rbuf, '\n'); + return (rbuf); } @@ -1284,7 +1343,6 @@ rcs_rev_add(RCSFILE *rf, RCSNUM *rev, const char *msg, time_t date, memset(rdp, 0, sizeof(*rdp)); TAILQ_INIT(&(rdp->rd_branches)); - TAILQ_INIT(&(rdp->rd_snodes)); rdp->rd_num = rcsnum_alloc(); rcsnum_cpy(rev, rdp->rd_num, 0); @@ -1355,43 +1413,56 @@ rcs_rev_remove(RCSFILE *rf, RCSNUM *rev) * * Find a specific revision's delta entry in the tree of the RCS file <rfp>. * The revision number is given in <rev>. + * + * If the given revision is a branch number, we translate it into the latest + * revision on the branch. + * * Returns a pointer to the delta on success, or NULL on failure. */ struct rcs_delta * rcs_findrev(RCSFILE *rfp, RCSNUM *rev) { u_int cmplen; - struct rcs_delta *rdp, *enddelta; - struct rcs_dlist *hp; - int found; + struct rcs_delta *rdp; + RCSNUM *brev, *frev; /* * We need to do more parsing if the last revision in the linked list * is greater than the requested revision. */ - enddelta = TAILQ_LAST(&(rfp->rf_delta), rcs_dlist); - if ((enddelta == NULL) - || (rcsnum_cmp(enddelta->rd_num, rev, 0) == -1)) { + rdp = TAILQ_LAST(&(rfp->rf_delta), rcs_dlist); + if ((rdp == NULL) + || (rcsnum_cmp(rdp->rd_num, rev, 0) == -1)) { rcs_parse_deltas(rfp, rev); } - cmplen = 2; - hp = &(rfp->rf_delta); + /* + * Translate a branch into the latest revision on the branch itself. + */ + if (RCSNUM_ISBRANCH(rev)) { + brev = rcsnum_brtorev(rev); + frev = brev; + for (;;) { + rdp = rcs_findrev(rfp, frev); + if (rdp == NULL) + fatal("failed to translate branch to last revision"); - do { - found = 0; - TAILQ_FOREACH(rdp, hp, rd_list) { - if (rcsnum_cmp(rdp->rd_num, rev, cmplen) == 0) { - if (cmplen == rev->rn_len) - return (rdp); - - hp = &(rdp->rd_snodes); - cmplen += 2; - found = 1; + if (rdp->rd_next->rn_len == 0) break; - } + + frev = rdp->rd_next; } - } while (found && cmplen < rev->rn_len); + + rcsnum_free(brev); + return (rdp); + } + + cmplen = rev->rn_len; + + TAILQ_FOREACH(rdp, &(rfp->rf_delta), rd_list) { + if (rcsnum_cmp(rdp->rd_num, rev, cmplen) == 0) + return (rdp); + } return (NULL); } @@ -1791,7 +1862,6 @@ rcs_parse_delta(RCSFILE *rfp) rdp->rd_next = rcsnum_alloc(); TAILQ_INIT(&(rdp->rd_branches)); - TAILQ_INIT(&(rdp->rd_snodes)); tok = rcs_gettok(rfp); if (tok == RCS_TOK_DESC) { @@ -2265,11 +2335,6 @@ rcs_freedelta(struct rcs_delta *rdp) xfree(rb); } - while ((crdp = TAILQ_FIRST(&(rdp->rd_snodes))) != NULL) { - TAILQ_REMOVE(&(rdp->rd_snodes), crdp, rd_list); - rcs_freedelta(crdp); - } - xfree(rdp); } |