patch: accept second matcher that applies only to copy sources (API)
authorMartin von Zweigbergk <martinvonz@google.com>
Wed, 06 Feb 2019 22:52:49 -0800
changeset 41620 74f53d3bd685
parent 41619 035cae1d197f
child 41621 0dc3ed4e712c
patch: accept second matcher that applies only to copy sources (API) See previous patch for motivation. Differential Revision: https://phab.mercurial-scm.org/D5893
mercurial/context.py
mercurial/logcmdutil.py
mercurial/patch.py
--- a/mercurial/context.py	Wed Feb 06 17:46:20 2019 -0800
+++ b/mercurial/context.py	Wed Feb 06 22:52:49 2019 -0800
@@ -295,7 +295,7 @@
 
     def diff(self, ctx2=None, match=None, changes=None, opts=None,
              losedatafn=None, prefix='', relroot='', copy=None,
-             hunksfilterfn=None):
+             copysourcematch=None, hunksfilterfn=None):
         """Returns a diff generator for the given contexts and matcher"""
         if ctx2 is None:
             ctx2 = self.p1()
@@ -304,6 +304,7 @@
         return patch.diff(self._repo, ctx2, self, match=match, changes=changes,
                           opts=opts, losedatafn=losedatafn, prefix=prefix,
                           relroot=relroot, copy=copy,
+                          copysourcematch=copysourcematch,
                           hunksfilterfn=hunksfilterfn)
 
     def dirs(self):
--- a/mercurial/logcmdutil.py	Wed Feb 06 17:46:20 2019 -0800
+++ b/mercurial/logcmdutil.py	Wed Feb 06 22:52:49 2019 -0800
@@ -64,6 +64,7 @@
         relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
     else:
         relroot = ''
+    copysourcematch = None
     if relroot != '':
         # XXX relative roots currently don't work if the root is within a
         # subrepo
@@ -76,6 +77,7 @@
 
         relrootmatch = scmutil.match(ctx2, pats=[relroot], default='path')
         match = matchmod.intersectmatchers(match, relrootmatch)
+        copysourcematch = relrootmatch
 
     if stat:
         diffopts = diffopts.copy(context=0, noprefix=False)
@@ -84,7 +86,8 @@
             width = ui.termwidth() - graphwidth
 
     chunks = ctx2.diff(ctx1, match, changes, opts=diffopts, prefix=prefix,
-                       relroot=relroot, hunksfilterfn=hunksfilterfn)
+                       relroot=relroot, copysourcematch=copysourcematch,
+                       hunksfilterfn=hunksfilterfn)
 
     if fp is not None or ui.canwritewithoutlabels():
         out = fp or ui
--- a/mercurial/patch.py	Wed Feb 06 17:46:20 2019 -0800
+++ b/mercurial/patch.py	Wed Feb 06 22:52:49 2019 -0800
@@ -2240,7 +2240,7 @@
 
 def diff(repo, node1=None, node2=None, match=None, changes=None,
          opts=None, losedatafn=None, prefix='', relroot='', copy=None,
-         hunksfilterfn=None):
+         copysourcematch=None, hunksfilterfn=None):
     '''yields diff of changes to files between two nodes, or node and
     working directory.
 
@@ -2264,6 +2264,9 @@
     copy, if not empty, should contain mappings {dst@y: src@x} of copy
     information.
 
+    if copysourcematch is not None, then copy sources will be filtered by this
+    matcher
+
     hunksfilterfn, if not None, should be a function taking a filectx and
     hunks generator that may yield filtered hunks.
     '''
@@ -2277,7 +2280,7 @@
             repo, ctx1=ctx1, ctx2=ctx2,
             match=match, changes=changes, opts=opts,
             losedatafn=losedatafn, prefix=prefix, relroot=relroot, copy=copy,
-    ):
+            copysourcematch=copysourcematch):
         if hunksfilterfn is not None:
             # If the file has been removed, fctx2 is None; but this should
             # not occur here since we catch removed files early in
@@ -2292,7 +2295,8 @@
             yield text
 
 def diffhunks(repo, ctx1, ctx2, match=None, changes=None,
-              opts=None, losedatafn=None, prefix='', relroot='', copy=None):
+              opts=None, losedatafn=None, prefix='', relroot='', copy=None,
+              copysourcematch=None):
     """Yield diff of changes to files in the form of (`header`, `hunks`) tuples
     where `header` is a list of diff headers and `hunks` is an iterable of
     (`hunkrange`, `hunklines`) tuples.
@@ -2337,11 +2341,11 @@
         if opts.git or opts.upgrade:
             copy = copies.pathcopies(ctx1, ctx2, match=match)
 
-    if relroot:
-        # filter out copies where source side isn't inside the relative root
+    if copysourcematch:
+        # filter out copies where source side isn't inside the matcher
         # (copies.pathcopies() already filtered out the destination)
         copy = {dst: src for dst, src in copy.iteritems()
-                if src.startswith(relroot)}
+                if copysourcematch(src)}
 
     modifiedset = set(modified)
     addedset = set(added)