Rev 4194: (andrew) Strengthen the smart server's jail, in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Mar 24 06:40:33 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4194
revision-id: pqm at pqm.ubuntu.com-20090324064026-a5a7mmoiaev5mpc9
parent: pqm at pqm.ubuntu.com-20090324051224-rneg6bkbzjyd85rl
parent: andrew.bennetts at canonical.com-20090324053815-3tcoyeuejfp4jud5
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2009-03-24 06:40:26 +0000
message:
(andrew) Strengthen the smart server's jail,
and add ignore_fallbacks parameter to BzrDir.open_branch.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/smart/bzrdir.py bzrdir.py-20061122024551-ol0l0o0oofsu9b3t-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
bzrlib/tests/test_branch.py test_branch.py-20060116013032-97819aa07b8ab3b5
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
bzrlib/tests/test_smart_request.py test_smart_request.p-20090211070731-o38wayv3asm25d6a-1
------------------------------------------------------------
revno: 4160.2.16
revision-id: andrew.bennetts at canonical.com-20090324053815-3tcoyeuejfp4jud5
parent: andrew.bennetts at canonical.com-20090324043838-3nhf0syvkz5iqdsz
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Tue 2009-03-24 16:38:15 +1100
message:
Update SampleBranchFormat in test_branch for ignore_fallbacks parameter.
modified:
bzrlib/tests/test_branch.py test_branch.py-20060116013032-97819aa07b8ab3b5
------------------------------------------------------------
revno: 4160.2.15
revision-id: andrew.bennetts at canonical.com-20090324043838-3nhf0syvkz5iqdsz
parent: andrew.bennetts at canonical.com-20090324042634-cf4y15a5y24fw2n0
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Tue 2009-03-24 15:38:38 +1100
message:
Restore lines accidentally removed in bad NEWS merge.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 4160.2.14
revision-id: andrew.bennetts at canonical.com-20090324042634-cf4y15a5y24fw2n0
parent: andrew.bennetts at canonical.com-20090324040153-7kjc38xuliwkymuo
parent: pqm at pqm.ubuntu.com-20090324015928-a4eisbr51odi0due
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Tue 2009-03-24 15:26:34 +1100
message:
Merge bzr.dev, improve NEWS entry and bzrlib.smart.request docs.
added:
bzrlib/filters/ filters-20080416080515-mkxl29amuwrf6uir-1
bzrlib/filters/__init__.py __init__.py-20080416080515-mkxl29amuwrf6uir-2
bzrlib/help_topics/en/content-filters.txt contentfilters.txt-20080516145112-7x1meuoci5w41isv-1
bzrlib/tests/ftp_server/ ftp_server-20090227112800-4r9jkezw2hw9tij7-1
bzrlib/tests/ftp_server/__init__.py __init__.py-20090227130107-4gcpgvr00l7v3fsw-1
bzrlib/tests/ftp_server/pyftpdlib_based.py pyftpdlib_based.py-20090227151014-882k9q34m1gwnhvi-1
bzrlib/tests/test_filters.py test_filters.py-20080417120614-tc3zok0vvvprsc99-1
bzrlib/tests/workingtree_implementations/test_content_filters.py test_content_filters-20080424071441-8navsrmrfdxpn90a-1
renamed:
bzrlib/tests/ftp_server.py => bzrlib/tests/ftp_server/medusa_based.py ftpserver.py-20071019102346-61jbvdkrr70igauv-1
doc/developers/ec2-windows.txt => doc/developers/ec2.txt ec2windows.txt-20090219062112-2ga0nqpcm7n02njf-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/btree_index.py index.py-20080624222253-p0x5f92uyh5hw734-7
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/diff.py diff.py-20050309040759-26944fbbf2ebbf36
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/export/__init__.py __init__.py-20051114235828-1ba62cb4062304e6
bzrlib/export/dir_exporter.py dir_exporter.py-20051114235828-b51397f56bc7b117
bzrlib/export/tar_exporter.py tar_exporter.py-20051114235828-1f6349a2f090a5d0
bzrlib/export/zip_exporter.py zip_exporter.py-20051114235828-8f57f954fba6497e
bzrlib/graph.py graph_walker.py-20070525030359-y852guab65d4wtn0-1
bzrlib/hashcache.py hashcache.py-20050706091756-fe3a8cc1143ff24f
bzrlib/help_topics/__init__.py help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
bzrlib/help_topics/en/debug-flags.txt debugflags.txt-20090312050229-rdspqbqq4fzbjtpe-1
bzrlib/hooks.py hooks.py-20070325015548-ix4np2q0kd8452au-1
bzrlib/index.py index.py-20070712131115-lolkarso50vjr64s-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repofmt/knitrepo.py knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repofmt/weaverepo.py presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/symbol_versioning.py symbol_versioning.py-20060105104851-9ecf8af605d15a80
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_add.py test_add.py-20060518072250-857e4f86f54a30b2
bzrlib/tests/blackbox/test_breakin.py test_breakin.py-20070424043903-qyy6zm4pj3h4sbp3-1
bzrlib/tests/blackbox/test_cat.py test_cat.py-20051201162916-f0937e4e19ea24b3
bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
bzrlib/tests/blackbox/test_selftest.py test_selftest.py-20060123024542-01c5f1bbcb596d78
bzrlib/tests/interrepository_implementations/test_interrepository.py test_interrepository.py-20060220061411-1ec13fa99e5e3eee
bzrlib/tests/inventory_implementations/basics.py basics.py-20070903044446-kdjwbiu1p1zi9phs-1
bzrlib/tests/per_repository/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
bzrlib/tests/per_repository/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
bzrlib/tests/test_hashcache.py testhashcache.py-20050706091800-0288ab2659338981
bzrlib/tests/test_hooks.py test_hooks.py-20070628030849-89rtsbe5dmer5npz-1
bzrlib/tests/test_log.py testlog.py-20050728115707-1a514809d7d49309
bzrlib/tests/test_merge.py testmerge.py-20050905070950-c1b5aa49ff911024
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/tests/test_plugins.py plugins.py-20050622075746-32002b55e5e943e9
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_revision.py testrevision.py-20050804210559-46f5e1eb67b01289
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
bzrlib/tests/test_symbol_versioning.py test_symbol_versioning.py-20060105104851-51d7722c2018d42b
bzrlib/tests/test_transport_implementations.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
bzrlib/tests/test_versionedfile.py test_versionedfile.py-20060222045249-db45c9ed14a1c2e5
bzrlib/tests/workingtree_implementations/__init__.py __init__.py-20060203003124-b2aa5aca21a8bfad
bzrlib/tests/workingtree_implementations/test_smart_add.py test_smart_add.py-20070215175752-9s5mxoz8aqpd80fm-1
bzrlib/trace.py trace.py-20050309040759-c8ed824bdcd4748a
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/transport/ftp/__init__.py ftp.py-20051116161804-58dc9506548c2a53
bzrlib/transport/ftp/_gssapi.py _gssapi.py-20080611190840-7ejrtp884bk5eu72-2
bzrlib/transport/log.py log.py-20080902041816-vh8x5yt5nvdzvew3-5
bzrlib/transport/readonly.py readonly.py-20060120032407-66d3166c39ffdc79
bzrlib/transport/remote.py ssh.py-20060608202016-c25gvf1ob7ypbus6-1
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
bzrlib/ui/text.py text.py-20051130153916-2e438cffc8afc478
bzrlib/version_info_formats/__init__.py generate_version_info.py-20051228204928-8358edabcddcd97e
bzrlib/weave.py knit.py-20050627021749-759c29984154256b
bzrlib/win32utils.py win32console.py-20051021033308-123c6c929d04973d
bzrlib/workingtree.py workingtree.py-20050511021032-29b6ec0a681e02e3
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
doc/developers/HACKING.txt HACKING-20050805200004-2a5dc975d870f78c
doc/developers/index.txt index.txt-20070508041241-qznziunkg0nffhiw-1
doc/developers/overview.txt overview.txt-20080904022501-ww2ggomrs5elxfm0-1
doc/developers/performance-contributing.txt performancecontribut-20070621063612-ac4zhhagjzkr21qp-1
doc/developers/releasing.txt releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
doc/en/user-guide/web_browsing.txt web_browsing.txt-20080509065016-cjc90f46407vi9a0-3
bzrlib/tests/ftp_server/medusa_based.py ftpserver.py-20071019102346-61jbvdkrr70igauv-1
doc/developers/ec2.txt ec2windows.txt-20090219062112-2ga0nqpcm7n02njf-1
------------------------------------------------------------
revno: 4160.2.13
revision-id: andrew.bennetts at canonical.com-20090324040153-7kjc38xuliwkymuo
parent: andrew.bennetts at canonical.com-20090323053049-mrknn26g68c69t61
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Tue 2009-03-24 15:01:53 +1100
message:
Add some tests for ignore_fallbacks.
modified:
bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
------------------------------------------------------------
revno: 4160.2.12
revision-id: andrew.bennetts at canonical.com-20090323053049-mrknn26g68c69t61
parent: andrew.bennetts at canonical.com-20090323033129-ci8b7zthtjt1036o
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Mon 2009-03-23 16:30:49 +1100
message:
Improve docstrings and remove a line of cruft.
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/smart/bzrdir.py bzrdir.py-20061122024551-ol0l0o0oofsu9b3t-1
------------------------------------------------------------
revno: 4160.2.11
revision-id: andrew.bennetts at canonical.com-20090323033129-ci8b7zthtjt1036o
parent: andrew.bennetts at canonical.com-20090323033124-273x2h5ut41ycx0p
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Mon 2009-03-23 14:31:29 +1100
message:
Add NEWS entry.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 4160.2.10
revision-id: andrew.bennetts at canonical.com-20090323033124-273x2h5ut41ycx0p
parent: andrew.bennetts at canonical.com-20090323032002-q2rbmpp5ne255d46
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Mon 2009-03-23 14:31:24 +1100
message:
Improve documentation of BzrDir.cloning_metadir RPC
modified:
bzrlib/smart/bzrdir.py bzrdir.py-20061122024551-ol0l0o0oofsu9b3t-1
------------------------------------------------------------
revno: 4160.2.9
revision-id: andrew.bennetts at canonical.com-20090323032002-q2rbmpp5ne255d46
parent: andrew.bennetts at canonical.com-20090319215751-4kypi4vo0vkp1nci
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Mon 2009-03-23 14:20:02 +1100
message:
Fix BzrDir.cloning_metadir RPC to fail on branch references, and make
RemoteBzrDir cope with that by opening the referenced branch and asking it for
the cloning_metadir. This can cause extra round trips, but only for callers
that haven't already resolved branch references, which only occurs in our test
suite, not UI code.
This theoretically breaks 1.13 clients that depend on the cloning_metadir RPC
resolving the reference for them, but again that never happens via any builtin
commands, and the new branch-open jail has already broken those clients.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/bzrdir.py bzrdir.py-20061122024551-ol0l0o0oofsu9b3t-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
------------------------------------------------------------
revno: 4160.2.8
revision-id: andrew.bennetts at canonical.com-20090319215751-4kypi4vo0vkp1nci
parent: andrew.bennetts at canonical.com-20090318094500-froh981qf37u5z57
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Fri 2009-03-20 08:57:51 +1100
message:
Slightly less messy BzrBranch7.__init__.
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
------------------------------------------------------------
revno: 4160.2.7
revision-id: andrew.bennetts at canonical.com-20090318094500-froh981qf37u5z57
parent: andrew.bennetts at canonical.com-20090318072814-chvt67ssr9jyz259
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 20:45:00 +1100
message:
Branch-from-stacked ratchet down to 23.
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
------------------------------------------------------------
revno: 4160.2.6
revision-id: andrew.bennetts at canonical.com-20090318072814-chvt67ssr9jyz259
parent: andrew.bennetts at canonical.com-20090318053325-w5xdsr0fjwcpatj2
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 18:28:14 +1100
message:
Add ignore_fallbacks flag.
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/branch.py branch.py-20061124031907-mzh3pla28r83r97f-1
bzrlib/smart/bzrdir.py bzrdir.py-20061122024551-ol0l0o0oofsu9b3t-1
------------------------------------------------------------
revno: 4160.2.5
revision-id: andrew.bennetts at canonical.com-20090318053325-w5xdsr0fjwcpatj2
parent: andrew.bennetts at canonical.com-20090318051733-l5rxgj31et1dkm6s
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 16:33:25 +1100
message:
Add test_jail_hook.
modified:
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/test_smart_request.py test_smart_request.p-20090211070731-o38wayv3asm25d6a-1
------------------------------------------------------------
revno: 4160.2.4
revision-id: andrew.bennetts at canonical.com-20090318051733-l5rxgj31et1dkm6s
parent: andrew.bennetts at canonical.com-20090318050656-ae2t1m7um2djp2pg
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 16:17:33 +1100
message:
Use BzrDir pre_open hook to jail request code from accessing transports other than the backing transport.
modified:
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
------------------------------------------------------------
revno: 4160.2.3
revision-id: andrew.bennetts at canonical.com-20090318050656-ae2t1m7um2djp2pg
parent: andrew.bennetts at canonical.com-20090318044931-uqq32ujozbz0csuv
parent: pqm at pqm.ubuntu.com-20090318043730-vt9fcxb6ndb8toxa
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 16:06:56 +1100
message:
Merge bzr.dev.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/hooks.py hooks.py-20070325015548-ix4np2q0kd8452au-1
bzrlib/tests/test__dirstate_helpers.py test_dirstate_helper-20070504035751-jsbn00xodv0y1eve-2
bzrlib/tests/test_bzrdir.py test_bzrdir.py-20060131065654-deba40eef51cf220
bzrlib/tests/test_dirstate.py test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
------------------------------------------------------------
revno: 4160.2.2
revision-id: andrew.bennetts at canonical.com-20090318044931-uqq32ujozbz0csuv
parent: andrew.bennetts at canonical.com-20090318032448-f93pjfrhwmv4hwhl
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 15:49:31 +1100
message:
Add setup_jail and teardown_jail to SmartServerRequest.
modified:
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/test_smart_request.py test_smart_request.p-20090211070731-o38wayv3asm25d6a-1
------------------------------------------------------------
revno: 4160.2.1
revision-id: andrew.bennetts at canonical.com-20090318032448-f93pjfrhwmv4hwhl
parent: pqm at pqm.ubuntu.com-20090318021431-md1n8o3542wwsvai
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: bzrdir-open-gaol
timestamp: Wed 2009-03-18 14:24:48 +1100
message:
Failing test for BzrDir.open_branchV2 RPC not opening stacked-on branch.
modified:
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
=== modified file 'NEWS'
--- a/NEWS 2009-03-24 04:24:57 +0000
+++ b/NEWS 2009-03-24 06:40:26 +0000
@@ -151,6 +151,11 @@
* The ``pb`` argument to ``fetch()`` is deprecated.
(Martin Pool)
+* The smart server jail now hooks into BzrDir.open to prevent any BzrDir
+ that is not inside the backing transport from being opened. See the
+ module documentation for ``bzrlib.smart.request`` for details.
+ (Andrew Bennetts, Robert Collins)
+
Testing
*******
@@ -172,14 +177,18 @@
Internals
*********
+* ``BtreeIndex._spill_mem_keys_to_disk()`` now generates disk index with
+ optmizations turned off. This only has effect when processing > 100,000
+ keys during something like ``bzr pack``. (John Arbash Meinel)
+
* ``bzr selftest`` now accepts ``--subunit`` to run in subunit output
mode. Requires ``lp:subunit`` installed to work, but is not a hard
dependency. (Robert Collins)
-* ``BtreeIndex._spill_mem_keys_to_disk()`` now generates disk index with
- optmizations turned off. This only has effect when processing > 100,000
- keys during something like ``bzr pack``. (John Arbash Meinel)
-
+* ``BzrDir.open_branch`` now takes an optional ``ignore_fallbacks``
+ parameter for controlling opening of stacked branches.
+ (Andrew Bennetts, Robert Collins)
+
* ``CommitBuilder`` has a new method, ``record_iter_changes`` which works
in terms of an iter_changes iterator rather than full tree scanning.
(Robert Collins)
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/branch.py 2009-03-24 06:40:26 +0000
@@ -1318,11 +1318,14 @@
"""
raise NotImplementedError(self.network_name)
- def open(self, a_bzrdir, _found=False):
+ def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
"""Return the branch object for a_bzrdir
- _found is a private parameter, do not use it. It is used to indicate
- if format probing has already be done.
+ :param a_bzrdir: A BzrDir that contains a branch.
+ :param _found: a private parameter, do not use it. It is used to
+ indicate if format probing has already be done.
+ :param ignore_fallbacks: when set, no fallback branches will be opened
+ (if there are any). Default is to open fallbacks.
"""
raise NotImplementedError(self.open)
@@ -1500,12 +1503,8 @@
"""The network name for this format is the control dirs disk label."""
return self._matchingbzrdir.get_format_string()
- def open(self, a_bzrdir, _found=False):
- """Return the branch object for a_bzrdir
-
- _found is a private parameter, do not use it. It is used to indicate
- if format probing has already be done.
- """
+ def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
+ """See BranchFormat.open()."""
if not _found:
# we are being called directly and must probe.
raise NotImplementedError
@@ -1532,12 +1531,8 @@
"""
return self.get_format_string()
- def open(self, a_bzrdir, _found=False):
- """Return the branch object for a_bzrdir.
-
- _found is a private parameter, do not use it. It is used to indicate
- if format probing has already be done.
- """
+ def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
+ """See BranchFormat.open()."""
if not _found:
format = BranchFormat.find_format(a_bzrdir)
if format.__class__ != self.__class__:
@@ -1550,7 +1545,8 @@
return self._branch_class()(_format=self,
_control_files=control_files,
a_bzrdir=a_bzrdir,
- _repository=a_bzrdir.find_repository())
+ _repository=a_bzrdir.find_repository(),
+ ignore_fallbacks=ignore_fallbacks)
except errors.NoSuchFile:
raise errors.NotBranchError(path=transport.base)
@@ -1736,11 +1732,18 @@
return clone
def open(self, a_bzrdir, _found=False, location=None,
- possible_transports=None):
+ possible_transports=None, ignore_fallbacks=False):
"""Return the branch that the branch reference in a_bzrdir points at.
- _found is a private parameter, do not use it. It is used to indicate
- if format probing has already be done.
+ :param a_bzrdir: A BzrDir that contains a branch.
+ :param _found: a private parameter, do not use it. It is used to
+ indicate if format probing has already be done.
+ :param ignore_fallbacks: when set, no fallback branches will be opened
+ (if there are any). Default is to open fallbacks.
+ :param location: The location of the referenced branch. If
+ unspecified, this will be determined from the branch reference in
+ a_bzrdir.
+ :param possible_transports: An optional reusable transports list.
"""
if not _found:
format = BranchFormat.find_format(a_bzrdir)
@@ -1751,7 +1754,7 @@
location = self.get_reference(a_bzrdir)
real_bzrdir = bzrdir.BzrDir.open(
location, possible_transports=possible_transports)
- result = real_bzrdir.open_branch()
+ result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
# this changes the behaviour of result.clone to create a new reference
# rather than a copy of the content of the branch.
# I did not use a proxy object because that needs much more extensive
@@ -1804,7 +1807,8 @@
"""
def __init__(self, _format=None,
- _control_files=None, a_bzrdir=None, _repository=None):
+ _control_files=None, a_bzrdir=None, _repository=None,
+ ignore_fallbacks=False):
"""Create new branch object at a particular location."""
if a_bzrdir is None:
raise ValueError('a_bzrdir must be supplied')
@@ -2304,6 +2308,8 @@
self._get_fallback_repository(url))
def _open_hook(self):
+ if self._ignore_fallbacks:
+ return
try:
url = self.get_stacked_on_url()
except (errors.UnstackableRepositoryFormat, errors.NotStacked,
@@ -2325,6 +2331,7 @@
self.repository.base)
def __init__(self, *args, **kwargs):
+ self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
super(BzrBranch7, self).__init__(*args, **kwargs)
self._last_revision_info_cache = None
self._partial_revision_history_cache = []
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py 2009-03-24 01:53:42 +0000
+++ b/bzrlib/bzrdir.py 2009-03-24 06:40:26 +0000
@@ -838,7 +838,7 @@
BzrDir._check_supported(format, _unsupported)
return format.open(transport, _found=True)
- def open_branch(self, unsupported=False):
+ def open_branch(self, unsupported=False, ignore_fallbacks=False):
"""Open the branch object at this BzrDir if one is present.
If unsupported is True, then no longer supported branch formats can
@@ -1019,7 +1019,7 @@
result_format = self._format.__class__()
try:
try:
- branch = self.open_branch()
+ branch = self.open_branch(ignore_fallbacks=True)
source_repository = branch.repository
result_format._branch_format = branch._format
except errors.NotBranchError:
@@ -1358,7 +1358,7 @@
format = BzrDirFormat.get_default_format()
return not isinstance(self._format, format.__class__)
- def open_branch(self, unsupported=False):
+ def open_branch(self, unsupported=False, ignore_fallbacks=False):
"""See BzrDir.open_branch."""
from bzrlib.branch import BzrBranchFormat4
format = BzrBranchFormat4()
@@ -1609,11 +1609,11 @@
pass
return False
- def open_branch(self, unsupported=False):
+ def open_branch(self, unsupported=False, ignore_fallbacks=False):
"""See BzrDir.open_branch."""
format = self.find_branch_format()
self._check_supported(format, unsupported)
- return format.open(self, _found=True)
+ return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
def open_repository(self, unsupported=False):
"""See BzrDir.open_repository."""
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2009-03-24 01:53:42 +0000
+++ b/bzrlib/remote.py 2009-03-24 06:40:26 +0000
@@ -153,6 +153,15 @@
except errors.UnknownSmartMethod:
medium._remember_remote_is_before((1, 13))
return self._vfs_cloning_metadir(require_stacking=require_stacking)
+ except errors.UnknownErrorFromSmartServer, err:
+ if err.error_tuple != ('BranchReference',):
+ raise
+ # We need to resolve the branch reference to determine the
+ # cloning_metadir. This causes unnecessary RPCs to open the
+ # referenced branch (and bzrdir, etc) but only when the caller
+ # didn't already resolve the branch reference.
+ referenced_branch = self.open_branch()
+ return referenced_branch.bzrdir.cloning_metadir()
if len(response) != 3:
raise errors.UnexpectedSmartServerResponse(response)
control_name, repo_name, branch_info = response
@@ -256,7 +265,7 @@
"""See BzrDir._get_tree_branch()."""
return None, self.open_branch()
- def open_branch(self, _unsupported=False):
+ def open_branch(self, _unsupported=False, ignore_fallbacks=False):
if _unsupported:
raise NotImplementedError('unsupported flag support not implemented yet.')
if self._next_open_branch_result is not None:
@@ -268,12 +277,14 @@
if response[0] == 'ref':
# a branch reference, use the existing BranchReference logic.
format = BranchReferenceFormat()
- return format.open(self, _found=True, location=response[1])
+ return format.open(self, _found=True, location=response[1],
+ ignore_fallbacks=ignore_fallbacks)
branch_format_name = response[1]
if not branch_format_name:
branch_format_name = None
format = RemoteBranchFormat(network_name=branch_format_name)
- return RemoteBranch(self, self.find_repository(), format=format)
+ return RemoteBranch(self, self.find_repository(), format=format,
+ setup_stacking=not ignore_fallbacks)
def _open_repo_v1(self, path):
verb = 'BzrDir.find_repository'
@@ -1733,8 +1744,8 @@
def network_name(self):
return self._network_name
- def open(self, a_bzrdir):
- return a_bzrdir.open_branch()
+ def open(self, a_bzrdir, ignore_fallbacks=False):
+ return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
def _vfs_initialize(self, a_bzrdir):
# Initialisation when using a local bzrdir object, or a non-vfs init
=== modified file 'bzrlib/smart/branch.py'
--- a/bzrlib/smart/branch.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/smart/branch.py 2009-03-24 06:40:26 +0000
@@ -45,7 +45,7 @@
bzrdir = BzrDir.open_from_transport(transport)
if bzrdir.get_branch_reference() is not None:
raise errors.NotBranchError(transport.base)
- branch = bzrdir.open_branch()
+ branch = bzrdir.open_branch(ignore_fallbacks=True)
return self.do_with_branch(branch, *args)
=== modified file 'bzrlib/smart/bzrdir.py'
--- a/bzrlib/smart/bzrdir.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/smart/bzrdir.py 2009-03-24 06:40:26 +0000
@@ -92,11 +92,25 @@
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
def do_bzrdir_request(self, require_stacking):
- """Get the format that should be used when cloning from this dir."""
+ """Get the format that should be used when cloning from this dir.
+
+ New in 1.13.
+
+ :return: on success, a 3-tuple of network names for (control,
+ repository, branch) directories, where '' signifies "not present".
+ If this BzrDir contains a branch reference then this will fail with
+ BranchReference; clients should resolve branch references before
+ calling this RPC.
+ """
try:
branch_ref = self._bzrdir.get_branch_reference()
except errors.NotBranchError:
branch_ref = None
+ if branch_ref is not None:
+ # The server shouldn't try to resolve references, and it quite
+ # possibly can't reach them anyway. The client needs to resolve
+ # the branch reference to determine the cloning_metadir.
+ return FailedSmartServerResponse(('BranchReference',))
if require_stacking == "True":
require_stacking = True
else:
@@ -104,16 +118,11 @@
control_format = self._bzrdir.cloning_metadir(
require_stacking=require_stacking)
control_name = control_format.network_name()
- # XXX: There should be a method that tells us that the format does/does not
- # have subformats.
+ # XXX: There should be a method that tells us that the format does/does
+ # not have subformats.
if isinstance(control_format, BzrDirMetaFormat1):
- if branch_ref is not None:
- # If there's a branch reference, the client will have to resolve
- # the branch reference to figure out the cloning metadir
- branch_name = ('ref', branch_ref)
- else:
- branch_name = ('branch',
- control_format.get_branch_format().network_name())
+ branch_name = ('branch',
+ control_format.get_branch_format().network_name())
repository_name = control_format.repository_format.network_name()
else:
# Only MetaDir has delegated formats today.
@@ -322,7 +331,8 @@
try:
reference_url = self._bzrdir.get_branch_reference()
if reference_url is None:
- format = self._bzrdir.open_branch()._format.network_name()
+ br = self._bzrdir.open_branch(ignore_fallbacks=True)
+ format = br._format.network_name()
return SuccessfulSmartServerResponse(('branch', format))
else:
return SuccessfulSmartServerResponse(('ref', reference_url))
=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/smart/request.py 2009-03-24 06:40:26 +0000
@@ -14,19 +14,25 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-"""Basic server-side logic for dealing with requests.
-
-**XXX**:
-
-The class names are a little confusing: the protocol will instantiate a
-SmartServerRequestHandler, whose dispatch_command method creates an instance of
-a SmartServerRequest subclass.
-
-The request_handlers registry tracks SmartServerRequest classes (rather than
-SmartServerRequestHandler).
+"""Infrastructure for server-side request handlers.
+
+Interesting module attributes:
+ * The request_handlers registry maps verb names to SmartServerRequest
+ classes.
+ * The jail_info threading.local() object is used to prevent accidental
+ opening of BzrDirs outside of the backing transport, or any other
+ transports placed in jail_info.transports. The jail_info is reset on
+ every call into a request handler (which can happen an arbitrary number
+ of times during a request).
"""
+# XXX: The class names are a little confusing: the protocol will instantiate a
+# SmartServerRequestHandler, whose dispatch_command method creates an instance
+# of a SmartServerRequest subclass.
+
+
import tempfile
+import threading
from bzrlib import (
bzrdir,
@@ -42,6 +48,33 @@
""")
+jail_info = threading.local()
+jail_info.transports = None
+
+
+def _install_hook():
+ bzrdir.BzrDir.hooks.install_named_hook(
+ 'pre_open', _pre_open_hook, 'checking server jail')
+
+
+def _pre_open_hook(transport):
+ allowed_transports = jail_info.transports
+ if allowed_transports is None:
+ return
+ abspath = transport.base
+ for allowed_transport in allowed_transports:
+ try:
+ allowed_transport.relpath(abspath)
+ except errors.PathNotChild:
+ continue
+ else:
+ return
+ raise errors.BzrError('jail break: %r' % (abspath,))
+
+
+_install_hook()
+
+
class SmartServerRequest(object):
"""Base class for request handlers.
@@ -121,6 +154,12 @@
self._body_chunks = None
return self.do_body(body_bytes)
+ def setup_jail(self):
+ jail_info.transports = [self._backing_transport]
+
+ def teardown_jail(self):
+ jail_info.transports = None
+
def translate_client_path(self, client_path):
"""Translate a path received from a network client into a local
relpath.
@@ -277,7 +316,11 @@
# XXX: most of this error conversion is VFS-related, and thus ought to
# be in SmartServerVFSRequestHandler somewhere.
try:
- return callable(*args, **kwargs)
+ self._command.setup_jail()
+ try:
+ return callable(*args, **kwargs)
+ finally:
+ self._command.teardown_jail()
except (KeyboardInterrupt, SystemExit):
raise
except Exception, err:
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2009-03-24 05:12:24 +0000
+++ b/bzrlib/tests/__init__.py 2009-03-24 06:40:26 +0000
@@ -77,7 +77,7 @@
from bzrlib.merge import merge_inner
import bzrlib.merge3
import bzrlib.plugin
-from bzrlib.smart import client, server
+from bzrlib.smart import client, request, server
import bzrlib.store
from bzrlib import symbol_versioning
from bzrlib.symbol_versioning import (
@@ -827,6 +827,8 @@
for key, factory in hooks.known_hooks.items():
parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
setattr(parent, name, factory())
+ # this hook should always be installed
+ request._install_hook()
def _silenceUI(self):
"""Turn off UI for duration of test"""
=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- a/bzrlib/tests/blackbox/test_branch.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/blackbox/test_branch.py 2009-03-24 06:40:26 +0000
@@ -302,13 +302,12 @@
self.reset_smart_call_log()
out, err = self.run_bzr(['branch', self.get_url('feature'),
'local-target'])
- rpc_count = len(self.hpss_calls)
# This figure represent the amount of work to perform this use case. It
# is entirely ok to reduce this number if a test fails due to rpc_count
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertEqual(74, rpc_count)
+ self.assertLength(23, self.hpss_calls)
class TestRemoteBranch(TestCaseWithSFTPServer):
=== modified file 'bzrlib/tests/branch_implementations/test_branch.py'
--- a/bzrlib/tests/branch_implementations/test_branch.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/branch_implementations/test_branch.py 2009-03-24 06:40:26 +0000
@@ -752,3 +752,25 @@
tree3.merge_from_branch(tree2.branch)
tree3.commit('empty commit 6')
tree2.pull(tree3.branch)
+
+
+class TestIgnoreFallbacksParameter(TestCaseWithBranch):
+
+ def make_branch_with_fallback(self):
+ fallback = self.make_branch('fallback')
+ if not fallback._format.supports_stacking():
+ raise tests.TestNotApplicable("format does not support stacking")
+ stacked = self.make_branch('stacked')
+ stacked.set_stacked_on_url(fallback.base)
+ return stacked
+
+ def test_fallbacks_not_opened(self):
+ stacked = self.make_branch_with_fallback()
+ self.get_transport('').rename('fallback', 'moved')
+ reopened = stacked.bzrdir.open_branch(ignore_fallbacks=True)
+ self.assertEqual([], reopened.repository._fallback_repositories)
+
+ def test_fallbacks_are_opened(self):
+ stacked = self.make_branch_with_fallback()
+ reopened = stacked.bzrdir.open_branch(ignore_fallbacks=False)
+ self.assertLength(1, reopened.repository._fallback_repositories)
=== modified file 'bzrlib/tests/test_branch.py'
--- a/bzrlib/tests/test_branch.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/test_branch.py 2009-03-24 06:40:26 +0000
@@ -151,7 +151,7 @@
def is_supported(self):
return False
- def open(self, transport, _found=False):
+ def open(self, transport, _found=False, ignore_fallbacks=False):
return "opened branch."
=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py 2009-03-24 01:53:42 +0000
+++ b/bzrlib/tests/test_remote.py 2009-03-24 06:40:26 +0000
@@ -408,6 +408,26 @@
call.call.method == verb])
self.assertEqual(1, call_count)
+ def test_branch_reference(self):
+ transport = self.get_transport('quack')
+ referenced = self.make_branch('referenced')
+ expected = referenced.bzrdir.cloning_metadir()
+ client = FakeClient(transport.base)
+ client.add_expected_call(
+ 'BzrDir.cloning_metadir', ('quack/', 'False'),
+ 'error', ('BranchReference',)),
+ client.add_expected_call(
+ 'BzrDir.open_branchV2', ('quack/',),
+ 'success', ('ref', self.get_url('referenced'))),
+ a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
+ _client=client)
+ result = a_bzrdir.cloning_metadir()
+ # We should have got a control dir matching the referenced branch.
+ self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
+ self.assertEqual(expected._repository_format, result._repository_format)
+ self.assertEqual(expected._branch_format, result._branch_format)
+ client.finished_test()
+
def test_current_server(self):
transport = self.get_transport('.')
transport = transport.clone('quack')
=== modified file 'bzrlib/tests/test_smart.py'
--- a/bzrlib/tests/test_smart.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/test_smart.py 2009-03-24 06:40:26 +0000
@@ -177,7 +177,7 @@
self.assertEqual(expected, request.execute('', 'False'))
def test_cloning_metadir_reference(self):
- """The request works when bzrdir contains a branch reference."""
+ """The request fails when bzrdir contains a branch reference."""
backing = self.get_transport()
referenced_branch = self.make_branch('referenced')
dir = self.make_bzrdir('.')
@@ -189,10 +189,7 @@
backing.rename('referenced', 'moved')
request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
request = request_class(backing)
- expected = SuccessfulSmartServerResponse(
- (local_result.network_name(),
- local_result.repository_format.network_name(),
- ('ref', reference_url)))
+ expected = FailedSmartServerResponse(('BranchReference',))
self.assertEqual(expected, request.execute('', 'False'))
@@ -389,6 +386,26 @@
self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
request.execute('reference'))
+ def test_stacked_branch(self):
+ """Opening a stacked branch does not open the stacked-on branch."""
+ trunk = self.make_branch('trunk')
+ feature = self.make_branch('feature', format='1.9')
+ feature.set_stacked_on_url(trunk.base)
+ opened_branches = []
+ Branch.hooks.install_named_hook('open', opened_branches.append, None)
+ backing = self.get_transport()
+ request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
+ request.setup_jail()
+ try:
+ response = request.execute('feature')
+ finally:
+ request.teardown_jail()
+ expected_format = feature._format.network_name()
+ self.assertEqual(
+ SuccessfulSmartServerResponse(('branch', expected_format)),
+ response)
+ self.assertLength(1, opened_branches)
+
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
=== modified file 'bzrlib/tests/test_smart_request.py'
--- a/bzrlib/tests/test_smart_request.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/test_smart_request.py 2009-03-24 06:40:26 +0000
@@ -16,9 +16,12 @@
"""Tests for smart server request infrastructure (bzrlib.smart.request)."""
+import threading
+
from bzrlib import errors
from bzrlib.smart import request
-from bzrlib.tests import TestCase
+from bzrlib.tests import TestCase, TestCaseWithMemoryTransport
+from bzrlib.transport import get_transport
class NoBodyRequest(request.SmartServerRequest):
@@ -61,6 +64,22 @@
raise errors.NoSuchFile('xyzzy')
+class CheckJailRequest(request.SmartServerRequest):
+
+ def __init__(self, *args):
+ request.SmartServerRequest.__init__(self, *args)
+ self.jail_transports_log = []
+
+ def do(self):
+ self.jail_transports_log.append(request.jail_info.transports)
+
+ def do_chunk(self, bytes):
+ self.jail_transports_log.append(request.jail_info.transports)
+
+ def do_end(self):
+ self.jail_transports_log.append(request.jail_info.transports)
+
+
class TestSmartRequest(TestCase):
def test_request_class_without_do_body(self):
@@ -76,6 +95,20 @@
handler.end_received()
# Request done, no exception was raised.
+ def test_only_request_code_is_jailed(self):
+ transport = 'dummy transport'
+ handler = request.SmartServerRequestHandler(
+ transport, {'foo': CheckJailRequest}, '/')
+ handler.args_received(('foo',))
+ self.assertEqual(None, request.jail_info.transports)
+ handler.accept_body('bytes')
+ self.assertEqual(None, request.jail_info.transports)
+ handler.end_received()
+ self.assertEqual(None, request.jail_info.transports)
+ self.assertEqual(
+ [[transport]] * 3, handler._command.jail_transports_log)
+
+
class TestSmartRequestHandlerErrorTranslation(TestCase):
"""Tests that SmartServerRequestHandler will translate exceptions raised by
@@ -134,3 +167,39 @@
('TokenMismatch', 'some-token', 'actual-token'),
errors.TokenMismatch('some-token', 'actual-token'))
+
+class TestRequestJail(TestCaseWithMemoryTransport):
+
+ def test_jail(self):
+ transport = self.get_transport('blah')
+ req = request.SmartServerRequest(transport)
+ self.assertEqual(None, request.jail_info.transports)
+ req.setup_jail()
+ self.assertEqual([transport], request.jail_info.transports)
+ req.teardown_jail()
+ self.assertEqual(None, request.jail_info.transports)
+
+
+class TestJailHook(TestCaseWithMemoryTransport):
+
+ def tearDown(self):
+ request.jail_info.transports = None
+ TestCaseWithMemoryTransport.tearDown(self)
+
+ def test_jail_hook(self):
+ request.jail_info.transports = None
+ _pre_open_hook = request._pre_open_hook
+ # Any transport is fine if jail_info.transports is None
+ t = self.get_transport('foo')
+ _pre_open_hook(t)
+ # A transport in jail_info.transports is allowed
+ request.jail_info.transports = [t]
+ _pre_open_hook(t)
+ # A child of a transport in jail_info is allowed
+ _pre_open_hook(t.clone('child'))
+ # A parent is not allowed
+ self.assertRaises(errors.BzrError, _pre_open_hook, t.clone('..'))
+ # A completely unrelated transport is not allowed
+ self.assertRaises(
+ errors.BzrError, _pre_open_hook, get_transport('http://host/'))
+
More information about the bazaar-commits
mailing list