Merge lp:~jml/bzr/default-stacking-bug-385132 into lp:~bzr/bzr/trunk-old

Proposed by Jonathan Lange
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jml/bzr/default-stacking-bug-385132
Merge into: lp:~bzr/bzr/trunk-old
Diff against target: 165 lines
To merge this branch: bzr merge lp:~jml/bzr/default-stacking-bug-385132
Reviewer Review Type Date Requested Status
Andrew Bennetts Approve
Review via email: mp+7330@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote :

Bazaar 1.15 added a verb for initialize_ex which broke certain default stacking policies, notably the one that Launchpad uses. This patch attempts to fix this regression by returning relative URLs when the stacking policy itself has a relative URL.

There are two interesting cases. One is where the policy looks like:
  default_stack_on=/foo/bar/baz

and the other where it looks like:
  default_stack_on=trunk

Current versions of Bazaar send these as ('/foo/bar/baz', 'chroot-123124:///') and ('trunk', 'chroot-15245:///). This patch changes them to be sent as ('/foo/bar/baz', '.') and ('trunk', '..').

Note that the fix touches both client and server side. That means that 1.15 clients will forever be broken when pushing new branches to Launchpad. This sucks, can we do something about it?

I think the rest of the patch is fairly simple: it adds some tests, trying to be as direct as possible; it changes the client to handle relative final_stack_pwd; it changes the server to generate relative final_stack & final_stack_pwd; it cleans up some lint & spelling mistakes found along the way.

This bug is blocking the 1.16rc1 release. I would greatly appreciate a swift review.

Thanks,
jml

Revision history for this message
Andrew Bennetts (spiv) wrote :

This feedback has already been given over IRC, but for the record:

38 + full_path = self._root_client_path + final_stack[1:]
39 + final_stack = urlutils.relative_url(
40 + target_transport.base, full_path)

didn't make sense to me.

What would make sense to me would be s/full_path/client_path/, and changing the first arg of relative_url to _root_client_path.

+ self.reset_smart_call_log()

Omit self.reset_smart_call_log() calls if you aren't going to inspect the call log in the test.

Everything else seems ok, I think.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/bzrdir.py'
--- bzrlib/bzrdir.py 2009-06-10 03:56:49 +0000
+++ bzrlib/bzrdir.py 2009-06-11 11:35:12 +0000
@@ -3249,6 +3249,9 @@
3249 repo_bzr = bzrdir3249 repo_bzr = bzrdir
3250 final_stack = response[8] or None3250 final_stack = response[8] or None
3251 final_stack_pwd = response[9] or None3251 final_stack_pwd = response[9] or None
3252 if final_stack_pwd:
3253 final_stack_pwd = urlutils.join(
3254 transport.base, final_stack_pwd)
3252 remote_repo = remote.RemoteRepository(repo_bzr, repo_format)3255 remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
3253 if len(response) > 10:3256 if len(response) > 10:
3254 # Updated server verb that locks remotely.3257 # Updated server verb that locks remotely.
32553258
=== modified file 'bzrlib/smart/bzrdir.py'
--- bzrlib/smart/bzrdir.py 2009-04-28 03:55:56 +0000
+++ bzrlib/smart/bzrdir.py 2009-06-11 11:35:12 +0000
@@ -17,7 +17,7 @@
17"""Server-side bzrdir related request implmentations."""17"""Server-side bzrdir related request implmentations."""
1818
1919
20from bzrlib import branch, errors, repository20from bzrlib import branch, errors, repository, urlutils
21from bzrlib.bzrdir import (21from bzrlib.bzrdir import (
22 BzrDir,22 BzrDir,
23 BzrDirFormat,23 BzrDirFormat,
@@ -407,6 +407,19 @@
407 repo.unlock()407 repo.unlock()
408 final_stack = final_stack or ''408 final_stack = final_stack or ''
409 final_stack_pwd = final_stack_pwd or ''409 final_stack_pwd = final_stack_pwd or ''
410
411 # We want this to be relative to the bzrdir.
412 if final_stack_pwd:
413 final_stack_pwd = urlutils.relative_url(
414 target_transport.base, final_stack_pwd)
415
416 # Can't meaningfully return a root path.
417 if final_stack.startswith('/'):
418 client_path = self._root_client_path + final_stack[1:]
419 final_stack = urlutils.relative_url(
420 self._root_client_path, client_path)
421 final_stack_pwd = '.'
422
410 return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,423 return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
411 external_lookup, repo_name, repo_bzrdir_name,424 external_lookup, repo_name, repo_bzrdir_name,
412 bzrdir._format.network_name(),425 bzrdir._format.network_name(),
413426
=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- bzrlib/tests/blackbox/test_push.py 2009-06-10 03:56:49 +0000
+++ bzrlib/tests/blackbox/test_push.py 2009-06-11 11:35:12 +0000
@@ -215,6 +215,31 @@
215 remote = branch.Branch.open('public')215 remote = branch.Branch.open('public')
216 self.assertEndsWith(remote.get_stacked_on_url(), '/parent')216 self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
217217
218 def test_push_smart_with_default_stacking_url_path_segment(self):
219 # If the default stacked-on location is a path element then branches
220 # we push there over the smart server are stacked and their
221 # stacked_on_url is that exact path segment. Added to nail bug 385132.
222 self.setup_smart_server_with_call_log()
223 self.make_branch('stack-on', format='1.9')
224 self.make_bzrdir('.').get_config().set_default_stack_on(
225 '/stack-on')
226 self.make_branch('from', format='1.9')
227 out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
228 b = branch.Branch.open(self.get_url('to'))
229 self.assertEqual('/extra/stack-on', b.get_stacked_on_url())
230
231 def test_push_smart_with_default_stacking_relative_path(self):
232 # If the default stacked-on location is a relative path then branches
233 # we push there over the smart server are stacked and their
234 # stacked_on_url is a relative path. Added to nail bug 385132.
235 self.setup_smart_server_with_call_log()
236 self.make_branch('stack-on', format='1.9')
237 self.make_bzrdir('.').get_config().set_default_stack_on('stack-on')
238 self.make_branch('from', format='1.9')
239 out, err = self.run_bzr(['push', '-d', 'from', self.get_url('to')])
240 b = branch.Branch.open(self.get_url('to'))
241 self.assertEqual('../stack-on', b.get_stacked_on_url())
242
218 def create_simple_tree(self):243 def create_simple_tree(self):
219 tree = self.make_branch_and_tree('tree')244 tree = self.make_branch_and_tree('tree')
220 self.build_tree(['tree/a'])245 self.build_tree(['tree/a'])
221246
=== modified file 'bzrlib/tests/bzrdir_implementations/test_bzrdir.py'
--- bzrlib/tests/bzrdir_implementations/test_bzrdir.py 2009-04-28 03:55:56 +0000
+++ bzrlib/tests/bzrdir_implementations/test_bzrdir.py 2009-06-11 11:35:12 +0000
@@ -1246,6 +1246,36 @@
1246 self.assertTrue(repo.is_write_locked())1246 self.assertTrue(repo.is_write_locked())
1247 repo.unlock()1247 repo.unlock()
12481248
1249 def test_format_initialize_on_transport_ex_default_stack_on(self):
1250 # When initialize_on_transport_ex uses a stacked-on branch because of
1251 # a stacking policy on the target, the location of the fallback
1252 # repository is the same as the external location of the stacked-on
1253 # branch.
1254 balloon = self.make_bzrdir('balloon')
1255 if isinstance(balloon, bzrdir.BzrDirMetaFormat1):
1256 stack_on = self.make_branch('stack-on', format='1.9')
1257 else:
1258 stack_on = self.make_branch('stack-on')
1259 config = self.make_bzrdir('.').get_config()
1260 try:
1261 config.set_default_stack_on('stack-on')
1262 except errors.BzrError:
1263 raise TestNotApplicable('Only relevant for stackable formats.')
1264 # Initialize a bzrdir subject to the policy.
1265 t = self.get_transport('stacked')
1266 repo_fmt = bzrdir.format_registry.make_bzrdir('1.9')
1267 repo_name = repo_fmt.repository_format.network_name()
1268 repo, control = self.assertInitializeEx(
1269 t, need_meta=True, repo_format_name=repo_name, stacked_on=None)
1270 if control is None:
1271 # uninitialisable format
1272 return
1273 # There's one fallback repo, with a public location.
1274 self.assertLength(1, repo._fallback_repositories)
1275 fallback_repo = repo._fallback_repositories[0]
1276 self.assertEqual(
1277 stack_on.base, fallback_repo.bzrdir.root_transport.base)
1278
1249 def test_format_initialize_on_transport_ex_repo_fmt_name_None(self):1279 def test_format_initialize_on_transport_ex_repo_fmt_name_None(self):
1250 t = self.get_transport('dir')1280 t = self.get_transport('dir')
1251 repo, control = self.assertInitializeEx(t)1281 repo, control = self.assertInitializeEx(t)
12521282
=== modified file 'bzrlib/tests/test_bzrdir.py'
--- bzrlib/tests/test_bzrdir.py 2009-03-23 14:59:43 +0000
+++ bzrlib/tests/test_bzrdir.py 2009-06-11 11:35:12 +0000
@@ -20,8 +20,6 @@
20"""20"""
2121
22import os22import os
23import os.path
24from StringIO import StringIO
25import subprocess23import subprocess
26import sys24import sys
2725
@@ -31,7 +29,6 @@
31 help_topics,29 help_topics,
32 repository,30 repository,
33 osutils,31 osutils,
34 symbol_versioning,
35 remote,32 remote,
36 urlutils,33 urlutils,
37 win32utils,34 win32utils,
@@ -47,7 +44,6 @@
47 TestCaseWithMemoryTransport,44 TestCaseWithMemoryTransport,
48 TestCaseWithTransport,45 TestCaseWithTransport,
49 TestSkipped,46 TestSkipped,
50 test_sftp_transport
51 )47 )
52from bzrlib.tests import(48from bzrlib.tests import(
53 http_server,49 http_server,
5450
=== modified file 'bzrlib/tests/test_smart.py'
--- bzrlib/tests/test_smart.py 2009-06-10 03:56:49 +0000
+++ bzrlib/tests/test_smart.py 2009-06-11 11:35:12 +0000
@@ -381,7 +381,7 @@
381 'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')381 'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')
382382
383 def test_initialized_dir(self):383 def test_initialized_dir(self):
384 """Initializing an extant dirctory should fail like the bzrdir api."""384 """Initializing an extant directory should fail like the bzrdir api."""
385 backing = self.get_transport()385 backing = self.get_transport()
386 name = self.make_bzrdir('reference')._format.network_name()386 name = self.make_bzrdir('reference')._format.network_name()
387 request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)387 request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)