2013-06-21 21:14:29 +04:00
|
|
|
# shallowrepo.py - shallow repository that uses remote filelogs
|
2013-05-18 05:08:53 +04:00
|
|
|
#
|
|
|
|
# Copyright 2013 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.
|
|
|
|
|
2013-06-13 04:56:18 +04:00
|
|
|
from mercurial.node import hex, nullid, bin
|
2013-05-18 05:08:53 +04:00
|
|
|
from mercurial.i18n import _
|
2013-06-13 04:56:18 +04:00
|
|
|
from mercurial import localrepo, context, mdiff, util
|
2013-05-21 02:03:07 +04:00
|
|
|
import remotefilelog
|
|
|
|
import remotefilectx
|
|
|
|
|
2013-06-12 03:41:55 +04:00
|
|
|
def wraprepo(repo):
|
2013-05-21 02:03:07 +04:00
|
|
|
class shallowrepository(repo.__class__):
|
|
|
|
def file(self, f):
|
|
|
|
if f[0] == '/':
|
|
|
|
f = f[1:]
|
2013-06-12 03:41:55 +04:00
|
|
|
return remotefilelog.remotefilelog(self.sopener, f, self)
|
2013-05-21 02:03:07 +04:00
|
|
|
|
|
|
|
def filectx(self, path, changeid=None, fileid=None):
|
|
|
|
"""changeid can be a changeset revision, node, or tag.
|
|
|
|
fileid can be a file revision or node."""
|
|
|
|
return remotefilectx.remotefilectx(self, path, changeid, fileid)
|
|
|
|
|
|
|
|
def addchangegroupfiles(self, source, revmap, trp, pr, needfiles):
|
|
|
|
files = 0
|
|
|
|
visited = set()
|
2013-06-13 04:56:18 +04:00
|
|
|
revisiondatas = {}
|
|
|
|
queue = []
|
2013-05-21 02:03:07 +04:00
|
|
|
|
|
|
|
# read all the file chunks but don't add them
|
|
|
|
while True:
|
|
|
|
chunkdata = source.filelogheader()
|
|
|
|
if not chunkdata:
|
|
|
|
break
|
|
|
|
f = chunkdata["filename"]
|
|
|
|
self.ui.debug("adding %s revisions\n" % f)
|
|
|
|
pr()
|
|
|
|
chain = None
|
|
|
|
while True:
|
|
|
|
revisiondata = source.deltachunk(chain)
|
|
|
|
if not revisiondata:
|
|
|
|
break
|
|
|
|
|
|
|
|
chain = revisiondata['node']
|
|
|
|
|
2013-06-13 04:56:18 +04:00
|
|
|
revisiondatas[(f, chain)] = revisiondata
|
|
|
|
queue.append((f, chain))
|
2013-05-21 02:03:07 +04:00
|
|
|
|
|
|
|
if f not in visited:
|
|
|
|
files += 1
|
|
|
|
visited.add(f)
|
|
|
|
|
|
|
|
if chain == None:
|
|
|
|
raise util.Abort(_("received file revlog group is empty"))
|
|
|
|
|
2013-06-13 04:56:18 +04:00
|
|
|
processed = set()
|
|
|
|
def available(f, node, depf, depnode):
|
|
|
|
if depnode != nullid and (depf, depnode) not in processed:
|
|
|
|
if not (depf, depnode) in revisiondatas:
|
|
|
|
# It's not in the changegroup, assume it's already
|
|
|
|
# in the repo
|
|
|
|
return True
|
|
|
|
# re-add self to queue
|
|
|
|
queue.insert(0, (f, node))
|
|
|
|
# add dependency in front
|
|
|
|
queue.insert(0, (depf, depnode))
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
skipcount = 0
|
|
|
|
|
|
|
|
while queue:
|
|
|
|
f, node = queue.pop(0)
|
|
|
|
if (f, node) in processed:
|
|
|
|
continue
|
|
|
|
|
|
|
|
skipcount += 1
|
|
|
|
if skipcount > len(queue) + 1:
|
|
|
|
raise util.Abort(_("circular node dependency"))
|
2013-05-21 02:03:07 +04:00
|
|
|
|
|
|
|
fl = self.file(f)
|
|
|
|
|
2013-06-13 04:56:18 +04:00
|
|
|
revisiondata = revisiondatas[(f, node)]
|
2013-05-21 02:03:07 +04:00
|
|
|
p1 = revisiondata['p1']
|
|
|
|
p2 = revisiondata['p2']
|
|
|
|
linknode = revisiondata['cs']
|
|
|
|
deltabase = revisiondata['deltabase']
|
|
|
|
delta = revisiondata['delta']
|
|
|
|
|
2013-06-13 04:56:18 +04:00
|
|
|
if not available(f, node, f, deltabase):
|
|
|
|
continue
|
|
|
|
|
2013-05-21 02:03:07 +04:00
|
|
|
base = fl.revision(deltabase)
|
|
|
|
text = mdiff.patch(base, delta)
|
|
|
|
if isinstance(text, buffer):
|
|
|
|
text = str(text)
|
|
|
|
|
|
|
|
meta, text = remotefilelog._parsemeta(text)
|
2013-06-13 04:56:18 +04:00
|
|
|
if 'copy' in meta:
|
|
|
|
copyfrom = meta['copy']
|
|
|
|
copynode = bin(meta['copyrev'])
|
|
|
|
copyfl = self.file(copyfrom)
|
|
|
|
if not available(f, node, copyfrom, copynode):
|
|
|
|
continue
|
|
|
|
|
|
|
|
for p in [p1, p2]:
|
|
|
|
if p != nullid:
|
|
|
|
if not available(f, node, f, p):
|
|
|
|
continue
|
|
|
|
|
2013-05-21 02:03:07 +04:00
|
|
|
fl.add(text, meta, trp, linknode, p1, p2)
|
2013-06-13 04:56:18 +04:00
|
|
|
processed.add((f, node))
|
|
|
|
skipcount = 0
|
2013-05-21 02:03:07 +04:00
|
|
|
|
|
|
|
self.ui.progress(_('files'), None)
|
|
|
|
|
|
|
|
return len(revisiondatas), files
|
|
|
|
|
|
|
|
repo.__class__ = shallowrepository
|