##// END OF EJS Templates
wrapfunction: use sysstr instead of bytes as argument in "schemes"...
marmoute -
r51684:d51a76b5 default
parent child Browse files
Show More
@@ -1,175 +1,175 b''
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
42
43 import os
43 import os
44 import re
44 import re
45
45
46 from mercurial.i18n import _
46 from mercurial.i18n import _
47 from mercurial import (
47 from mercurial import (
48 error,
48 error,
49 extensions,
49 extensions,
50 hg,
50 hg,
51 pycompat,
51 pycompat,
52 registrar,
52 registrar,
53 templater,
53 templater,
54 )
54 )
55 from mercurial.utils import (
55 from mercurial.utils import (
56 urlutil,
56 urlutil,
57 )
57 )
58
58
59 cmdtable = {}
59 cmdtable = {}
60 command = registrar.command(cmdtable)
60 command = registrar.command(cmdtable)
61 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
61 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
62 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
62 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
63 # be specifying the version(s) of Mercurial they are tested with, or
63 # be specifying the version(s) of Mercurial they are tested with, or
64 # leave the attribute unspecified.
64 # leave the attribute unspecified.
65 testedwith = b'ships-with-hg-core'
65 testedwith = b'ships-with-hg-core'
66
66
67 _partre = re.compile(br'{(\d+)\}')
67 _partre = re.compile(br'{(\d+)\}')
68
68
69
69
70 class ShortRepository:
70 class ShortRepository:
71 def __init__(self, url, scheme, templater):
71 def __init__(self, url, scheme, templater):
72 self.scheme = scheme
72 self.scheme = scheme
73 self.templater = templater
73 self.templater = templater
74 self.url = url
74 self.url = url
75 try:
75 try:
76 self.parts = max(map(int, _partre.findall(self.url)))
76 self.parts = max(map(int, _partre.findall(self.url)))
77 except ValueError:
77 except ValueError:
78 self.parts = 0
78 self.parts = 0
79
79
80 def __repr__(self):
80 def __repr__(self):
81 return b'<ShortRepository: %s>' % self.scheme
81 return b'<ShortRepository: %s>' % self.scheme
82
82
83 def make_peer(self, ui, path, *args, **kwargs):
83 def make_peer(self, ui, path, *args, **kwargs):
84 new_url = self.resolve(path.rawloc)
84 new_url = self.resolve(path.rawloc)
85 path = path.copy(new_raw_location=new_url)
85 path = path.copy(new_raw_location=new_url)
86 cls = hg.peer_schemes.get(path.url.scheme)
86 cls = hg.peer_schemes.get(path.url.scheme)
87 if cls is not None:
87 if cls is not None:
88 return cls.make_peer(ui, path, *args, **kwargs)
88 return cls.make_peer(ui, path, *args, **kwargs)
89 return None
89 return None
90
90
91 def instance(self, ui, url, create, intents=None, createopts=None):
91 def instance(self, ui, url, create, intents=None, createopts=None):
92 url = self.resolve(url)
92 url = self.resolve(url)
93 u = urlutil.url(url)
93 u = urlutil.url(url)
94 scheme = u.scheme or b'file'
94 scheme = u.scheme or b'file'
95 if scheme in hg.peer_schemes:
95 if scheme in hg.peer_schemes:
96 cls = hg.peer_schemes[scheme]
96 cls = hg.peer_schemes[scheme]
97 elif scheme in hg.repo_schemes:
97 elif scheme in hg.repo_schemes:
98 cls = hg.repo_schemes[scheme]
98 cls = hg.repo_schemes[scheme]
99 else:
99 else:
100 cls = hg.LocalFactory
100 cls = hg.LocalFactory
101 return cls.instance(
101 return cls.instance(
102 ui, url, create, intents=intents, createopts=createopts
102 ui, url, create, intents=intents, createopts=createopts
103 )
103 )
104
104
105 def resolve(self, url):
105 def resolve(self, url):
106 # Should this use the urlutil.url class, or is manual parsing better?
106 # Should this use the urlutil.url class, or is manual parsing better?
107 try:
107 try:
108 url = url.split(b'://', 1)[1]
108 url = url.split(b'://', 1)[1]
109 except IndexError:
109 except IndexError:
110 raise error.Abort(_(b"no '://' in scheme url '%s'") % url)
110 raise error.Abort(_(b"no '://' in scheme url '%s'") % url)
111 parts = url.split(b'/', self.parts)
111 parts = url.split(b'/', self.parts)
112 if len(parts) > self.parts:
112 if len(parts) > self.parts:
113 tail = parts[-1]
113 tail = parts[-1]
114 parts = parts[:-1]
114 parts = parts[:-1]
115 else:
115 else:
116 tail = b''
116 tail = b''
117 context = {b'%d' % (i + 1): v for i, v in enumerate(parts)}
117 context = {b'%d' % (i + 1): v for i, v in enumerate(parts)}
118 return b''.join(self.templater.process(self.url, context)) + tail
118 return b''.join(self.templater.process(self.url, context)) + tail
119
119
120
120
121 def hasdriveletter(orig, path):
121 def hasdriveletter(orig, path):
122 if path:
122 if path:
123 for scheme in schemes:
123 for scheme in schemes:
124 if path.startswith(scheme + b':'):
124 if path.startswith(scheme + b':'):
125 return False
125 return False
126 return orig(path)
126 return orig(path)
127
127
128
128
129 schemes = {
129 schemes = {
130 b'py': b'http://hg.python.org/',
130 b'py': b'http://hg.python.org/',
131 b'bb': b'https://bitbucket.org/',
131 b'bb': b'https://bitbucket.org/',
132 b'bb+ssh': b'ssh://hg@bitbucket.org/',
132 b'bb+ssh': b'ssh://hg@bitbucket.org/',
133 b'gcode': b'https://{1}.googlecode.com/hg/',
133 b'gcode': b'https://{1}.googlecode.com/hg/',
134 b'kiln': b'https://{1}.kilnhg.com/Repo/',
134 b'kiln': b'https://{1}.kilnhg.com/Repo/',
135 }
135 }
136
136
137
137
138 def _check_drive_letter(scheme: bytes) -> None:
138 def _check_drive_letter(scheme: bytes) -> None:
139 """check if a scheme conflict with a Windows drive letter"""
139 """check if a scheme conflict with a Windows drive letter"""
140 if (
140 if (
141 pycompat.iswindows
141 pycompat.iswindows
142 and len(scheme) == 1
142 and len(scheme) == 1
143 and scheme.isalpha()
143 and scheme.isalpha()
144 and os.path.exists(b'%s:\\' % scheme)
144 and os.path.exists(b'%s:\\' % scheme)
145 ):
145 ):
146 msg = _(b'custom scheme %s:// conflicts with drive letter %s:\\\n')
146 msg = _(b'custom scheme %s:// conflicts with drive letter %s:\\\n')
147 msg %= (scheme, scheme.upper())
147 msg %= (scheme, scheme.upper())
148 raise error.Abort(msg)
148 raise error.Abort(msg)
149
149
150
150
151 def extsetup(ui):
151 def extsetup(ui):
152 schemes.update(dict(ui.configitems(b'schemes')))
152 schemes.update(dict(ui.configitems(b'schemes')))
153 t = templater.engine(templater.parse)
153 t = templater.engine(templater.parse)
154 for scheme, url in schemes.items():
154 for scheme, url in schemes.items():
155 _check_drive_letter(scheme)
155 _check_drive_letter(scheme)
156 url_scheme = urlutil.url(url).scheme
156 url_scheme = urlutil.url(url).scheme
157 if url_scheme in hg.peer_schemes:
157 if url_scheme in hg.peer_schemes:
158 hg.peer_schemes[scheme] = ShortRepository(url, scheme, t)
158 hg.peer_schemes[scheme] = ShortRepository(url, scheme, t)
159 else:
159 else:
160 hg.repo_schemes[scheme] = ShortRepository(url, scheme, t)
160 hg.repo_schemes[scheme] = ShortRepository(url, scheme, t)
161
161
162 extensions.wrapfunction(urlutil, b'hasdriveletter', hasdriveletter)
162 extensions.wrapfunction(urlutil, 'hasdriveletter', hasdriveletter)
163
163
164
164
165 @command(b'debugexpandscheme', norepo=True)
165 @command(b'debugexpandscheme', norepo=True)
166 def expandscheme(ui, url, **opts):
166 def expandscheme(ui, url, **opts):
167 """given a repo path, provide the scheme-expanded path"""
167 """given a repo path, provide the scheme-expanded path"""
168 scheme = urlutil.url(url).scheme
168 scheme = urlutil.url(url).scheme
169 if scheme in hg.peer_schemes:
169 if scheme in hg.peer_schemes:
170 cls = hg.peer_schemes[scheme]
170 cls = hg.peer_schemes[scheme]
171 else:
171 else:
172 cls = hg.repo_schemes.get(scheme)
172 cls = hg.repo_schemes.get(scheme)
173 if cls is not None and isinstance(cls, ShortRepository):
173 if cls is not None and isinstance(cls, ShortRepository):
174 url = cls.resolve(url)
174 url = cls.resolve(url)
175 ui.write(url + b'\n')
175 ui.write(url + b'\n')
General Comments 0
You need to be logged in to leave comments. Login now