effectflag: detect when diff changed
authorBoris Feld <boris.feld@octobus.net>
Thu, 06 Jul 2017 15:00:07 +0200
changeset 34421 187bc224554a
parent 34420 95759620d492
child 34422 2fd06499dc8e
effectflag: detect when diff changed Store in effect flag when the diff changed between the predecessor and its successors. Comparing the diff is not easy because we do not want to incorrectly detect a
mercurial/obsutil.py
tests/test-obsmarkers-effectflag.t
--- a/mercurial/obsutil.py	Thu Jul 06 14:58:44 2017 +0200
+++ b/mercurial/obsutil.py	Thu Jul 06 15:00:07 2017 +0200
@@ -312,6 +312,7 @@
 
 DESCCHANGED = 1 << 0 # action changed the description
 METACHANGED = 1 << 1 # action change the meta
+DIFFCHANGED = 1 << 3 # action change diff introduced by the changeset
 PARENTCHANGED = 1 << 2 # action change the parent
 USERCHANGED = 1 << 4 # the user changed
 DATECHANGED = 1 << 5 # the date changed
@@ -332,6 +333,47 @@
 
     return not any(pattern.match(metakey) for pattern in METABLACKLIST)
 
+def _prepare_hunk(hunk):
+    """Drop all information but the username and patch"""
+    cleanhunk = []
+    for line in hunk.splitlines():
+        if line.startswith(b'# User') or not line.startswith(b'#'):
+            if line.startswith(b'@@'):
+                line = b'@@\n'
+            cleanhunk.append(line)
+    return cleanhunk
+
+def _getdifflines(iterdiff):
+    """return a cleaned up lines"""
+    lines = next(iterdiff, None)
+
+    if lines is None:
+        return lines
+
+    return _prepare_hunk(lines)
+
+def _cmpdiff(leftctx, rightctx):
+    """return True if both ctx introduce the "same diff"
+
+    This is a first and basic implementation, with many shortcoming.
+    """
+
+    # Leftctx or right ctx might be filtered, so we need to use the contexts
+    # with an unfiltered repository to safely compute the diff
+    leftunfi = leftctx._repo.unfiltered()[leftctx.rev()]
+    leftdiff = leftunfi.diff(git=1)
+    rightunfi = rightctx._repo.unfiltered()[rightctx.rev()]
+    rightdiff = rightunfi.diff(git=1)
+
+    left, right = (0, 0)
+    while None not in (left, right):
+        left = _getdifflines(leftdiff)
+        right = _getdifflines(rightdiff)
+
+        if left != right:
+            return False
+    return True
+
 def geteffectflag(relation):
     """ From an obs-marker relation, compute what changed between the
     predecessor and the successor.
@@ -371,6 +413,10 @@
         if ctxmeta != srcmeta:
             effects |= METACHANGED
 
+        # Check if the diff has changed
+        if not _cmpdiff(source, changectx):
+            effects |= DIFFCHANGED
+
     return effects
 
 def getobsoleted(repo, tr):
--- a/tests/test-obsmarkers-effectflag.t	Thu Jul 06 14:58:44 2017 +0200
+++ b/tests/test-obsmarkers-effectflag.t	Thu Jul 06 15:00:07 2017 +0200
@@ -93,7 +93,7 @@
 check result
 
   $ hg debugobsolete --rev .
-  ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f 75781fdbdbf58a987516b00c980bccda1e9ae588 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'amend', 'user': 'test'}
+  ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f 75781fdbdbf58a987516b00c980bccda1e9ae588 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
 
 amend with multiple effect (desc and meta)
 -------------------------------------------