changeset 1410:85981b27e740

Merge with stable.
author Augie Fackler <raf@durin42.com>
date Wed, 11 May 2016 10:11:59 -0400
parents c79fdd5f615d (current diff) fc80c25bc94b (diff)
children 025e849d22f0
files hgsubversion/svnexternals.py
diffstat 5 files changed, 165 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags
+++ b/.hgtags
@@ -20,3 +20,4 @@ 38be7a6b6def3298fe9ffff141eb58e1370a53cc
 759cafce6becef077fb1a152b554a05ff66b04cd 1.8.3
 89997a5fc18163c5f65b83272b4521cdbf29984e 1.8.4
 bd979667611d9df733c61251e7668899f3e77a8f 1.8.5
+49d324e11856f5d65bd7f83f7ffb3a2f07bf82c1 1.8.6
--- a/hgsubversion/__init__.py
+++ b/hgsubversion/__init__.py
@@ -15,7 +15,7 @@ details.
 For more information and instructions, see :hg:`help subversion`.
 '''
 
-testedwith = '2.8.2 3.0.1 3.1 3.2.2 3.3 3.4 3.5 3.6 3.7'
+testedwith = '2.8.2 3.0.1 3.1 3.2.2 3.3 3.4 3.5 3.6 3.7 3.8'
 
 import os
 import sys
@@ -42,7 +42,6 @@ demandimport.ignore.extend([
     'svn.ra',
     ])
 
-from mercurial import templatekw
 from mercurial import revset
 from mercurial import subrepo
 
@@ -51,6 +50,7 @@ import util
 import svnrepo
 import wrappers
 import svnexternals
+import compathacks
 
 svnopts = [
     ('', 'stupid', None,
@@ -165,8 +165,6 @@ def extsetup(ui):
 
     help.helptable.extend(entries)
 
-    templatekw.keywords.update(util.templatekeywords)
-
     revset.symbols.update(util.revsets)
 
     subrepo.types['hgsubversion'] = svnexternals.svnsubrepo
@@ -219,3 +217,74 @@ cmdtable = {
 
 # only these methods are public
 __all__ = ('cmdtable', 'reposetup', 'uisetup')
+
+# set up templatekeywords (written this way to maintain backwards compatibility
+# until we drop support for 3.7)
+try:
+    from mercurial import registrar
+    templatekeyword = registrar.templatekeyword()
+    loadkeyword = lambda registrarobj: None  # no-op
+except (ImportError, AttributeError):
+    # registrar.templatekeyword isn't available = loading by old hg
+
+    templatekeyword = compathacks._funcregistrarbase()
+    templatekeyword._docformat = ":%s: %s"
+
+    # minimum copy from templatekw.loadkeyword
+    def loadkeyword(registrarobj):
+        from mercurial import templatekw
+        for name, func in registrarobj._table.iteritems():
+            templatekw.keywords[name] = func
+
+def _templatehelper(ctx, kw):
+    '''
+    Helper function for displaying information about converted changesets.
+    '''
+    convertinfo = util.getsvnrev(ctx, '')
+
+    if not convertinfo or not convertinfo.startswith('svn:'):
+        return ''
+
+    if kw == 'svnuuid':
+        return convertinfo[4:40]
+    elif kw == 'svnpath':
+        return convertinfo[40:].rsplit('@', 1)[0]
+    elif kw == 'svnrev':
+        return convertinfo[40:].rsplit('@', 1)[-1]
+    else:
+        raise hgutil.Abort('unrecognized hgsubversion keyword %s' % kw)
+
+@templatekeyword('svnrev')
+def svnrevkw(**args):
+    """:svnrev: String. Converted subversion revision number."""
+    return _templatehelper(args['ctx'], 'svnrev')
+
+@templatekeyword('svnpath')
+def svnpathkw(**args):
+    """:svnpath: String. Converted subversion revision project path."""
+    return _templatehelper(args['ctx'], 'svnpath')
+
+@templatekeyword('svnuuid')
+def svnuuidkw(**args):
+    """:svnuuid: String. Converted subversion revision repository identifier."""
+    return _templatehelper(args['ctx'], 'svnuuid')
+
+def listsvnkeys(repo):
+    keys = {}
+    repo = repo.local()
+    metadir = os.path.join(repo.path, 'svn')
+
+    if util.subversionmetaexists(repo.path):
+        w = repo.wlock()
+        try:
+            for key in util.pushkeyfiles:
+                fullpath = os.path.join(metadir, key)
+                if os.path.isfile(fullpath):
+                    data = open(fullpath).read()
+
+                    # Some of the files could be large, but also quite compressible
+                    keys[key] = base85.b85encode(zlib.compress(data))
+        finally:
+            w.release()
+
+    return keys
--- a/hgsubversion/compathacks.py
+++ b/hgsubversion/compathacks.py
@@ -3,6 +3,8 @@
 import errno
 import sys
 
+from mercurial import util
+
 def branchset(repo):
     """Return the set of branches present in a repo.
 
@@ -67,3 +69,83 @@ def filectxfn_deleted_reraise(memctx):
         return None
     # preserve traceback info
     raise exc_info[0], exc_info[1], exc_info[2]
+
+# copied from hg 3.8
+class _funcregistrarbase(object):
+    """Base of decorator to register a fuction for specific purpose
+
+    This decorator stores decorated functions into own dict 'table'.
+
+    The least derived class can be defined by overriding 'formatdoc',
+    for example::
+
+        class keyword(_funcregistrarbase):
+            _docformat = ":%s: %s"
+
+    This should be used as below:
+
+        keyword = registrar.keyword()
+
+        @keyword('bar')
+        def barfunc(*args, **kwargs):
+            '''Explanation of bar keyword ....
+            '''
+            pass
+
+    In this case:
+
+    - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
+    - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
+    """
+    def __init__(self, table=None):
+        if table is None:
+            self._table = {}
+        else:
+            self._table = table
+
+    def __call__(self, decl, *args, **kwargs):
+        return lambda func: self._doregister(func, decl, *args, **kwargs)
+
+    def _doregister(self, func, decl, *args, **kwargs):
+        name = self._getname(decl)
+
+        if func.__doc__ and not util.safehasattr(func, '_origdoc'):
+            doc = func.__doc__.strip()
+            func._origdoc = doc
+            func.__doc__ = self._formatdoc(decl, doc)
+
+        self._table[name] = func
+        self._extrasetup(name, func, *args, **kwargs)
+
+        return func
+
+    def _parsefuncdecl(self, decl):
+        """Parse function declaration and return the name of function in it
+        """
+        i = decl.find('(')
+        if i >= 0:
+            return decl[:i]
+        else:
+            return decl
+
+    def _getname(self, decl):
+        """Return the name of the registered function from decl
+
+        Derived class should override this, if it allows more
+        descriptive 'decl' string than just a name.
+        """
+        return decl
+
+    _docformat = None
+
+    def _formatdoc(self, decl, doc):
+        """Return formatted document of the registered function for help
+
+        'doc' is '__doc__.strip()' of the registered function.
+        """
+        return self._docformat % (decl, doc)
+
+    def _extrasetup(self, name, func):
+        """Execute exra setup for registered function, if needed
+        """
+        pass
--- a/hgsubversion/svnexternals.py
+++ b/hgsubversion/svnexternals.py
@@ -457,10 +457,17 @@ def parse(ui, ctx):
         raise hgutil.Abort(_('unknown externals modes: %s') % mode)
     return external
 
+_notset = object()
+
 class svnsubrepo(subrepo.svnsubrepo):
-    def __init__(self, ctx, path, state):
+    def __init__(self, ctx, path, state, allowcreate=_notset):
         state = (state[0].split(':', 1)[1], state[1])
-        super(svnsubrepo, self).__init__(ctx, path, state)
+        if allowcreate is _notset:
+            # Mercurial 3.7 and earlier
+            super(svnsubrepo, self).__init__(ctx, path, state)
+        else:
+            # Mercurial 3.8 and later
+            super(svnsubrepo, self).__init__(ctx, path, state, allowcreate)
         # Mercurial 3.3+ set 'ui' rather than '_ui' -- set that and use 'ui'
         # everywhere to maintain compatibility across versions
         if not hgutil.safehasattr(self, 'ui'):
--- a/hgsubversion/util.py
+++ b/hgsubversion/util.py
@@ -307,48 +307,10 @@ def issamefile(parentctx, childctx, f):
     # parentctx is not an ancestor of childctx, files are unrelated
     return False
 
-
 def getsvnrev(ctx, defval=None):
     '''Extract SVN revision from commit metadata'''
     return ctx.extra().get('convert_revision', defval)
 
-
-def _templatehelper(ctx, kw):
-    '''
-    Helper function for displaying information about converted changesets.
-    '''
-    convertinfo = getsvnrev(ctx, '')
-
-    if not convertinfo or not convertinfo.startswith('svn:'):
-        return ''
-
-    if kw == 'svnuuid':
-        return convertinfo[4:40]
-    elif kw == 'svnpath':
-        return convertinfo[40:].rsplit('@', 1)[0]
-    elif kw == 'svnrev':
-        return convertinfo[40:].rsplit('@', 1)[-1]
-    else:
-        raise hgutil.Abort('unrecognized hgsubversion keyword %s' % kw)
-
-def svnrevkw(**args):
-    """:svnrev: String. Converted subversion revision number."""
-    return _templatehelper(args['ctx'], 'svnrev')
-
-def svnpathkw(**args):
-    """:svnpath: String. Converted subversion revision project path."""
-    return _templatehelper(args['ctx'], 'svnpath')
-
-def svnuuidkw(**args):
-    """:svnuuid: String. Converted subversion revision repository identifier."""
-    return _templatehelper(args['ctx'], 'svnuuid')
-
-templatekeywords = {
-    'svnrev': svnrevkw,
-    'svnpath': svnpathkw,
-    'svnuuid': svnuuidkw,
-}
-
 def revset_fromsvn(repo, subset, x):
     '''``fromsvn()``
     Select changesets that originate from Subversion.