mercurial/exchangev2.py
changeset 40327 55836a34f41b
parent 40179 b843356d4ae1
child 40330 00a4cd368e3f
--- a/mercurial/exchangev2.py	Tue Oct 09 08:50:13 2018 -0700
+++ b/mercurial/exchangev2.py	Wed Sep 26 14:38:43 2018 -0700
@@ -19,6 +19,7 @@
     bookmarks,
     error,
     mdiff,
+    narrowspec,
     phases,
     pycompat,
     setdiscovery,
@@ -30,6 +31,23 @@
     remote = pullop.remote
     tr = pullop.trmanager.transaction()
 
+    # We don't use the repo's narrow matcher here because the patterns passed
+    # to exchange.pull() could be different.
+    narrowmatcher = narrowspec.match(repo.root,
+                                     # Empty maps to nevermatcher. So always
+                                     # set includes if missing.
+                                     pullop.includepats or {'path:.'},
+                                     pullop.excludepats)
+
+    if pullop.includepats or pullop.excludepats:
+        pathfilter = {}
+        if pullop.includepats:
+            pathfilter[b'include'] = sorted(pullop.includepats)
+        if pullop.excludepats:
+            pathfilter[b'exclude'] = sorted(pullop.excludepats)
+    else:
+        pathfilter = None
+
     # Figure out what needs to be fetched.
     common, fetch, remoteheads = _pullchangesetdiscovery(
         repo, remote, pullop.heads, abortwhenunrelated=pullop.force)
@@ -63,8 +81,8 @@
 
     # Find all file nodes referenced by added manifests and fetch those
     # revisions.
-    fnodes = _derivefilesfrommanifests(repo, manres['added'])
-    _fetchfilesfromcsets(repo, tr, remote, fnodes, csetres['added'],
+    fnodes = _derivefilesfrommanifests(repo, narrowmatcher, manres['added'])
+    _fetchfilesfromcsets(repo, tr, remote, pathfilter, fnodes, csetres['added'],
                          manres['linkrevs'])
 
 def _pullchangesetdiscovery(repo, remote, heads, abortwhenunrelated=True):
@@ -315,7 +333,7 @@
         'linkrevs': linkrevs,
     }
 
-def _derivefilesfrommanifests(repo, manifestnodes):
+def _derivefilesfrommanifests(repo, matcher, manifestnodes):
     """Determine what file nodes are relevant given a set of manifest nodes.
 
     Returns a dict mapping file paths to dicts of file node to first manifest
@@ -340,7 +358,8 @@
             md = m.readfast()
 
             for path, fnode in md.items():
-                fnodes[path].setdefault(fnode, manifestnode)
+                if matcher(path):
+                    fnodes[path].setdefault(fnode, manifestnode)
 
             progress.increment()
 
@@ -421,7 +440,8 @@
                     locallinkrevs[path].__getitem__,
                     weakref.proxy(tr))
 
-def _fetchfilesfromcsets(repo, tr, remote, fnodes, csets, manlinkrevs):
+def _fetchfilesfromcsets(repo, tr, remote, pathfilter, fnodes, csets,
+                         manlinkrevs):
     """Fetch file data from explicit changeset revisions."""
 
     def iterrevisions(objs, remaining, progress):
@@ -481,6 +501,9 @@
                 b'haveparents': True,
             }
 
+            if pathfilter:
+                args[b'pathfilter'] = pathfilter
+
             objs = e.callcommand(b'filesdata', args).result()
 
             # First object is an overall header.