[PATCH 5 of 5] changegroup: introduce cg2packer/unpacker
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Tue Nov 4 08:20:48 CST 2014
# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1413549671 -7200
# Fri Oct 17 14:41:11 2014 +0200
# Node ID d86e8a57e2070d2213d80d26b2000d3a626d157c
# Parent 7407e3ea154921922956cbaf2e7ff0d89d48634c
changegroup: introduce cg2packer/unpacker
cg2 supports generaldelta in changegroups, to be used in bundle2.
Since generaldelta is handled directly in cg2, reordering is switched
off by default.
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -11,10 +11,11 @@ from node import nullrev, nullid, hex, s
import mdiff, util, dagutil
import struct, os, bz2, zlib, tempfile
import discovery, error, phases, branchmap
_CHANGEGROUPV1_DELTA_HEADER = "20s20s20s20s"
+_CHANGEGROUPV2_DELTA_HEADER = "20s20s20s20s20s"
def readexactly(stream, n):
'''read n bytes from stream.read and abort if less was available'''
s = stream.read(n)
if len(s) < n:
@@ -213,10 +214,19 @@ class cg1unpacker(object):
next = pos + 2**20
yield chunk[pos:next]
pos = next
yield closechunk()
+class cg2unpacker(cg1unpacker):
+ deltaheader = _CHANGEGROUPV2_DELTA_HEADER
+ deltaheadersize = struct.calcsize(deltaheader)
+
+ def _deltaheader(self, headertuple, prevnode):
+ node, p1, p2, deltabase, cs = headertuple
+ return node, p1, p2, deltabase, cs
+
+
class headerlessfixup(object):
def __init__(self, fh, h):
self._h = h
self._fh = fh
def read(self, n):
@@ -408,14 +418,17 @@ class cg1packer(object):
yield self.fileheader(fname)
for chunk in self.group(filenodes, filerevlog, lookupfilelog,
reorder=reorder):
yield chunk
+ def deltaparent(self, revlog, rev, p1, p2, prev):
+ return prev
+
def revchunk(self, revlog, rev, prev, linknode):
node = revlog.node(rev)
p1, p2 = revlog.parentrevs(rev)
- base = prev
+ base = self.deltaparent(revlog, rev, p1, p2, prev)
prefix = ''
if base == nullrev:
delta = revlog.revision(node)
prefix = mdiff.trivialdiffheader(len(delta))
@@ -431,11 +444,33 @@ class cg1packer(object):
yield delta
def builddeltaheader(self, node, p1n, p2n, basenode, linknode):
# do nothing with basenode, it is implicitly the previous one in HG10
return struct.pack(self.deltaheader, node, p1n, p2n, linknode)
-packermap = {'01': (cg1packer, cg1unpacker)}
+class cg2packer(cg1packer):
+
+ deltaheader = _CHANGEGROUPV2_DELTA_HEADER
+
+ def group(self, nodelist, revlog, lookup, units=None, reorder=None):
+ if (revlog._generaldelta and reorder is not True):
+ reorder = False
+ return cg1packer.group(self, nodelist, revlog, lookup,
+ units=units, reorder=reorder)
+
+ def deltaparent(self, revlog, rev, p1, p2, prev):
+ dp = revlog.deltaparent(rev)
+ # avoid storing full revisions; pick prev in those cases
+ # also pick prev when we can't be sure remote has dp
+ if dp == nullrev or (dp != p1 and dp != p2 and dp != prev):
+ return prev
+ return dp
+
+ def builddeltaheader(self, node, p1n, p2n, basenode, linknode):
+ return struct.pack(self.deltaheader, node, p1n, p2n, basenode, linknode)
+
+packermap = {'01': (cg1packer, cg1unpacker),
+ '02': (cg2packer, cg2unpacker)}
def _changegroupinfo(repo, nodes, source):
if repo.ui.verbose or source == 'bundle':
repo.ui.status(_("%d changesets found\n") % len(nodes))
if repo.ui.debugflag:
More information about the Mercurial-devel
mailing list