##// END OF EJS Templates
schemes: move re construction to module-level and python3-ify...
Augie Fackler -
r31181:150cd512 default
parent child Browse files
Show More
@@ -1,133 +1,134
1 # Copyright 2009, Alexander Solovyov <piranha@piranha.org.ua>
1 # Copyright 2009, Alexander Solovyov <piranha@piranha.org.ua>
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6 """extend schemes with shortcuts to repository swarms
6 """extend schemes with shortcuts to repository swarms
7
7
8 This extension allows you to specify shortcuts for parent URLs with a
8 This extension allows you to specify shortcuts for parent URLs with a
9 lot of repositories to act like a scheme, for example::
9 lot of repositories to act like a scheme, for example::
10
10
11 [schemes]
11 [schemes]
12 py = http://code.python.org/hg/
12 py = http://code.python.org/hg/
13
13
14 After that you can use it like::
14 After that you can use it like::
15
15
16 hg clone py://trunk/
16 hg clone py://trunk/
17
17
18 Additionally there is support for some more complex schemas, for
18 Additionally there is support for some more complex schemas, for
19 example used by Google Code::
19 example used by Google Code::
20
20
21 [schemes]
21 [schemes]
22 gcode = http://{1}.googlecode.com/hg/
22 gcode = http://{1}.googlecode.com/hg/
23
23
24 The syntax is taken from Mercurial templates, and you have unlimited
24 The syntax is taken from Mercurial templates, and you have unlimited
25 number of variables, starting with ``{1}`` and continuing with
25 number of variables, starting with ``{1}`` and continuing with
26 ``{2}``, ``{3}`` and so on. This variables will receive parts of URL
26 ``{2}``, ``{3}`` and so on. This variables will receive parts of URL
27 supplied, split by ``/``. Anything not specified as ``{part}`` will be
27 supplied, split by ``/``. Anything not specified as ``{part}`` will be
28 just appended to an URL.
28 just appended to an URL.
29
29
30 For convenience, the extension adds these schemes by default::
30 For convenience, the extension adds these schemes by default::
31
31
32 [schemes]
32 [schemes]
33 py = http://hg.python.org/
33 py = http://hg.python.org/
34 bb = https://bitbucket.org/
34 bb = https://bitbucket.org/
35 bb+ssh = ssh://hg@bitbucket.org/
35 bb+ssh = ssh://hg@bitbucket.org/
36 gcode = https://{1}.googlecode.com/hg/
36 gcode = https://{1}.googlecode.com/hg/
37 kiln = https://{1}.kilnhg.com/Repo/
37 kiln = https://{1}.kilnhg.com/Repo/
38
38
39 You can override a predefined scheme by defining a new scheme with the
39 You can override a predefined scheme by defining a new scheme with the
40 same name.
40 same name.
41 """
41 """
42 from __future__ import absolute_import
42 from __future__ import absolute_import
43
43
44 import os
44 import os
45 import re
45 import re
46
46
47 from mercurial.i18n import _
47 from mercurial.i18n import _
48 from mercurial import (
48 from mercurial import (
49 cmdutil,
49 cmdutil,
50 error,
50 error,
51 extensions,
51 extensions,
52 hg,
52 hg,
53 pycompat,
53 pycompat,
54 templater,
54 templater,
55 util,
55 util,
56 )
56 )
57
57
58 cmdtable = {}
58 cmdtable = {}
59 command = cmdutil.command(cmdtable)
59 command = cmdutil.command(cmdtable)
60 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
60 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
61 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
61 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
62 # be specifying the version(s) of Mercurial they are tested with, or
62 # be specifying the version(s) of Mercurial they are tested with, or
63 # leave the attribute unspecified.
63 # leave the attribute unspecified.
64 testedwith = 'ships-with-hg-core'
64 testedwith = 'ships-with-hg-core'
65
65
66 _partre = re.compile(r'\{(\d+)\}'.encode(u'latin1'))
66
67
67 class ShortRepository(object):
68 class ShortRepository(object):
68 def __init__(self, url, scheme, templater):
69 def __init__(self, url, scheme, templater):
69 self.scheme = scheme
70 self.scheme = scheme
70 self.templater = templater
71 self.templater = templater
71 self.url = url
72 self.url = url
72 try:
73 try:
73 self.parts = max(map(int, re.findall(r'\{(\d+)\}', self.url)))
74 self.parts = max(map(int, _partre.findall(self.url)))
74 except ValueError:
75 except ValueError:
75 self.parts = 0
76 self.parts = 0
76
77
77 def __repr__(self):
78 def __repr__(self):
78 return '<ShortRepository: %s>' % self.scheme
79 return '<ShortRepository: %s>' % self.scheme
79
80
80 def instance(self, ui, url, create):
81 def instance(self, ui, url, create):
81 url = self.resolve(url)
82 url = self.resolve(url)
82 return hg._peerlookup(url).instance(ui, url, create)
83 return hg._peerlookup(url).instance(ui, url, create)
83
84
84 def resolve(self, url):
85 def resolve(self, url):
85 # Should this use the util.url class, or is manual parsing better?
86 # Should this use the util.url class, or is manual parsing better?
86 try:
87 try:
87 url = url.split('://', 1)[1]
88 url = url.split('://', 1)[1]
88 except IndexError:
89 except IndexError:
89 raise error.Abort(_("no '://' in scheme url '%s'") % url)
90 raise error.Abort(_("no '://' in scheme url '%s'") % url)
90 parts = url.split('/', self.parts)
91 parts = url.split('/', self.parts)
91 if len(parts) > self.parts:
92 if len(parts) > self.parts:
92 tail = parts[-1]
93 tail = parts[-1]
93 parts = parts[:-1]
94 parts = parts[:-1]
94 else:
95 else:
95 tail = ''
96 tail = ''
96 context = dict((str(i + 1), v) for i, v in enumerate(parts))
97 context = dict((str(i + 1), v) for i, v in enumerate(parts))
97 return ''.join(self.templater.process(self.url, context)) + tail
98 return ''.join(self.templater.process(self.url, context)) + tail
98
99
99 def hasdriveletter(orig, path):
100 def hasdriveletter(orig, path):
100 if path:
101 if path:
101 for scheme in schemes:
102 for scheme in schemes:
102 if path.startswith(scheme + ':'):
103 if path.startswith(scheme + ':'):
103 return False
104 return False
104 return orig(path)
105 return orig(path)
105
106
106 schemes = {
107 schemes = {
107 'py': 'http://hg.python.org/',
108 'py': 'http://hg.python.org/',
108 'bb': 'https://bitbucket.org/',
109 'bb': 'https://bitbucket.org/',
109 'bb+ssh': 'ssh://hg@bitbucket.org/',
110 'bb+ssh': 'ssh://hg@bitbucket.org/',
110 'gcode': 'https://{1}.googlecode.com/hg/',
111 'gcode': 'https://{1}.googlecode.com/hg/',
111 'kiln': 'https://{1}.kilnhg.com/Repo/'
112 'kiln': 'https://{1}.kilnhg.com/Repo/'
112 }
113 }
113
114
114 def extsetup(ui):
115 def extsetup(ui):
115 schemes.update(dict(ui.configitems('schemes')))
116 schemes.update(dict(ui.configitems('schemes')))
116 t = templater.engine(lambda x: x)
117 t = templater.engine(lambda x: x)
117 for scheme, url in schemes.items():
118 for scheme, url in schemes.items():
118 if (pycompat.osname == 'nt' and len(scheme) == 1 and scheme.isalpha()
119 if (pycompat.osname == 'nt' and len(scheme) == 1 and scheme.isalpha()
119 and os.path.exists('%s:\\' % scheme)):
120 and os.path.exists('%s:\\' % scheme)):
120 raise error.Abort(_('custom scheme %s:// conflicts with drive '
121 raise error.Abort(_('custom scheme %s:// conflicts with drive '
121 'letter %s:\\\n') % (scheme, scheme.upper()))
122 'letter %s:\\\n') % (scheme, scheme.upper()))
122 hg.schemes[scheme] = ShortRepository(url, scheme, t)
123 hg.schemes[scheme] = ShortRepository(url, scheme, t)
123
124
124 extensions.wrapfunction(util, 'hasdriveletter', hasdriveletter)
125 extensions.wrapfunction(util, 'hasdriveletter', hasdriveletter)
125
126
126 @command('debugexpandscheme', norepo=True)
127 @command('debugexpandscheme', norepo=True)
127 def expandscheme(ui, url, **opts):
128 def expandscheme(ui, url, **opts):
128 """given a repo path, provide the scheme-expanded path
129 """given a repo path, provide the scheme-expanded path
129 """
130 """
130 repo = hg._peerlookup(url)
131 repo = hg._peerlookup(url)
131 if isinstance(repo, ShortRepository):
132 if isinstance(repo, ShortRepository):
132 url = repo.resolve(url)
133 url = repo.resolve(url)
133 ui.write(url + '\n')
134 ui.write(url + '\n')
General Comments 0
You need to be logged in to leave comments. Login now