Mercurial > public > mercurial-scm > hg
comparison mercurial/revset.py @ 17102:d9a046ae4d8e
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.
author | Angel Ezquerra <angel.ezquerra@gmail.com> |
---|---|
date | Wed, 13 Jun 2012 23:32:58 +0200 |
parents | ee2370d866fc |
children | 63a4a3871607 |
comparison
equal
deleted
inserted
replaced
17101:6bc275593d07 | 17102:d9a046ae4d8e |
---|---|
1056 by spaces (e.g. ``author description``). | 1056 by spaces (e.g. ``author description``). |
1057 | 1057 |
1058 Valid fields are most regular revision fields and some special fields. | 1058 Valid fields are most regular revision fields and some special fields. |
1059 | 1059 |
1060 Regular revision fields are ``description``, ``author``, ``branch``, | 1060 Regular revision fields are ``description``, ``author``, ``branch``, |
1061 ``date``, ``files``, ``phase``, ``parents``, ``substate`` and ``user``. | 1061 ``date``, ``files``, ``phase``, ``parents``, ``substate``, ``user`` |
1062 Note that ``author`` and ``user`` are synonyms. | 1062 and ``diff``. |
1063 Note that ``author`` and ``user`` are synonyms. ``diff`` refers to the | |
1064 contents of the revision. Two revisions matching their ``diff`` will | |
1065 also match their ``files``. | |
1063 | 1066 |
1064 Special fields are ``summary`` and ``metadata``: | 1067 Special fields are ``summary`` and ``metadata``: |
1065 ``summary`` matches the first line of the description. | 1068 ``summary`` matches the first line of the description. |
1066 ``metadata`` is equivalent to matching ``description user date`` | 1069 ``metadata`` is equivalent to matching ``description user date`` |
1067 (i.e. it matches the main metadata fields). | 1070 (i.e. it matches the main metadata fields). |
1077 if len(l) > 1: | 1080 if len(l) > 1: |
1078 fieldlist = getstring(l[1], | 1081 fieldlist = getstring(l[1], |
1079 _("matching requires a string " | 1082 _("matching requires a string " |
1080 "as its second argument")).split() | 1083 "as its second argument")).split() |
1081 | 1084 |
1082 # Make sure that there are no repeated fields, and expand the | 1085 # Make sure that there are no repeated fields, |
1083 # 'special' 'metadata' field type | 1086 # expand the 'special' 'metadata' field type |
1087 # and check the 'files' whenever we check the 'diff' | |
1084 fields = [] | 1088 fields = [] |
1085 for field in fieldlist: | 1089 for field in fieldlist: |
1086 if field == 'metadata': | 1090 if field == 'metadata': |
1087 fields += ['user', 'description', 'date'] | 1091 fields += ['user', 'description', 'date'] |
1092 elif field == 'diff': | |
1093 # a revision matching the diff must also match the files | |
1094 # since matching the diff is very costly, make sure to | |
1095 # also match the files first | |
1096 fields += ['files', 'diff'] | |
1088 else: | 1097 else: |
1089 if field == 'author': | 1098 if field == 'author': |
1090 field = 'user' | 1099 field = 'user' |
1091 fields.append(field) | 1100 fields.append(field) |
1092 fields = set(fields) | 1101 fields = set(fields) |
1096 | 1105 |
1097 # We may want to match more than one field | 1106 # We may want to match more than one field |
1098 # Not all fields take the same amount of time to be matched | 1107 # Not all fields take the same amount of time to be matched |
1099 # Sort the selected fields in order of increasing matching cost | 1108 # Sort the selected fields in order of increasing matching cost |
1100 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary', | 1109 fieldorder = ['phase', 'parents', 'user', 'date', 'branch', 'summary', |
1101 'files', 'description', 'substate'] | 1110 'files', 'description', 'substate', 'diff'] |
1102 def fieldkeyfunc(f): | 1111 def fieldkeyfunc(f): |
1103 try: | 1112 try: |
1104 return fieldorder.index(f) | 1113 return fieldorder.index(f) |
1105 except ValueError: | 1114 except ValueError: |
1106 # assume an unknown field is very costly | 1115 # assume an unknown field is very costly |
1119 'files': lambda r: repo[r].files(), | 1128 'files': lambda r: repo[r].files(), |
1120 'parents': lambda r: repo[r].parents(), | 1129 'parents': lambda r: repo[r].parents(), |
1121 'phase': lambda r: repo[r].phase(), | 1130 'phase': lambda r: repo[r].phase(), |
1122 'substate': lambda r: repo[r].substate, | 1131 'substate': lambda r: repo[r].substate, |
1123 'summary': lambda r: repo[r].description().splitlines()[0], | 1132 'summary': lambda r: repo[r].description().splitlines()[0], |
1133 'diff': lambda r: list(repo[r].diff(git=True),) | |
1124 } | 1134 } |
1125 for info in fields: | 1135 for info in fields: |
1126 getfield = _funcs.get(info, None) | 1136 getfield = _funcs.get(info, None) |
1127 if getfield is None: | 1137 if getfield is None: |
1128 raise error.ParseError( | 1138 raise error.ParseError( |