summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@cvs.openbsd.org>2007-10-09 12:59:54 +0000
committerTobias Stoeckmann <tobias@cvs.openbsd.org>2007-10-09 12:59:54 +0000
commit868da502acb914afd9fd6404607bb4374154c97a (patch)
tree7a927eea01461164dfaa078db3a4e3bcbbb82b49 /usr.bin
parent121846ddfbd76e9f8e2cf4234cda9c8cb2f92457 (diff)
Added proper support for branch revisions in annotate.
OK niallo@, twice :)
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/cvs/annotate.c45
-rw-r--r--usr.bin/cvs/rcs.c117
-rw-r--r--usr.bin/cvs/rcs.h4
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 *);