Rev 3807: Fix tracebacks caused by 'Permission denied' errors from a smart in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Oct 29 21:51:40 GMT 2008
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3807
revision-id: pqm at pqm.ubuntu.com-20081029215135-qbnx14rn0gagdvik
parent: pqm at pqm.ubuntu.com-20081029070146-p1cqjt23zctbpg51
parent: andrew.bennetts at canonical.com-20081029011946-m408t8eco1klvoio
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2008-10-29 21:51:35 +0000
message:
Fix tracebacks caused by 'Permission denied' errors from a smart
server (bug 278673),
and refactor client-side smart error handling. (Andrew Bennetts)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/smart/vfs.py vfs.py-20061108095550-gunadhxmzkdjfeek-2
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart_transport.py test_ssh_transport.py-20060608202016-c25gvf1ob7ypbus6-2
bzrlib/transport/remote.py ssh.py-20060608202016-c25gvf1ob7ypbus6-1
------------------------------------------------------------
revno: 3786.2.6
revision-id: andrew.bennetts at canonical.com-20081029011946-m408t8eco1klvoio
parent: andrew.bennetts at canonical.com-20081021214652-uruf96yloni2nq7q
parent: andrew.bennetts at canonical.com-20081029011826-jm8g7g2enemhekcc
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Refactor error catching in Remote* classes.
timestamp: Wed 2008-10-29 12:19:46 +1100
message:
Merge loom thread (includes latest bzr.dev and new tests in bt.test_remote).
added:
bzrlib/tests/fake_command.py fake_command.py-20081021195002-r9v65tgxx63c25v9-1
doc/developers/btree_index_prefetch.txt btree_index_request_-20081004155340-2u6apsy53f43f0xn-1
tools/packaging/lp-upload-release lpuploadrelease-20081020075647-56zdf9z6yav1bx81-1
modified:
Makefile Makefile-20050805140406-d96e3498bb61c5bb
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/_walkdirs_win32.pyx _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/btree_index.py index.py-20080624222253-p0x5f92uyh5hw734-7
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/chunk_writer.py chunk_writer.py-20080630234519-6ggn4id17nipovny-1
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
bzrlib/index.py index.py-20070712131115-lolkarso50vjr64s-1
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/lru_cache.py lru_cache.py-20070119165515-tlw203kuwh0id5gv-1
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/plugins/launchpad/account.py account.py-20071011033320-50y6vfftywf4yllw-1
bzrlib/plugins/launchpad/test_account.py test_account.py-20071011033320-50y6vfftywf4yllw-2
bzrlib/python-compat.h pythoncompat.h-20080924041409-9kvi0fgtuuqp743j-1
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/revisiontree.py revisiontree.py-20060724012533-bg8xyryhxd0o0i0h-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_command_encoding.py test_command_encoding.py-20060106032110-45431fd2ce9ff21f
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
bzrlib/tests/test_chunk_writer.py test_chunk_writer.py-20080630234519-6ggn4id17nipovny-2
bzrlib/tests/test_commands.py test_command.py-20051019190109-3b17be0f52eaa7a8
bzrlib/tests/test_index.py test_index.py-20070712131115-lolkarso50vjr64s-2
bzrlib/tests/test_knit.py test_knit.py-20051212171302-95d4c00dd5f11f2b
bzrlib/tests/test_lru_cache.py test_lru_cache.py-20070119165535-hph6rk4h9rzy4180-1
bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
bzrlib/tests/test_plugins.py plugins.py-20050622075746-32002b55e5e943e9
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
bzrlib/tests/test_store.py teststore.py-20050826022702-f6caadb647395769
bzrlib/tests/tree_implementations/test_tree.py test_tree.py-20061215160206-usu7lwcj8aq2n3br-1
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
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/ppa.txt ppa.txt-20080722055539-606u7t2z32t3ae4w-1
doc/developers/releasing.txt releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
doc/en/user-guide/branching_a_project.txt branching_a_project.-20071122141511-0knao2lklsdsvb1q-2
doc/en/user-guide/core_concepts.txt core_concepts.txt-20071114035000-q36a9h57ps06uvnl-2
doc/en/user-guide/using_checkouts.txt using_checkouts.txt-20071123055134-k5x4ekduci2lbn36-4
------------------------------------------------------------
revno: 3786.3.3
revision-id: andrew.bennetts at canonical.com-20081029011826-jm8g7g2enemhekcc
parent: andrew.bennetts at canonical.com-20081029010456-7j0c3bji305f9uy7
parent: andrew.bennetts at canonical.com-20081029011707-yz42ky3kn63eh5th
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Unify error decoding
timestamp: Wed 2008-10-29 12:18:26 +1100
message:
Merge new tests from 'Always encode PermissionDenied and ReadError'.
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
------------------------------------------------------------
revno: 3786.4.3
revision-id: andrew.bennetts at canonical.com-20081029011707-yz42ky3kn63eh5th
parent: andrew.bennetts at canonical.com-20081029011622-sbppwxeujj23y6bo
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Always encode PermissionDenied and ReadError
timestamp: Wed 2008-10-29 12:17:07 +1100
message:
Add __repr__ to BzrError to make some test failure output clearer.
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
------------------------------------------------------------
revno: 3786.4.2
revision-id: andrew.bennetts at canonical.com-20081029011622-sbppwxeujj23y6bo
parent: andrew.bennetts at canonical.com-20081029004917-3xnmjrj0z9skkjsr
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Always encode PermissionDenied and ReadError
timestamp: Wed 2008-10-29 12:16:22 +1100
message:
Add tests and fix code to make sure ReadError and PermissionDenied are robustly handled by _translate_error.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
------------------------------------------------------------
revno: 3786.3.2
revision-id: andrew.bennetts at canonical.com-20081029010456-7j0c3bji305f9uy7
parent: andrew.bennetts at canonical.com-20081021214543-cxhpfnoqwoav35y1
parent: andrew.bennetts at canonical.com-20081029004917-3xnmjrj0z9skkjsr
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Unify error decoding
timestamp: Wed 2008-10-29 12:04:56 +1100
message:
Merge thread.
added:
bzrlib/tests/fake_command.py fake_command.py-20081021195002-r9v65tgxx63c25v9-1
doc/developers/btree_index_prefetch.txt btree_index_request_-20081004155340-2u6apsy53f43f0xn-1
tools/packaging/lp-upload-release lpuploadrelease-20081020075647-56zdf9z6yav1bx81-1
modified:
Makefile Makefile-20050805140406-d96e3498bb61c5bb
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/_walkdirs_win32.pyx _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/btree_index.py index.py-20080624222253-p0x5f92uyh5hw734-7
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/chunk_writer.py chunk_writer.py-20080630234519-6ggn4id17nipovny-1
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
bzrlib/index.py index.py-20070712131115-lolkarso50vjr64s-1
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/lru_cache.py lru_cache.py-20070119165515-tlw203kuwh0id5gv-1
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/plugins/launchpad/account.py account.py-20071011033320-50y6vfftywf4yllw-1
bzrlib/plugins/launchpad/test_account.py test_account.py-20071011033320-50y6vfftywf4yllw-2
bzrlib/python-compat.h pythoncompat.h-20080924041409-9kvi0fgtuuqp743j-1
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/revisiontree.py revisiontree.py-20060724012533-bg8xyryhxd0o0i0h-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_command_encoding.py test_command_encoding.py-20060106032110-45431fd2ce9ff21f
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
bzrlib/tests/test_chunk_writer.py test_chunk_writer.py-20080630234519-6ggn4id17nipovny-2
bzrlib/tests/test_commands.py test_command.py-20051019190109-3b17be0f52eaa7a8
bzrlib/tests/test_index.py test_index.py-20070712131115-lolkarso50vjr64s-2
bzrlib/tests/test_knit.py test_knit.py-20051212171302-95d4c00dd5f11f2b
bzrlib/tests/test_lru_cache.py test_lru_cache.py-20070119165535-hph6rk4h9rzy4180-1
bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
bzrlib/tests/test_plugins.py plugins.py-20050622075746-32002b55e5e943e9
bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
bzrlib/tests/test_store.py teststore.py-20050826022702-f6caadb647395769
bzrlib/tests/tree_implementations/test_tree.py test_tree.py-20061215160206-usu7lwcj8aq2n3br-1
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
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/ppa.txt ppa.txt-20080722055539-606u7t2z32t3ae4w-1
doc/developers/releasing.txt releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
doc/en/user-guide/branching_a_project.txt branching_a_project.-20071122141511-0knao2lklsdsvb1q-2
doc/en/user-guide/core_concepts.txt core_concepts.txt-20071114035000-q36a9h57ps06uvnl-2
doc/en/user-guide/using_checkouts.txt using_checkouts.txt-20071123055134-k5x4ekduci2lbn36-4
------------------------------------------------------------
revno: 3786.4.1
revision-id: andrew.bennetts at canonical.com-20081029004917-3xnmjrj0z9skkjsr
parent: andrew.bennetts at canonical.com-20081020120522-z5ogdmu0citd690d
parent: pqm at pqm.ubuntu.com-20081028202057-u3csau9zvf0hapya
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Always encode PermissionDenied and ReadError
timestamp: Wed 2008-10-29 11:49:17 +1100
message:
Merge from bzr.dev.
added:
bzrlib/tests/fake_command.py fake_command.py-20081021195002-r9v65tgxx63c25v9-1
doc/developers/btree_index_prefetch.txt btree_index_request_-20081004155340-2u6apsy53f43f0xn-1
tools/packaging/lp-upload-release lpuploadrelease-20081020075647-56zdf9z6yav1bx81-1
modified:
Makefile Makefile-20050805140406-d96e3498bb61c5bb
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/_walkdirs_win32.pyx _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/btree_index.py index.py-20080624222253-p0x5f92uyh5hw734-7
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/chunk_writer.py chunk_writer.py-20080630234519-6ggn4id17nipovny-1
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
bzrlib/index.py index.py-20070712131115-lolkarso50vjr64s-1
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/lru_cache.py lru_cache.py-20070119165515-tlw203kuwh0id5gv-1
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/plugins/launchpad/account.py account.py-20071011033320-50y6vfftywf4yllw-1
bzrlib/plugins/launchpad/test_account.py test_account.py-20071011033320-50y6vfftywf4yllw-2
bzrlib/python-compat.h pythoncompat.h-20080924041409-9kvi0fgtuuqp743j-1
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/repofmt/pack_repo.py pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/revisiontree.py revisiontree.py-20060724012533-bg8xyryhxd0o0i0h-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_command_encoding.py test_command_encoding.py-20060106032110-45431fd2ce9ff21f
bzrlib/tests/blackbox/test_missing.py test_missing.py-20051211212735-a2cf4c1840bb84c4
bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
bzrlib/tests/test_chunk_writer.py test_chunk_writer.py-20080630234519-6ggn4id17nipovny-2
bzrlib/tests/test_commands.py test_command.py-20051019190109-3b17be0f52eaa7a8
bzrlib/tests/test_index.py test_index.py-20070712131115-lolkarso50vjr64s-2
bzrlib/tests/test_knit.py test_knit.py-20051212171302-95d4c00dd5f11f2b
bzrlib/tests/test_lru_cache.py test_lru_cache.py-20070119165535-hph6rk4h9rzy4180-1
bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
bzrlib/tests/test_plugins.py plugins.py-20050622075746-32002b55e5e943e9
bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
bzrlib/tests/test_store.py teststore.py-20050826022702-f6caadb647395769
bzrlib/tests/tree_implementations/test_tree.py test_tree.py-20061215160206-usu7lwcj8aq2n3br-1
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
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/ppa.txt ppa.txt-20080722055539-606u7t2z32t3ae4w-1
doc/developers/releasing.txt releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
doc/en/user-guide/branching_a_project.txt branching_a_project.-20071122141511-0knao2lklsdsvb1q-2
doc/en/user-guide/core_concepts.txt core_concepts.txt-20071114035000-q36a9h57ps06uvnl-2
doc/en/user-guide/using_checkouts.txt using_checkouts.txt-20071123055134-k5x4ekduci2lbn36-4
------------------------------------------------------------
revno: 3786.2.5
revision-id: andrew.bennetts at canonical.com-20081021214652-uruf96yloni2nq7q
parent: andrew.bennetts at canonical.com-20081021055910-u6yii5k2add0sw2s
parent: andrew.bennetts at canonical.com-20081021214543-cxhpfnoqwoav35y1
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Refactor error catching in Remote* classes.
timestamp: Wed 2008-10-22 08:46:52 +1100
message:
Merge from loom thread.
------------------------------------------------------------
revno: 3786.3.1
revision-id: andrew.bennetts at canonical.com-20081021214543-cxhpfnoqwoav35y1
parent: andrew.bennetts at canonical.com-20081020120656-jqttn3kqvu1u5pfa
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Unify error decoding
timestamp: Wed 2008-10-22 08:45:43 +1100
message:
Fix unbound local in _translate_error.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
------------------------------------------------------------
revno: 3786.2.4
revision-id: andrew.bennetts at canonical.com-20081021055910-u6yii5k2add0sw2s
parent: andrew.bennetts at canonical.com-20081020125231-gv4dn91he3j4e7zk
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Refactor error catching in Remote* classes.
timestamp: Tue 2008-10-21 16:59:10 +1100
message:
Add NEWS entry, because this branch fixes #278673.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
------------------------------------------------------------
revno: 3786.2.3
revision-id: andrew.bennetts at canonical.com-20081020125231-gv4dn91he3j4e7zk
parent: andrew.bennetts at canonical.com-20081020120656-jqttn3kqvu1u5pfa
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Refactor error catching in Remote* classes.
timestamp: Mon 2008-10-20 23:52:31 +1100
message:
Remove duplicated 'call & translate errors' code in bzrlib.remote.
Also fixes many places in bzrlib.remote that were missing error translation!
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
------------------------------------------------------------
revno: 3786.2.2
revision-id: andrew.bennetts at canonical.com-20081020120656-jqttn3kqvu1u5pfa
parent: andrew.bennetts at canonical.com-20081020120522-z5ogdmu0citd690d
parent: andrew.bennetts at canonical.com-20081017060607-zk5au6wuq2vpdhkw
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Unify error decoding
timestamp: Mon 2008-10-20 23:06:56 +1100
message:
Unify error translation done in bzrlib.remote and bzrlib.transport.remote.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/test_smart_transport.py test_ssh_transport.py-20060608202016-c25gvf1ob7ypbus6-2
bzrlib/transport/remote.py ssh.py-20060608202016-c25gvf1ob7ypbus6-1
------------------------------------------------------------
revno: 3779.3.3
revision-id: andrew.bennetts at canonical.com-20081017060607-zk5au6wuq2vpdhkw
parent: andrew.bennetts at canonical.com-20081017060110-hx8shx11fhyiionq
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: hpss-error-translation
timestamp: Fri 2008-10-17 17:06:07 +1100
message:
Add a docstring.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
------------------------------------------------------------
revno: 3779.3.2
revision-id: andrew.bennetts at canonical.com-20081017060110-hx8shx11fhyiionq
parent: andrew.bennetts at canonical.com-20081016055443-nsppqkpy3ospbhu3
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: hpss-error-translation
timestamp: Fri 2008-10-17 17:01:10 +1100
message:
Unify error translation done in bzrlib.remote and bzrlib.transport.remote.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/tests/test_smart_transport.py test_ssh_transport.py-20060608202016-c25gvf1ob7ypbus6-2
bzrlib/transport/remote.py ssh.py-20060608202016-c25gvf1ob7ypbus6-1
------------------------------------------------------------
revno: 3786.2.1
revision-id: andrew.bennetts at canonical.com-20081020120522-z5ogdmu0citd690d
parent: pqm at pqm.ubuntu.com-20081020020359-7f8c4hviijt1m5vq
parent: andrew.bennetts at canonical.com-20081016055443-nsppqkpy3ospbhu3
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: Always encode PermissionDenied and ReadError
timestamp: Mon 2008-10-20 23:05:22 +1100
message:
Move encoding/decoding logic of PermissionDenied and ReadError so that it happens for all RPCs.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/smart/vfs.py vfs.py-20061108095550-gunadhxmzkdjfeek-2
------------------------------------------------------------
revno: 3779.3.1
revision-id: andrew.bennetts at canonical.com-20081016055443-nsppqkpy3ospbhu3
parent: pqm at pqm.ubuntu.com-20081016043554-38i4ho6svnlyba65
committer: Andrew Bennetts <andrew.bennetts at canonical.com>
branch nick: hpss-error-translation
timestamp: Thu 2008-10-16 16:54:43 +1100
message:
Move encoding/decoding logic of PermissionDenied and ReadError so that it happens for all RPCs.
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/smart/vfs.py vfs.py-20061108095550-gunadhxmzkdjfeek-2
=== modified file 'NEWS'
--- a/NEWS 2008-10-29 06:19:35 +0000
+++ b/NEWS 2008-10-29 21:51:35 +0000
@@ -67,6 +67,9 @@
could only happen if ``bzr reconcile`` decided that the parent
ordering was incorrect in the file graph. (John Arbash Meinel)
+ * "Permission denied" errors that occur when pushing a new branch to a
+ smart server no longer cause tracebacks. (Andrew Bennetts, #278673)
+
* Some compatibility fixes for building the extensions with MSVC and
for python2.4. (John Arbash Meinel, #277484)
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py 2008-10-21 03:47:13 +0000
+++ b/bzrlib/errors.py 2008-10-29 01:17:07 +0000
@@ -134,6 +134,9 @@
s = str(s)
return s
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, str(self))
+
def _get_format_string(self):
"""Return format string for this exception or None"""
fmt = getattr(self, '_fmt', None)
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2008-10-27 06:14:45 +0000
+++ b/bzrlib/remote.py 2008-10-29 01:19:46 +0000
@@ -43,9 +43,32 @@
from bzrlib.trace import mutter, note, warning
+class _RpcHelper(object):
+ """Mixin class that helps with issuing RPCs."""
+
+ def _call(self, method, *args, **err_context):
+ try:
+ return self._client.call(method, *args)
+ except errors.ErrorFromSmartServer, err:
+ self._translate_error(err, **err_context)
+
+ def _call_expecting_body(self, method, *args, **err_context):
+ try:
+ return self._client.call_expecting_body(method, *args)
+ except errors.ErrorFromSmartServer, err:
+ self._translate_error(err, **err_context)
+
+ def _call_with_body_bytes_expecting_body(self, method, args, body_bytes,
+ **err_context):
+ try:
+ return self._client.call_with_body_bytes_expecting_body(
+ method, args, body_bytes)
+ except errors.ErrorFromSmartServer, err:
+ self._translate_error(err, **err_context)
+
# Note: RemoteBzrDirFormat is in bzrdir.py
-class RemoteBzrDir(BzrDir):
+class RemoteBzrDir(BzrDir, _RpcHelper):
"""Control directory on a remote server, accessed via bzr:// or similar."""
def __init__(self, transport, _client=None):
@@ -67,7 +90,7 @@
return
path = self._path_for_remote_call(self._client)
- response = self._client.call('BzrDir.open', path)
+ response = self._call('BzrDir.open', path)
if response not in [('yes',), ('no',)]:
raise errors.UnexpectedSmartServerResponse(response)
if response == ('no',):
@@ -82,13 +105,13 @@
self._real_bzrdir = BzrDir.open_from_transport(
self.root_transport, _server_formats=False)
+ def _translate_error(self, err, **context):
+ _translate_error(err, bzrdir=self, **context)
+
def cloning_metadir(self, stacked=False):
self._ensure_real()
return self._real_bzrdir.cloning_metadir(stacked)
- def _translate_error(self, err, **context):
- _translate_error(err, bzrdir=self, **context)
-
def create_repository(self, shared=False):
self._ensure_real()
self._real_bzrdir.create_repository(shared=shared)
@@ -123,10 +146,7 @@
def get_branch_reference(self):
"""See BzrDir.get_branch_reference()."""
path = self._path_for_remote_call(self._client)
- try:
- response = self._client.call('BzrDir.open_branch', path)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err)
+ response = self._call('BzrDir.open_branch', path)
if response[0] == 'ok':
if response[1] == '':
# branch at this location.
@@ -157,13 +177,10 @@
path = self._path_for_remote_call(self._client)
verb = 'BzrDir.find_repositoryV2'
try:
- try:
- response = self._client.call(verb, path)
- except errors.UnknownSmartMethod:
- verb = 'BzrDir.find_repository'
- response = self._client.call(verb, path)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err)
+ response = self._call(verb, path)
+ except errors.UnknownSmartMethod:
+ verb = 'BzrDir.find_repository'
+ response = self._call(verb, path)
if response[0] != 'ok':
raise errors.UnexpectedSmartServerResponse(response)
if verb == 'BzrDir.find_repository':
@@ -270,7 +287,7 @@
'Does not support nested trees', target_format)
-class RemoteRepository(object):
+class RemoteRepository(_RpcHelper):
"""Repository accessed over rpc.
For the moment most operations are performed using local transport-backed
@@ -396,11 +413,8 @@
return {}
path = self.bzrdir._path_for_remote_call(self._client)
- try:
- response = self._client.call_expecting_body(
- 'Repository.get_revision_graph', path, revision_id)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err)
+ response = self._call_expecting_body(
+ 'Repository.get_revision_graph', path, revision_id)
response_tuple, response_handler = response
if response_tuple[0] != 'ok':
raise errors.UnexpectedSmartServerResponse(response_tuple)
@@ -422,8 +436,7 @@
# The null revision is always present.
return True
path = self.bzrdir._path_for_remote_call(self._client)
- response = self._client.call(
- 'Repository.has_revision', path, revision_id)
+ response = self._call('Repository.has_revision', path, revision_id)
if response[0] not in ('yes', 'no'):
raise errors.UnexpectedSmartServerResponse(response)
if response[0] == 'yes':
@@ -469,7 +482,7 @@
fmt_committers = 'no'
else:
fmt_committers = 'yes'
- response_tuple, response_handler = self._client.call_expecting_body(
+ response_tuple, response_handler = self._call_expecting_body(
'Repository.gather_stats', path, fmt_revid, fmt_committers)
if response_tuple[0] != 'ok':
raise errors.UnexpectedSmartServerResponse(response_tuple)
@@ -514,7 +527,7 @@
def is_shared(self):
"""See Repository.is_shared()."""
path = self.bzrdir._path_for_remote_call(self._client)
- response = self._client.call('Repository.is_shared', path)
+ response = self._call('Repository.is_shared', path)
if response[0] not in ('yes', 'no'):
raise SmartProtocolError('unexpected response code %s' % (response,))
return response[0] == 'yes'
@@ -539,11 +552,9 @@
path = self.bzrdir._path_for_remote_call(self._client)
if token is None:
token = ''
- try:
- response = self._client.call('Repository.lock_write', path, token)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err, token=token)
-
+ err_context = {'token': token}
+ response = self._call('Repository.lock_write', path, token,
+ **err_context)
if response[0] == 'ok':
ok, token = response
return token
@@ -626,10 +637,9 @@
if not token:
# with no token the remote repository is not persistently locked.
return
- try:
- response = self._client.call('Repository.unlock', path, token)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err, token=token)
+ err_context = {'token': token}
+ response = self._call('Repository.unlock', path, token,
+ **err_context)
if response == ('ok',):
return
else:
@@ -676,7 +686,7 @@
import tempfile
path = self.bzrdir._path_for_remote_call(self._client)
try:
- response, protocol = self._client.call_expecting_body(
+ response, protocol = self._call_expecting_body(
'Repository.tarball', path, compression)
except errors.UnknownSmartMethod:
protocol.cancel_read_body()
@@ -962,7 +972,7 @@
verb = 'Repository.get_parent_map'
args = (path,) + tuple(keys)
try:
- response = self._client.call_with_body_bytes_expecting_body(
+ response = self._call_with_body_bytes_expecting_body(
verb, args, self._serialise_search_recipe(recipe))
except errors.UnknownSmartMethod:
# Server does not support this method, so get the whole graph.
@@ -1252,7 +1262,7 @@
return True
-class RemoteBranch(branch.Branch):
+class RemoteBranch(branch.Branch, _RpcHelper):
"""Branch stored on a server accessed by HPSS RPC.
At the moment most operations are mapped down to simple file operations.
@@ -1409,11 +1419,10 @@
stacking.
"""
try:
+ # there may not be a repository yet, so we can't use
+ # self._translate_error, so we can't use self._call either.
response = self._client.call('Branch.get_stacked_on_url',
self._remote_path())
- if response[0] != 'ok':
- raise errors.UnexpectedSmartServerResponse(response)
- return response[1]
except errors.ErrorFromSmartServer, err:
# there may not be a repository yet, so we can't call through
# its _translate_error
@@ -1421,6 +1430,9 @@
except errors.UnknownSmartMethod, err:
self._ensure_real()
return self._real_branch.get_stacked_on_url()
+ if response[0] != 'ok':
+ raise errors.UnexpectedSmartServerResponse(response)
+ return response[1]
def lock_read(self):
self.repository.lock_read()
@@ -1439,12 +1451,10 @@
branch_token = token
repo_token = self.repository.lock_write()
self.repository.unlock()
- try:
- response = self._client.call(
- 'Branch.lock_write', self._remote_path(),
- branch_token, repo_token or '')
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err, token=token)
+ err_context = {'token': token}
+ response = self._call(
+ 'Branch.lock_write', self._remote_path(), branch_token,
+ repo_token or '', **err_context)
if response[0] != 'ok':
raise errors.UnexpectedSmartServerResponse(response)
ok, branch_token, repo_token = response
@@ -1484,11 +1494,10 @@
return self._lock_token or None
def _unlock(self, branch_token, repo_token):
- try:
- response = self._client.call('Branch.unlock', self._remote_path(), branch_token,
- repo_token or '')
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err, token=str((branch_token, repo_token)))
+ err_context = {'token': str((branch_token, repo_token))}
+ response = self._call(
+ 'Branch.unlock', self._remote_path(), branch_token,
+ repo_token or '', **err_context)
if response == ('ok',):
return
raise errors.UnexpectedSmartServerResponse(response)
@@ -1539,7 +1548,7 @@
self._leave_lock = False
def _last_revision_info(self):
- response = self._client.call('Branch.last_revision_info', self._remote_path())
+ response = self._call('Branch.last_revision_info', self._remote_path())
if response[0] != 'ok':
raise SmartProtocolError('unexpected response code %s' % (response,))
revno = int(response[1])
@@ -1548,7 +1557,7 @@
def _gen_revision_history(self):
"""See Branch._gen_revision_history()."""
- response_tuple, response_handler = self._client.call_expecting_body(
+ response_tuple, response_handler = self._call_expecting_body(
'Branch.revision_history', self._remote_path())
if response_tuple[0] != 'ok':
raise errors.UnexpectedSmartServerResponse(response_tuple)
@@ -1562,12 +1571,11 @@
def _set_last_revision_descendant(self, revision_id, other_branch,
allow_diverged=False, allow_overwrite_descendant=False):
- try:
- response = self._client.call('Branch.set_last_revision_ex',
- self._remote_path(), self._lock_token, self._repo_lock_token, revision_id,
- int(allow_diverged), int(allow_overwrite_descendant))
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err, other_branch=other_branch)
+ err_context = {'other_branch': other_branch}
+ response = self._call('Branch.set_last_revision_ex',
+ self._remote_path(), self._lock_token, self._repo_lock_token,
+ revision_id, int(allow_diverged), int(allow_overwrite_descendant),
+ **err_context)
self._clear_cached_state()
if len(response) != 3 and response[0] != 'ok':
raise errors.UnexpectedSmartServerResponse(response)
@@ -1579,11 +1587,9 @@
def _set_last_revision(self, revision_id):
self._clear_cached_state()
- try:
- response = self._client.call('Branch.set_last_revision',
- self._remote_path(), self._lock_token, self._repo_lock_token, revision_id)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err)
+ response = self._call('Branch.set_last_revision',
+ self._remote_path(), self._lock_token, self._repo_lock_token,
+ revision_id)
if response != ('ok',):
raise errors.UnexpectedSmartServerResponse(response)
@@ -1657,16 +1663,15 @@
def set_last_revision_info(self, revno, revision_id):
revision_id = ensure_null(revision_id)
try:
- response = self._client.call('Branch.set_last_revision_info',
- self._remote_path(), self._lock_token, self._repo_lock_token, str(revno), revision_id)
+ response = self._call('Branch.set_last_revision_info',
+ self._remote_path(), self._lock_token, self._repo_lock_token,
+ str(revno), revision_id)
except errors.UnknownSmartMethod:
self._ensure_real()
self._clear_cached_state_of_remote_branch_only()
self._real_branch.set_last_revision_info(revno, revision_id)
self._last_revision_info_cache = revno, revision_id
return
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err)
if response == ('ok',):
self._clear_cached_state()
self._last_revision_info_cache = revno, revision_id
@@ -1760,6 +1765,7 @@
- bzrdir
- token
- other_branch
+ - path
If the error from the server doesn't match a known pattern, then
UnknownErrorFromSmartServer is raised.
@@ -1767,9 +1773,23 @@
def find(name):
try:
return context[name]
- except KeyError, keyErr:
- mutter('Missing key %r in context %r', keyErr.args[0], context)
+ except KeyError, key_err:
+ mutter('Missing key %r in context %r', key_err.args[0], context)
raise err
+ def get_path():
+ """Get the path from the context if present, otherwise use first error
+ arg.
+ """
+ try:
+ return context['path']
+ except KeyError, key_err:
+ try:
+ return err.error_args[0]
+ except IndexError, idx_err:
+ mutter(
+ 'Missing key %r in context %r', key_err.args[0], context)
+ raise err
+
if err.error_verb == 'NoSuchRevision':
raise NoSuchRevision(find('branch'), err.error_args[0])
elif err.error_verb == 'nosuchrevision':
@@ -1796,4 +1816,41 @@
raise errors.UnstackableRepositoryFormat(*err.error_args)
elif err.error_verb == 'NotStacked':
raise errors.NotStacked(branch=find('branch'))
+ elif err.error_verb == 'PermissionDenied':
+ path = get_path()
+ if len(err.error_args) >= 2:
+ extra = err.error_args[1]
+ else:
+ extra = None
+ raise errors.PermissionDenied(path, extra=extra)
+ elif err.error_verb == 'ReadError':
+ path = get_path()
+ raise errors.ReadError(path)
+ elif err.error_verb == 'NoSuchFile':
+ path = get_path()
+ raise errors.NoSuchFile(path)
+ elif err.error_verb == 'FileExists':
+ raise errors.FileExists(err.error_args[0])
+ elif err.error_verb == 'DirectoryNotEmpty':
+ raise errors.DirectoryNotEmpty(err.error_args[0])
+ elif err.error_verb == 'ShortReadvError':
+ args = err.error_args
+ raise errors.ShortReadvError(
+ args[0], int(args[1]), int(args[2]), int(args[3]))
+ elif err.error_verb in ('UnicodeEncodeError', 'UnicodeDecodeError'):
+ encoding = str(err.error_args[0]) # encoding must always be a string
+ val = err.error_args[1]
+ start = int(err.error_args[2])
+ end = int(err.error_args[3])
+ reason = str(err.error_args[4]) # reason must always be a string
+ if val.startswith('u:'):
+ val = val[2:].decode('utf-8')
+ elif val.startswith('s:'):
+ val = val[2:].decode('base64')
+ if err.error_verb == 'UnicodeDecodeError':
+ raise UnicodeDecodeError(encoding, val, start, end, reason)
+ elif err.error_verb == 'UnicodeEncodeError':
+ raise UnicodeEncodeError(encoding, val, start, end, reason)
+ elif err.error_verb == 'ReadOnlyError':
+ raise errors.TransportNotPossible('readonly transport')
raise errors.UnknownErrorFromSmartServer(err)
=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py 2008-10-01 05:40:45 +0000
+++ b/bzrlib/smart/request.py 2008-10-16 05:54:43 +0000
@@ -303,8 +303,9 @@
# with a plain string
str_or_unicode = e.object
if isinstance(str_or_unicode, unicode):
- # XXX: UTF-8 might have \x01 (our seperator byte) in it. We
- # should escape it somehow.
+ # XXX: UTF-8 might have \x01 (our protocol v1 and v2 seperator
+ # byte) in it, so this encoding could cause broken responses.
+ # Newer clients use protocol v3, so will be fine.
val = 'u:' + str_or_unicode.encode('utf-8')
else:
val = 's:' + str_or_unicode.encode('base64')
@@ -316,6 +317,12 @@
return FailedSmartServerResponse(('ReadOnlyError', ))
else:
raise
+ except errors.ReadError, e:
+ # cannot read the file
+ return FailedSmartServerResponse(('ReadError', e.path))
+ except errors.PermissionDenied, e:
+ return FailedSmartServerResponse(
+ ('PermissionDenied', e.path, e.extra))
def headers_received(self, headers):
# Just a no-op at the moment.
=== modified file 'bzrlib/smart/vfs.py'
--- a/bzrlib/smart/vfs.py 2008-01-04 03:12:11 +0000
+++ b/bzrlib/smart/vfs.py 2008-10-16 05:54:43 +0000
@@ -72,13 +72,7 @@
def do(self, relpath):
relpath = self.translate_client_path(relpath)
- try:
- backing_bytes = self._backing_transport.get_bytes(relpath)
- except errors.ReadError:
- # cannot read the file
- return request.FailedSmartServerResponse(('ReadError', ))
- except errors.PermissionDenied:
- return request.FailedSmartServerResponse(('PermissionDenied',))
+ backing_bytes = self._backing_transport.get_bytes(relpath)
return request.SuccessfulSmartServerResponse(('ok',), backing_bytes)
=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py 2008-10-15 18:45:28 +0000
+++ b/bzrlib/tests/test_remote.py 2008-10-29 01:16:22 +0000
@@ -1551,6 +1551,50 @@
expected_error = errors.DivergedBranches(branch, other_branch)
self.assertEqual(expected_error, translated_error)
+ def test_ReadError_no_args(self):
+ path = 'a path'
+ translated_error = self.translateTuple(('ReadError',), path=path)
+ expected_error = errors.ReadError(path)
+ self.assertEqual(expected_error, translated_error)
+
+ def test_ReadError(self):
+ path = 'a path'
+ translated_error = self.translateTuple(('ReadError', path))
+ expected_error = errors.ReadError(path)
+ self.assertEqual(expected_error, translated_error)
+
+ def test_PermissionDenied_no_args(self):
+ path = 'a path'
+ translated_error = self.translateTuple(('PermissionDenied',), path=path)
+ expected_error = errors.PermissionDenied(path)
+ self.assertEqual(expected_error, translated_error)
+
+ def test_PermissionDenied_one_arg(self):
+ path = 'a path'
+ translated_error = self.translateTuple(('PermissionDenied', path))
+ expected_error = errors.PermissionDenied(path)
+ self.assertEqual(expected_error, translated_error)
+
+ def test_PermissionDenied_one_arg_and_context(self):
+ """Given a choice between a path from the local context and a path on
+ the wire, _translate_error prefers the path from the local context.
+ """
+ local_path = 'local path'
+ remote_path = 'remote path'
+ translated_error = self.translateTuple(
+ ('PermissionDenied', remote_path), path=local_path)
+ expected_error = errors.PermissionDenied(local_path)
+ self.assertEqual(expected_error, translated_error)
+
+ def test_PermissionDenied_two_args(self):
+ path = 'a path'
+ extra = 'a string with extra info'
+ translated_error = self.translateTuple(
+ ('PermissionDenied', path, extra))
+ expected_error = errors.PermissionDenied(path, extra)
+ self.assertEqual(expected_error, translated_error)
+
+
class TestErrorTranslationRobustness(TestErrorTranslationBase):
"""Unit tests for bzrlib.remote._translate_error's robustness.
@@ -1589,6 +1633,20 @@
self._get_log(keep_log_file=True),
"Missing key 'branch' in context")
+ def test_path_missing(self):
+ """Some translations (PermissionDenied, ReadError) can determine the
+ 'path' variable from either the wire or the local context. If neither
+ has it, then an error is raised.
+ """
+ error_tuple = ('ReadError',)
+ server_error = errors.ErrorFromSmartServer(error_tuple)
+ translated_error = self.translateErrorFromSmartServer(server_error)
+ self.assertEqual(server_error, translated_error)
+ # In addition to re-raising ErrorFromSmartServer, some debug info has
+ # been muttered to the log file for developer to look at.
+ self.assertContainsRe(
+ self._get_log(keep_log_file=True), "Missing key 'path' in context")
+
class TestStacking(tests.TestCaseWithTransport):
"""Tests for operations on stacked remote repositories.
=== modified file 'bzrlib/tests/test_smart_transport.py'
--- a/bzrlib/tests/test_smart_transport.py 2008-08-29 19:32:00 +0000
+++ b/bzrlib/tests/test_smart_transport.py 2008-10-17 06:01:10 +0000
@@ -992,12 +992,9 @@
smart_server.start_background_thread('-' + self.id())
try:
transport = remote.RemoteTCPTransport(smart_server.get_url())
- try:
- transport.get('something')
- except errors.TransportError, e:
- self.assertContainsRe(str(e), 'some random exception')
- else:
- self.fail("get did not raise expected error")
+ err = self.assertRaises(errors.UnknownErrorFromSmartServer,
+ transport.get, 'something')
+ self.assertContainsRe(str(err), 'some random exception')
transport.disconnect()
finally:
smart_server.stop_background_thread()
@@ -1091,12 +1088,9 @@
# asked for by the client. This gives meaningful and unsurprising errors
# for users.
self._captureVar('BZR_NO_SMART_VFS', None)
- try:
- self.transport.get('not%20a%20file')
- except errors.NoSuchFile, e:
- self.assertEqual('not%20a%20file', e.path)
- else:
- self.fail("get did not raise expected error")
+ err = self.assertRaises(
+ errors.NoSuchFile, self.transport.get, 'not%20a%20file')
+ self.assertEqual('not%20a%20file', err.path)
def test_simple_clone_conn(self):
"""Test that cloning reuses the same connection."""
@@ -1400,8 +1394,9 @@
client_medium = medium.SmartSimplePipesClientMedium(None, None, 'base')
transport = remote.RemoteTransport(
'bzr://localhost/', medium=client_medium)
+ err = errors.ErrorFromSmartServer(("ReadOnlyError", ))
self.assertRaises(errors.TransportNotPossible,
- transport._translate_error, ("ReadOnlyError", ))
+ transport._translate_error, err)
class TestSmartProtocol(tests.TestCase):
=== modified file 'bzrlib/transport/remote.py'
--- a/bzrlib/transport/remote.py 2008-10-15 18:45:28 +0000
+++ b/bzrlib/transport/remote.py 2008-10-17 06:01:10 +0000
@@ -28,6 +28,7 @@
config,
debug,
errors,
+ remote,
trace,
transport,
urlutils,
@@ -143,8 +144,7 @@
elif resp == ('no', ):
return False
else:
- self._translate_error(resp)
- raise errors.UnexpectedSmartServerResponse(resp)
+ raise errors.UnexpectedSmartServerResponse(resp)
def get_smart_client(self):
return self._get_connection()
@@ -161,25 +161,22 @@
return self._combine_paths(self._path, relpath)
def _call(self, method, *args):
- try:
- resp = self._call2(method, *args)
- except errors.ErrorFromSmartServer, err:
- self._translate_error(err.error_tuple)
- self._translate_error(resp)
+ resp = self._call2(method, *args)
+ self._ensure_ok(resp)
def _call2(self, method, *args):
"""Call a method on the remote server."""
try:
return self._client.call(method, *args)
except errors.ErrorFromSmartServer, err:
- self._translate_error(err.error_tuple)
+ self._translate_error(err)
def _call_with_body_bytes(self, method, args, body):
"""Call a method on the remote server with body bytes."""
try:
return self._client.call_with_body_bytes(method, args, body)
except errors.ErrorFromSmartServer, err:
- self._translate_error(err.error_tuple)
+ self._translate_error(err)
def has(self, relpath):
"""Indicate whether a remote file of the given name exists or not.
@@ -192,7 +189,7 @@
elif resp == ('no', ):
return False
else:
- self._translate_error(resp)
+ raise errors.UnexpectedSmartServerResponse(resp)
def get(self, relpath):
"""Return file-like object reading the contents of a remote file.
@@ -206,7 +203,7 @@
try:
resp, response_handler = self._client.call_expecting_body('get', remote)
except errors.ErrorFromSmartServer, err:
- self._translate_error(err.error_tuple, relpath)
+ self._translate_error(err, relpath)
if resp != ('ok', ):
response_handler.cancel_read_body()
raise errors.UnexpectedSmartServerResponse(resp)
@@ -221,7 +218,6 @@
def mkdir(self, relpath, mode=None):
resp = self._call2('mkdir', self._remote_path(relpath),
self._serialise_optional_mode(mode))
- self._translate_error(resp)
def open_write_stream(self, relpath, mode=None):
"""See Transport.open_write_stream."""
@@ -243,7 +239,7 @@
resp = self._call_with_body_bytes('put',
(self._remote_path(relpath), self._serialise_optional_mode(mode)),
upload_contents)
- self._translate_error(resp)
+ self._ensure_ok(resp)
return len(upload_contents)
def put_bytes_non_atomic(self, relpath, bytes, mode=None,
@@ -260,7 +256,7 @@
(self._remote_path(relpath), self._serialise_optional_mode(mode),
create_parent_str, self._serialise_optional_mode(dir_mode)),
bytes)
- self._translate_error(resp)
+ self._ensure_ok(resp)
def put_file(self, relpath, upload_file, mode=None):
# its not ideal to seek back, but currently put_non_atomic_file depends
@@ -290,11 +286,11 @@
bytes)
if resp[0] == 'appended':
return int(resp[1])
- self._translate_error(resp)
+ raise errors.UnexpectedSmartServerResponse(resp)
def delete(self, relpath):
resp = self._call2('delete', self._remote_path(relpath))
- self._translate_error(resp)
+ self._ensure_ok(resp)
def external_url(self):
"""See bzrlib.transport.Transport.external_url."""
@@ -322,7 +318,7 @@
[(c.start, c.length) for c in coalesced])
resp, response_handler = result
except errors.ErrorFromSmartServer, err:
- self._translate_error(err.error_tuple)
+ self._translate_error(err)
if resp[0] != 'readv':
# This should raise an exception
@@ -381,59 +377,12 @@
def rmdir(self, relpath):
resp = self._call('rmdir', self._remote_path(relpath))
- def _translate_error(self, resp, orig_path=None):
- """Raise an exception from a response"""
- if resp is None:
- what = None
- else:
- what = resp[0]
- if what == 'ok':
- return
- elif what == 'NoSuchFile':
- if orig_path is not None:
- error_path = orig_path
- else:
- error_path = resp[1]
- raise errors.NoSuchFile(error_path)
- elif what == 'error':
- raise errors.SmartProtocolError(unicode(resp[1]))
- elif what == 'FileExists':
- raise errors.FileExists(resp[1])
- elif what == 'DirectoryNotEmpty':
- raise errors.DirectoryNotEmpty(resp[1])
- elif what == 'ShortReadvError':
- raise errors.ShortReadvError(resp[1], int(resp[2]),
- int(resp[3]), int(resp[4]))
- elif what in ('UnicodeEncodeError', 'UnicodeDecodeError'):
- encoding = str(resp[1]) # encoding must always be a string
- val = resp[2]
- start = int(resp[3])
- end = int(resp[4])
- reason = str(resp[5]) # reason must always be a string
- if val.startswith('u:'):
- val = val[2:].decode('utf-8')
- elif val.startswith('s:'):
- val = val[2:].decode('base64')
- if what == 'UnicodeDecodeError':
- raise UnicodeDecodeError(encoding, val, start, end, reason)
- elif what == 'UnicodeEncodeError':
- raise UnicodeEncodeError(encoding, val, start, end, reason)
- elif what == "ReadOnlyError":
- raise errors.TransportNotPossible('readonly transport')
- elif what == "ReadError":
- if orig_path is not None:
- error_path = orig_path
- else:
- error_path = resp[1]
- raise errors.ReadError(error_path)
- elif what == "PermissionDenied":
- if orig_path is not None:
- error_path = orig_path
- else:
- error_path = resp[1]
- raise errors.PermissionDenied(error_path)
- else:
- raise errors.SmartProtocolError('unexpected smart server error: %r' % (resp,))
+ def _ensure_ok(self, resp):
+ if resp[0] != 'ok':
+ raise errors.UnexpectedSmartServerResponse(resp)
+
+ def _translate_error(self, err, orig_path=None):
+ remote._translate_error(err, path=orig_path)
def disconnect(self):
self.get_smart_medium().disconnect()
@@ -442,8 +391,7 @@
resp = self._call2('stat', self._remote_path(relpath))
if resp[0] == 'stat':
return _SmartStat(int(resp[1]), int(resp[2], 8))
- else:
- self._translate_error(resp)
+ raise errors.UnexpectedSmartServerResponse(resp)
## def lock_read(self, relpath):
## """Lock the given file for shared (read) access.
@@ -465,15 +413,13 @@
resp = self._call2('list_dir', self._remote_path(relpath))
if resp[0] == 'names':
return [name.encode('ascii') for name in resp[1:]]
- else:
- self._translate_error(resp)
+ raise errors.UnexpectedSmartServerResponse(resp)
def iter_files_recursive(self):
resp = self._call2('iter_files_recursive', self._remote_path(''))
if resp[0] == 'names':
return resp[1:]
- else:
- self._translate_error(resp)
+ raise errors.UnexpectedSmartServerResponse(resp)
class RemoteTCPTransport(RemoteTransport):
More information about the bazaar-commits
mailing list