Merge lp:~jameinel/bzr/2.5-remote-wt-tests-1046697 into lp:bzr/2.5

Proposed by John A Meinel on 2012-09-06
Status: Merged
Approved by: John A Meinel on 2012-09-07
Approved revision: 6523
Merged at revision: 6509
Proposed branch: lp:~jameinel/bzr/2.5-remote-wt-tests-1046697
Merge into: lp:bzr/2.5
Diff against target: 596 lines (+189/-76)
14 files modified
bzrlib/remote.py (+15/-6)
bzrlib/smart/repository.py (+12/-9)
bzrlib/tests/per_tree/__init__.py (+18/-4)
bzrlib/tests/per_workingtree/__init__.py (+39/-6)
bzrlib/tests/per_workingtree/test_commit.py (+3/-2)
bzrlib/tests/per_workingtree/test_executable.py (+1/-2)
bzrlib/tests/per_workingtree/test_parents.py (+5/-3)
bzrlib/tests/per_workingtree/test_remove.py (+1/-1)
bzrlib/tests/per_workingtree/test_smart_add.py (+3/-0)
bzrlib/tests/per_workingtree/test_views.py (+2/-2)
bzrlib/tests/per_workingtree/test_workingtree.py (+24/-29)
bzrlib/tests/test_selftest.py (+39/-9)
bzrlib/workingtree_4.py (+19/-3)
doc/en/release-notes/bzr-2.5.txt (+8/-0)
To merge this branch: bzr merge lp:~jameinel/bzr/2.5-remote-wt-tests-1046697
Reviewer Review Type Date Requested Status
Richard Wilbur 2012-09-06 Approve on 2012-09-07
Review via email: mp+123061@code.launchpad.net

Commit message

Add per_workingtree test scenario for a lightweight checkout of a RemoteRepository (bug #1046697) and cleanup all associated fallout.

Description of the change

This branch aggregates most of the branches I proposed today.
It adds a test permutation of a lightweight WT6 checkout of a remote repository.
That resulted in a fair number of tests failing for various reasons.

1) RemoteBranch.initialize not preserving the Repository. bzrdir.sprout() creates the repo, fetches into it, and then passes the locked repo to the branch. The branch then wants to write_lock itself to initialize, but it can't write lock an already locked repository (and we don't want it to). RemoteBranch was using ._vfs_initialize() when the target was local, but wasn't passing down the repository.

2) RemoteBranch.peek_lock_mode() wasn't implemented. This is trivial to implement, so I just did so.

3) Repository.record_stream() was not always finalizing its progress bar. It takes out a progress bar in a generator. However, the generator is often run in sync with some other stepper, which means it isn't always run to completion. I just put it into a try/finally so if the generator gets garbage collected, we pop off the nested progress bar. This only works in python ? (2.5 maybe?) but I've been testing it with python2.6 which I'm pretty sure is our min requirement for newer bzr.

