CVS 1.10.8 incorrectly merges. Enclosed is a reproducible test
case and a bug fix.
It is only CVS that fails; the programs diff3, merge, and rcsmerge
correctly merge the enclosed test case.
The problem is that the ordinary diff (not diff3) in CVS inhibits hunk
merges in some cases. The ordinary diff in the package
diffutils-2.7.tar.gz does NOT inhibit. I changed the CVS file
diff/analyze.c to be more like diffutils-2.7.tar.gz, and then cvs
worked with the enclosed test case. Specifically, I changed the
following code to set the variable to 0 which allows hunk merging,
which then allows diff to output data which allows diff3 to correctly
merge the enclosed test case:
shift_boundaries (filevec)
struct file_data filevec[];
{
int f;
int inhibit_hunk_merge = horizon_lines != context;
I changed it to say:
int inhibit_hunk_merge = 0;
diff3 makes 2 calls to diff. Without my bug fix, one of those calls
to diff apparently results in hunk merging. The other diff does not.
I have not studied it enough to figure out why that is. Since the two
diffs output different hunk info, diff3 thinks there is a conflict
when there really is not a conflict. The 2 diffs really are equivalent.
One is simpler than the other. But because the exact form varies
between the two diffs, diff3 thinks they are not equivalent, and that
therefore there is a conflict.
In addition to incorrectly claiming there is a conflict, there is an
even worse problem in that it completely ignores one change.
Specifically the file in my test case called "base", says:
First change will also delete this line.
But the result of the merge still has that line in it and the line is
not indicated to be in conflict. So if a user decides to ignore areas
not marked as conflicts, he might never even notice that cvs lost his
change.
Whoever changed the diff code after copying that code into cvs, must
have thought that occasionally inhibiting hunk merging gives
some benefit, although I don't know what benefit that might be since I
have not studied the code enough. So although my change lets the
enclosed test case work, it may break other test cases like ones in
which inhibiting is beneficial. So therefore, my change is probably
not the best solution in the long run.
To run my enclosed test case, do this:
tar zxf cvs_bug.tgz
cd cvs_bug
cvstest.csh
The test contains a base file and two other files which represent two
parallel changes to the base file. Before I can get cvs to merge these
three files, I have to do a lot of set up which is why the test script
is so complicated.
The following command is similar to the options used in
src/rcscmds.c, but yet the following command works:
diff3 -E -am second_change base first_change
Also, the following command works:
merge -p second_change base first_change
Also included is a script called rcstest.csh which demonstrates how rcs
correctly merges the test case.
Although diff3 from the diffutils package correctly handles the
enclosed test case, I have a second test case which both diff3 and cvs
incorrectly handle. Therefore, this second bug is the responsibility
of the diff maintainers, not the cvs maintainers. However, I am still
mentioning it here since this second test case also causes incorrect
behavior when using cvs, since cvs copied most of the source code from
diff3. So far, I only sent the details about this second case to
[EMAIL PROTECTED] But if any cvs maintainers or other
people are interested, I will be glad to send them the full details of
this second bug.
cvs_bug.tgz