revlog: do not use delta for lfs revisions

Summary:
This is similar to what we have done for changegroups, but for non-changegroup
(addrawrevision) case. This is needed to make sure the delta application code
path can assume deltas are always against vanilla (non-LFS) rawtext so the next
fix becomes possible.

Reviewed By: DurhamG

Differential Revision: D6906202

fbshipit-source-id: a7d62dfed4206d45b42299f1dabf013620ae52b3
This commit is contained in:
Jun Wu 2018-02-06 14:18:30 -08:00 committed by Saurabh Singh
parent 1be09a10bc
commit 453b043043
4 changed files with 35 additions and 30 deletions

View File

@ -1904,6 +1904,14 @@ class revlog(object):
return btext[0]
def builddelta(rev):
chainbase = self.chainbase(rev)
if self._generaldelta:
base = rev
else:
base = chainbase
# Refuse to build delta if deltabase rev has a non-zero flag
if self.flags(base):
return None
# can we use the cached delta?
if cachedelta and cachedelta[0] == rev:
delta = cachedelta[1]
@ -1923,12 +1931,7 @@ class revlog(object):
delta = mdiff.textdiff(ptext, t)
header, data = self.compress(delta)
deltalen = len(header) + len(data)
chainbase = self.chainbase(rev)
dist = deltalen + offset - self.start(chainbase)
if self._generaldelta:
base = rev
else:
base = chainbase
chainlen, compresseddeltalen = self._chaininfo(rev)
chainlen += 1
compresseddeltalen += deltalen
@ -1950,7 +1953,7 @@ class revlog(object):
textlen = len(rawtext)
# should we try to build a delta?
if prev != nullrev and self.storedeltachains:
if prev != nullrev and self.storedeltachains and not flags:
tested = set()
# This condition is true most of the time when processing
# changegroup data into a generaldelta repo. The only time it

View File

@ -90,11 +90,11 @@ XXX: shallow bundle application is broken (seems to be infinite loop)
X: bin=0 lnk=0 flag=2000 size=41 copied='' chain=e59d6c47cda0
Y: bin=0 lnk=0 flag=2000 size=41 copied='' chain=583fc1cb5a72
9f4445d5e0fc: Y
X: bin=0 lnk=0 flag=2000 size=42 copied='Y' chain=e59d6c47cda0,c6fdd3c3ab39
Y: bin=0 lnk=0 flag=2000 size=42 copied='X' chain=583fc1cb5a72,88c7303c7f80
X: bin=0 lnk=0 flag=2000 size=42 copied='Y' chain=c6fdd3c3ab39
Y: bin=0 lnk=0 flag=2000 size=42 copied='X' chain=88c7303c7f80
c73835eb729c: Z
X: bin=0 lnk=0 flag=2000 size=41 copied='Y' chain=e59d6c47cda0,c6fdd3c3ab39,5322d1c20036
Y: bin=0 lnk=0 flag=2000 size=41 copied='X' chain=583fc1cb5a72,88c7303c7f80,78eb25c15608
X: bin=0 lnk=0 flag=2000 size=41 copied='Y' chain=5322d1c20036
Y: bin=0 lnk=0 flag=2000 size=41 copied='X' chain=78eb25c15608
Z: bin=0 lnk=0 flag=2000 size=3 copied='' chain=0ad6e257ad34
Note: full normal repo has a wrong size=45 where it should be 41, see XXX note
@ -150,11 +150,10 @@ Apply bundles
Y: bin=0 lnk=0 flag=0 size=41 copied='X' chain=583fc1cb5a72,88c7303c7f80,78eb25c15608
Z: bin=0 lnk=0 flag=0 size=7 copied='' chain=0ad6e257ad34
---- Applying src-full-normal.bundle to dst-full-lfs ----
CRASHED!
9f4445d5e0fc: Y
X: bin=0 lnk=0 flag=2000 size=42 copied='Y' chain=e59d6c47cda0,c6fdd3c3ab39
Y: bin=0 lnk=0 flag=2000 size=42 copied='X' chain=583fc1cb5a72,88c7303c7f80
c73835eb729c: Z
abort: integrity check failed on data/X.i:2!
X: bin=0 lnk=0 flag=2000 size=42 copied='Y' chain=c6fdd3c3ab39
Y: bin=0 lnk=0 flag=2000 size=42 copied='X' chain=88c7303c7f80
---- Applying src-full-lfs.bundle to dst-shallow-normal ----
9f4445d5e0fc: Y
X: bin=0 lnk=0 flag=2000 size=207 copied='' chain=c6fdd3c3ab39
@ -176,14 +175,14 @@ Apply bundles
X: bin=0 lnk=0 flag=0 size=42 copied='Y' chain=e59d6c47cda0,c6fdd3c3ab39
Y: bin=0 lnk=0 flag=0 size=42 copied='X' chain=583fc1cb5a72,88c7303c7f80
c73835eb729c: Z
X: bin=0 lnk=0 flag=2000 size=41 copied='Y' chain=000000000000,5322d1c20036
Y: bin=0 lnk=0 flag=2000 size=41 copied='X' chain=000000000000,78eb25c15608
X: bin=0 lnk=0 flag=2000 size=41 copied='Y' chain=5322d1c20036
Y: bin=0 lnk=0 flag=2000 size=41 copied='X' chain=78eb25c15608
Z: bin=0 lnk=0 flag=2000 size=3 copied='' chain=0ad6e257ad34
---- Applying src-full-lfs.bundle to dst-full-lfs ----
9f4445d5e0fc: Y
X: bin=0 lnk=0 flag=2000 size=42 copied='Y' chain=e59d6c47cda0,c6fdd3c3ab39
Y: bin=0 lnk=0 flag=2000 size=42 copied='X' chain=583fc1cb5a72,88c7303c7f80
X: bin=0 lnk=0 flag=2000 size=42 copied='Y' chain=c6fdd3c3ab39
Y: bin=0 lnk=0 flag=2000 size=42 copied='X' chain=88c7303c7f80
c73835eb729c: Z
X: bin=0 lnk=0 flag=2000 size=41 copied='Y' chain=000000000000,5322d1c20036
Y: bin=0 lnk=0 flag=2000 size=41 copied='X' chain=000000000000,78eb25c15608
X: bin=0 lnk=0 flag=2000 size=41 copied='Y' chain=5322d1c20036
Y: bin=0 lnk=0 flag=2000 size=41 copied='X' chain=78eb25c15608
Z: bin=0 lnk=0 flag=2000 size=3 copied='' chain=0ad6e257ad34

