diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -126,17 +126,20 @@ def _cmp(a, b): return (a > b) - (a < b) class _lazymanifest(object): - def __init__(self, data, positions=None, extrainfo=None, extradata=None): + def __init__(self, data, positions=None, extrainfo=None, extradata=None, + hasremovals=False): if positions is None: self.positions = self.findlines(data) self.extrainfo = [0] * len(self.positions) self.data = data self.extradata = [] + self.hasremovals = False else: self.positions = positions[:] self.extrainfo = extrainfo[:] self.extradata = extradata[:] self.data = data + self.hasremovals = hasremovals def findlines(self, data): if not data: @@ -244,6 +247,7 @@ class _lazymanifest(object): self.extrainfo = self.extrainfo[:needle] + self.extrainfo[needle + 1:] if cur >= 0: self.data = self.data[:cur] + '\x00' + self.data[cur + 1:] + self.hasremovals = True def __setitem__(self, key, value): if not isinstance(key, bytes): @@ -279,11 +283,11 @@ class _lazymanifest(object): def copy(self): # XXX call _compact like in C? return _lazymanifest(self.data, self.positions, self.extrainfo, - self.extradata) + self.extradata, self.hasremovals) def _compact(self): # hopefully not called TOO often - if len(self.extradata) == 0: + if len(self.extradata) == 0 and not self.hasremovals: return l = [] i = 0 @@ -298,6 +302,16 @@ class _lazymanifest(object): i += 1 if i == len(self.positions) or self.positions[i] < 0: break + + # A removed file has no positions[] entry, but does have an + # overwritten first byte. Break out and find the end of the + # current good entry/entries if there is a removed file + # before the next position. + if (self.hasremovals + and self.data.find('\n\x00', cur, + self.positions[i]) != -1): + break + offset += self.positions[i] - cur cur = self.positions[i] end_cut = self.data.find('\n', cur) @@ -316,6 +330,7 @@ class _lazymanifest(object): offset += len(l[-1]) i += 1 self.data = ''.join(l) + self.hasremovals = False self.extradata = [] def _pack(self, d): diff --git a/tests/test-manifest.t b/tests/test-manifest.t --- a/tests/test-manifest.t +++ b/tests/test-manifest.t @@ -219,7 +219,7 @@ will be contiguous spans of existing ent > manifest = $TESTTMP/manifest.py > EOF -BROKEN: Pure removes should actually remove all dropped entries +Pure removes should actually remove all dropped entries $ hg init repo $ cd repo @@ -239,32 +239,25 @@ BROKEN: Pure removes should actually rem $ hg debugdata -m 1 a.txt\x00b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (esc) aa.txt\x00a4bdc161c8fbb523c9a60409603f8710ff49a571 (esc) - \x00.txt\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc) (pure !) c.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) cc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) ccc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) - \x00.txt\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc) (pure !) e.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) - $ hg up -C . 2>&1 | grep ValueError || true - raise ValueError("Manifest lines not in sorted order.") (pure !) - ValueError: Manifest lines not in sorted order. (pure !) + $ hg up -qC . - $ hg verify || true + $ hg verify checking changesets checking manifests - manifest@1: reading delta c1f6b2f803ac: Non-hexadecimal digit found (pure !) crosschecking files in changesets and manifests checking files checked 2 changesets with 8 changes to 8 files - 1 integrity errors encountered! (pure !) - (first damaged changeset appears to be 1) (pure !) $ hg rollback -q --config ui.rollback=True $ hg rm b.txt d.txt $ echo bb > bb.txt -BROKEN: A mix of adds and removes should remove all dropped entries. +A mix of adds and removes should remove all dropped entries. $ hg ci -Aqm 'remove b and d; add bb' @@ -275,20 +268,11 @@ BROKEN: A mix of adds and removes should c.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) cc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) ccc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) - \x00.txt\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc) (pure !) e.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) - $ hg up -C . 2>&1 | grep ValueError || true - raise ValueError("Manifest lines not in sorted order.") (pure !) - ValueError: Manifest lines not in sorted order. (pure !) - - $ hg verify || true + $ hg verify checking changesets checking manifests - manifest@1: reading delta 0a0385480090: Manifest lines not in sorted order. (pure !) crosschecking files in changesets and manifests - bb.txt@1: in changeset but not in manifest (pure !) checking files checked 2 changesets with 9 changes to 9 files - 2 integrity errors encountered! (pure !) - (first damaged changeset appears to be 1) (pure !)