changeset 33699:50c44dee741a

filemerge: move decorator definition for internal merge tools to registrar This patch also adds extra loading entry for internal merge tools to extensions.py, for similarity to other decorators defined in registrar.py. This patch uses "internalmerge" for decorator class name, instead of original "internaltool", because the latter is too generic. BTW, after this patch, 4-spaces indentation is added to the 1st line of internal merge tool description docstring, and this may make already translated entries in *.po fuzzy. Even though this indentation is required for "definition list" in reST syntax, absence of it has been overlooked, because help.makeitemsdoc() forcibly inserts it at generation of online help. But this forcible insertion causes formatting issue (I'll send another patch series for this). Therefore, this additional indentation should be reasonable.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Sun, 06 Aug 2017 01:13:57 +0900
parents 3748098d072a
children 970967e0a917
files mercurial/extensions.py mercurial/filemerge.py mercurial/registrar.py
diffstat 3 files changed, 81 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/extensions.py	Sat Aug 05 05:25:36 2017 +0530
+++ b/mercurial/extensions.py	Sun Aug 06 01:13:57 2017 +0900
@@ -250,6 +250,7 @@
     from . import (
         color,
         commands,
+        filemerge,
         fileset,
         revset,
         templatefilters,
@@ -268,6 +269,7 @@
         ('colortable', color, 'loadcolortable'),
         ('configtable', configitems, 'loadconfigtable'),
         ('filesetpredicate', fileset, 'loadpredicate'),
+        ('internalmerge', filemerge, 'loadinternalmerge'),
         ('revsetpredicate', revset, 'loadpredicate'),
         ('templatefilter', templatefilters, 'loadfilter'),
         ('templatefunc', templater, 'loadfunction'),
--- a/mercurial/filemerge.py	Sat Aug 05 05:25:36 2017 +0530
+++ b/mercurial/filemerge.py	Sun Aug 06 01:13:57 2017 +0900
@@ -21,6 +21,7 @@
     formatter,
     match,
     pycompat,
+    registrar,
     scmutil,
     simplemerge,
     tagmerge,
@@ -44,10 +45,12 @@
 # Merge tools to document.
 internalsdoc = {}
 
+internaltool = registrar.internalmerge()
+
 # internal tool merge types
-nomerge = None
-mergeonly = 'mergeonly'  # just the full merge, no premerge
-fullmerge = 'fullmerge'  # both premerge and merge
+nomerge = internaltool.nomerge
+mergeonly = internaltool.mergeonly # just the full merge, no premerge
+fullmerge = internaltool.fullmerge # both premerge and merge
 
 _localchangedotherdeletedmsg = _(
     "local%(l)s changed %(fd)s which other%(o)s deleted\n"
@@ -104,21 +107,6 @@
     def isabsent(self):
         return True
 
-def internaltool(name, mergetype, onfailure=None, precheck=None):
-    '''return a decorator for populating internal merge tool table'''
-    def decorator(func):
-        fullname = ':' + name
-        func.__doc__ = (pycompat.sysstr("``%s``\n" % fullname)
-                        + func.__doc__.strip())
-        internals[fullname] = func
-        internals['internal:' + name] = func
-        internalsdoc[fullname] = func
-        func.mergetype = mergetype
-        func.onfailure = onfailure
-        func.precheck = precheck
-        return func
-    return decorator
-
 def _findtool(ui, tool):
     if tool in internals:
         return tool
@@ -743,5 +731,17 @@
 def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
     return _filemerge(False, repo, mynode, orig, fcd, fco, fca, labels=labels)
 
+def loadinternalmerge(ui, extname, registrarobj):
+    """Load internal merge tool from specified registrarobj
+    """
+    for name, func in registrarobj._table.iteritems():
+        fullname = ':' + name
+        internals[fullname] = func
+        internals['internal:' + name] = func
+        internalsdoc[fullname] = func
+
+# load built-in merge tools explicitly to setup internalsdoc
+loadinternalmerge(None, None, internaltool)
+
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = internals.values()
--- a/mercurial/registrar.py	Sat Aug 05 05:25:36 2017 +0530
+++ b/mercurial/registrar.py	Sun Aug 06 01:13:57 2017 +0900
@@ -308,3 +308,64 @@
 
     def _extrasetup(self, name, func, argspec=None):
         func._argspec = argspec
+
+class internalmerge(_funcregistrarbase):
+    """Decorator to register in-process merge tool
+
+    Usage::
+
+        internalmerge = registrar.internalmerge()
+
+        @internalmerge('mymerge', internalmerge.mergeonly,
+                       onfailure=None, precheck=None):
+        def mymergefunc(repo, mynode, orig, fcd, fco, fca,
+                        toolconf, files, labels=None):
+            '''Explanation of this internal merge tool ....
+            '''
+            return 1, False # means "conflicted", "no deletion needed"
+
+    The first string argument is used to compose actual merge tool name,
+    ":name" and "internal:name" (the latter is historical one).
+
+    The second argument is one of merge types below:
+
+    ========== ======== ======== =========
+    merge type precheck premerge fullmerge
+    ========== ======== ======== =========
+    nomerge     x        x        x
+    mergeonly   o        x        o
+    fullmerge   o        o        o
+    ========== ======== ======== =========
+
+    Optional argument 'onfalure' is the format of warning message
+    to be used at failure of merging (target filename is specified
+    at formatting). Or, None or so, if warning message should be
+    suppressed.
+
+    Optional argument 'precheck' is the function to be used
+    before actual invocation of internal merge tool itself.
+    It takes as same arguments as internal merge tool does, other than
+    'files' and 'labels'. If it returns false value, merging is aborted
+    immediately (and file is marked as "unresolved").
+
+    'internalmerge' instance in example above can be used to
+    decorate multiple functions.
+
+    Decorated functions are registered automatically at loading
+    extension, if an instance named as 'internalmerge' is used for
+    decorating in extension.
+
+    Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
+    """
+    _docformat = "``:%s``\n    %s"
+
+    # merge type definitions:
+    nomerge = None
+    mergeonly = 'mergeonly'  # just the full merge, no premerge
+    fullmerge = 'fullmerge'  # both premerge and merge
+
+    def _extrasetup(self, name, func, mergetype,
+                    onfailure=None, precheck=None):
+        func.mergetype = mergetype
+        func.onfailure = onfailure
+        func.precheck = precheck