narrow: filter merge actions in core
authorMartin von Zweigbergk <martinvonz@google.com>
Thu, 17 May 2018 15:12:48 -0700
changeset 38044 8f37b5fc5abf
parent 38043 5989261a8356
child 38045 18e6ea9ba81d
narrow: filter merge actions in core Part of the ongoing effort to move narrow into core. Differential Revision: https://phab.mercurial-scm.org/D3574
hgext/narrow/narrowmerge.py
mercurial/merge.py
--- a/hgext/narrow/narrowmerge.py	Thu May 17 12:23:38 2018 -0700
+++ b/hgext/narrow/narrowmerge.py	Thu May 17 15:12:48 2018 -0700
@@ -7,48 +7,13 @@
 
 from __future__ import absolute_import
 
-from mercurial.i18n import _
 from mercurial import (
     copies,
-    error,
     extensions,
     merge,
 )
 
 def setup():
-    def _manifestmerge(orig, repo, wctx, p2, pa, branchmerge, *args, **kwargs):
-        """Filter updates to only lay out files that match the narrow spec."""
-        actions, diverge, renamedelete = orig(
-            repo, wctx, p2, pa, branchmerge, *args, **kwargs)
-
-        narrowmatch = repo.narrowmatch()
-        if narrowmatch.always():
-            return actions, diverge, renamedelete
-
-        nooptypes = set(['k']) # TODO: handle with nonconflicttypes
-        nonconflicttypes = set('a am c cm f g r e'.split())
-        # We mutate the items in the dict during iteration, so iterate
-        # over a copy.
-        for f, action in list(actions.items()):
-            if narrowmatch(f):
-                pass
-            elif not branchmerge:
-                del actions[f] # just updating, ignore changes outside clone
-            elif action[0] in nooptypes:
-                del actions[f] # merge does not affect file
-            elif action[0] in nonconflicttypes:
-                raise error.Abort(_('merge affects file \'%s\' outside narrow, '
-                                    'which is not yet supported') % f,
-                                  hint=_('merging in the other direction '
-                                         'may work'))
-            else:
-                raise error.Abort(_('conflict in file \'%s\' is outside '
-                                    'narrow clone') % f)
-
-        return actions, diverge, renamedelete
-
-    extensions.wrapfunction(merge, 'manifestmerge', _manifestmerge)
-
     def _checkcollision(orig, repo, wmf, actions):
         narrowmatch = repo.narrowmatch()
         if not narrowmatch.always():
--- a/mercurial/merge.py	Thu May 17 12:23:38 2018 -0700
+++ b/mercurial/merge.py	Thu May 17 15:12:48 2018 -0700
@@ -1072,6 +1072,33 @@
             repo.ui.warn(_("%s: is both a file and a directory\n") % p)
         raise error.Abort(_("destination manifest contains path conflicts"))
 
+def _filternarrowactions(narrowmatch, branchmerge, actions):
+    """
+    Filters out actions that can ignored because the repo is narrowed.
+
+    Raise an exception if the merge cannot be completed because the repo is
+    narrowed.
+    """
+    nooptypes = set(['k']) # TODO: handle with nonconflicttypes
+    nonconflicttypes = set('a am c cm f g r e'.split())
+    # We mutate the items in the dict during iteration, so iterate
+    # over a copy.
+    for f, action in list(actions.items()):
+        if narrowmatch(f):
+            pass
+        elif not branchmerge:
+            del actions[f] # just updating, ignore changes outside clone
+        elif action[0] in nooptypes:
+            del actions[f] # merge does not affect file
+        elif action[0] in nonconflicttypes:
+            raise error.Abort(_('merge affects file \'%s\' outside narrow, '
+                                'which is not yet supported') % f,
+                              hint=_('merging in the other direction '
+                                     'may work'))
+        else:
+            raise error.Abort(_('conflict in file \'%s\' is outside '
+                                'narrow clone') % f)
+
 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher,
                   acceptremote, followcopies, forcefulldiff=False):
     """
@@ -1256,6 +1283,11 @@
         # If we are merging, look for path conflicts.
         checkpathconflicts(repo, wctx, p2, actions)
 
+    narrowmatch = repo.narrowmatch()
+    if not narrowmatch.always():
+        # Updates "actions" in place
+        _filternarrowactions(narrowmatch, branchmerge, actions)
+
     return actions, diverge, renamedelete
 
 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):