changeset 48711:9bc86adf32f6

merge-actions: make merge action a full featured object This open the way for having "smarter" value as action, making the usage code simpler and more flexible. We have to explicitly use __bytes__ call in a couple of place because Python2… Differential Revision: https://phab.mercurial-scm.org/D12114
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 28 Jan 2022 17:08:30 +0100
parents b0aa9b0b9c21
children 773ad0f5152d
files hgext/largefiles/overrides.py mercurial/merge.py mercurial/mergestate.py
diffstat 3 files changed, 58 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/largefiles/overrides.py	Fri Jan 28 16:25:41 2022 +0100
+++ b/hgext/largefiles/overrides.py	Fri Jan 28 17:08:30 2022 +0100
@@ -61,7 +61,7 @@
 
 lfstatus = lfutil.lfstatus
 
-MERGE_ACTION_LARGEFILE_MARK_REMOVED = b'lfmr'
+MERGE_ACTION_LARGEFILE_MARK_REMOVED = mergestatemod.MergeAction('lfmr')
 
 # -- Utility functions: commonly/repeatedly needed functionality ---------------
 
--- a/mercurial/merge.py	Fri Jan 28 16:25:41 2022 +0100
+++ b/mercurial/merge.py	Fri Jan 28 17:08:30 2022 +0100
@@ -1201,7 +1201,7 @@
 
             for f, a in mresult1.filemap(sort=True):
                 m, args, msg = a
-                repo.ui.debug(b' %s: %s -> %s\n' % (f, msg, m))
+                repo.ui.debug(b' %s: %s -> %s\n' % (f, msg, m.__bytes__()))
                 if f in fbids:
                     d = fbids[f]
                     if m in d:
@@ -1222,13 +1222,15 @@
                 repo.ui.debug(b" list of bids for %s:\n" % f)
                 for m, l in sorted(bids.items()):
                     for _f, args, msg in l:
-                        repo.ui.debug(b'   %s -> %s\n' % (msg, m))
+                        repo.ui.debug(b'   %s -> %s\n' % (msg, m.__bytes__()))
             # bids is a mapping from action method to list af actions
             # Consensus?
             if len(bids) == 1:  # all bids are the same kind of method
                 m, l = list(bids.items())[0]
                 if all(a == l[0] for a in l[1:]):  # len(bids) is > 1
-                    repo.ui.note(_(b" %s: consensus for %s\n") % (f, m))
+                    repo.ui.note(
+                        _(b" %s: consensus for %s\n") % (f, m.__bytes__())
+                    )
                     mresult.addfile(f, *l[0])
                     continue
             # If keep is an option, just do it.
@@ -1286,11 +1288,12 @@
             repo.ui.note(_(b' %s: multiple bids for merge action:\n') % f)
             for m, l in sorted(bids.items()):
                 for _f, args, msg in l:
-                    repo.ui.note(b'  %s -> %s\n' % (msg, m))
+                    repo.ui.note(b'  %s -> %s\n' % (msg, m.__bytes__()))
             # Pick random action. TODO: Instead, prompt user when resolving
             m, l = list(bids.items())[0]
             repo.ui.warn(
-                _(b' %s: ambiguous merge - picked %s action\n') % (f, m)
+                _(b' %s: ambiguous merge - picked %s action\n')
+                % (f, m.__bytes__())
             )
             mresult.addfile(f, *l[0])
             continue
@@ -1623,7 +1626,7 @@
     # keep (noop, just log it)
     for a in mergestatemod.NO_OP_ACTIONS:
         for f, args, msg in mresult.getactions((a,), sort=True):
-            repo.ui.debug(b" %s: %s -> %s\n" % (f, msg, a))
+            repo.ui.debug(b" %s: %s -> %s\n" % (f, msg, a.__bytes__()))
             # no progress
 
     # directory rename, move local
--- a/mercurial/mergestate.py	Fri Jan 28 16:25:41 2022 +0100
+++ b/mercurial/mergestate.py	Fri Jan 28 17:08:30 2022 +0100
@@ -98,29 +98,59 @@
 LEGACY_MERGE_DRIVER_MERGE = b'D'
 
 
-ACTION_FORGET = b'f'
-ACTION_REMOVE = b'r'
-ACTION_ADD = b'a'
-ACTION_GET = b'g'
-ACTION_PATH_CONFLICT = b'p'
-ACTION_PATH_CONFLICT_RESOLVE = b'pr'
-ACTION_ADD_MODIFIED = b'am'
-ACTION_CREATED = b'c'
-ACTION_DELETED_CHANGED = b'dc'
-ACTION_CHANGED_DELETED = b'cd'
-ACTION_MERGE = b'm'
-ACTION_LOCAL_DIR_RENAME_GET = b'dg'
-ACTION_DIR_RENAME_MOVE_LOCAL = b'dm'
-ACTION_KEEP = b'k'
+class MergeAction(object):
+    """represent an "action" merge need to take for a given file
+
+    Attributes:
+
+    _short: internal representation used to identify each action
+    """
+
+    def __init__(self, short):
+        self._short = short
+
+    def __hash__(self):
+        return hash(self._short)
+
+    def __repr__(self):
+        return 'MergeAction<%s>' % self._short.decode('ascii')
+
+    def __bytes__(self):
+        return self._short
+
+    def __eq__(self, other):
+        if other is None:
+            return False
+        assert isinstance(other, MergeAction)
+        return self._short == other._short
+
+    def __lt__(self, other):
+        return self._short < other._short
+
+
+ACTION_FORGET = MergeAction(b'f')
+ACTION_REMOVE = MergeAction(b'r')
+ACTION_ADD = MergeAction(b'a')
+ACTION_GET = MergeAction(b'g')
+ACTION_PATH_CONFLICT = MergeAction(b'p')
+ACTION_PATH_CONFLICT_RESOLVE = MergeAction('pr')
+ACTION_ADD_MODIFIED = MergeAction(b'am')
+ACTION_CREATED = MergeAction(b'c')
+ACTION_DELETED_CHANGED = MergeAction(b'dc')
+ACTION_CHANGED_DELETED = MergeAction(b'cd')
+ACTION_MERGE = MergeAction(b'm')
+ACTION_LOCAL_DIR_RENAME_GET = MergeAction(b'dg')
+ACTION_DIR_RENAME_MOVE_LOCAL = MergeAction(b'dm')
+ACTION_KEEP = MergeAction(b'k')
 # the file was absent on local side before merge and we should
 # keep it absent (absent means file not present, it can be a result
 # of file deletion, rename etc.)
-ACTION_KEEP_ABSENT = b'ka'
+ACTION_KEEP_ABSENT = MergeAction(b'ka')
 # the file is absent on the ancestor and remote side of the merge
 # hence this file is new and we should keep it
-ACTION_KEEP_NEW = b'kn'
-ACTION_EXEC = b'e'
-ACTION_CREATED_MERGE = b'cm'
+ACTION_KEEP_NEW = MergeAction(b'kn')
+ACTION_EXEC = MergeAction(b'e')
+ACTION_CREATED_MERGE = MergeAction(b'cm')
 
 # actions which are no op
 NO_OP_ACTIONS = (