diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -748,20 +748,21 @@ class patchfile(object): 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 --git a/tests/test-import.t b/tests/test-import.t --- a/tests/test-import.t +++ b/tests/test-import.t @@ -996,3 +996,79 @@ import a unified diff with no lines of c 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 +