4) Lots of test suite fixups. Quite a few tests
 a) assumed that WT.branch was in the same location as WT
 b) assumed that make_branch().bzrdir.create_workingtree() would work. It doesn't when the Branch created is on a remote location, and you want a local workingtree.
 c) WorkingTreeFormat6._matchingbzrdir did *not* create a WorkingTreeFormat6 tree. It would create a Format4 tree because it just inherited the attribute from there. This adds a _get_matchingbzrdir attribute that returns the right thing. (the symptom here is that stuff like views and filters would check self.workingtree_format.supports_views but then self.bzrdir_format.make_workingtree wouldn't actually create a WT that supported views.)

I only ran the per_workingtree tests, but that should be enough since that is the only new permutations that were added.

To post a comment you must log in.
Richard Wilbur (richard-wilbur) wrote :

Lots of good fixes for working trees and tests. This looks like good stuff for the baseline. +1

Interesting behaviour from .iter_files_bytes() in get_file_text(): yielding empty results until the last result which contains the full contents of the file.

Nice cleanup on the progress bars.

review: Approve
6523. By John A Meinel on 2012-09-07

rename some variables for clarity.

John A Meinel (jameinel) wrote :

sent to pqm by email

6524. By John A Meinel on 2012-09-07

per_tree re-uses the per_workingtree scenarios.

Which means we have to update the per_tree tests to handle the new model,
as well as update the test_selftest code that explicitly tested the
permutation code.

John A Meinel (jameinel) wrote :

sent to pqm by email

6525. By John A Meinel on 2012-09-07

Change the attribute lookup, I missed it in the first pass.

John A Meinel (jameinel) wrote :

sent to pqm by email

6526. By John A Meinel on 2012-09-07

And naturally I missed some tests from the last patch.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/remote.py'
--- bzrlib/remote.py 2012-01-28 00:56:56 +0000
+++ bzrlib/remote.py 2012-09-07 10:36:18 +0000
@@ -3129,7 +3129,8 @@
3129 return a_bzrdir.open_branch(name=name, 3129 return a_bzrdir.open_branch(name=name,
3130 ignore_fallbacks=ignore_fallbacks)3130 ignore_fallbacks=ignore_fallbacks)
31313131
3132 def _vfs_initialize(self, a_bzrdir, name, append_revisions_only):3132 def _vfs_initialize(self, a_bzrdir, name, append_revisions_only,
3133 repository=None):
3133 # Initialisation when using a local bzrdir object, or a non-vfs init3134 # Initialisation when using a local bzrdir object, or a non-vfs init
3134 # method is not available on the server.3135 # method is not available on the server.
3135 # self._custom_format is always set - the start of initialize ensures3136 # self._custom_format is always set - the start of initialize ensures
@@ -3137,11 +3138,13 @@
3137 if isinstance(a_bzrdir, RemoteBzrDir):3138 if isinstance(a_bzrdir, RemoteBzrDir):
3138 a_bzrdir._ensure_real()3139 a_bzrdir._ensure_real()
3139 result = self._custom_format.initialize(a_bzrdir._real_bzrdir,3140 result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
3140 name=name, append_revisions_only=append_revisions_only)3141 name=name, append_revisions_only=append_revisions_only,
3142 repository=repository)
3141 else:3143 else:
3142 # We assume the bzrdir is parameterised; it may not be.3144 # We assume the bzrdir is parameterised; it may not be.
3143 result = self._custom_format.initialize(a_bzrdir, name=name,3145 result = self._custom_format.initialize(a_bzrdir, name=name,
3144 append_revisions_only=append_revisions_only)3146 append_revisions_only=append_revisions_only,
3147 repository=repository)
3145 if (isinstance(a_bzrdir, RemoteBzrDir) and3148 if (isinstance(a_bzrdir, RemoteBzrDir) and
3146 not isinstance(result, RemoteBranch)):3149 not isinstance(result, RemoteBranch)):
3147 result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,3150 result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
@@ -3164,11 +3167,13 @@
3164 # Being asked to create on a non RemoteBzrDir:3167 # Being asked to create on a non RemoteBzrDir:
3165 if not isinstance(a_bzrdir, RemoteBzrDir):3168 if not isinstance(a_bzrdir, RemoteBzrDir):
3166 return self._vfs_initialize(a_bzrdir, name=name,3169 return self._vfs_initialize(a_bzrdir, name=name,
3167 append_revisions_only=append_revisions_only)3170 append_revisions_only=append_revisions_only,
3171 repository=repository)
3168 medium = a_bzrdir._client._medium3172 medium = a_bzrdir._client._medium
3169 if medium._is_remote_before((1, 13)):3173 if medium._is_remote_before((1, 13)):
3170 return self._vfs_initialize(a_bzrdir, name=name,3174 return self._vfs_initialize(a_bzrdir, name=name,
3171 append_revisions_only=append_revisions_only)3175 append_revisions_only=append_revisions_only,
3176 repository=repository)
3172 # Creating on a remote bzr dir.3177 # Creating on a remote bzr dir.
3173 # 2) try direct creation via RPC3178 # 2) try direct creation via RPC
3174 path = a_bzrdir._path_for_remote_call(a_bzrdir._client)3179 path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
@@ -3182,7 +3187,8 @@
3182 # Fallback - use vfs methods3187 # Fallback - use vfs methods
3183 medium._remember_remote_is_before((1, 13))3188 medium._remember_remote_is_before((1, 13))
3184 return self._vfs_initialize(a_bzrdir, name=name,3189 return self._vfs_initialize(a_bzrdir, name=name,
3185 append_revisions_only=append_revisions_only)3190 append_revisions_only=append_revisions_only,
3191 repository=repository)
3186 if response[0] != 'ok':3192 if response[0] != 'ok':
3187 raise errors.UnexpectedSmartServerResponse(response)3193 raise errors.UnexpectedSmartServerResponse(response)
3188 # Turn the response into a RemoteRepository object.3194 # Turn the response into a RemoteRepository object.
@@ -3867,6 +3873,9 @@
3867 target, overwrite=overwrite, stop_revision=stop_revision, lossy=lossy,3873 target, overwrite=overwrite, stop_revision=stop_revision, lossy=lossy,
3868 _override_hook_source_branch=self)3874 _override_hook_source_branch=self)
38693875
3876 def peek_lock_mode(self):
3877 return self._lock_mode
3878
3870 def is_locked(self):3879 def is_locked(self):
3871 return self._lock_count >= 13880 return self._lock_count >= 1
38723881
38733882
=== modified file 'bzrlib/smart/repository.py'
--- bzrlib/smart/repository.py 2011-12-19 13:23:58 +0000
+++ bzrlib/smart/repository.py 2012-09-07 10:36:18 +0000
@@ -736,15 +736,18 @@
736 self.seed_state()736 self.seed_state()
737 pb = ui.ui_factory.nested_progress_bar()737 pb = ui.ui_factory.nested_progress_bar()
738 rc = self._record_counter738 rc = self._record_counter
739 # Make and consume sub generators, one per substream type:739 try:
740 while self.first_bytes is not None:740 # Make and consume sub generators, one per substream type:
741 substream = NetworkRecordStream(self.iter_substream_bytes())741 while self.first_bytes is not None:
742 # after substream is fully consumed, self.current_type is set to742 substream = NetworkRecordStream(self.iter_substream_bytes())
743 # the next type, and self.first_bytes is set to the matching bytes.743 # after substream is fully consumed, self.current_type is set
744 yield self.current_type, wrap_and_count(pb, rc, substream)744 # to the next type, and self.first_bytes is set to the matching
745 if rc:745 # bytes.
746 pb.update('Done', rc.max, rc.max)746 yield self.current_type, wrap_and_count(pb, rc, substream)
747 pb.finished()747 finally:
748 if rc:
749 pb.update('Done', rc.max, rc.max)
750 pb.finished()
748751
749 def seed_state(self):752 def seed_state(self):
750 """Prepare the _ByteStreamDecoder to decode from the pack stream."""753 """Prepare the _ByteStreamDecoder to decode from the pack stream."""
751754
=== modified file 'bzrlib/tests/per_tree/__init__.py'
--- bzrlib/tests/per_tree/__init__.py 2011-06-14 01:26:41 +0000
+++ bzrlib/tests/per_tree/__init__.py 2012-09-07 10:36:18 +0000
@@ -29,6 +29,7 @@
29 errors,29 errors,
30 tests,30 tests,
31 transform,31 transform,
32 transport,
32 )33 )
33from bzrlib.tests.per_controldir.test_controldir import TestCaseWithControlDir34from bzrlib.tests.per_controldir.test_controldir import TestCaseWithControlDir
34from bzrlib.tests.per_workingtree import (35from bzrlib.tests.per_workingtree import (
@@ -99,11 +100,24 @@
99class TestCaseWithTree(TestCaseWithControlDir):100class TestCaseWithTree(TestCaseWithControlDir):
100101
101 def make_branch_and_tree(self, relpath):102 def make_branch_and_tree(self, relpath):
102 made_control = self.make_bzrdir(relpath, format=103 bzrdir_format = self.workingtree_format.get_controldir_for_branch()
103 self.workingtree_format._matchingbzrdir)104 made_control = self.make_bzrdir(relpath, format=bzrdir_format)
104 made_control.create_repository()105 made_control.create_repository()
105 made_control.create_branch()106 b = made_control.create_branch()
106 return self.workingtree_format.initialize(made_control)107 if getattr(self, 'repo_is_remote', False):
108 # If the repo is remote, then we just create a local lightweight
109 # checkout
110 # XXX: This duplicates a lot of Branch.create_checkout, but we know
111 # we want a) lightweight, and b) a specific WT format. We also
112 # know that nothing should already exist, etc.
113 t = transport.get_transport(relpath)
114 t.ensure_base()
115 wt_dir = bzrdir_format.initialize_on_transport(t)
116 branch_ref = wt_dir.set_branch_reference(b)
117 wt = wt_dir.create_workingtree(None, from_branch=branch_ref)
118 else:
119 wt = self.workingtree_format.initialize(made_control)
120 return wt
107121
108 def workingtree_to_test_tree(self, tree):122 def workingtree_to_test_tree(self, tree):
109 return self._workingtree_to_test_tree(self, tree)123 return self._workingtree_to_test_tree(self, tree)
110124
=== modified file 'bzrlib/tests/per_workingtree/__init__.py'
--- bzrlib/tests/per_workingtree/__init__.py 2011-09-23 12:32:30 +0000
+++ bzrlib/tests/per_workingtree/__init__.py 2012-09-07 10:36:18 +0000
@@ -25,18 +25,37 @@
25from bzrlib import (25from bzrlib import (
26 branchbuilder,26 branchbuilder,
27 tests,27 tests,
28 transport,
28 workingtree,29 workingtree,
29 )30 )
30from bzrlib.tests import per_controldir31from bzrlib.transport import memory
3132from bzrlib.tests import (
3233 per_controldir,
33def make_scenarios(transport_server, transport_readonly_server, formats):34 test_server,
35 )
36
37
38def make_scenarios(transport_server, transport_readonly_server, formats,
39 remote_server=None, remote_readonly_server=None,
40 remote_backing_server=None):
34 result = []41 result = []
35 for workingtree_format in formats:42 for workingtree_format in formats:
36 result.append((workingtree_format.__class__.__name__,43 result.append((workingtree_format.__class__.__name__,
37 make_scenario(transport_server,44 make_scenario(transport_server,
38 transport_readonly_server,45 transport_readonly_server,
39 workingtree_format)))46 workingtree_format)))
47 default_wt_format = workingtree.format_registry.get_default()
48 if remote_server is None:
49 remote_server = test_server.SmartTCPServer_for_testing
50 if remote_readonly_server is None:
51 remote_readonly_server = test_server.ReadonlySmartTCPServer_for_testing
52 if remote_backing_server is None:
53 remote_backing_server = memory.MemoryServer
54 scenario = make_scenario(remote_server, remote_readonly_server,
55 default_wt_format)
56 scenario['repo_is_remote'] = True;
57 scenario['vfs_transport_factory'] = remote_backing_server
58 result.append((default_wt_format.__class__.__name__ + ',remote', scenario))
40 return result59 return result
4160
4261
@@ -71,8 +90,22 @@
71 def make_branch_and_tree(self, relpath, format=None):90 def make_branch_and_tree(self, relpath, format=None):
72 made_control = self.make_bzrdir(relpath, format=format)91 made_control = self.make_bzrdir(relpath, format=format)
73 made_control.create_repository()92 made_control.create_repository()
74 made_control.create_branch()93 b = made_control.create_branch()
75 return self.workingtree_format.initialize(made_control)94 if getattr(self, 'repo_is_remote', False):
95 # If the repo is remote, then we just create a local lightweight
96 # checkout
97 # XXX: This duplicates a lot of Branch.create_checkout, but we know
98 # we want a) lightweight, and b) a specific WT format. We also
99 # know that nothing should already exist, etc.
100 t = transport.get_transport(relpath)
101 t.ensure_base()
102 bzrdir_format = self.workingtree_format.get_controldir_for_branch()
103 wt_dir = bzrdir_format.initialize_on_transport(t)
104 branch_ref = wt_dir.set_branch_reference(b)
105 wt = wt_dir.create_workingtree(None, from_branch=branch_ref)
106 else:
107 wt = self.workingtree_format.initialize(made_control)
108 return wt
76109
77 def make_branch_builder(self, relpath, format=None):110 def make_branch_builder(self, relpath, format=None):
78 if format is None:111 if format is None:
79112
=== modified file 'bzrlib/tests/per_workingtree/test_commit.py'
--- bzrlib/tests/per_workingtree/test_commit.py 2012-01-25 21:13:15 +0000
+++ bzrlib/tests/per_workingtree/test_commit.py 2012-09-07 10:36:18 +0000
@@ -26,6 +26,7 @@
26 osutils,26 osutils,
27 revision as _mod_revision,27 revision as _mod_revision,
28 tests,28 tests,
29 transport as _mod_transport,
29 ui,30 ui,
30 )31 )
31from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree32from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
@@ -316,7 +317,7 @@
316 wt.lock_write()317 wt.lock_write()
317 self.build_tree(['a', 'b/', 'b/c', 'd'])318 self.build_tree(['a', 'b/', 'b/c', 'd'])
318 wt.add(['a', 'b', 'b/c', 'd'], ['a-id', 'b-id', 'c-id', 'd-id'])319 wt.add(['a', 'b', 'b/c', 'd'], ['a-id', 'b-id', 'c-id', 'd-id'])
319 this_dir = self.get_transport()320 this_dir = wt.bzrdir.root_transport
320 this_dir.delete_tree('b')321 this_dir.delete_tree('b')
321 this_dir.delete('d')322 this_dir.delete('d')
322 # now we have a tree with a through d in the inventory, but only323 # now we have a tree with a through d in the inventory, but only
@@ -352,7 +353,7 @@
352 wt.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])353 wt.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
353 wt.commit('first')354 wt.commit('first')
354 wt.remove('b/c')355 wt.remove('b/c')
355 this_dir = self.get_transport()356 this_dir = wt.bzrdir.root_transport
356 this_dir.delete_tree('b')357 this_dir.delete_tree('b')
357 wt.lock_write()358 wt.lock_write()
358 wt.commit('commit deleted rename')359 wt.commit('commit deleted rename')
359360
=== modified file 'bzrlib/tests/per_workingtree/test_executable.py'
--- bzrlib/tests/per_workingtree/test_executable.py 2011-12-19 16:59:14 +0000
+++ bzrlib/tests/per_workingtree/test_executable.py 2012-09-07 10:36:18 +0000
@@ -71,8 +71,7 @@
71 self.wt.commit('adding a,b', rev_id='r1')71 self.wt.commit('adding a,b', rev_id='r1')
72 # Now make sure that 'bzr branch' also preserves the72 # Now make sure that 'bzr branch' also preserves the
73 # executable bit73 # executable bit
74 # TODO: Maybe this should be a blackbox test74 dir2 = self.wt.branch.bzrdir.sprout('b2', revision_id='r1')
75 dir2 = self.wt.branch.bzrdir.clone('b2', revision_id='r1')
76 wt2 = dir2.open_workingtree()75 wt2 = dir2.open_workingtree()
77 self.assertEqual(['r1'], wt2.get_parent_ids())76 self.assertEqual(['r1'], wt2.get_parent_ids())
78 self.assertEqual('r1', wt2.branch.last_revision())77 self.assertEqual('r1', wt2.branch.last_revision())
7978
=== modified file 'bzrlib/tests/per_workingtree/test_parents.py'
--- bzrlib/tests/per_workingtree/test_parents.py 2011-06-14 01:26:41 +0000
+++ bzrlib/tests/per_workingtree/test_parents.py 2012-09-07 10:36:18 +0000
@@ -21,9 +21,7 @@
2121
22from bzrlib import (22from bzrlib import (
23 errors,23 errors,
24 osutils,
25 revision as _mod_revision,24 revision as _mod_revision,
26 tests,
27 )25 )
28from bzrlib.inventory import (26from bzrlib.inventory import (
29 Inventory,27 Inventory,
@@ -475,7 +473,11 @@
475 # large hammer, this is a particularly sensitive area of code, so the473 # large hammer, this is a particularly sensitive area of code, so the
476 # extra assurance is well worth it.474 # extra assurance is well worth it.
477 tree._validate()475 tree._validate()
478 osutils.rmtree('tree')476 # If tree.branch is remote
477 if tree.user_url != tree.branch.user_url:
478 # We have a lightweight checkout, delete both locations
479 tree.branch.bzrdir.root_transport.delete_tree('.')
480 tree.bzrdir.root_transport.delete_tree('.')
479481
480 def test_no_parents_just_root(self):482 def test_no_parents_just_root(self):
481 """Test doing an empty commit - no parent, set a root only."""483 """Test doing an empty commit - no parent, set a root only."""
482484
=== modified file 'bzrlib/tests/per_workingtree/test_remove.py'
--- bzrlib/tests/per_workingtree/test_remove.py 2011-05-13 12:51:05 +0000
+++ bzrlib/tests/per_workingtree/test_remove.py 2012-09-07 10:36:18 +0000
@@ -173,7 +173,7 @@
173 """Removing a absent directory succeeds without corruption (#150438)."""173 """Removing a absent directory succeeds without corruption (#150438)."""
174 paths = ['a/', 'a/b']174 paths = ['a/', 'a/b']
175 tree = self.get_committed_tree(paths)175 tree = self.get_committed_tree(paths)
176 self.get_transport('.').delete_tree('a')176 tree.bzrdir.root_transport.delete_tree('a')
177 tree.remove(['a'])177 tree.remove(['a'])
178 self.assertRemovedAndDeleted('b')178 self.assertRemovedAndDeleted('b')
179 tree._validate()179 tree._validate()
180180
=== modified file 'bzrlib/tests/per_workingtree/test_smart_add.py'
--- bzrlib/tests/per_workingtree/test_smart_add.py 2011-09-06 09:51:45 +0000
+++ bzrlib/tests/per_workingtree/test_smart_add.py 2012-09-07 10:36:18 +0000
@@ -135,6 +135,9 @@
135135
136 self.build_tree(build_paths)136 self.build_tree(build_paths)
137 wt = self.make_branch_and_tree('.')137 wt = self.make_branch_and_tree('.')
138 if wt.user_url != wt.branch.user_url:
139 # Lightweight checkout, make sure we have a repo location.
140 wt.branch.bzrdir.root_transport.mkdir('original')
138 child_tree = self.make_branch_and_tree('original/child')141 child_tree = self.make_branch_and_tree('original/child')
139 wt.smart_add((".",))142 wt.smart_add((".",))
140 for path in paths:143 for path in paths:
141144
=== modified file 'bzrlib/tests/per_workingtree/test_views.py'
--- bzrlib/tests/per_workingtree/test_views.py 2009-07-10 07:14:02 +0000
+++ bzrlib/tests/per_workingtree/test_views.py 2012-09-07 10:36:18 +0000
@@ -22,7 +22,7 @@
2222
2323
24from bzrlib import views, errors24from bzrlib import views, errors
25from bzrlib.tests import TestSkipped25from bzrlib.tests import TestNotApplicable, TestSkipped
26from bzrlib.workingtree import WorkingTree26from bzrlib.workingtree import WorkingTree
2727
28from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree28from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
@@ -39,7 +39,7 @@
39 raise TestSkipped("format %s doesn't declare whether it "39 raise TestSkipped("format %s doesn't declare whether it "
40 "supports views, assuming not" % fmt)40 "supports views, assuming not" % fmt)
41 if not f():41 if not f():
42 raise TestSkipped("format %s doesn't support views" % fmt)42 raise TestNotApplicable("format %s doesn't support views" % fmt)
43 TestCaseWithWorkingTree.setUp(self)43 TestCaseWithWorkingTree.setUp(self)
4444
45 def test_views_initially_empty(self):45 def test_views_initially_empty(self):
4646
=== modified file 'bzrlib/tests/per_workingtree/test_workingtree.py'
--- bzrlib/tests/per_workingtree/test_workingtree.py 2012-01-25 21:13:15 +0000
+++ bzrlib/tests/per_workingtree/test_workingtree.py 2012-09-07 10:36:18 +0000
@@ -57,10 +57,20 @@
5757
58class TestWorkingTree(TestCaseWithWorkingTree):58class TestWorkingTree(TestCaseWithWorkingTree):
5959
60 def requireBranchReference(self):
61 test_branch = self.make_branch('test-branch')
62 try:
63 # if there is a working tree now, this is not supported.
64 test_branch.bzrdir.open_workingtree()
65 raise TestNotApplicable("only on trees that can be separate"
66 " from their branch.")
67 except (errors.NoWorkingTree, errors.NotLocalUrl):
68 pass
69
60 def test_branch_builder(self):70 def test_branch_builder(self):
61 # Just a smoke test that we get a branch at the specified relpath71 # Just a smoke test that we get a branch at the specified relpath
62 builder = self.make_branch_builder('foobar')72 builder = self.make_branch_builder('foobar')
63 br = branch.Branch.open('foobar')73 br = branch.Branch.open(self.get_url('foobar'))
6474
65 def test_list_files(self):75 def test_list_files(self):
66 tree = self.make_branch_and_tree('.')76 tree = self.make_branch_and_tree('.')
@@ -122,8 +132,10 @@
122 result[0][:4])132 result[0][:4])
123133
124 def test_open_containing(self):134 def test_open_containing(self):
125 branch = self.make_branch_and_tree('.').branch135 local_wt = self.make_branch_and_tree('.')
126 local_base = urlutils.local_path_from_url(branch.base)136 local_url = local_wt.bzrdir.root_transport.base
137 local_base = urlutils.local_path_from_url(local_url)
138 del local_wt
127139
128 # Empty opens '.'140 # Empty opens '.'
129 wt, relpath = WorkingTree.open_containing()141 wt, relpath = WorkingTree.open_containing()
@@ -161,6 +173,7 @@
161173
162 def test_lock_locks_branch(self):174 def test_lock_locks_branch(self):
163 tree = self.make_branch_and_tree('.')175 tree = self.make_branch_and_tree('.')
176 self.assertEqual(None, tree.branch.peek_lock_mode())
164 tree.lock_read()177 tree.lock_read()
165 self.assertEqual('r', tree.branch.peek_lock_mode())178 self.assertEqual('r', tree.branch.peek_lock_mode())
166 tree.unlock()179 tree.unlock()
@@ -362,14 +375,8 @@
362 # that formats where initialising a branch does not initialise a375 # that formats where initialising a branch does not initialise a
363 # tree - and thus have separable entities - support skewing the376 # tree - and thus have separable entities - support skewing the
364 # two things.377 # two things.
365 branch = self.make_branch('tree')378 self.requireBranchReference()
366 try:379 wt = self.make_branch_and_tree('tree')
367 # if there is a working tree now, this is not supported.
368 branch.bzrdir.open_workingtree()
369 return
370 except errors.NoWorkingTree:
371 pass
372 wt = branch.bzrdir.create_workingtree()
373 wt.commit('A', allow_pointless=True, rev_id='A')380 wt.commit('A', allow_pointless=True, rev_id='A')
374 wt.set_last_revision(None)381 wt.set_last_revision(None)
375 self.assertEqual([], wt.get_parent_ids())382 self.assertEqual([], wt.get_parent_ids())
@@ -478,19 +485,13 @@
478 # that formats where initialising a branch does not initialise a485 # that formats where initialising a branch does not initialise a
479 # tree - and thus have separable entities - support skewing the486 # tree - and thus have separable entities - support skewing the
480 # two things.487 # two things.
481 main_branch = self.make_branch('tree')488 self.requireBranchReference()
482 try:489 wt = self.make_branch_and_tree('tree')
483 # if there is a working tree now, this is not supported.
484 main_branch.bzrdir.open_workingtree()
485 return
486 except errors.NoWorkingTree:
487 pass
488 wt = main_branch.bzrdir.create_workingtree()
489 # create an out of date working tree by making a checkout in this490 # create an out of date working tree by making a checkout in this
490 # current format491 # current format
491 self.build_tree(['checkout/', 'tree/file'])492 self.build_tree(['checkout/', 'tree/file'])
492 checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')493 checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
493 checkout.set_branch_reference(main_branch)494 checkout.set_branch_reference(wt.branch)
494 old_tree = self.workingtree_format.initialize(checkout)495 old_tree = self.workingtree_format.initialize(checkout)
495 # now commit to 'tree'496 # now commit to 'tree'
496 wt.add('file')497 wt.add('file')
@@ -545,19 +546,13 @@
545 # that formats where initialising a branch does not initialise a546 # that formats where initialising a branch does not initialise a
546 # tree - and thus have separable entities - support skewing the547 # tree - and thus have separable entities - support skewing the
547 # two things.548 # two things.
548 main_branch = self.make_branch('tree')549 self.requireBranchReference()
549 try:550 wt = self.make_branch_and_tree('tree')
550 # if there is a working tree now, this is not supported.
551 main_branch.bzrdir.open_workingtree()
552 return
553 except errors.NoWorkingTree:
554 pass
555 wt = main_branch.bzrdir.create_workingtree()
556 # create an out of date working tree by making a checkout in this551 # create an out of date working tree by making a checkout in this
557 # current format552 # current format
558 self.build_tree(['checkout/', 'tree/file'])553 self.build_tree(['checkout/', 'tree/file'])
559 checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')554 checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
560 checkout.set_branch_reference(main_branch)555 checkout.set_branch_reference(wt.branch)
561 old_tree = self.workingtree_format.initialize(checkout)556 old_tree = self.workingtree_format.initialize(checkout)
562 # now commit to 'tree'557 # now commit to 'tree'
563 wt.add('file')558 wt.add('file')
564559
=== modified file 'bzrlib/tests/test_selftest.py'
--- bzrlib/tests/test_selftest.py 2011-11-08 17:07:23 +0000
+++ bzrlib/tests/test_selftest.py 2012-09-07 10:36:18 +0000
@@ -334,8 +334,11 @@
334 server1 = "a"334 server1 = "a"
335 server2 = "b"335 server2 = "b"
336 formats = [workingtree_4.WorkingTreeFormat4(),336 formats = [workingtree_4.WorkingTreeFormat4(),
337 workingtree_3.WorkingTreeFormat3(),]337 workingtree_3.WorkingTreeFormat3(),
338 scenarios = make_scenarios(server1, server2, formats)338 workingtree_4.WorkingTreeFormat6()]
339 scenarios = make_scenarios(server1, server2, formats,
340 remote_server='c', remote_readonly_server='d',
341 remote_backing_server='e')
339 self.assertEqual([342 self.assertEqual([
340 ('WorkingTreeFormat4',343 ('WorkingTreeFormat4',
341 {'bzrdir_format': formats[0]._matchingbzrdir,344 {'bzrdir_format': formats[0]._matchingbzrdir,
@@ -346,19 +349,33 @@
346 {'bzrdir_format': formats[1]._matchingbzrdir,349 {'bzrdir_format': formats[1]._matchingbzrdir,
347 'transport_readonly_server': 'b',350 'transport_readonly_server': 'b',
348 'transport_server': 'a',351 'transport_server': 'a',
349 'workingtree_format': formats[1]})],352 'workingtree_format': formats[1]}),
350 scenarios)353 ('WorkingTreeFormat6',
354 {'bzrdir_format': formats[2]._matchingbzrdir,
355 'transport_readonly_server': 'b',
356 'transport_server': 'a',
357 'workingtree_format': formats[2]}),
358 ('WorkingTreeFormat6,remote',
359 {'bzrdir_format': formats[2]._matchingbzrdir,
360 'repo_is_remote': True,
361 'transport_readonly_server': 'd',
362 'transport_server': 'c',
363 'vfs_transport_factory': 'e',
364 'workingtree_format': formats[2]}),
365 ], scenarios)
351366
352367
353class TestTreeScenarios(tests.TestCase):368class TestTreeScenarios(tests.TestCase):
354369
355 def test_scenarios(self):370 def test_scenarios(self):
356 # the tree implementation scenario generator is meant to setup one371 # the tree implementation scenario generator is meant to setup one
357 # instance for each working tree format, and one additional instance372 # instance for each working tree format, one additional instance
358 # that will use the default wt format, but create a revision tree for373 # that will use the default wt format, but create a revision tree for
359 # the tests. this means that the wt ones should have the374 # the tests, and one more that uses the default wt format as a
360 # workingtree_to_test_tree attribute set to 'return_parameter' and the375 # lightweight checkout of a remote repository. This means that the wt
361 # revision one set to revision_tree_from_workingtree.376 # ones should have the workingtree_to_test_tree attribute set to
377 # 'return_parameter' and the revision one set to
378 # revision_tree_from_workingtree.
362379
363 from bzrlib.tests.per_tree import (380 from bzrlib.tests.per_tree import (
364 _dirstate_tree_from_workingtree,381 _dirstate_tree_from_workingtree,
@@ -370,13 +387,17 @@
370 )387 )
371 server1 = "a"388 server1 = "a"
372 server2 = "b"389 server2 = "b"
390 smart_server = test_server.SmartTCPServer_for_testing
391 smart_readonly_server = test_server.ReadonlySmartTCPServer_for_testing
392 mem_server = memory.MemoryServer
373 formats = [workingtree_4.WorkingTreeFormat4(),393 formats = [workingtree_4.WorkingTreeFormat4(),
374 workingtree_3.WorkingTreeFormat3(),]394 workingtree_3.WorkingTreeFormat3(),]
375 scenarios = make_scenarios(server1, server2, formats)395 scenarios = make_scenarios(server1, server2, formats)
376 self.assertEqual(7, len(scenarios))396 self.assertEqual(8, len(scenarios))
377 default_wt_format = workingtree.format_registry.get_default()397 default_wt_format = workingtree.format_registry.get_default()
378 wt4_format = workingtree_4.WorkingTreeFormat4()398 wt4_format = workingtree_4.WorkingTreeFormat4()
379 wt5_format = workingtree_4.WorkingTreeFormat5()399 wt5_format = workingtree_4.WorkingTreeFormat5()
400 wt6_format = workingtree_4.WorkingTreeFormat6()
380 expected_scenarios = [401 expected_scenarios = [
381 ('WorkingTreeFormat4',402 ('WorkingTreeFormat4',
382 {'bzrdir_format': formats[0]._matchingbzrdir,403 {'bzrdir_format': formats[0]._matchingbzrdir,
@@ -392,6 +413,15 @@
392 'workingtree_format': formats[1],413 'workingtree_format': formats[1],
393 '_workingtree_to_test_tree': return_parameter,414 '_workingtree_to_test_tree': return_parameter,
394 }),415 }),
416 ('WorkingTreeFormat6,remote',
417 {'bzrdir_format': wt6_format._matchingbzrdir,
418 'repo_is_remote': True,
419 'transport_readonly_server': smart_readonly_server,
420 'transport_server': smart_server,
421 'vfs_transport_factory': mem_server,
422 'workingtree_format': wt6_format,
423 '_workingtree_to_test_tree': return_parameter,
424 }),
395 ('RevisionTree',425 ('RevisionTree',
396 {'_workingtree_to_test_tree': revision_tree_from_workingtree,426 {'_workingtree_to_test_tree': revision_tree_from_workingtree,
397 'bzrdir_format': default_wt_format._matchingbzrdir,427 'bzrdir_format': default_wt_format._matchingbzrdir,
398428
=== modified file 'bzrlib/workingtree_4.py'
--- bzrlib/workingtree_4.py 2012-01-06 14:09:04 +0000
+++ bzrlib/workingtree_4.py 2012-09-07 10:36:18 +0000
@@ -1,4 +1,4 @@
1# Copyright (C) 2007-2011 Canonical Ltd1# Copyright (C) 2007-2012 Canonical Ltd
2#2#
3# This program is free software; you can redistribute it and/or modify3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by4# it under the terms of the GNU General Public License as published by
@@ -1677,6 +1677,12 @@
1677 def supports_views(self):1677 def supports_views(self):
1678 return True1678 return True
16791679
1680 def _get_matchingbzrdir(self):
1681 """Overrideable method to get a bzrdir for testing."""
1682 # We use 'development-subtree' instead of '2a', because we have a
1683 # few tests that want to test tree references
1684 return bzrdir.format_registry.make_bzrdir('development-subtree')
1685
16801686
1681class DirStateRevisionTree(InventoryTree):1687class DirStateRevisionTree(InventoryTree):
1682 """A revision tree pulling the inventory from a dirstate.1688 """A revision tree pulling the inventory from a dirstate.
@@ -1882,8 +1888,18 @@
1882 return self.inventory[file_id].text_size1888 return self.inventory[file_id].text_size
18831889
1884 def get_file_text(self, file_id, path=None):1890 def get_file_text(self, file_id, path=None):
1885 _, content = list(self.iter_files_bytes([(file_id, None)]))[0]1891 content = None
1886 return ''.join(content)1892 for _, content_iter in self.iter_files_bytes([(file_id, None)]):
1893 if content is not None:
1894 raise AssertionError('iter_files_bytes returned'
1895 ' too many entries')
1896 # For each entry returned by iter_files_bytes, we must consume the
1897 # content_iter before we step the files iterator.
1898 content = ''.join(content_iter)
1899 if content is None:
1900 raise AssertionError('iter_files_bytes did not return'
1901 ' the requested data')
1902 return content
18871903
1888 def get_reference_revision(self, file_id, path=None):1904 def get_reference_revision(self, file_id, path=None):
1889 return self.inventory[file_id].reference_revision1905 return self.inventory[file_id].reference_revision
18901906
=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- doc/en/release-notes/bzr-2.5.txt 2012-08-01 08:51:57 +0000
+++ doc/en/release-notes/bzr-2.5.txt 2012-09-07 10:36:18 +0000
@@ -35,8 +35,16 @@
35* ``bzr config`` properly handles aliases and references in the35* ``bzr config`` properly handles aliases and references in the
36 ``--directory`` parameter (Vincent Ladeuil, Wouter van Heyst, #947049)36 ``--directory`` parameter (Vincent Ladeuil, Wouter van Heyst, #947049)
3737
38* Lightweight checkouts of remote repositories had a bug with how they
39 extracted texts from the repository. (Just an ordering constraint on how
40 they consumed the stream.) (John Arbash Meinel, #1046284)
41
38* Revert use of --no-tty when gpg signing commits. (Jelmer Vernooij, #1014570)42* Revert use of --no-tty when gpg signing commits. (Jelmer Vernooij, #1014570)
3943
44* Some small bug fixes wrt lightweight checkouts and remote repositories.
45 A test permutation was added that runs all working tree tests against a
46 lightweight checkout. (John Arbash Meinel, #1046697)
47
40Documentation48Documentation
41*************49*************
4250

Subscribers

People subscribed via source and target branches