View File

@ -158,12 +158,12 @@
s: bin=0 lnk=0 flag=0 size=8 copied='small' chain=594f4fdf95ce
e8e237bfd98f: large to small, small to large
l: bin=0 lnk=0 flag=0 size=6 copied='' chain=b484bd96359a
s: bin=0 lnk=0 flag=2000 size=27 copied='' chain=594f4fdf95ce,2521c65ce463
s: bin=0 lnk=0 flag=2000 size=27 copied='' chain=2521c65ce463
15c00ca48977: random modifications
l: bin=0 lnk=0 flag=0 size=8 copied='' chain=8f150b4b7e9f
s: bin=0 lnk=0 flag=2000 size=29 copied='' chain=552783341059
5adf850972b9: switch large and small again
l: bin=0 lnk=0 flag=2000 size=20 copied='' chain=8f150b4b7e9f,6f1ff1f39c11
l: bin=0 lnk=0 flag=2000 size=20 copied='' chain=6f1ff1f39c11
s: bin=0 lnk=0 flag=0 size=8 copied='' chain=0c1fa52a67c6
# Test lfs_files template
@ -279,12 +279,12 @@
9cd6bdffdac0: b
a1: bin=0 lnk=0 flag=0 size=6 copied='a2' chain=0d759f317f5a
rawdata: '\x01\ncopy: a2\ncopyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9\n\x01\nSMALL\n'
a2: bin=0 lnk=0 flag=2000 size=29 copied='a1' chain=50470ad23cf9,b982e9429db8
a2: bin=0 lnk=0 flag=2000 size=29 copied='a1' chain=b982e9429db8
rawdata: 'version https://git-lfs.github.com/spec/v1\noid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024\nsize 29\nx-hg-copy a1\nx-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4\nx-is-binary 0\n'
0fae949de7fa: meta
a1: bin=0 lnk=0 flag=0 size=11 copied='' chain=0984adb90885
rawdata: '\x01\n\x01\n\x01\nMETA\n'
a2: bin=0 lnk=0 flag=2000 size=32 copied='' chain=50470ad23cf9,b982e9429db8,7691bcc594f0
a2: bin=0 lnk=0 flag=2000 size=32 copied='' chain=7691bcc594f0
rawdata: 'version https://git-lfs.github.com/spec/v1\noid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943\nsize 32\nx-is-binary 0\n'
$ cd ..

View File

@ -20,7 +20,7 @@ tvfs.options = {'generaldelta': True, 'revlogv1': True}
# The test wants to control whether to use delta explicitly, based on
# "storedeltachains".
revlog.revlog._isgooddelta = lambda self, d, textlen: self.storedeltachains
revlog.revlog._isgooddelta = lambda self, d, tlen: d and self.storedeltachains
def abort(msg):
print('abort: %s' % msg)
@ -114,6 +114,8 @@ def addgroupcopy(rlog, tr, destname=b'_destrevlog.i', optimaldelta=True):
else:
# suboptimal deltaparent
deltaparent = min(0, parentrev)
if not rlog.candelta(deltaparent, r):
deltaparent = -1
return {'node': rlog.node(r), 'p1': pnode, 'p2': node.nullid,
'cs': rlog.node(rlog.linkrev(r)), 'flags': rlog.flags(r),
'deltabase': rlog.node(deltaparent),
@ -151,12 +153,12 @@ def lowlevelcopy(rlog, tr, destname=b'_destrevlog.i'):
for r in rlog:
p1 = rlog.node(r - 1)
p2 = node.nullid
if r == 0:
if r == 0 or rlog.flags(r):
text = rlog.revision(r, raw=True)
cachedelta = None
else:
# deltaparent is more interesting if it has the EXTSTORED flag.
deltaparent = max([0] + [p for p in range(r - 2) if rlog.flags(p)])
# deltaparent cannot have EXTSTORED flag.
deltaparent = max([-1] + [p for p in range(r) if not rlog.flags(p)])
text = None
cachedelta = (deltaparent, rlog.revdiff(deltaparent, r))
flags = rlog.flags(r)
@ -262,8 +264,9 @@ def writecases(rlog, tr):
result.append((text, rawtext))
# Verify flags like isdelta, isext work as expected
if bool(rlog.deltaparent(rev) > -1) != isdelta:
abort('rev %d: isdelta is ineffective' % rev)
# isdelta can be overridden to False if this or p1 has isext set
if bool(rlog.deltaparent(rev) > -1) and not isdelta:
abort('rev %d: isdelta is unexpected' % rev)
if bool(rlog.flags(rev)) != isext:
abort('rev %d: isext is ineffective' % rev)
return result