Skip to content
Snippets Groups Projects
Commit cfdc6f55 authored by Pierre-Yves David's avatar Pierre-Yves David :octopus:
Browse files

pullbundle: improve slicing of the lower part of range

The previous method could get confuse by merge and overslice. The new method
is better at using sticking on power of two boundaries.
parent 21a3c051
No related branches found
No related tags found
No related merge requests found
......@@ -213,6 +213,16 @@
size = rangelength(rangeid)
slices.append((rangeid, nodes[idx:idx + size]))
idx += size
### slow code block to validate ranges content
# rev = repo.changelog.nodemap.get
# for ri, ns in slices:
# a = set(rev(n) for n in ns)
# b = set(repo.stablerange.revsfromrange(repo, ri))
# l = repo.stablerange.rangelength(repo, ri)
# repo.ui.write('range-length: %d-%d %s %s\n' % (ri[0], ri[1], l, len(a)))
# if a != b:
# d = (ri[0], ri[1], b - a, a - b)
# repo.ui.write("mismatching content: %d-%d -%s +%s\n" % d)
return slices
def canonicalsubranges(repo, stablerange, rangeid):
......@@ -246,6 +256,5 @@
# 2. optimise, bottom part
if skip != cut:
tailranges = []
tailsize = cut - skip
currentsize = tailsize = cut - skip
assert 0 < tailsize, tailsize
......@@ -251,2 +260,8 @@
assert 0 < tailsize, tailsize
# we need to take several "standard cut" in the bottom part
#
# This is similar to what we will do for the top part, we reusing the
# existing structure is a bit more complex.
allcuts = list(reversed(standardcut(tailsize)))
prerange = (headrev, precut)
......@@ -252,11 +267,10 @@
prerange = (headrev, precut)
size = stablerange.rangelength(repo, prerange)
sub = stablerange.subranges(repo, prerange)[:-1]
# This power of two check is too simplistic and misbehave when too many
# merge are involved. because de merge, there can be "canonical" range
# with various size.
while not poweroftwo(tailsize):
for prerange in reversed(sub):
if tailsize <= 0:
break
### slow code block to check we operate on the right data
# rev = repo.changelog.nodemap.get
# allrevs = [rev(n) for n in nodes]
# allrevs.reverse()
# prerevs = repo.stablerange.revsfromrange(repo, prerange)
# assert allrevs == prerevs[(len(prerevs) - len(allrevs)):]
# end of check
sub = list(stablerange.subranges(repo, prerange)[:-1])
......@@ -262,22 +276,31 @@
assert stablerange.depthrev(repo, prerange[0]) != prerange[1], prerange
tailrev, tailskip = prerange
size = stablerange.rangelength(repo, (tailrev, tailskip))
if tailsize < size:
tailskip += size - tailsize
size = tailsize
tailranges.append((tailrev, tailskip))
tailsize -= size
else:
# size of the last block
tailsize = stablerange.rangelength(repo, tailranges[-1])
if poweroftwo(tailsize):
continue # exit the loop
prerange = tailranges.pop()
sub = stablerange.subranges(repo, prerange)
tailranges.reverse()
canonicals.extend(tailranges)
bottomranges = []
# XXX we might be able to reuse core stable-range logic instead of
# redoing this manually
currentrange = sub.pop()
currentsize = stablerange.rangelength(repo, currentrange)
currentcut = None
while allcuts or currentcut is not None:
# get the next cut if needed
if currentcut is None:
currentcut = allcuts.pop()
# deal attemp a cut
if currentsize == currentcut:
bottomranges.append(currentrange)
currentcut = None
elif currentsize < currentcut:
bottomranges.append(currentrange)
currentcut -= currentsize
else: # currentsize > currentcut
newskip = currentrange[1] + (currentsize - currentcut)
currentsub = stablerange._slicesrangeat(repo, currentrange, newskip)
bottomranges.append(currentsub.pop())
sub.extend(currentsub)
currentcut = None
currentrange = sub.pop()
currentsize = stablerange.rangelength(repo, currentrange)
bottomranges.reverse()
canonicals.extend(bottomranges)
# 3. take recursive subrange until we get to a power of two size?
current = (headrev, cut)
......@@ -289,6 +312,22 @@
return canonicals
def standardcut(size):
assert 0 < size
# 0. find the first power of 2 higher than this range depth
cut = 1
while cut <= size:
cut *= 2
allcuts = []
# 1. find all standard expected cut
while 1 < cut and size:
cut //= 2
if cut <= size:
allcuts.append(cut)
size -= cut
return allcuts
def poweroftwo(num):
return num and not num & (num - 1)
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment