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
--- 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 = (