This is how it is done everywhere else.
But the logic here is a bit more complex because shallow clone
needs to reference the original linknode implementation. But
at least now all function implementations are defined in the
same place.
hg-reviewers |
This is how it is done everywhere else.
But the logic here is a bit more complex because shallow clone
needs to reference the original linknode implementation. But
at least now all function implementations are defined in the
same place.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/changegroup.py (38 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg | ||
Closed | indygreg |
mfdicts = None | mfdicts = None | ||||
if self._ellipses and self._isshallow: | if self._ellipses and self._isshallow: | ||||
mfdicts = [(self._repo.manifestlog[n].read(), lr) | mfdicts = [(self._repo.manifestlog[n].read(), lr) | ||||
for (n, lr) in mfs.iteritems()] | for (n, lr) in mfs.iteritems()] | ||||
mfs.clear() | mfs.clear() | ||||
clrevs = set(cl.rev(x) for x in clnodes) | clrevs = set(cl.rev(x) for x in clnodes) | ||||
if not fastpathlinkrev: | for chunk in self.generatefiles(changedfiles, commonrevs, | ||||
def linknodes(unused, fname): | source, mfdicts, fastpathlinkrev, | ||||
return fnodes.get(fname, {}) | fnodes, clrevs): | ||||
else: | |||||
cln = cl.node | |||||
def linknodes(filerevlog, fname): | |||||
llr = filerevlog.linkrev | |||||
fln = filerevlog.node | |||||
revs = ((r, llr(r)) for r in filerevlog) | |||||
return dict((fln(r), cln(lr)) for r, lr in revs if lr in clrevs) | |||||
for chunk in self.generatefiles(changedfiles, linknodes, commonrevs, | |||||
source, mfdicts): | |||||
yield chunk | yield chunk | ||||
yield self._close() | yield self._close() | ||||
if clnodes: | if clnodes: | ||||
repo.hook('outgoing', node=hex(clnodes[0]), source=source) | repo.hook('outgoing', node=hex(clnodes[0]), source=source) | ||||
def _generatechangelog(self, cl, nodes): | def _generatechangelog(self, cl, nodes): | ||||
for x in self._packmanifests(dir, store, revs, lookupfn): | for x in self._packmanifests(dir, store, revs, lookupfn): | ||||
size += len(x) | size += len(x) | ||||
yield x | yield x | ||||
self._verbosenote(_('%8.i (manifests)\n') % size) | self._verbosenote(_('%8.i (manifests)\n') % size) | ||||
yield self._manifestsend | yield self._manifestsend | ||||
# The 'source' parameter is useful for extensions | # The 'source' parameter is useful for extensions | ||||
def generatefiles(self, changedfiles, linknodes, commonrevs, source, | def generatefiles(self, changedfiles, commonrevs, source, | ||||
mfdicts): | mfdicts, fastpathlinkrev, fnodes, clrevs): | ||||
changedfiles = list(filter(self._filematcher, changedfiles)) | changedfiles = list(filter(self._filematcher, changedfiles)) | ||||
if not fastpathlinkrev: | |||||
def normallinknodes(unused, fname): | |||||
return fnodes.get(fname, {}) | |||||
else: | |||||
cln = self._repo.changelog.node | |||||
def normallinknodes(store, fname): | |||||
flinkrev = store.linkrev | |||||
fnode = store.node | |||||
revs = ((r, flinkrev(r)) for r in store) | |||||
return dict((fnode(r), cln(lr)) | |||||
for r, lr in revs if lr in clrevs) | |||||
if self._isshallow: | if self._isshallow: | ||||
# In a shallow clone, the linknodes callback needs to also include | # In a shallow clone, the linknodes callback needs to also include | ||||
# those file nodes that are in the manifests we sent but weren't | # those file nodes that are in the manifests we sent but weren't | ||||
# introduced by those manifests. | # introduced by those manifests. | ||||
commonctxs = [self._repo[c] for c in commonrevs] | commonctxs = [self._repo[c] for c in commonrevs] | ||||
oldlinknodes = linknodes | |||||
clrev = self._repo.changelog.rev | clrev = self._repo.changelog.rev | ||||
# Defining this function has a side-effect of overriding the | # Defining this function has a side-effect of overriding the | ||||
# function of the same name that was passed in as an argument. | # function of the same name that was passed in as an argument. | ||||
# TODO have caller pass in appropriate function. | # TODO have caller pass in appropriate function. | ||||
def linknodes(flog, fname): | def linknodes(flog, fname): | ||||
for c in commonctxs: | for c in commonctxs: | ||||
try: | try: | ||||
fnode = c.filenode(fname) | fnode = c.filenode(fname) | ||||
self._clrevtolocalrev[c.rev()] = flog.rev(fnode) | self._clrevtolocalrev[c.rev()] = flog.rev(fnode) | ||||
except error.ManifestLookupError: | except error.ManifestLookupError: | ||||
pass | pass | ||||
links = oldlinknodes(flog, fname) | links = normallinknodes(flog, fname) | ||||
if len(links) != len(mfdicts): | if len(links) != len(mfdicts): | ||||
for mf, lr in mfdicts: | for mf, lr in mfdicts: | ||||
fnode = mf.get(fname, None) | fnode = mf.get(fname, None) | ||||
if fnode in links: | if fnode in links: | ||||
links[fnode] = min(links[fnode], lr, key=clrev) | links[fnode] = min(links[fnode], lr, key=clrev) | ||||
elif fnode: | elif fnode: | ||||
links[fnode] = lr | links[fnode] = lr | ||||
return links | return links | ||||
else: | |||||
linknodes = normallinknodes | |||||
return self._generatefiles(changedfiles, linknodes, commonrevs, source) | return self._generatefiles(changedfiles, linknodes, commonrevs, source) | ||||
def _generatefiles(self, changedfiles, linknodes, commonrevs, source): | def _generatefiles(self, changedfiles, linknodes, commonrevs, source): | ||||
repo = self._repo | repo = self._repo | ||||
cl = repo.changelog | cl = repo.changelog | ||||
progress = repo.ui.makeprogress(_('bundling'), unit=_('files'), | progress = repo.ui.makeprogress(_('bundling'), unit=_('files'), | ||||
total=len(changedfiles)) | total=len(changedfiles)) |