revset: add "diff" field to "matching" keyword
authorAngel Ezquerra <angel.ezquerra@gmail.com>
Wed, 13 Jun 2012 23:32:58 +0200
changeset 17102 d9a046ae4d8e
parent 17101 6bc275593d07
child 17103 5146de7bce96
revset: add "diff" field to "matching" keyword The new "diff" field lets you use the matching revset keyword to find revisions that apply the same change as the selected revisions. The match must be exact (i.e. same additions, same deletions, same modified lines and same change context, same file renames and copies). Two revisions matching their diff must also match their files. Thus, to match the diff much faster we will always check that the 'files' match first, and only then check that the 'diff' matches as well.
mercurial/revset.py
--- a/mercurial/revset.py	Fri Jun 08 23:27:59 2012 -0400
+++ b/mercurial/revset.py	Wed Jun 13 23:32:58 2012 +0200
@@ -1058,8 +1058,11 @@
     Valid fields are most regular revision fields and some special fields.
 
     Regular revision fields are ``description``, ``author``, ``branch``,
-    ``date``, ``files``, ``phase``, ``parents``, ``substate`` and ``user``.
-    Note that ``author`` and ``user`` are synonyms.
+    ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user``
+    and ``diff``.
+    Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the
+    contents of the revision. Two revisions matching their ``diff`` will
+    also match their ``files``.
 
     Special fields are ``summary`` and ``metadata``:
     ``summary`` matches the first line of the description.
@@ -1079,12 +1082,18 @@
                 _("matching requires a string "
                 "as its second argument")).split()
 
-    # Make sure that there are no repeated fields, and expand the
-    # 'special' 'metadata' field type
+    # Make sure that there are no repeated fields,
+    # expand the 'special' 'metadata' field type
+    # and check the 'files' whenever we check the 'diff'
     fields = []
     for field in fieldlist:
         if field == 'metadata':
             fields += ['user', 'description', 'date']
+        elif field == 'diff':
+            # a revision matching the diff must also match the files
+            # since matching the diff is very costly, make sure to
+            # also match the files first
+            fields += ['files', 'diff']
         else:
             if field == 'author':
                 field = 'user'
@@ -1098,7 +1107,7 @@
     # Not all fields take the same amount of time to be matched
     # Sort the selected fields in order of increasing matching cost
     fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary',
-        'files', 'description', 'substate']
+        'files', 'description', 'substate', 'diff']
     def fieldkeyfunc(f):
         try:
             return fieldorder.index(f)
@@ -1121,6 +1130,7 @@
         'phase': lambda r: repo[r].phase(),
         'substate': lambda r: repo[r].substate,
         'summary': lambda r: repo[r].description().splitlines()[0],
+        'diff': lambda r: list(repo[r].diff(git=True),)
     }
     for info in fields:
         getfield = _funcs.get(info, None)