version 1.155, 2006/03/29 09:16:53 |
version 1.156, 2006/03/30 23:06:25 |
|
|
BUF* |
BUF* |
rcs_getrev(RCSFILE *rfp, RCSNUM *frev) |
rcs_getrev(RCSFILE *rfp, RCSNUM *frev) |
{ |
{ |
int res; |
u_int i, numlen; |
|
int isbranch, lookonbranch; |
size_t len; |
size_t len; |
void *bp; |
void *bp; |
RCSNUM *crev, *rev; |
RCSNUM *crev, *rev, *brev; |
BUF *rbuf; |
BUF *rbuf; |
struct rcs_delta *rdp = NULL; |
struct rcs_delta *rdp = NULL; |
|
struct rcs_branch *rb; |
|
|
if (rfp->rf_head == NULL) |
if (rfp->rf_head == NULL) |
return (NULL); |
return (NULL); |
|
|
else |
else |
rev = frev; |
rev = frev; |
|
|
res = rcsnum_cmp(rfp->rf_head, rev, 0); |
/* XXX rcsnum_cmp() */ |
if (res == 1) { |
for (i = 0; i < rfp->rf_head->rn_len; i++) { |
rcs_errno = RCS_ERR_NOENT; |
if (rfp->rf_head->rn_id[i] < rev->rn_id[i]) { |
return (NULL); |
rcs_errno = RCS_ERR_NOENT; |
|
return (NULL); |
|
} |
} |
} |
|
|
/* No matter what, we're going to need up the the description parsed */ |
/* No matter what, we're going to need up the the description parsed */ |
|
|
cvs_log(LP_ERR, "failed to get RCS HEAD revision"); |
cvs_log(LP_ERR, "failed to get RCS HEAD revision"); |
return (NULL); |
return (NULL); |
} |
} |
|
|
if (rdp->rd_tlen == 0) |
if (rdp->rd_tlen == 0) |
rcs_parse_deltatexts(rfp, rfp->rf_head); |
rcs_parse_deltatexts(rfp, rfp->rf_head); |
|
|
len = rdp->rd_tlen; |
len = rdp->rd_tlen; |
if (len == 0) { |
if (len == 0) { |
rbuf = cvs_buf_alloc(1, 0); |
rbuf = cvs_buf_alloc(1, 0); |
|
|
rbuf = cvs_buf_alloc(len, BUF_AUTOEXT); |
rbuf = cvs_buf_alloc(len, BUF_AUTOEXT); |
cvs_buf_append(rbuf, rdp->rd_text, len); |
cvs_buf_append(rbuf, rdp->rd_text, len); |
|
|
if (res != 0) { |
isbranch = 0; |
/* Apply patches backwards to get the right version. |
brev = NULL; |
* 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, |
* If a branch was passed, get the latest revision on it. |
rcs_patch_lines); |
*/ |
xfree(bp); |
if (RCSNUM_ISBRANCH(rev)) { |
if (rbuf == NULL) |
brev = rev; |
break; |
rdp = rcs_findrev(rfp, rev); |
} while (rcsnum_cmp(crev, rev, 0) != 0); |
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' |
if (cvs_buf_getc(rbuf, cvs_buf_len(rbuf)-1) != '\n' |
&& rbuf != NULL) |
&& rbuf != NULL) |
cvs_buf_putc(rbuf, '\n'); |
cvs_buf_putc(rbuf, '\n'); |
|
|
return (rbuf); |
return (rbuf); |
} |
} |
|
|
|
|
memset(rdp, 0, sizeof(*rdp)); |
memset(rdp, 0, sizeof(*rdp)); |
|
|
TAILQ_INIT(&(rdp->rd_branches)); |
TAILQ_INIT(&(rdp->rd_branches)); |
TAILQ_INIT(&(rdp->rd_snodes)); |
|
|
|
rdp->rd_num = rcsnum_alloc(); |
rdp->rd_num = rcsnum_alloc(); |
rcsnum_cpy(rev, rdp->rd_num, 0); |
rcsnum_cpy(rev, rdp->rd_num, 0); |
|
|
* |
* |
* Find a specific revision's delta entry in the tree of the RCS file <rfp>. |
* Find a specific revision's delta entry in the tree of the RCS file <rfp>. |
* The revision number is given in <rev>. |
* 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. |
* Returns a pointer to the delta on success, or NULL on failure. |
*/ |
*/ |
struct rcs_delta * |
struct rcs_delta * |
rcs_findrev(RCSFILE *rfp, RCSNUM *rev) |
rcs_findrev(RCSFILE *rfp, RCSNUM *rev) |
{ |
{ |
u_int cmplen; |
u_int cmplen; |
struct rcs_delta *rdp, *enddelta; |
struct rcs_delta *rdp; |
struct rcs_dlist *hp; |
RCSNUM *brev, *frev; |
int found; |
|
|
|
/* |
/* |
* We need to do more parsing if the last revision in the linked list |
* We need to do more parsing if the last revision in the linked list |
* is greater than the requested revision. |
* is greater than the requested revision. |
*/ |
*/ |
enddelta = TAILQ_LAST(&(rfp->rf_delta), rcs_dlist); |
rdp = TAILQ_LAST(&(rfp->rf_delta), rcs_dlist); |
if ((enddelta == NULL) |
if ((rdp == NULL) |
|| (rcsnum_cmp(enddelta->rd_num, rev, 0) == -1)) { |
|| (rcsnum_cmp(rdp->rd_num, rev, 0) == -1)) { |
rcs_parse_deltas(rfp, rev); |
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 { |
if (rdp->rd_next->rn_len == 0) |
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; |
|
break; |
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); |
return (NULL); |
} |
} |
|
|
|
|
rdp->rd_next = rcsnum_alloc(); |
rdp->rd_next = rcsnum_alloc(); |
|
|
TAILQ_INIT(&(rdp->rd_branches)); |
TAILQ_INIT(&(rdp->rd_branches)); |
TAILQ_INIT(&(rdp->rd_snodes)); |
|
|
|
tok = rcs_gettok(rfp); |
tok = rcs_gettok(rfp); |
if (tok == RCS_TOK_DESC) { |
if (tok == RCS_TOK_DESC) { |
|
|
TAILQ_REMOVE(&(rdp->rd_branches), rb, rb_list); |
TAILQ_REMOVE(&(rdp->rd_branches), rb, rb_list); |
rcsnum_free(rb->rb_num); |
rcsnum_free(rb->rb_num); |
xfree(rb); |
xfree(rb); |
} |
|
|
|
while ((crdp = TAILQ_FIRST(&(rdp->rd_snodes))) != NULL) { |
|
TAILQ_REMOVE(&(rdp->rd_snodes), crdp, rd_list); |
|
rcs_freedelta(crdp); |
|
} |
} |
|
|
xfree(rdp); |
xfree(rdp); |