Show More
@@ -60,10 +60,8 b' def _packellipsischangegroup(repo, commo' | |||||
60 | # set, we know we have an ellipsis node and we should defer |
|
60 | # set, we know we have an ellipsis node and we should defer | |
61 | # sending that node's data. We override close() to detect |
|
61 | # sending that node's data. We override close() to detect | |
62 | # pending ellipsis nodes and flush them. |
|
62 | # pending ellipsis nodes and flush them. | |
63 |
packer = changegroup.getbundler(version, repo |
|
63 | packer = changegroup.getbundler(version, repo, | |
64 | # Let the packer have access to the narrow matcher so it can |
|
64 | filematcher=match) | |
65 | # omit filelogs and dirlogs as needed |
|
|||
66 | packer._narrow_matcher = lambda : match |
|
|||
67 | # Give the packer the list of nodes which should not be |
|
65 | # Give the packer the list of nodes which should not be | |
68 | # ellipsis nodes. We store this rather than the set of nodes |
|
66 | # ellipsis nodes. We store this rather than the set of nodes | |
69 | # that should be an ellipsis because for very large histories |
|
67 | # that should be an ellipsis because for very large histories | |
@@ -107,13 +105,9 b' def getbundlechangegrouppart_narrow(bund' | |||||
107 | outgoing = exchange._computeoutgoing(repo, heads, common) |
|
105 | outgoing = exchange._computeoutgoing(repo, heads, common) | |
108 | if not outgoing.missing: |
|
106 | if not outgoing.missing: | |
109 | return |
|
107 | return | |
110 | def wrappedgetbundler(orig, *args, **kwargs): |
|
108 | ||
111 | bundler = orig(*args, **kwargs) |
|
109 | cg = changegroup.makestream(repo, outgoing, version, source, | |
112 | bundler._narrow_matcher = lambda : newmatch |
|
110 | filematcher=newmatch) | |
113 | return bundler |
|
|||
114 | with extensions.wrappedfunction(changegroup, 'getbundler', |
|
|||
115 | wrappedgetbundler): |
|
|||
116 | cg = changegroup.makestream(repo, outgoing, version, source) |
|
|||
117 | part = bundler.newpart('changegroup', data=cg) |
|
111 | part = bundler.newpart('changegroup', data=cg) | |
118 | part.addparam('version', version) |
|
112 | part.addparam('version', version) | |
119 | if 'treemanifest' in repo.requirements: |
|
113 | if 'treemanifest' in repo.requirements: |
@@ -13,7 +13,6 b' from mercurial import (' | |||||
13 | error, |
|
13 | error, | |
14 | extensions, |
|
14 | extensions, | |
15 | manifest, |
|
15 | manifest, | |
16 | match as matchmod, |
|
|||
17 | mdiff, |
|
16 | mdiff, | |
18 | node, |
|
17 | node, | |
19 | pycompat, |
|
18 | pycompat, | |
@@ -22,30 +21,19 b' from mercurial import (' | |||||
22 | ) |
|
21 | ) | |
23 |
|
22 | |||
24 | def setup(): |
|
23 | def setup(): | |
25 |
|
||||
26 | def _cgmatcher(cgpacker): |
|
|||
27 | localmatcher = cgpacker._repo.narrowmatch() |
|
|||
28 | remotematcher = getattr(cgpacker, '_narrow_matcher', lambda: None)() |
|
|||
29 | if remotematcher: |
|
|||
30 | return matchmod.intersectmatchers(localmatcher, remotematcher) |
|
|||
31 | else: |
|
|||
32 | return localmatcher |
|
|||
33 |
|
||||
34 | def prune(orig, self, revlog, missing, commonrevs): |
|
24 | def prune(orig, self, revlog, missing, commonrevs): | |
35 | if isinstance(revlog, manifest.manifestrevlog): |
|
25 | if isinstance(revlog, manifest.manifestrevlog): | |
36 | matcher = _cgmatcher(self) |
|
26 | if not self._filematcher.visitdir(revlog._dir[:-1] or '.'): | |
37 | if (matcher and |
|
|||
38 | not matcher.visitdir(revlog._dir[:-1] or '.')): |
|
|||
39 | return [] |
|
27 | return [] | |
|
28 | ||||
40 | return orig(self, revlog, missing, commonrevs) |
|
29 | return orig(self, revlog, missing, commonrevs) | |
41 |
|
30 | |||
42 | extensions.wrapfunction(changegroup.cg1packer, 'prune', prune) |
|
31 | extensions.wrapfunction(changegroup.cg1packer, 'prune', prune) | |
43 |
|
32 | |||
44 | def generatefiles(orig, self, changedfiles, linknodes, commonrevs, |
|
33 | def generatefiles(orig, self, changedfiles, linknodes, commonrevs, | |
45 | source): |
|
34 | source): | |
46 | matcher = _cgmatcher(self) |
|
35 | changedfiles = list(filter(self._filematcher, changedfiles)) | |
47 | if matcher: |
|
36 | ||
48 | changedfiles = list(filter(matcher, changedfiles)) |
|
|||
49 | if getattr(self, 'is_shallow', False): |
|
37 | if getattr(self, 'is_shallow', False): | |
50 | # See comment in generate() for why this sadness is a thing. |
|
38 | # See comment in generate() for why this sadness is a thing. | |
51 | mfdicts = self._mfdicts |
|
39 | mfdicts = self._mfdicts |
@@ -21,6 +21,7 b' from .node import (' | |||||
21 | from . import ( |
|
21 | from . import ( | |
22 | dagutil, |
|
22 | dagutil, | |
23 | error, |
|
23 | error, | |
|
24 | match as matchmod, | |||
24 | mdiff, |
|
25 | mdiff, | |
25 | phases, |
|
26 | phases, | |
26 | pycompat, |
|
27 | pycompat, | |
@@ -496,14 +497,20 b' class headerlessfixup(object):' | |||||
496 | class cg1packer(object): |
|
497 | class cg1packer(object): | |
497 | deltaheader = _CHANGEGROUPV1_DELTA_HEADER |
|
498 | deltaheader = _CHANGEGROUPV1_DELTA_HEADER | |
498 | version = '01' |
|
499 | version = '01' | |
499 | def __init__(self, repo, bundlecaps=None): |
|
500 | def __init__(self, repo, filematcher, bundlecaps=None): | |
500 | """Given a source repo, construct a bundler. |
|
501 | """Given a source repo, construct a bundler. | |
501 |
|
502 | |||
|
503 | filematcher is a matcher that matches on files to include in the | |||
|
504 | changegroup. Used to facilitate sparse changegroups. | |||
|
505 | ||||
502 | bundlecaps is optional and can be used to specify the set of |
|
506 | bundlecaps is optional and can be used to specify the set of | |
503 | capabilities which can be used to build the bundle. While bundlecaps is |
|
507 | capabilities which can be used to build the bundle. While bundlecaps is | |
504 | unused in core Mercurial, extensions rely on this feature to communicate |
|
508 | unused in core Mercurial, extensions rely on this feature to communicate | |
505 | capabilities to customize the changegroup packer. |
|
509 | capabilities to customize the changegroup packer. | |
506 | """ |
|
510 | """ | |
|
511 | assert filematcher | |||
|
512 | self._filematcher = filematcher | |||
|
513 | ||||
507 | # Set of capabilities we can use to build the bundle. |
|
514 | # Set of capabilities we can use to build the bundle. | |
508 | if bundlecaps is None: |
|
515 | if bundlecaps is None: | |
509 | bundlecaps = set() |
|
516 | bundlecaps = set() | |
@@ -813,8 +820,10 b' class cg2packer(cg1packer):' | |||||
813 | version = '02' |
|
820 | version = '02' | |
814 | deltaheader = _CHANGEGROUPV2_DELTA_HEADER |
|
821 | deltaheader = _CHANGEGROUPV2_DELTA_HEADER | |
815 |
|
822 | |||
816 | def __init__(self, repo, bundlecaps=None): |
|
823 | def __init__(self, repo, filematcher, bundlecaps=None): | |
817 |
super(cg2packer, self).__init__(repo, |
|
824 | super(cg2packer, self).__init__(repo, filematcher, | |
|
825 | bundlecaps=bundlecaps) | |||
|
826 | ||||
818 | if self._reorder is None: |
|
827 | if self._reorder is None: | |
819 | # Since generaldelta is directly supported by cg2, reordering |
|
828 | # Since generaldelta is directly supported by cg2, reordering | |
820 | # generally doesn't help, so we disable it by default (treating |
|
829 | # generally doesn't help, so we disable it by default (treating | |
@@ -927,9 +936,23 b' def safeversion(repo):' | |||||
927 | assert versions |
|
936 | assert versions | |
928 | return min(versions) |
|
937 | return min(versions) | |
929 |
|
938 | |||
930 | def getbundler(version, repo, bundlecaps=None): |
|
939 | def getbundler(version, repo, bundlecaps=None, filematcher=None): | |
931 | assert version in supportedoutgoingversions(repo) |
|
940 | assert version in supportedoutgoingversions(repo) | |
932 | return _packermap[version][0](repo, bundlecaps) |
|
941 | ||
|
942 | if filematcher is None: | |||
|
943 | filematcher = matchmod.alwaysmatcher(repo.root, '') | |||
|
944 | ||||
|
945 | if version == '01' and not filematcher.always(): | |||
|
946 | raise error.ProgrammingError('version 01 changegroups do not support ' | |||
|
947 | 'sparse file matchers') | |||
|
948 | ||||
|
949 | # Requested files could include files not in the local store. So | |||
|
950 | # filter those out. | |||
|
951 | filematcher = matchmod.intersectmatchers(repo.narrowmatch(), | |||
|
952 | filematcher) | |||
|
953 | ||||
|
954 | return _packermap[version][0](repo, filematcher=filematcher, | |||
|
955 | bundlecaps=bundlecaps) | |||
933 |
|
956 | |||
934 | def getunbundler(version, fh, alg, extras=None): |
|
957 | def getunbundler(version, fh, alg, extras=None): | |
935 | return _packermap[version][1](fh, alg, extras=extras) |
|
958 | return _packermap[version][1](fh, alg, extras=extras) | |
@@ -950,8 +973,9 b' def makechangegroup(repo, outgoing, vers' | |||||
950 | {'clcount': len(outgoing.missing) }) |
|
973 | {'clcount': len(outgoing.missing) }) | |
951 |
|
974 | |||
952 | def makestream(repo, outgoing, version, source, fastpath=False, |
|
975 | def makestream(repo, outgoing, version, source, fastpath=False, | |
953 | bundlecaps=None): |
|
976 | bundlecaps=None, filematcher=None): | |
954 |
bundler = getbundler(version, repo, bundlecaps=bundlecaps |
|
977 | bundler = getbundler(version, repo, bundlecaps=bundlecaps, | |
|
978 | filematcher=filematcher) | |||
955 |
|
979 | |||
956 | repo = repo.unfiltered() |
|
980 | repo = repo.unfiltered() | |
957 | commonrevs = outgoing.common |
|
981 | commonrevs = outgoing.common |
General Comments 0
You need to be logged in to leave comments.
Login now