apply: do not patch lines that were already patched
authorJunio C Hamano <gitster@pobox.com>
Fri, 4 Mar 2011 20:25:34 +0000 (12:25 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 4 Mar 2011 22:47:18 +0000 (14:47 -0800)
commit9d158601b3cb9753825e21441c88d31297b97be5
treea13c3fe79c27bb93316296198ef26ad0d0a7b103
parent964498e7f90bc5d822746bbf953fb66c6b01ac1c
apply: do not patch lines that were already patched

When looking for a place to apply a hunk, we used to check lines that
match the preimage of it, starting from the line that the patch wants to
apply the hunk at, looking forward and backward with increasing offsets
until we find a match.

Colin Guthrie found an interesting case where this misapplied a patch that
wanted to touch a preimage that consists of

                        }
                }

                return 0;
        }

which is a rather unfortunately common pattern.

The target version of the file originally had only one such location, but
the hunk immediately before that created another instance of such block of
lines, and find_pos() happily reported that the preimage of the hunk
matched what it wanted to modify.

Oops.

By marking the lines application of earlier hunks touched and preventing
match_fragment() from considering them as a match with preimage of other
hunks, we can reduce such an accident.

I also considered to teach apply_one_fragment() to take the offset we have
found while applying the previous hunk into account when looking for a
match with find_pos(), but dismissed that approach, because it would
sometimes work better but sometimes worse, depending on the difference
between the version the patch was created against and the version the
patch is being applied.

This does _not_ prevent misapplication of patches to a file that has many
similar looking blocks of lines and a preimage cannot identify which one
of them should be applied.  For that, we would need to scan beyond the
first match in find_pos(), and issue a warning (or error out).  That will
be a separate topic.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/apply.c