##// END OF EJS Templates
scheme: don't crash on invalid URLs
Mads Kiilerich -
r18910:b52404a9 default
parent child Browse files
Show More
@@ -1,101 +1,104 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, re
43 import os, re
44 from mercurial import extensions, hg, templater, util
44 from mercurial import extensions, hg, templater, util
45 from mercurial.i18n import _
45 from mercurial.i18n import _
46
46
47 testedwith = 'internal'
47 testedwith = 'internal'
48
48
49
49
50 class ShortRepository(object):
50 class ShortRepository(object):
51 def __init__(self, url, scheme, templater):
51 def __init__(self, url, scheme, templater):
52 self.scheme = scheme
52 self.scheme = scheme
53 self.templater = templater
53 self.templater = templater
54 self.url = url
54 self.url = url
55 try:
55 try:
56 self.parts = max(map(int, re.findall(r'\{(\d+)\}', self.url)))
56 self.parts = max(map(int, re.findall(r'\{(\d+)\}', self.url)))
57 except ValueError:
57 except ValueError:
58 self.parts = 0
58 self.parts = 0
59
59
60 def __repr__(self):
60 def __repr__(self):
61 return '<ShortRepository: %s>' % self.scheme
61 return '<ShortRepository: %s>' % self.scheme
62
62
63 def instance(self, ui, url, create):
63 def instance(self, ui, url, create):
64 # Should this use the util.url class, or is manual parsing better?
64 # Should this use the util.url class, or is manual parsing better?
65 url = url.split('://', 1)[1]
65 try:
66 url = url.split('://', 1)[1]
67 except IndexError:
68 raise util.Abort(_("no '://' in scheme url '%s'") % url)
66 parts = url.split('/', self.parts)
69 parts = url.split('/', self.parts)
67 if len(parts) > self.parts:
70 if len(parts) > self.parts:
68 tail = parts[-1]
71 tail = parts[-1]
69 parts = parts[:-1]
72 parts = parts[:-1]
70 else:
73 else:
71 tail = ''
74 tail = ''
72 context = dict((str(i + 1), v) for i, v in enumerate(parts))
75 context = dict((str(i + 1), v) for i, v in enumerate(parts))
73 url = ''.join(self.templater.process(self.url, context)) + tail
76 url = ''.join(self.templater.process(self.url, context)) + tail
74 return hg._peerlookup(url).instance(ui, url, create)
77 return hg._peerlookup(url).instance(ui, url, create)
75
78
76 def hasdriveletter(orig, path):
79 def hasdriveletter(orig, path):
77 if path:
80 if path:
78 for scheme in schemes:
81 for scheme in schemes:
79 if path.startswith(scheme + ':'):
82 if path.startswith(scheme + ':'):
80 return False
83 return False
81 return orig(path)
84 return orig(path)
82
85
83 schemes = {
86 schemes = {
84 'py': 'http://hg.python.org/',
87 'py': 'http://hg.python.org/',
85 'bb': 'https://bitbucket.org/',
88 'bb': 'https://bitbucket.org/',
86 'bb+ssh': 'ssh://hg@bitbucket.org/',
89 'bb+ssh': 'ssh://hg@bitbucket.org/',
87 'gcode': 'https://{1}.googlecode.com/hg/',
90 'gcode': 'https://{1}.googlecode.com/hg/',
88 'kiln': 'https://{1}.kilnhg.com/Repo/'
91 'kiln': 'https://{1}.kilnhg.com/Repo/'
89 }
92 }
90
93
91 def extsetup(ui):
94 def extsetup(ui):
92 schemes.update(dict(ui.configitems('schemes')))
95 schemes.update(dict(ui.configitems('schemes')))
93 t = templater.engine(lambda x: x)
96 t = templater.engine(lambda x: x)
94 for scheme, url in schemes.items():
97 for scheme, url in schemes.items():
95 if (os.name == 'nt' and len(scheme) == 1 and scheme.isalpha()
98 if (os.name == 'nt' and len(scheme) == 1 and scheme.isalpha()
96 and os.path.exists('%s:\\' % scheme)):
99 and os.path.exists('%s:\\' % scheme)):
97 raise util.Abort(_('custom scheme %s:// conflicts with drive '
100 raise util.Abort(_('custom scheme %s:// conflicts with drive '
98 'letter %s:\\\n') % (scheme, scheme.upper()))
101 'letter %s:\\\n') % (scheme, scheme.upper()))
99 hg.schemes[scheme] = ShortRepository(url, scheme, t)
102 hg.schemes[scheme] = ShortRepository(url, scheme, t)
100
103
101 extensions.wrapfunction(util, 'hasdriveletter', hasdriveletter)
104 extensions.wrapfunction(util, 'hasdriveletter', hasdriveletter)
@@ -1,50 +1,59 b''
1 $ "$TESTDIR/hghave" serve || exit 80
1 $ "$TESTDIR/hghave" serve || exit 80
2
2
3 $ cat <<EOF >> $HGRCPATH
3 $ cat <<EOF >> $HGRCPATH
4 > [extensions]
4 > [extensions]
5 > schemes=
5 > schemes=
6 >
6 >
7 > [schemes]
7 > [schemes]
8 > l = http://localhost:$HGPORT/
8 > l = http://localhost:$HGPORT/
9 > parts = http://{1}:$HGPORT/
9 > parts = http://{1}:$HGPORT/
10 > z = file:\$PWD/
10 > z = file:\$PWD/
11 > EOF
11 > EOF
12 $ hg init test
12 $ hg init test
13 $ cd test
13 $ cd test
14 $ echo a > a
14 $ echo a > a
15 $ hg ci -Am initial
15 $ hg ci -Am initial
16 adding a
16 adding a
17
18 invalid scheme
19
20 $ hg log -R z:z
21 abort: no '://' in scheme url 'z:z'
22 [255]
23
24 http scheme
25
17 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
26 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
18 $ cat hg.pid >> $DAEMON_PIDS
27 $ cat hg.pid >> $DAEMON_PIDS
19 $ hg incoming l://
28 $ hg incoming l://
20 comparing with l://
29 comparing with l://
21 searching for changes
30 searching for changes
22 no changes found
31 no changes found
23 [1]
32 [1]
24
33
25 check that {1} syntax works
34 check that {1} syntax works
26
35
27 $ hg incoming --debug parts://localhost
36 $ hg incoming --debug parts://localhost
28 using http://localhost:$HGPORT/
37 using http://localhost:$HGPORT/
29 sending capabilities command
38 sending capabilities command
30 comparing with parts://localhost/
39 comparing with parts://localhost/
31 query 1; heads
40 query 1; heads
32 sending batch command
41 sending batch command
33 searching for changes
42 searching for changes
34 all remote heads known locally
43 all remote heads known locally
35 no changes found
44 no changes found
36 [1]
45 [1]
37
46
38 check that paths are expanded
47 check that paths are expanded
39
48
40 $ PWD=`pwd` hg incoming z://
49 $ PWD=`pwd` hg incoming z://
41 comparing with z://
50 comparing with z://
42 searching for changes
51 searching for changes
43 no changes found
52 no changes found
44 [1]
53 [1]
45
54
46 errors
55 errors
47
56
48 $ cat errors.log
57 $ cat errors.log
49
58
50 $ cd ..
59 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now