Patchwork filemerge: move decorator definition for internal merge tools to registrar

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Aug. 5, 2017, 6:51 p.m.
Message ID <2430ac5b30e11c6cdc73.1501959109@speaknoevil>
Download mbox | patch
Permalink /patch/22694/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - Aug. 5, 2017, 6:51 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1501949637 -32400
#      Sun Aug 06 01:13:57 2017 +0900
# Node ID 2430ac5b30e11c6cdc7309b3c2741cd3878b4b36
# Parent  93422d0068f8979b33a02e5003fd4b6c23413361
# Available At https://bitbucket.org/foozy/mercurial-wip
#              hg pull https://bitbucket.org/foozy/mercurial-wip -r 2430ac5b30e1
# EXP-Topic filemerge-refactor
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.
Yuya Nishihara - Aug. 6, 2017, 1:16 p.m.
On Sun, 06 Aug 2017 03:51:49 +0900, FUJIWARA Katsunori wrote:
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1501949637 -32400
> #      Sun Aug 06 01:13:57 2017 +0900
> # Node ID 2430ac5b30e11c6cdc7309b3c2741cd3878b4b36
> # Parent  93422d0068f8979b33a02e5003fd4b6c23413361
> # Available At https://bitbucket.org/foozy/mercurial-wip
> #              hg pull https://bitbucket.org/foozy/mercurial-wip -r 2430ac5b30e1
> # EXP-Topic filemerge-refactor
> filemerge: move decorator definition for internal merge tools to registrar

Queued, thanks. Do you have any example extension that will register an
inprocess merge tool?
Katsunori FUJIWARA - Aug. 6, 2017, 3:20 p.m.
At Sun, 6 Aug 2017 22:16:04 +0900,
Yuya Nishihara wrote:
> 
> On Sun, 06 Aug 2017 03:51:49 +0900, FUJIWARA Katsunori wrote:
> > # HG changeset patch
> > # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> > # Date 1501949637 -32400
> > #      Sun Aug 06 01:13:57 2017 +0900
> > # Node ID 2430ac5b30e11c6cdc7309b3c2741cd3878b4b36
> > # Parent  93422d0068f8979b33a02e5003fd4b6c23413361
> > # Available At https://bitbucket.org/foozy/mercurial-wip
> > #              hg pull https://bitbucket.org/foozy/mercurial-wip -r 2430ac5b30e1
> > # EXP-Topic filemerge-refactor
> > filemerge: move decorator definition for internal merge tools to registrar
> 
> Queued, thanks. Do you have any example extension that will register an
> inprocess merge tool?
> 

Once I wrote an inprocess merge tool "mergebypatch". This already uses
filemerge.internaltool decorator directly, but can become an example
client of new registrar decorator, too.

    https://bitbucket.org/foozy/hgext-mergebypatch
Yuya Nishihara - Aug. 7, 2017, 3:12 p.m.
On Mon, 07 Aug 2017 00:20:36 +0900, FUJIWARA Katsunori wrote:
> At Sun, 6 Aug 2017 22:16:04 +0900,
> Yuya Nishihara wrote:
> > On Sun, 06 Aug 2017 03:51:49 +0900, FUJIWARA Katsunori wrote:
> > > # HG changeset patch
> > > # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> > > # Date 1501949637 -32400
> > > #      Sun Aug 06 01:13:57 2017 +0900
> > > # Node ID 2430ac5b30e11c6cdc7309b3c2741cd3878b4b36
> > > # Parent  93422d0068f8979b33a02e5003fd4b6c23413361
> > > # Available At https://bitbucket.org/foozy/mercurial-wip
> > > #              hg pull https://bitbucket.org/foozy/mercurial-wip -r 2430ac5b30e1
> > > # EXP-Topic filemerge-refactor
> > > filemerge: move decorator definition for internal merge tools to registrar
> > 
> > Queued, thanks. Do you have any example extension that will register an
> > inprocess merge tool?
> 
> Once I wrote an inprocess merge tool "mergebypatch". This already uses
> filemerge.internaltool decorator directly, but can become an example
> client of new registrar decorator, too.
> 
>     https://bitbucket.org/foozy/hgext-mergebypatch

Thanks for the info. It'll be nice if we have at least one example in core
hgext or tests.
Katsunori FUJIWARA - Aug. 7, 2017, 3:31 p.m.
At Tue, 8 Aug 2017 00:12:51 +0900,
Yuya Nishihara wrote:
> 
> On Mon, 07 Aug 2017 00:20:36 +0900, FUJIWARA Katsunori wrote:
> > At Sun, 6 Aug 2017 22:16:04 +0900,
> > Yuya Nishihara wrote:
> > > On Sun, 06 Aug 2017 03:51:49 +0900, FUJIWARA Katsunori wrote:
> > > > # HG changeset patch
> > > > # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> > > > # Date 1501949637 -32400
> > > > #      Sun Aug 06 01:13:57 2017 +0900
> > > > # Node ID 2430ac5b30e11c6cdc7309b3c2741cd3878b4b36
> > > > # Parent  93422d0068f8979b33a02e5003fd4b6c23413361
> > > > # Available At https://bitbucket.org/foozy/mercurial-wip
> > > > #              hg pull https://bitbucket.org/foozy/mercurial-wip -r 2430ac5b30e1
> > > > # EXP-Topic filemerge-refactor
> > > > filemerge: move decorator definition for internal merge tools to registrar
> > > 
> > > Queued, thanks. Do you have any example extension that will register an
> > > inprocess merge tool?
> > 
> > Once I wrote an inprocess merge tool "mergebypatch". This already uses
> > filemerge.internaltool decorator directly, but can become an example
> > client of new registrar decorator, too.
> > 
> >     https://bitbucket.org/foozy/hgext-mergebypatch
> 
> Thanks for the info. It'll be nice if we have at least one example in core
> hgext or tests.

I'll post follow up for that.

Patch

diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -250,6 +250,7 @@  def loadall(ui, whitelist=None):
     from . import (
         color,
         commands,
+        filemerge,
         fileset,
         revset,
         templatefilters,
@@ -268,6 +269,7 @@  def loadall(ui, whitelist=None):
         ('colortable', color, 'loadcolortable'),
         ('configtable', configitems, 'loadconfigtable'),
         ('filesetpredicate', fileset, 'loadpredicate'),
+        ('internalmerge', filemerge, 'loadinternalmerge'),
         ('revsetpredicate', revset, 'loadpredicate'),
         ('templatefilter', templatefilters, 'loadfilter'),
         ('templatefunc', templater, 'loadfunction'),
diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -21,6 +21,7 @@  from . import (
     formatter,
     match,
     pycompat,
+    registrar,
     scmutil,
     simplemerge,
     tagmerge,
@@ -44,10 +45,12 @@  internals = {}
 # 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 @@  class absentfilectx(object):
     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 premerge(repo, mynode, orig, fcd, fc
 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()
diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -308,3 +308,64 @@  class templatefunc(_templateregistrarbas
 
     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