# HG changeset patch # User Patrick Mezard # Date 1329148051 -3600 # Node ID b0c7525f826df69b51568b41718593e9fb0f5b74 # Parent 9ef3a4a2c6c05b1c64e09147ffef562301c5413f patch: fix fuzzing of hunks without previous lines (issue3264) When applying hunks such as: @@ -2,1 +2,2 @@ context +change fuzzing would empty the "old" block and make patchfile.apply() traceback. Instead, we apply the new block at specified location without testing. The "bottom hunk" test was removed as patch(1) has no problem applying hunk with no context in the middle of a file. diff -r 9ef3a4a2c6c0 -r b0c7525f826d mercurial/patch.py --- a/mercurial/patch.py Mon Feb 13 13:51:38 2012 +0100 +++ b/mercurial/patch.py Mon Feb 13 16:47:31 2012 +0100 @@ -748,20 +748,21 @@ self.hash = {} for x, s in enumerate(self.lines): self.hash.setdefault(s, []).append(x) - if h.hunk[-1][0] != ' ': - # if the hunk tried to put something at the bottom of the file - # override the start line and use eof here - search_start = len(self.lines) - else: - search_start = orig_start + self.skew for fuzzlen in xrange(3): for toponly in [True, False]: old, oldstart, new, newstart = h.fuzzit(fuzzlen, toponly) + oldstart = oldstart + self.offset + self.skew + oldstart = min(oldstart, len(self.lines)) + if old: + cand = self.findlines(old[0][1:], oldstart) + else: + # Only adding lines with no or fuzzed context, just + # take the skew in account + cand = [oldstart] - cand = self.findlines(old[0][1:], search_start) for l in cand: - if diffhelpers.testhunk(old, self.lines, l) == 0: + if not old or diffhelpers.testhunk(old, self.lines, l) == 0: self.lines[l : l + len(old)] = new self.offset += len(new) - len(old) self.skew = l - orig_start diff -r 9ef3a4a2c6c0 -r b0c7525f826d tests/test-import.t --- a/tests/test-import.t Mon Feb 13 13:51:38 2012 +0100 +++ b/tests/test-import.t Mon Feb 13 16:47:31 2012 +0100 @@ -996,3 +996,79 @@ c2 c3 c4 + +Test corner case involving fuzz and skew + + $ hg init morecornercases + $ cd morecornercases + + $ cat > 01-no-context-beginning-of-file.diff < diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,0 +1,1 @@ + > +line + > EOF + + $ cat > 02-no-context-middle-of-file.diff < diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -1,1 +1,1 @@ + > -2 + > +add some skew + > @@ -2,0 +2,1 @@ + > +line + > EOF + + $ cat > 03-no-context-end-of-file.diff < diff --git a/a b/a + > --- a/a + > +++ b/a + > @@ -10,0 +10,1 @@ + > +line + > EOF + + $ cat > a < 1 + > 2 + > 3 + > 4 + > EOF + $ hg ci -Am adda a + $ for p in *.diff; do + > hg import -v --no-commit $p + > cat a + > hg revert -aqC a + > # patch -p1 < $p + > # cat a + > # hg revert -aC a + > done + applying 01-no-context-beginning-of-file.diff + patching file a + applied to working directory + 1 + line + 2 + 3 + 4 + applying 02-no-context-middle-of-file.diff + patching file a + Hunk #1 succeeded at 2 (offset 1 lines). + Hunk #2 succeeded at 4 (offset 1 lines). + applied to working directory + 1 + add some skew + 3 + line + 4 + applying 03-no-context-end-of-file.diff + patching file a + Hunk #1 succeeded at 5 (offset -6 lines). + applied to working directory + 1 + 2 + 3 + 4 + line +