Rev 6079: (jelmer) Allow specifying the colocated branch to use in the branch URL, in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Aug 17 18:14:09 UTC 2011
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 6079 [merge]
revision-id: pqm at pqm.ubuntu.com-20110817181357-y5q5eth1hk8bl3om
parent: pqm at pqm.ubuntu.com-20110817153820-fadqb9cj9kadzqpy
parent: jelmer at samba.org-20110817011917-nde9fanxwp2ie838
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2011-08-17 18:13:57 +0000
message:
(jelmer) Allow specifying the colocated branch to use in the branch URL,
and retrieving the branch name using ControlDir._get_selected_branch.
(Jelmer Vernooij)
modified:
bzrlib/controldir.py controldir.py-20100802102926-hvtvh0uae5epuibp-1
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/blackbox/test_upgrade.py test_upgrade.py-20060120060132-b41e5ed2f886ad28
bzrlib/tests/per_controldir/test_controldir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
bzrlib/tests/per_transport.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
bzrlib/tests/stub_sftp.py stub_sftp.py-20051027032739-0e7ef4f7bab0e174
bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
bzrlib/tests/test_smart_transport.py test_ssh_transport.py-20060608202016-c25gvf1ob7ypbus6-2
bzrlib/tests/test_transport.py testtransport.py-20050718175618-e5cdb99f4555ddce
bzrlib/tests/test_urlutils.py test_urlutils.py-20060502192900-46b1f9579987cf9c
bzrlib/tests/transport_util.py transportutil.py-20070525113600-5v2igk89s8fensom-1
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/transport/decorator.py decorator.py-20060402223305-e913a0f25319ab42
bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
bzrlib/transport/local.py local_transport.py-20050711165921-9b1f142bfe480c24
bzrlib/urlutils.py urlutils.py-20060502195429-e8a161ecf8fac004
doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
=== modified file 'bzrlib/controldir.py'
--- a/bzrlib/controldir.py 2011-08-15 16:06:58 +0000
+++ b/bzrlib/controldir.py 2011-08-17 18:13:57 +0000
@@ -31,6 +31,7 @@
revision as _mod_revision,
transport as _mod_transport,
ui,
+ urlutils,
)
from bzrlib.push import (
PushResult,
@@ -273,6 +274,16 @@
except errors.NotBranchError:
return False
+ def _get_selected_branch(self):
+ """Return the name of the branch selected by the user.
+
+ :return: Name of the branch selected by the user, or None.
+ """
+ branch = self.root_transport.get_segment_parameters().get("branch")
+ if branch is not None:
+ branch = urlutils.unescape(branch)
+ return branch
+
def has_workingtree(self):
"""Tell if this controldir contains a working tree.
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2011-06-18 13:57:17 +0000
+++ b/bzrlib/remote.py 2011-08-17 01:19:17 +0000
@@ -669,7 +669,8 @@
def _path_for_remote_call(self, client):
"""Return the path to be used for this bzrdir in a remote call."""
- return client.remote_path_from_transport(self.root_transport)
+ return urlutils.split_segment_parameters_raw(
+ client.remote_path_from_transport(self.root_transport))[0]
def get_branch_transport(self, branch_format, name=None):
self._ensure_real()
=== modified file 'bzrlib/tests/blackbox/test_upgrade.py'
--- a/bzrlib/tests/blackbox/test_upgrade.py 2011-04-05 14:47:30 +0000
+++ b/bzrlib/tests/blackbox/test_upgrade.py 2011-08-12 13:04:56 +0000
@@ -254,7 +254,7 @@
t = self.get_transport()
url = t.base
out, err = self.run_bzr(['upgrade', '--format=2a', url])
- backup_dir = 'backup.bzr.~1~'
+ backup_dir = 'backup.bzr.%7E1%7E'
self.assertEqualDiff("""Upgrading branch %s ...
starting upgrade of %s
making backup of %s.bzr
@@ -262,7 +262,7 @@
starting repository conversion
repository converted
finished
-""" % (url, url, url, url,backup_dir), out)
+""" % (url, url, url, url, backup_dir), out)
self.assertEqual('', err)
=== modified file 'bzrlib/tests/per_controldir/test_controldir.py'
--- a/bzrlib/tests/per_controldir/test_controldir.py 2011-08-10 14:02:04 +0000
+++ b/bzrlib/tests/per_controldir/test_controldir.py 2011-08-15 13:26:00 +0000
@@ -998,7 +998,8 @@
repo_name = old_fmt.repository_format.network_name()
# Should end up with a 1.9 format (stackable)
repo, control = self.assertInitializeEx(t, need_meta=True,
- repo_format_name=repo_name, stacked_on='../trunk', stack_on_pwd=t.base)
+ repo_format_name=repo_name, stacked_on='../trunk',
+ stack_on_pwd=t.base)
if control is None:
# uninitialisable format
return
@@ -1282,6 +1283,41 @@
self.assertIsInstance(opened_tree, made_tree.__class__)
self.assertIsInstance(opened_tree._format, made_tree._format.__class__)
+ def test_get_selected_branch(self):
+ # The segment parameters are accessible from the root transport
+ # if a URL with segment parameters is opened.
+ if not self.bzrdir_format.is_supported():
+ # unsupported formats are not loopback testable
+ # because the default open will not open them and
+ # they may not be initializable.
+ return
+ t = self.get_transport()
+ try:
+ made_control = self.bzrdir_format.initialize(t.base)
+ except (errors.NotLocalUrl, errors.UnsupportedOperation):
+ raise TestSkipped("Can't initialize %r on transport %r"
+ % (self.bzrdir_format, t))
+ dir = bzrdir.BzrDir.open(t.base+",branch=foo")
+ self.assertEquals({"branch": "foo"},
+ dir.user_transport.get_segment_parameters())
+ self.assertEquals("foo", dir._get_selected_branch())
+
+ def test_get_selected_branch_none_selected(self):
+ # _get_selected_branch defaults to None
+ if not self.bzrdir_format.is_supported():
+ # unsupported formats are not loopback testable
+ # because the default open will not open them and
+ # they may not be initializable.
+ return
+ t = self.get_transport()
+ try:
+ made_control = self.bzrdir_format.initialize(t.base)
+ except (errors.NotLocalUrl, errors.UnsupportedOperation):
+ raise TestSkipped("Can't initialize %r on transport %r"
+ % (self.bzrdir_format, t))
+ dir = bzrdir.BzrDir.open(t.base)
+ self.assertIs(None, dir._get_selected_branch())
+
def test_root_transport(self):
dir = self.make_bzrdir('.')
self.assertEqual(dir.root_transport.base,
=== modified file 'bzrlib/tests/per_transport.py'
--- a/bzrlib/tests/per_transport.py 2011-08-08 17:52:59 +0000
+++ b/bzrlib/tests/per_transport.py 2011-08-15 11:19:03 +0000
@@ -1230,7 +1230,7 @@
if host is None: host = t._parsed_url.host
if port is None: port = t._parsed_url.port
if path is None: path = t._parsed_url.path
- return t._unsplit_url(scheme, user, password, host, port, path)
+ return str(urlutils.URL(scheme, user, password, host, port, path))
if t._parsed_url.scheme == 'ftp':
scheme = 'sftp'
@@ -1776,6 +1776,21 @@
self.assertListRaises((errors.ShortReadvError, errors.InvalidRange),
transport.readv, 'a', [(12,2)])
+ def test_no_segment_parameters(self):
+ """Segment parameters should be stripped and stored in
+ transport.segment_parameters."""
+ transport = self.get_transport("foo")
+ self.assertEquals({}, transport.get_segment_parameters())
+
+ def test_segment_parameters(self):
+ """Segment parameters should be stripped and stored in
+ transport.get_segment_parameters()."""
+ base_url = self._server.get_url()
+ parameters = {"key1": "val1", "key2": "val2"}
+ url = urlutils.join_segment_parameters(base_url, parameters)
+ transport = _mod_transport.get_transport(url)
+ self.assertEquals(parameters, transport.get_segment_parameters())
+
def test_stat_symlink(self):
# if a transport points directly to a symlink (and supports symlinks
# at all) you can tell this. helps with bug 32669.
=== modified file 'bzrlib/tests/stub_sftp.py'
--- a/bzrlib/tests/stub_sftp.py 2011-01-12 01:01:53 +0000
+++ b/bzrlib/tests/stub_sftp.py 2011-08-15 12:37:25 +0000
@@ -553,7 +553,7 @@
def get_url(self):
"""See bzrlib.transport.Server.get_url."""
- return self._get_sftp_url("~/")
+ return self._get_sftp_url("%7E/")
class SFTPSiblingAbsoluteServer(SFTPAbsoluteServer):
=== modified file 'bzrlib/tests/test_ftp_transport.py'
--- a/bzrlib/tests/test_ftp_transport.py 2011-08-08 17:52:59 +0000
+++ b/bzrlib/tests/test_ftp_transport.py 2011-08-15 12:26:33 +0000
@@ -16,6 +16,7 @@
import ftplib
import getpass
+import urllib
from bzrlib import (
config,
@@ -82,10 +83,12 @@
"""Overrides get_url to inject our user."""
base = super(TestFTPTestServerUI, self).get_url(relpath)
parsed_url = transport.ConnectedTransport._split_url(base)
- url = transport.ConnectedTransport._unsplit_url(
- parsed_url.scheme, self.user, self.password, parsed_url.host,
- parsed_url.port, parsed_url.path)
- return url
+ new_url = parsed_url.clone()
+ new_url.user = self.user
+ new_url.quoted_user = urllib.quote(self.user)
+ new_url.password = self.password
+ new_url.quoted_password = urllib.quote(self.password)
+ return str(new_url)
def test_no_prompt_for_username(self):
"""ensure getpass.getuser() is used if there's no username in the
=== modified file 'bzrlib/tests/test_smart_transport.py'
--- a/bzrlib/tests/test_smart_transport.py 2011-08-08 17:52:59 +0000
+++ b/bzrlib/tests/test_smart_transport.py 2011-08-12 15:34:53 +0000
@@ -3558,7 +3558,7 @@
# still work correctly.
base_transport = remote.RemoteHTTPTransport('bzr+http://host/%7Ea/b')
new_transport = base_transport.clone('c')
- self.assertEqual('bzr+http://host/~a/b/c/', new_transport.base)
+ self.assertEqual('bzr+http://host/%7Ea/b/c/', new_transport.base)
self.assertEqual(
'c/',
new_transport._client.remote_path_from_transport(new_transport))
=== modified file 'bzrlib/tests/test_transport.py'
--- a/bzrlib/tests/test_transport.py 2011-08-12 18:48:36 +0000
+++ b/bzrlib/tests/test_transport.py 2011-08-15 14:31:55 +0000
@@ -701,6 +701,15 @@
self.assertIsInstance(t, local.LocalTransport)
self.assertEquals(t.base.rstrip("/"), url)
+ def test_with_url_and_segment_parameters(self):
+ url = urlutils.local_path_to_url(self.test_dir)+",branch=foo"
+ t = transport.get_transport_from_url(url)
+ self.assertIsInstance(t, local.LocalTransport)
+ self.assertEquals(t.base.rstrip("/"), url)
+ with open(os.path.join(self.test_dir, "afile"), 'w') as f:
+ f.write("data")
+ self.assertTrue(t.has("afile"))
+
class TestLocalTransports(tests.TestCase):
@@ -796,7 +805,7 @@
self.assertEquals(t._parsed_url.path, '/path/')
# Base should not keep track of the password
- self.assertEquals(t.base, 'http://robey@exAmple.com:2222/path/')
+ self.assertEquals(t.base, 'http://ro%62ey@ex%41mple.com:2222/path/')
def test_parse_invalid_url(self):
self.assertRaises(errors.InvalidURL,
=== modified file 'bzrlib/tests/test_urlutils.py'
--- a/bzrlib/tests/test_urlutils.py 2011-08-11 14:46:42 +0000
+++ b/bzrlib/tests/test_urlutils.py 2011-08-15 13:12:36 +0000
@@ -336,17 +336,24 @@
def test_function_type(self):
if sys.platform == 'win32':
- self.assertEqual(urlutils._win32_local_path_to_url, urlutils.local_path_to_url)
- self.assertEqual(urlutils._win32_local_path_from_url, urlutils.local_path_from_url)
+ self.assertEqual(urlutils._win32_local_path_to_url,
+ urlutils.local_path_to_url)
+ self.assertEqual(urlutils._win32_local_path_from_url,
+ urlutils.local_path_from_url)
else:
- self.assertEqual(urlutils._posix_local_path_to_url, urlutils.local_path_to_url)
- self.assertEqual(urlutils._posix_local_path_from_url, urlutils.local_path_from_url)
+ self.assertEqual(urlutils._posix_local_path_to_url,
+ urlutils.local_path_to_url)
+ self.assertEqual(urlutils._posix_local_path_from_url,
+ urlutils.local_path_from_url)
def test_posix_local_path_to_url(self):
to_url = urlutils._posix_local_path_to_url
self.assertEqual('file:///path/to/foo',
to_url('/path/to/foo'))
+ self.assertEqual('file:///path/to/foo%2Cbar',
+ to_url('/path/to/foo,bar'))
+
try:
result = to_url(u'/path/to/r\xe4ksm\xf6rg\xe5s')
except UnicodeError:
@@ -359,6 +366,8 @@
from_url = urlutils._posix_local_path_from_url
self.assertEqual('/path/to/foo',
from_url('file:///path/to/foo'))
+ self.assertEqual('/path/to/foo',
+ from_url('file:///path/to/foo,branch=foo'))
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
from_url('file:///path/to/r%C3%A4ksm%C3%B6rg%C3%A5s'))
self.assertEqual(u'/path/to/r\xe4ksm\xf6rg\xe5s',
@@ -386,6 +395,8 @@
self.assertEqual('file:///', to_url('/'))
+ self.assertEqual('file:///C:/path/to/foo%2Cbar',
+ to_url('C:/path/to/foo,bar'))
try:
result = to_url(u'd:/path/to/r\xe4ksm\xf6rg\xe5s')
except UnicodeError:
@@ -418,6 +429,8 @@
self.assertEqual(u'D:/path/to/r\xe4ksm\xf6rg\xe5s',
from_url('file:///d:/path/to/r%c3%a4ksm%c3%b6rg%c3%a5s'))
self.assertEqual('/', from_url('file:///'))
+ self.assertEqual('C:/path/to/foo',
+ from_url('file:///C|/path/to/foo,branch=foo'))
self.assertRaises(InvalidURL, from_url, 'file:///C:')
self.assertRaises(InvalidURL, from_url, 'file:///c')
@@ -428,6 +441,8 @@
def test_win32_unc_path_from_url(self):
from_url = urlutils._win32_local_path_from_url
self.assertEqual('//HOST/path', from_url('file://HOST/path'))
+ self.assertEqual('//HOST/path',
+ from_url('file://HOST/path,branch=foo'))
# despite IE allows 2, 4, 5 and 6 slashes in URL to another machine
# we want to use only 2 slashes
# Firefox understand only 5 slashes in URL, but it's ugly
@@ -494,6 +509,8 @@
split_segment_parameters_raw(",key1=val1"))
self.assertEquals(("foo/", ["key1=val1"]),
split_segment_parameters_raw("foo/,key1=val1"))
+ self.assertEquals(("/foo", ["key1=val1"]),
+ split_segment_parameters_raw("foo,key1=val1"))
self.assertEquals(("foo/base,la=bla/other/elements", []),
split_segment_parameters_raw("foo/base,la=bla/other/elements"))
self.assertEquals(("foo/base,la=bla/other/elements", ["a=b"]),
=== modified file 'bzrlib/tests/transport_util.py'
--- a/bzrlib/tests/transport_util.py 2011-08-08 17:52:59 +0000
+++ b/bzrlib/tests/transport_util.py 2011-08-15 12:27:36 +0000
@@ -78,12 +78,7 @@
# The following is needed to minimize the effects of our trick above
# while retaining the best compatibility.
self._parsed_url.scheme = _hooked_scheme
- base = self._unsplit_url(self._parsed_url.scheme,
- self._parsed_url.user,
- self._parsed_url.password,
- self._parsed_url.host, self._parsed_url.port,
- self._parsed_url.path)
- super(ConnectedTransport, self).__init__(base)
+ super(ConnectedTransport, self).__init__(str(self._parsed_url))
class ConnectionHookedTransport(InstrumentedTransport):
=== modified file 'bzrlib/transport/__init__.py'
--- a/bzrlib/transport/__init__.py 2011-08-11 15:13:57 +0000
+++ b/bzrlib/transport/__init__.py 2011-08-12 15:34:53 +0000
@@ -310,6 +310,8 @@
def __init__(self, base):
super(Transport, self).__init__()
self.base = base
+ self._segment_parameters = urlutils.split_segment_parameters(
+ base.rstrip("/"))[1]
def _translate_error(self, e, path, raise_generic=True):
"""Translate an IOError or OSError into an appropriate bzr error.
@@ -409,6 +411,11 @@
"""
raise NotImplementedError(self.external_url)
+ def get_segment_parameters(self):
+ """Return the segment parameters for the top segment of the URL.
+ """
+ return self._segment_parameters
+
def _pump(self, from_file, to_file):
"""Most children will need to copy from one file-like
object or string to another one.
@@ -1329,10 +1336,7 @@
self._parsed_url.quoted_password = (
_from_transport._parsed_url.quoted_password)
- base = self._unsplit_url(self._parsed_url.scheme,
- self._parsed_url.user, self._parsed_url.password,
- self._parsed_url.host, self._parsed_url.port,
- self._parsed_url.path)
+ base = str(self._parsed_url)
super(ConnectedTransport, self).__init__(base)
if _from_transport is None:
@@ -1434,9 +1438,7 @@
:returns: the Unicode version of the absolute path for relpath.
"""
- other = self._parsed_url.clone(relpath)
- return self._unsplit_url(other.scheme, other.user, other.password,
- other.host, other.port, other.path)
+ return str(self._parsed_url.clone(relpath))
def _remote_path(self, relpath):
"""Return the absolute path part of the url to the given relative path.
=== modified file 'bzrlib/transport/decorator.py'
--- a/bzrlib/transport/decorator.py 2010-06-20 11:18:38 +0000
+++ b/bzrlib/transport/decorator.py 2011-03-17 10:52:31 +0000
@@ -156,6 +156,15 @@
"""See Transport.rmdir."""
return self._decorated.rmdir(relpath)
+ def _get_segment_parameters(self):
+ return self._decorated.segment_parameters
+
+ def _set_segment_parameters(self, value):
+ self._decorated.segment_parameters = value
+
+ segment_parameters = property(_get_segment_parameters,
+ _set_segment_parameters, "See Transport.segment_parameters")
+
def stat(self, relpath):
"""See Transport.stat()."""
return self._decorated.stat(relpath)
=== modified file 'bzrlib/transport/http/__init__.py'
--- a/bzrlib/transport/http/__init__.py 2011-08-11 16:24:09 +0000
+++ b/bzrlib/transport/http/__init__.py 2011-08-15 12:32:05 +0000
@@ -148,10 +148,11 @@
user and passwords are not embedded in the path provided to the server.
"""
- path = self._parsed_url.clone(relpath).path
- return self._unsplit_url(self._unqualified_scheme,
- None, None, self._parsed_url.host,
- self._parsed_url.port, path)
+ url = self._parsed_url.clone(relpath)
+ url.user = url.quoted_user = None
+ url.password = url.quoted_password = None
+ url.scheme = self._unqualified_scheme
+ return str(url)
def _create_auth(self):
"""Returns a dict containing the credentials provided at build time."""
@@ -412,10 +413,9 @@
"""See bzrlib.transport.Transport.external_url."""
# HTTP URL's are externally usable as long as they don't mention their
# implementation qualifier
- return self._unsplit_url(self._unqualified_scheme,
- self._parsed_url.user, self._parsed_url.password,
- self._parsed_url.host, self._parsed_url.port,
- self._parsed_url.path)
+ url = self._parsed_url.clone()
+ url.scheme = self._unqualified_scheme
+ return str(url)
def is_readonly(self):
"""See Transport.is_readonly."""
@@ -538,7 +538,7 @@
new_transport = None
parsed_url = self._split_url(target)
# Recalculate base path. This is needed to ensure that when the
- # redirected tranport will be used to re-try whatever request was
+ # redirected transport will be used to re-try whatever request was
# redirected, we end up with the same url
base_path = parsed_url.path[:-len(relpath)]
if parsed_url.scheme in ('http', 'https'):
=== modified file 'bzrlib/transport/local.py'
--- a/bzrlib/transport/local.py 2011-07-05 06:41:37 +0000
+++ b/bzrlib/transport/local.py 2011-08-15 14:31:55 +0000
@@ -72,6 +72,8 @@
super(LocalTransport, self).__init__(base)
self._local_base = urlutils.local_path_from_url(base)
+ if self._local_base[-1] != '/':
+ self._local_base = self._local_base + '/'
def clone(self, offset=None):
"""Return a new LocalTransport with root at self.base + offset
=== modified file 'bzrlib/urlutils.py'
--- a/bzrlib/urlutils.py 2011-08-11 14:46:42 +0000
+++ b/bzrlib/urlutils.py 2011-08-15 13:12:36 +0000
@@ -181,6 +181,7 @@
# jam 20060502 Sorted to 'l' because the final target is 'local_path_from_url'
def _posix_local_path_from_url(url):
"""Convert a url like file:///path/to/foo into /path/to/foo"""
+ url = split_segment_parameters_raw(url)[0]
file_localhost_prefix = 'file://localhost/'
if url.startswith(file_localhost_prefix):
path = url[len(file_localhost_prefix) - 1:]
@@ -209,6 +210,7 @@
if not url.startswith('file://'):
raise errors.InvalidURL(url, 'local urls must start with file:///, '
'UNC path urls must start with file://')
+ url = split_segment_parameters_raw(url)[0]
# We strip off all 3 slashes
win32_url = url[len('file:'):]
# check for UNC path: //HOST/path
=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt 2011-08-17 08:40:16 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt 2011-08-17 18:13:57 +0000
@@ -174,6 +174,10 @@
.. Major internal changes, unlikely to be visible to users or plugin
developers, but interesting for bzr developers.
+* New method ``ControlDir._get_selected_branch`` which returns the
+ colocated branch selected using path segment parameters.
+ (Jelmer Vernooij, #380871)
+
Testing
*******
More information about the bazaar-commits
mailing list