Hi, OpenCVS does not agree with the annotation output of GNU cvs and blame (blame.sourceforge.net). I discovered this today when trying to use opencvs with cvsweb.
------------------------------------------------------------------------------ Replicating the problem ------------------------------------------------------------------------------ $ cvs -v Concurrent Versions System (CVS) 1.11.1p1 (client/server) * snip * $ blame --version blame 1.3.1; emulating RCS version 5 $ export CVSROOT=/tmp/repo $ mkdir $CVSROOT $ cvs init $ mkdir test $ cd test $ echo line1 > file $ cvs import -m hey test mwb start N test/file No conflicts created by this import $ cd $ cvs co test cvs checkout: Updating test U test/file $ cd test $ echo line2 >> file $ cvs commit -m line2 file Checking in file; /tmp/repo/test/file,v <-- file new revision: 1.2; previous revision: 1.1 done $ echo line3 >> file $ cvs commit -m line3 file Checking in file; /tmp/repo/test/file,v <-- file new revision: 1.3; previous revision: 1.2 done $ cat file line1 line2 line3 $ cat /tmp/repo/test/file,v head 1.3; access; symbols start:1.1.1.1 mwb:1.1.1; locks; strict; comment @# @; 1.3 date 2012.12.31.02.57.41; author mwb; state Exp; branches; next 1.2; 1.2 date 2012.12.31.02.57.08; author mwb; state Exp; branches; next 1.1; 1.1 date 2012.12.31.02.56.04; author mwb; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2012.12.31.02.56.04; author mwb; state Exp; branches; next ; desc @@ 1.3 log @line3 @ text @line1 line2 line3 @ 1.2 log @line2 @ text @d3 1 @ 1.1 log @Initial revision @ text @d2 1 @ 1.1.1.1 log @hey @ text @@ $ blame -r1.3 /tmp/repo/test/file,v Annotations for file *************** 1.1 (mwb 31-Dec-12): line1 1.2 (mwb 31-Dec-12): line2 1.3 (mwb 31-Dec-12): line3 $ cvs annotate -r1.3 file Annotations for file *************** 1.1 (mwb 31-Dec-12): line1 1.2 (mwb 31-Dec-12): line2 1.3 (mwb 31-Dec-12): line3 $ opencvs annotate -r1.3 file Annotations for file *************** 1.1 (mwb 31-Dec-12): line1 1.1 (mwb 31-Dec-12): line2 1.3 (mwb 31-Dec-12): line3 ^^^ Line 2 is from revision 1.2 not 1.1 ^^^ ------------------------------------------------------------------------------ Debugging steps ------------------------------------------------------------------------------ I added the following code to check the return value of rcs_rev_getlines()... void gotlines(struct rcs_line **alines) { int i; struct rcs_line *line; char rnum[13]; for (i = 0; alines[i] != NULL; i++) { line = alines[i]; rcsnum_tostr(line->l_delta->rd_num, rnum, sizeof(rnum)); printf("line=(%d): rev=(%s) text=(%s)\n", i+1, rnum, line->l_line); } exit(0); } The alines structure looks like this... $ opencvs annotate -r1.3 line=(1): rev=(1.1) text=(line1 line2 line3 ) line=(2): rev=(1.1) text=(line2 line3 ) line=(3): rev=(1.3) text=(line3 ) Now it's clear that rcs_rev_getlines() marks line 2 incorrectly. Adding more trace statements... $ opencvs annotate -r1.3 rcs_patch_lines: begin rcs_patch_lines: op='d' lineno=3 nbln=1 line=(1): rev=(1.1) text=(line1 line2 line3 ) line=(2): rev=(1.1) text=(line2 line3 ) line=(3): rev=(1.3) text=(line3 ) For some reason, rcs_patch_lines() is only being called once. It is called on revision 1.2, which contains the change "d3 1". rcs_patch_lines() is not being called for revision 1.1. Now it's clear why not all lines are annotated properly. Adding trace statements, it's clear that the loop is broken at the rdp->rd_next->rn_len test. $ opencvs annotate -r1.3 rcs_rev_getlines: top of for(;;) loop rcs_rev_getlines: might call rcs_patch_lines() rcs_patch_lines: begin rcs_patch_lines: op='d' lineno=3 nbln=1 rcs_rev_getlines: top of for(;;) loop rcs_rev_getlines: exit loop: rdp->rd_next->rn_len == 0 When I remove the "break" altogether the annotate works properly. :) $ opencvs annotate -r1.4 $ opencvs annotate -r1.3 Annotations for file *************** 1.1 (mwb 31-Dec-12): line1 1.2 (mwb 31-Dec-12): line2 1.3 (mwb 31-Dec-12): line3 $ opencvs annotate -r1.2 Annotations for file *************** 1.1 (mwb 31-Dec-12): line1 1.2 (mwb 31-Dec-12): line2 $ opencvs annotate -r1.1 Annotations for file *************** 1.1 (mwb 31-Dec-12): line1 ------------------------------------------------------------------------------ Patch ------------------------------------------------------------------------------ It is possible that removing the 'break' might cause something else to stop working; however, the XXX looks a bit suspect. I am submitting this fix for comment... - Michael Index: rcs.c =================================================================== RCS file: /data/open/anoncvs/cvs/src/usr.bin/cvs/rcs.c,v retrieving revision 1.310 diff -u -r1.310 rcs.c --- rcs.c 2 May 2011 22:22:54 -0000 1.310 +++ rcs.c 31 Dec 2012 04:15:19 -0000 @@ -1823,15 +1823,7 @@ trdp = rcs_findrev(rfp, rdp->rd_next); if (trdp == NULL) fatal("failed to grab next revision"); - } else { - /* - * XXX Fail, although the caller does not always do the - * right thing (eg cvs diff when the tree is ahead of - * the repository). - */ - break; } - if (rdp->rd_tlen == 0) { if (rcsparse_deltatexts(rfp, rdp->rd_num)) fatal("rcs_rev_getlines: rcsparse_deltatexts");