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");

Reply via email to