Merge lp:~jelmer/brz/rcp-url into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/rcp-url
Merge into: lp:brz
Diff against target: 189 lines (+79/-12)
6 files modified
breezy/directory_service.py (+2/-2)
breezy/location.py (+33/-2)
breezy/tests/test_location.py (+26/-0)
breezy/tests/test_transport.py (+7/-5)
breezy/transport/remote.py (+7/-3)
doc/en/release-notes/brz-3.0.txt (+4/-0)
To merge this branch: bzr merge lp:~jelmer/brz/rcp-url
Reviewer Review Type Date Requested Status
Martin Packman Approve
Review via email: mp+362712@code.launchpad.net

Commit message

Add support for rcp-style location string for SSH operations.

Description of the change

Add support for rcp-style location stringfor SSH operations.

For the moment, these are converted to ssh:// URLs. Breezy prints an error when
opening these, suggesting the user use either bzr+ssh or git+ssh. This is not
ideal, but better than giving a more confusing error.

Unfortunately this requires some heuristics, since it may be hard to tell apart
real "URLs" and RCP style location strings. E.g. "http:foo".

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Thanks, seem couple of comments inline.

review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'breezy/directory_service.py'
--- breezy/directory_service.py 2019-02-09 03:23:20 +0000
+++ breezy/directory_service.py 2019-03-03 20:13:19 +0000
@@ -185,8 +185,8 @@
185185
186 def look_up(self, name, url, purpose=None):186 def look_up(self, name, url, purpose=None):
187 dir = _mod_controldir.ControlDir.open_containing('.')[0]187 dir = _mod_controldir.ControlDir.open_containing('.')[0]
188 return urlutils.join_segment_parameters(dir.user_url,188 return urlutils.join_segment_parameters(
189 {"branch": urlutils.escape(name)})189 dir.user_url, {"branch": urlutils.escape(name)})
190190
191191
192directories.register('co:', ColocatedDirectory,192directories.register('co:', ColocatedDirectory,
193193
=== modified file 'breezy/location.py'
--- breezy/location.py 2019-02-09 03:23:20 +0000
+++ breezy/location.py 2019-03-03 20:13:19 +0000
@@ -19,6 +19,8 @@
1919
20from __future__ import absolute_import20from __future__ import absolute_import
2121
22import re
23
22from . import (24from . import (
23 urlutils,25 urlutils,
24 )26 )
@@ -44,6 +46,28 @@
44hooks = LocationHooks()46hooks = LocationHooks()
4547
4648
49def rcp_location_to_url(location, scheme='ssh'):
50 """Convert a rcp-style location to a URL.
51
52 :param location: Location to convert, e.g. "foo:bar"
53 :param schenme: URL scheme to return, defaults to "ssh"
54 :return: A URL, e.g. "ssh://foo/bar"
55 :raises ValueError: if this is not a RCP-style URL
56 """
57 m = re.match('^(?P<user>[^@:/]+@)?(?P<host>[^/:]+):(?P<path>.*)$', location)
58 if not m:
59 raise ValueError("Not a RCP URL")
60 if m.group('path').startswith('//'):
61 raise ValueError("Not a RCP URL: already looks like a URL")
62 quoted_user = urlutils.quote(m.group('user')[:-1]) if m.group('user') else None
63 url = urlutils.URL(
64 scheme=scheme, quoted_user=quoted_user,
65 port=None, quoted_password=None,
66 quoted_host=urlutils.quote(m.group('host')),
67 quoted_path=urlutils.quote(m.group('path')))
68 return str(url)
69
70
47def location_to_url(location, purpose=None):71def location_to_url(location, purpose=None):
48 """Determine a fully qualified URL from a location string.72 """Determine a fully qualified URL from a location string.
4973
@@ -65,8 +89,8 @@
65 location = location.encode('ascii')89 location = location.encode('ascii')
66 except UnicodeError:90 except UnicodeError:
67 if urlutils.is_url(location):91 if urlutils.is_url(location):
68 raise urlutils.InvalidURL(path=location,92 raise urlutils.InvalidURL(
69 extra='URLs must be properly escaped')93 path=location, extra='URLs must be properly escaped')
70 location = urlutils.local_path_to_url(location)94 location = urlutils.local_path_to_url(location)
71 else:95 else:
72 if PY3:96 if PY3:
@@ -75,6 +99,13 @@
75 if location.startswith("file:") and not location.startswith("file://"):99 if location.startswith("file:") and not location.startswith("file://"):
76 return urlutils.join(urlutils.local_path_to_url("."), location[5:])100 return urlutils.join(urlutils.local_path_to_url("."), location[5:])
77101
102 try:
103 url = rcp_location_to_url(location, scheme="ssh")
104 except ValueError:
105 pass
106 else:
107 return url
108
78 if not urlutils.is_url(location):109 if not urlutils.is_url(location):
79 return urlutils.local_path_to_url(location)110 return urlutils.local_path_to_url(location)
80111
81112
=== modified file 'breezy/tests/test_location.py'
--- breezy/tests/test_location.py 2019-02-09 02:59:15 +0000
+++ breezy/tests/test_location.py 2019-03-03 20:13:19 +0000
@@ -25,6 +25,7 @@
25from ..location import (25from ..location import (
26 hooks as location_hooks,26 hooks as location_hooks,
27 location_to_url,27 location_to_url,
28 rcp_location_to_url,
28 )29 )
2930
3031
@@ -75,6 +76,11 @@
75 def test_absolute_file_url(self):76 def test_absolute_file_url(self):
76 self.assertEqual("file:///bar", location_to_url("file:/bar"))77 self.assertEqual("file:///bar", location_to_url("file:/bar"))
7778
79 def test_rcp_url(self):
80 self.assertEqual(
81 "ssh://example.com/srv/git/bar",
82 location_to_url("example.com:/srv/git/bar"))
83
78 def test_rewrite_hook(self):84 def test_rewrite_hook(self):
79 self.assertEqual(85 self.assertEqual(
80 'http://foo.example.com/blah', location_to_url('http://foo.example.com/blah'))86 'http://foo.example.com/blah', location_to_url('http://foo.example.com/blah'))
@@ -84,3 +90,23 @@
84 location_hooks.install_named_hook('rewrite_url', rewrite_url, 'test')90 location_hooks.install_named_hook('rewrite_url', rewrite_url, 'test')
85 self.assertEqual(91 self.assertEqual(
86 'http://bar.example.com/bar', location_to_url('http://foo.example.com/foo'))92 'http://bar.example.com/bar', location_to_url('http://foo.example.com/foo'))
93
94
95class RCPLocationTests(tests.TestCase):
96
97 def test_without_user(self):
98 self.assertEqual(
99 "git+ssh://example.com/srv/git/bar",
100 rcp_location_to_url("example.com:/srv/git/bar", scheme='git+ssh'))
101 self.assertEqual(
102 "ssh://example.com/srv/git/bar",
103 rcp_location_to_url("example.com:/srv/git/bar"))
104
105 def test_with_user(self):
106 self.assertEqual(
107 "git+ssh://foo@example.com/srv/git/bar",
108 rcp_location_to_url("foo@example.com:/srv/git/bar", scheme='git+ssh'))
109
110 def test_invalid(self):
111 self.assertRaises(ValueError, rcp_location_to_url, "http://srv/git/bar")
112 self.assertRaises(ValueError, rcp_location_to_url, "git/bar")
87113
=== modified file 'breezy/tests/test_transport.py'
--- breezy/tests/test_transport.py 2018-11-23 23:51:34 +0000
+++ breezy/tests/test_transport.py 2019-03-03 20:13:19 +0000
@@ -119,11 +119,13 @@
119 try:119 try:
120 transport.get_transport_from_url('ssh://fooserver/foo')120 transport.get_transport_from_url('ssh://fooserver/foo')
121 except errors.UnsupportedProtocol as e:121 except errors.UnsupportedProtocol as e:
122 self.assertEqual('Unsupported protocol'122 self.assertEqual(
123 ' for url "ssh://fooserver/foo":'123 'Unsupported protocol'
124 ' bzr supports bzr+ssh to operate over ssh,'124 ' for url "ssh://fooserver/foo":'
125 ' use "bzr+ssh://fooserver/foo".',125 ' Use bzr+ssh for Bazaar operations over SSH, '
126 str(e))126 'e.g. "bzr+ssh://fooserver/foo". Use git+ssh '
127 'for Git operations over SSH, e.g. "git+ssh://fooserver/foo".',
128 str(e))
127 else:129 else:
128 self.fail('Did not raise UnsupportedProtocol')130 self.fail('Did not raise UnsupportedProtocol')
129131
130132
=== modified file 'breezy/transport/remote.py'
--- breezy/transport/remote.py 2018-11-11 04:08:32 +0000
+++ breezy/transport/remote.py 2019-03-03 20:13:19 +0000
@@ -602,11 +602,15 @@
602602
603603
604class HintingSSHTransport(transport.Transport):604class HintingSSHTransport(transport.Transport):
605 """Simple transport that handles ssh:// and points out bzr+ssh://."""605 """Simple transport that handles ssh:// and points out bzr+ssh:// and git+ssh://."""
606
607 # TODO(jelmer): Implement support for detecting whether the repository at the
608 # other end is a git or bzr repository.
606609
607 def __init__(self, url):610 def __init__(self, url):
608 raise errors.UnsupportedProtocol(url,611 raise errors.UnsupportedProtocol(
609 'bzr supports bzr+ssh to operate over ssh, use "bzr+%s".' % url)612 url, 'Use bzr+ssh for Bazaar operations over SSH, e.g. "bzr+%s". '
613 'Use git+ssh for Git operations over SSH, e.g. "git+%s".' % (url, url))
610614
611615
612def get_test_permutations():616def get_test_permutations():
613617
=== modified file 'doc/en/release-notes/brz-3.0.txt'
--- doc/en/release-notes/brz-3.0.txt 2019-02-14 06:21:45 +0000
+++ doc/en/release-notes/brz-3.0.txt 2019-03-03 20:13:19 +0000
@@ -137,6 +137,10 @@
137 * Plugins can now be registered using the 'entrypoints' mechanism in137 * Plugins can now be registered using the 'entrypoints' mechanism in
138 setuptools. (Jelmer Vernooij, #1802647)138 setuptools. (Jelmer Vernooij, #1802647)
139139
140 * The Breezy UI now handles RCP-style URLs and suggests the
141 user specify either ``git+ssh`` or ``bzr+ssh``.
142 (Jelmer Vernooij)
143
140Improvements144Improvements
141************145************
142146

Subscribers

People subscribed via source and target branches