diff options
author | Tobias Stoeckmann <tobias@cvs.openbsd.org> | 2007-10-09 12:59:54 +0000 |
---|---|---|
committer | Tobias Stoeckmann <tobias@cvs.openbsd.org> | 2007-10-09 12:59:54 +0000 |
commit | 868da502acb914afd9fd6404607bb4374154c97a (patch) | |
tree | 7a927eea01461164dfaa078db3a4e3bcbbb82b49 /usr.bin | |
parent | 121846ddfbd76e9f8e2cf4234cda9c8cb2f92457 (diff) |
Added proper support for branch revisions in annotate.
OK niallo@, twice :)
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/cvs/annotate.c | 45 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.c | 117 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.h | 4 |
3 files changed, 149 insertions, 17 deletions
diff --git a/usr.bin/cvs/annotate.c b/usr.bin/cvs/annotate.c index ff62d658de9..46782571018 100644 --- a/usr.bin/cvs/annotate.c +++ b/usr.bin/cvs/annotate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: annotate.c,v 1.42 2007/10/09 12:25:27 tobias Exp $ */ +/* $OpenBSD: annotate.c,v 1.43 2007/10/09 12:59:53 tobias Exp $ */ /* * Copyright (c) 2007 Tobias Stoeckmann <tobias@openbsd.org> * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org> @@ -29,6 +29,8 @@ void cvs_annotate_local(struct cvs_file *); +extern char *cvs_specified_tag; + static int force_head = 0; struct cvs_cmd cvs_cmd_annotate = { @@ -115,7 +117,7 @@ cvs_annotate_local(struct cvs_file *cf) { int i; char date[10], rnum[13], *p; - RCSNUM *rev; + RCSNUM *bnum, *rev; struct cvs_line *line; struct cvs_line **alines; @@ -127,29 +129,44 @@ cvs_annotate_local(struct cvs_file *cf) cf->file_type != CVS_FILE) return; - if (cvs_specified_tag == NULL) - rcs_rev_getlines(cf->file_rcs, cf->file_rcs->rf_head, &alines); - else { + if (cvs_specified_tag != NULL) { if ((rev = rcs_translate_tag(cvs_specified_tag, cf->file_rcs)) == NULL) { if (!force_head) /* Stick at weird GNU cvs, ignore error. */ return; + rev = rcsnum_alloc(); rcsnum_cpy(cf->file_rcs->rf_head, rev, 0); } - /* rcs_translate_tag may give back an unavailable revision. */ - if (rcs_findrev(cf->file_rcs, rev) == NULL) { - if (!force_head) { - /* Stick at weird GNU cvs, ignore error. */ - rcsnum_free(rev); - return; - } - rcsnum_cpy(cf->file_rcs->rf_head, rev, 0); + /* + * If this is a revision in a branch, we have to go first + * from HEAD to branch, then down to 1.1. After that, take + * annotated branch and go up to branch revision. This must + * be done this way due to different handling of "a" and + * "d" in rcs file for annotation. + */ + if (!RCSNUM_ISBRANCHREV(rev)) { + bnum = rev; + } else { + bnum = rcsnum_alloc(); + rcsnum_cpy(rev, bnum, 2); + } + + rcs_rev_getlines(cf->file_rcs, bnum, &alines); + + /* + * Go into branch and receive annotations for branch revision, + * with inverted "a" and "d" meaning. + */ + if (bnum != rev) { + rcs_annotate_getlines(cf->file_rcs, rev, &alines); + rcsnum_free(bnum); } - rcs_rev_getlines(cf->file_rcs, rev, &alines); rcsnum_free(rev); + } else { + rcs_rev_getlines(cf->file_rcs, cf->file_rcs->rf_head, &alines); } /* Stick at weird GNU cvs, ignore error. */ diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index d3d7048bba2..c93eea9c11f 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.224 2007/10/09 12:18:53 tobias Exp $ */ +/* $OpenBSD: rcs.c,v 1.225 2007/10/09 12:59:53 tobias Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -1091,6 +1091,7 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines, lp->l_line = NULL; lp->l_needsfree = 0; } + lp->l_delta = rdp; TAILQ_INSERT_AFTER(&(dlines->l_lines), dlp, lp, l_list); dlp = lp; @@ -2800,7 +2801,7 @@ next: goto again; } done: - /* put remaining lines of 1.1 into annotate buffer */ + /* put remaining lines into annotate buffer */ if (annotate == ANNOTATE_NOW) { for (line = TAILQ_FIRST(&(dlines->l_lines)); line != NULL; line = nline) { @@ -2825,6 +2826,118 @@ done: return (dlines); } +void +rcs_annotate_getlines(RCSFILE *rfp, RCSNUM *frev, struct cvs_line ***alines) +{ + size_t plen; + int i, nextroot; + RCSNUM *bnum; + struct rcs_branch *brp; + struct rcs_delta *rdp, *trdp; + u_char *patch; + struct cvs_line *line; + struct cvs_lines *dlines, *plines; + + if (!RCSNUM_ISBRANCHREV(frev)) + fatal("rcs_annotate_getlines: branch revision expected"); + + /* revision on branch, get the branch root */ + nextroot = 2; + bnum = rcsnum_alloc(); + rcsnum_cpy(frev, bnum, nextroot); + + /* + * Going from HEAD to 1.1 enables the use of an array, which is + * much faster. Unfortunately this is not possible with branch + * revisions, so copy over our alines (array) into dlines (tailq). + */ + dlines = xcalloc(1, sizeof(*dlines)); + TAILQ_INIT(&(dlines->l_lines)); + line = xcalloc(1, sizeof(*line)); + TAILQ_INSERT_TAIL(&(dlines->l_lines), line, l_list); + + for (i = 0; (*alines)[i] != NULL; i++) { + line = (*alines)[i]; + line->l_lineno = i + 1; + TAILQ_INSERT_TAIL(&(dlines->l_lines), line, l_list); + } + + rdp = rcs_findrev(rfp, bnum); + if (rdp == NULL) + fatal("failed to grab branch root revision"); + + do { + nextroot += 2; + rcsnum_cpy(frev, bnum, nextroot); + + TAILQ_FOREACH(brp, &(rdp->rd_branches), rb_list) { + for (i = 0; i < nextroot - 1; i++) + if (brp->rb_num->rn_id[i] != bnum->rn_id[i]) + break; + if (i == nextroot - 1) + break; + } + + if (brp == NULL) + fatal("expected branch not found on branch list"); + + if ((rdp = rcs_findrev(rfp, brp->rb_num)) == NULL) + fatal("failed to get delta for target rev"); + + for (;;) { + if (rdp->rd_next->rn_len != 0) { + trdp = rcs_findrev(rfp, rdp->rd_next); + if (trdp == NULL) + fatal("failed to grab next revision"); + } + + 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; + } + } + + plen = rdp->rd_tlen; + patch = rdp->rd_text; + plines = cvs_splitlines(patch, plen); + rcs_patch_lines(dlines, plines, NULL, rdp); + cvs_freelines(plines); + + if (!rcsnum_differ(rdp->rd_num, bnum)) + break; + + rdp = trdp; + } + } while (rcsnum_differ(rdp->rd_num, frev)); + + if (bnum != frev) + rcsnum_free(bnum); + + /* + * All lines have been parsed, now they must be copied over + * into alines (array) again. + */ + xfree(*alines); + + i = 0; + TAILQ_FOREACH(line, &(dlines->l_lines), l_list) { + if (line->l_line != NULL) + i++; + } + *alines = xmalloc((i + 1) * sizeof(struct cvs_line *)); + (*alines)[i] = NULL; + + i = 0; + TAILQ_FOREACH(line, &(dlines->l_lines), l_list) { + if (line->l_line != NULL) + (*alines)[i++] = line; + } +} + /* * rcs_rev_getbuf() * diff --git a/usr.bin/cvs/rcs.h b/usr.bin/cvs/rcs.h index dec6a798419..16ea366dc36 100644 --- a/usr.bin/cvs/rcs.h +++ b/usr.bin/cvs/rcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.h,v 1.79 2007/09/24 13:44:20 joris Exp $ */ +/* $OpenBSD: rcs.h,v 1.80 2007/10/09 12:59:53 tobias Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -263,6 +263,8 @@ void rcs_rev_write_stmp(RCSFILE *, RCSNUM *, char *, int); void rcs_rev_write_fd(RCSFILE *, RCSNUM *, int, int); struct cvs_lines *rcs_rev_getlines(RCSFILE *, RCSNUM *, struct cvs_line ***); +void rcs_annotate_getlines(RCSFILE *, RCSNUM *, + struct cvs_line ***); BUF *rcs_rev_getbuf(RCSFILE *, RCSNUM *, int); int rcs_kflag_get(const char *); |