sapling/remotefilelog/wirepack.py
Durham Goode c8c72f8201 packs: add progress bar to receiving pack files
Summary:
This adds a simple progress bar while the client receives a pack.  We don't know
ahead of time how large it will be, so we can only provide the bouncy bar kind.
But we can show an increasing number of things downloaded, so they know
something is actually happening.

Test Plan:
Ran hg pull with the extension enabled, verified there was a progress
bar during the tree prefetch.

Reviewers: #mercurial, quark

Reviewed By: quark

Subscribers: mjpieters

Differential Revision: https://phabricator.intern.facebook.com/D5098564

Signature: t1:5098564:1495235358:0020b28da890813f11dba70b157e526e7be418f8
2017-05-21 17:09:08 -07:00

112 lines
3.8 KiB
Python

# wirepack.py - wireprotocol for exchanging packs
#
# Copyright 2017 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from mercurial.i18n import _
from mercurial.node import nullid
import constants
import struct
from collections import defaultdict
from shallowutil import readexactly, readunpack, mkstickygroupdir, readpath
import datapack, historypack, shallowutil
def sendpackpart(filename, history, data):
rawfilenamelen = struct.pack(constants.FILENAMESTRUCT,
len(filename))
yield '%s%s' % (rawfilenamelen, filename)
# Serialize and send history
historylen = struct.pack('!I', len(history))
rawhistory = ''
for entry in history:
copyfrom = entry[4] or ''
copyfromlen = len(copyfrom)
tup = entry[:-1] + (copyfromlen,)
rawhistory += struct.pack('!20s20s20s20sH', *tup)
if copyfrom:
rawhistory += copyfrom
yield '%s%s' % (historylen, rawhistory)
# Serialize and send data
yield struct.pack('!I', len(data))
for node, deltabase, delta in data:
deltalen = struct.pack('!Q', len(delta))
yield '%s%s%s%s' % (node, deltabase, deltalen, delta)
def closepart():
return '\0' * 10
def receivepack(ui, fh, packpath):
receiveddata = []
receivedhistory = []
mkstickygroupdir(ui, packpath)
totalcount = 0
ui.progress(_("receiving pack"), totalcount)
with datapack.mutabledatapack(ui, packpath) as dpack:
with historypack.mutablehistorypack(ui, packpath) as hpack:
pendinghistory = defaultdict(dict)
while True:
filename = readpath(fh)
count = 0
# Store the history for later sorting
for value in readhistory(fh):
node = value[0]
pendinghistory[filename][node] = value
receivedhistory.append((filename, node))
count += 1
for node, deltabase, delta in readdeltas(fh):
dpack.add(filename, node, deltabase, delta)
receiveddata.append((filename, node))
count += 1
if count == 0 and filename == '':
break
totalcount += 1
ui.progress(_("receiving pack"), totalcount)
# Add history to pack in toposorted order
for filename, nodevalues in sorted(pendinghistory.iteritems()):
def _parentfunc(node):
p1, p2 = nodevalues[node][1:3]
parents = []
if p1 != nullid:
parents.append(p1)
if p2 != nullid:
parents.append(p2)
return parents
sortednodes = reversed(shallowutil.sortnodes(
nodevalues.iterkeys(),
_parentfunc))
for node in sortednodes:
node, p1, p2, linknode, copyfrom = nodevalues[node]
hpack.add(filename, node, p1, p2, linknode, copyfrom)
ui.progress(_("receiving pack"), None)
return receiveddata, receivedhistory
def readhistory(fh):
count = readunpack(fh, '!I')[0]
for i in xrange(count):
entry = readunpack(fh,'!20s20s20s20sH')
if entry[4] != 0:
copyfrom = readexactly(fh, entry[4])
else:
copyfrom = ''
entry = entry[:4] + (copyfrom,)
yield entry
def readdeltas(fh):
count = readunpack(fh, '!I')[0]
for i in xrange(count):
node, deltabase, deltalen = readunpack(fh, '!20s20sQ')
delta = readexactly(fh, deltalen)
yield (node, deltabase, delta)