[The annotate command in CVS currently just looks backwards; it tells you what revision a given line was last changed in. For example, if you are annotating revision 1.2 and a line was changed in producing 1.1, annotate will display 1.1. This patch allows annotate to look both forwards and backwards. So it also shows what revision a given line will next be changed in. For example, if you are annotating revision 1.2 and the line was changed from 1.2->1.3, the patched annotate will display 1.3 as the forward revision. -kingdon] To: bug-cvs@gnu.org Subject: RE: extension of cvs annotate From: KOIE Hidetaka (=?iso-2022-jp?B?GyRCOHE5PjFRTjQbKEI=?=) Content-Type: Multipart/Mixed; boundary="--Next_Part(Sat_Feb_27_02:51:48_1999_479)--" Date: Sat, 27 Feb 1999 02:52:09 +0900 ----Next_Part(Sat_Feb_27_02:51:48_1999_479)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit From: Jim Kingdon Subject: Re: extension of cvs annotate Date: Sat, 27 Feb 1999 02:15:14 +0900 | Please submit patches to bug-cvs@gnu.org. Note that submissions to | bug-cvs may be distributed under the terms of the GNU Public License, | so if you don't like this, don't submit them. Sorry. I hope this patch is under GPL. -- KOIE Hidetaka / koie@suri.co.jp / SURIGIKEN Co.,LTD. ----Next_Part(Sat_Feb_27_02:51:48_1999_479)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: overview Content-Disposition: attachment; filename=ann.txt Annotate subcommand prints a appearance/modification revision for each line. This patch applied to cvs-1.10.5, then annotate subcommand prints a modification/disappearance revision for each line. For example: There is a file "dir/file". 1.2.2.1 1.2.2.2 O-----------O-----------> (B1) / / O---------O-----------O-----------> 1.1 1.2 1.3 (T1) Contents of the file are: revision 1.1 foo revision 1.2 (T1) foo bar revision 1.3 bar revision 1.2.2.1 bar revision 1.2.2.2 foo bar Annotate subcommand output are: % cvs ann -r 1.1 1.1 koie 99-02-24 1.3 koie 99-02-24 | foo % cvs ann -r 1.2 1.1 koie 99-02-24 1.3 koie 99-02-24 | foo 1.2 koie 99-02-24 | bar % cvs ann -r 1.3 1.2 koie 99-02-24 | bar % cvs ann -r 1.2.2.1 1.2 koie 99-02-24 | bar % cvs ann -r 1.2.2.2 1.2.2.2 koie 99-02-24 | foo 1.2 koie 99-02-24 | bar % cvs ann -r B1 1.2.2.2 koie 99-02-24 | foo 1.2 koie 99-02-24 | bar Known bug: There is a problem that cvs cannot handle deletion between a branching point and first revision on the branch. Supposing cvs annotate subcommand is extended, CVS reports like this: % cvs ann -rT1/B1 1.1 koie 99-02-24 1.2.2.1 koie 99-02-24 | foo 1.2 koie 99-02-24 | bar If execute `cvs ann -rT1', then CVS traces along main line: 1.2.2.1 1.2.2.2 O-----------O-----------> (B1) / / O<<==(2)==O<<===(1)===O-----------> 1.1 1.2 1.3 (T1) If execute `cvs ann -rT1/B1', then CVS traces along brach B1 1.2.2.1 1.2.2.2 O===(2)===>>O-----------> (B1) // // O<<==(3)==O<<===(1)===O-----------> 1.1 1.2 1.3 (T1) Workaround: After create branch by `cvs tag -b', do `checkout -r branch' and then, first of all, do `checkin -f -R -m "Force"'. ----Next_Part(Sat_Feb_27_02:51:48_1999_479)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: patch for rcs.c based cvs-1.10.5 Content-Disposition: attachment; filename="rcs.c-diff" --- rcs.c.org Sat Feb 20 00:22:33 1999 +++ rcs.c Fri Feb 26 22:43:55 1999 @@ -6852,6 +6852,8 @@ size_t len; /* Version in which it was introduced. */ RCSVers *vers; + /* Version in which it was junked. */ + RCSVers *delvers; /* Nonzero if this line ends with \n. This will always be true except possibly for the last line. */ int has_newline; @@ -6882,7 +6884,7 @@ } static int linevector_add PROTO ((struct linevector *vec, const char *text, - size_t len, RCSVers *vers, + size_t len, int onbranch, RCSVers *vers, RCSVers *prev_vers, unsigned int pos)); /* Given some text TEXT, add each of its lines to VEC before line POS @@ -6896,11 +6898,13 @@ the linevector (and freed by linevector_free). So the caller doesn't need to keep TEXT around after the call to this function. */ static int -linevector_add (vec, text, len, vers, pos) +linevector_add (vec, text, len, onbranch, vers, prev_vers, pos) struct linevector *vec; const char *text; size_t len; + int onbranch; RCSVers *vers; + RCSVers *prev_vers; unsigned int pos; { const char *textend; @@ -6955,7 +6959,16 @@ break; nextline_len = p - nextline_text; q = (struct line *) xmalloc (sizeof (struct line) + nextline_len); - q->vers = vers; + if (onbranch) + { + q->vers = vers; + q->delvers = NULL; + } + else + { + q->vers = NULL; + q->delvers = prev_vers; + } q->text = (char *)q + sizeof (struct line); q->len = nextline_len; q->has_newline = nextline_newline; @@ -6968,7 +6981,16 @@ } nextline_len = p - nextline_text; q = (struct line *) xmalloc (sizeof (struct line) + nextline_len); - q->vers = vers; + if (onbranch) + { + q->vers = vers; + q->delvers = NULL; + } + else + { + q->vers = NULL; + q->delvers = prev_vers; + } q->text = (char *)q + sizeof (struct line); q->len = nextline_len; q->has_newline = nextline_newline; @@ -7081,7 +7103,7 @@ static int apply_rcs_changes PROTO ((struct linevector *, const char *, size_t, - const char *, RCSVers *, RCSVers *)); + const char *, int, RCSVers *, RCSVers *)); /* Apply changes to the line vector LINES. DIFFBUF is a buffer of length DIFFLEN holding the change text from an RCS file (the output @@ -7096,13 +7118,14 @@ calls error with a status of 1, causing the program to exit. */ static int -apply_rcs_changes (lines, diffbuf, difflen, name, addvers, delvers) +apply_rcs_changes (lines, diffbuf, difflen, name, onbranch, vers, prev_vers) struct linevector *lines; const char *diffbuf; size_t difflen; const char *name; - RCSVers *addvers; - RCSVers *delvers; + int onbranch; + RCSVers *vers; + RCSVers *prev_vers; { const char *p; const char *q; @@ -7192,7 +7215,8 @@ switch (df->type) { case ADD: - if (! linevector_add (lines, df->new_lines, df->len, addvers, + if (! linevector_add (lines, df->new_lines, df->len, + onbranch, vers, prev_vers, df->pos)) return 0; break; @@ -7200,9 +7224,12 @@ if (df->pos > lines->nlines || df->pos + df->nlines > lines->nlines) return 0; - if (delvers != NULL) + if (onbranch) + for (ln = df->pos; ln < df->pos + df->nlines; ++ln) + lines->vector[ln]->delvers = vers; + else for (ln = df->pos; ln < df->pos + df->nlines; ++ln) - lines->vector[ln]->vers = delvers; + lines->vector[ln]->vers = prev_vers; linevector_delete (lines, df->pos, df->nlines); break; } @@ -7241,10 +7268,10 @@ linevector_init (&lines); - if (! linevector_add (&lines, textbuf, textlen, NULL, 0)) + if (! linevector_add (&lines, textbuf, textlen, 0, NULL, NULL, 0)) error (1, 0, "cannot initialize line vector"); - if (! apply_rcs_changes (&lines, diffbuf, difflen, name, NULL, NULL)) + if (! apply_rcs_changes (&lines, diffbuf, difflen, name, 0, NULL, NULL)) { error (0, 0, "invalid change text in %s", name); ret = 0; @@ -7322,6 +7349,8 @@ RCSVers *prev_vers; RCSVers *trunk_vers; char *next; + RCSVers *trunk_prev; + char *trunk_next; int ishead, isnext, isversion, onbranch; Node *node; struct linevector headlines; @@ -7340,6 +7369,8 @@ prev_vers = NULL; trunk_vers = NULL; next = NULL; + trunk_prev = NULL; + trunk_next = NULL; onbranch = 0; foundhead = 0; @@ -7413,7 +7444,7 @@ rcsbuf_valpolish (rcsbuf, value, 0, &vallen); if (ishead) { - if (! linevector_add (&curlines, value, vallen, NULL, 0)) + if (! linevector_add (&curlines, value, vallen, 0, NULL, NULL, 0)) error (1, 0, "invalid rcs file %s", rcs->path); ishead = 0; @@ -7421,9 +7452,8 @@ else if (isnext) { if (! apply_rcs_changes (&curlines, value, vallen, - rcs->path, - onbranch ? vers : NULL, - onbranch ? NULL : prev_vers)) + rcs->path, onbranch, + vers, prev_vers)) error (1, 0, "invalid change text in %s", rcs->path); } break; @@ -7439,25 +7469,21 @@ /* This is the version we want. */ linevector_copy (&headlines, &curlines); foundhead = 1; - if (onbranch) + if (onbranch && trunk_next == NULL) { /* We have found this version by tracking up a branch. Restore back to the lines we saved when we left the trunk, and continue tracking down the trunk. */ - onbranch = 0; - vers = trunk_vers; - next = vers->next; - linevector_copy (&curlines, &trunklines); + next = vers->next; + trunk_prev = trunk_vers; + trunk_next = trunk_vers->next; } } else { Node *p; - /* We need to look up the branch. */ - onbranch = 1; - if (numdots (branchversion) < 2) { unsigned int ln; @@ -7475,6 +7501,19 @@ curlines.vector[ln]->vers = NULL; } + if (trunk_prev) + { + onbranch = 0; + vers = trunk_prev; + next = trunk_next; + trunk_next = NULL; + linevector_copy (&curlines, &trunklines); + goto return_to_trunk; + } + + /* We need to look up the branch. */ + onbranch = 1; + /* The next version we want is the entry on VERS->branches which matches this branch. For example, suppose VERSION is 1.21.4.3 and @@ -7509,6 +7548,15 @@ *cpversion = '\0'; } } + return_to_trunk: + if (next == NULL && trunk_prev) + { + onbranch = 0; + vers = trunk_prev; + next = trunk_next; + trunk_next = NULL; + linevector_copy (&curlines, &trunklines); + } if (op == RCS_FETCH && foundhead) break; } while (next != NULL); @@ -7530,23 +7578,21 @@ for (ln = 0; ln < headlines.nlines; ++ln) { - char buf[80]; + char buf[160]; /* Period which separates year from month in date. */ char *ym; /* Period which separates month from day in date. */ char *md; + char *y1, *m1, *d1; + char *y2, *m2, *d2; + int c; RCSVers *prvers; + RCSVers *pdrvers; prvers = headlines.vector[ln]->vers; if (prvers == NULL) prvers = vers; - sprintf (buf, "%-12s (%-8.8s ", - prvers->version, - prvers->author); - cvs_output (buf, 0); - - /* Now output the date. */ ym = strchr (prvers->date, '.'); if (ym == NULL) { @@ -7557,27 +7603,44 @@ ("??" "-???") is also an ANSI-ism. Testing __STDC__ seems to be a can of worms, since compilers do all kinds of things with it. */ - cvs_output ("??", 0); - cvs_output ("-???", 0); - cvs_output ("-??", 0); + y1 = m1 = d1 = "??"; } else { - md = strchr (ym + 1, '.'); - if (md == NULL) - cvs_output ("??", 0); - else - cvs_output (md + 1, 2); - - cvs_output ("-", 1); - cvs_output (month_printname (ym + 1), 0); - cvs_output ("-", 1); /* Only output the last two digits of the year. Our output lines are long enough as it is without printing the century. */ - cvs_output (ym - 2, 2); + y1 = ym - 2; + m1 = ym + 1; + md = strchr (ym + 1, '.'); + d1 = md ? md + 1 : "??"; } - cvs_output ("): ", 0); + + pdrvers = headlines.vector[ln]->delvers; + + if (pdrvers == NULL || + (ym = strchr (pdrvers->date, '.')) == NULL) + { + c = ' '; + y2 = m2 = d2 = ""; + } + else + { + c = '-'; + y2 = ym - 2; + m2 = ym + 1; + md = strchr (ym + 1, '.'); + d2 = md ? md + 1 : "??"; + } + + sprintf (buf, "%-12s %-8.8s %2.2s-%2.2s-%2.2s " + "%-12s %-8.8s %2.2s%c%2.2s%c%2.2s | ", + prvers->version, prvers->author, y1, m1, d1, + pdrvers ? pdrvers->version : "", + pdrvers ? pdrvers->author : "", + y2, c, m2, c, d2); + cvs_output (buf, 0); + if (headlines.vector[ln]->len != 0) cvs_output (headlines.vector[ln]->text, headlines.vector[ln]->len); @@ -8658,7 +8721,11 @@ version = RCS_getversion (finfo->rcs, tag, date, force_tag_match, (int *) NULL); if (version == NULL) + { + if (rcsbufp != NULL) + rcsbuf_close (rcsbufp); return 0; + } /* Distinguish output for various files if we are processing several files. */ ----Next_Part(Sat_Feb_27_02:51:48_1999_479)----