Merge lp:~spiv/bzr/reconfigure-unstacked-copies-tagged-revisions-401646 into lp:bzr

Proposed by Andrew Bennetts
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merged at revision: 5660
Proposed branch: lp:~spiv/bzr/reconfigure-unstacked-copies-tagged-revisions-401646
Merge into: lp:bzr
Diff against target: 303 lines (+86/-53)
8 files modified
bzrlib/branch.py (+8/-7)
bzrlib/tests/blackbox/test_branch.py (+3/-8)
bzrlib/tests/blackbox/test_pull.py (+5/-6)
bzrlib/tests/fixtures.py (+28/-0)
bzrlib/tests/per_branch/test_pull.py (+14/-17)
bzrlib/tests/per_branch/test_stacking.py (+22/-11)
bzrlib/tests/per_controldir/test_controldir.py (+2/-4)
doc/en/release-notes/bzr-2.4.txt (+4/-0)
To merge this branch: bzr merge lp:~spiv/bzr/reconfigure-unstacked-copies-tagged-revisions-401646
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Jelmer Vernooij (community) code Approve
Review via email: mp+49353@code.launchpad.net

Commit message

Copy tagged revisions as part of 'bzr reconfigure --unstacked' (#401646)

Description of the change

Fixes bug 401646 ('bzr reconfigure --unstacked' should copy tagged revisions), as a follow-on from the fix for bug 309682.

I added a smaller helper function to bzrlib.tests.fixtures. I'm a little uncertain about if it really paid off, but it does result in slightly more concise tests in a few places. I suppose it might be clearer if the canned branch/repo it produces had more obviously named revision IDs than 'rev-1' and 'rev-2'. Maybe 'branch-tip' and 'outside-tip-ancestry'? Not sure.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

I hadn't seen the fixtures used for branch construction yet, that looks very interesting.

review: Approve (code)
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

> I hadn't seen the fixtures used for branch construction yet, that looks very
> interesting.
I think the alternative revision ids you suggest would be useful. Perhaps not particularly in this case, but moreso as this pattern gets copied by other people.

Revision history for this message
Vincent Ladeuil (vila) wrote :

+1 on meaningful names. I also use '1' instead of 'rev-1' in some log tests as this matches directly with the revnos and provide an different way to check for expected results.

review: Approve
Revision history for this message
Vincent Ladeuil (vila) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/branch.py'
--- bzrlib/branch.py 2011-02-07 04:30:00 +0000
+++ bzrlib/branch.py 2011-02-11 06:11:19 +0000
@@ -880,13 +880,14 @@
880 # XXX: If you unstack a branch while it has a working tree880 # XXX: If you unstack a branch while it has a working tree
881 # with a pending merge, the pending-merged revisions will no881 # with a pending merge, the pending-merged revisions will no
882 # longer be present. You can (probably) revert and remerge.882 # longer be present. You can (probably) revert and remerge.
883 #883 try:
884 # XXX: This only fetches up to the tip of the repository; it884 tags_to_fetch = set(self.tags.get_reverse_tag_dict())
885 # doesn't bring across any tags. That's fairly consistent885 except errors.TagsNotSupported:
886 # with how branch works, but perhaps not ideal.886 tags_to_fetch = set()
887 self.repository.fetch(old_repository,887 fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
888 revision_id=self.last_revision(),888 old_repository, required_ids=[self.last_revision()],
889 find_ghosts=True)889 if_present_ids=tags_to_fetch, find_ghosts=True).execute()
890 self.repository.fetch(old_repository, fetch_spec=fetch_spec)
890 finally:891 finally:
891 old_repository.unlock()892 old_repository.unlock()
892 finally:893 finally:
893894
=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- bzrlib/tests/blackbox/test_branch.py 2011-01-12 23:33:40 +0000
+++ bzrlib/tests/blackbox/test_branch.py 2011-02-11 06:11:19 +0000
@@ -28,6 +28,7 @@
28from bzrlib.repofmt.knitrepo import RepositoryFormatKnit128from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
29from bzrlib.tests import TestCaseWithTransport29from bzrlib.tests import TestCaseWithTransport
30from bzrlib.tests import (30from bzrlib.tests import (
31 fixtures,
31 HardlinkFeature,32 HardlinkFeature,
32 test_server,33 test_server,
33 )34 )
@@ -270,11 +271,8 @@
270271
271 def test_branch_fetches_all_tags(self):272 def test_branch_fetches_all_tags(self):
272 builder = self.make_branch_builder('source')273 builder = self.make_branch_builder('source')
273 builder.build_commit(message="Rev 1", rev_id='rev-1')274 source = fixtures.build_branch_with_non_ancestral_rev(builder)
274 builder.build_commit(message="Rev 2", rev_id='rev-2')
275 source = builder.get_branch()
276 source.tags.set_tag('tag-a', 'rev-2')275 source.tags.set_tag('tag-a', 'rev-2')
277 source.set_last_revision_info(1, 'rev-1')
278 # Now source has a tag not in its ancestry. Make a branch from it.276 # Now source has a tag not in its ancestry. Make a branch from it.
279 self.run_bzr('branch source new-branch')277 self.run_bzr('branch source new-branch')
280 new_branch = branch.Branch.open('new-branch')278 new_branch = branch.Branch.open('new-branch')
@@ -466,12 +464,9 @@
466 def test_branch_from_branch_with_tags(self):464 def test_branch_from_branch_with_tags(self):
467 self.setup_smart_server_with_call_log()465 self.setup_smart_server_with_call_log()
468 builder = self.make_branch_builder('source')466 builder = self.make_branch_builder('source')
469 builder.build_commit(message="Rev 1", rev_id='rev-1')467 source = fixtures.build_branch_with_non_ancestral_rev(builder)
470 builder.build_commit(message="Rev 2", rev_id='rev-2')
471 source = builder.get_branch()
472 source.tags.set_tag('tag-a', 'rev-2')468 source.tags.set_tag('tag-a', 'rev-2')
473 source.tags.set_tag('tag-missing', 'missing-rev')469 source.tags.set_tag('tag-missing', 'missing-rev')
474 source.set_last_revision_info(1, 'rev-1')
475 # Now source has a tag not in its ancestry. Make a branch from it.470 # Now source has a tag not in its ancestry. Make a branch from it.
476 self.reset_smart_call_log()471 self.reset_smart_call_log()
477 out, err = self.run_bzr(['branch', self.get_url('source'), 'target'])472 out, err = self.run_bzr(['branch', self.get_url('source'), 'target'])
478473
=== modified file 'bzrlib/tests/blackbox/test_pull.py'
--- bzrlib/tests/blackbox/test_pull.py 2011-02-07 04:14:29 +0000
+++ bzrlib/tests/blackbox/test_pull.py 2011-02-11 06:11:19 +0000
@@ -29,7 +29,10 @@
29from bzrlib.branch import Branch29from bzrlib.branch import Branch
30from bzrlib.directory_service import directories30from bzrlib.directory_service import directories
31from bzrlib.osutils import pathjoin31from bzrlib.osutils import pathjoin
32from bzrlib.tests import TestCaseWithTransport32from bzrlib.tests import (
33 fixtures,
34 TestCaseWithTransport,
35 )
33from bzrlib.uncommit import uncommit36from bzrlib.uncommit import uncommit
34from bzrlib.workingtree import WorkingTree37from bzrlib.workingtree import WorkingTree
3538
@@ -148,13 +151,9 @@
148 """151 """
149 # Make a source, sprout a target off it152 # Make a source, sprout a target off it
150 builder = self.make_branch_builder('source')153 builder = self.make_branch_builder('source')
151 builder.build_commit(message="Rev 1", rev_id='rev-1')154 source = fixtures.build_branch_with_non_ancestral_rev(builder)
152 source = builder.get_branch()
153 target_bzrdir = source.bzrdir.sprout('target')155 target_bzrdir = source.bzrdir.sprout('target')
154 # Add a non-ancestry tag to source
155 builder.build_commit(message="Rev 2", rev_id='rev-2')
156 source.tags.set_tag('tag-a', 'rev-2')156 source.tags.set_tag('tag-a', 'rev-2')
157 source.set_last_revision_info(1, 'rev-1')
158 # Pull from source157 # Pull from source
159 self.run_bzr('pull -d target source')158 self.run_bzr('pull -d target source')
160 target = target_bzrdir.open_branch()159 target = target_bzrdir.open_branch()
161160
=== modified file 'bzrlib/tests/fixtures.py'
--- bzrlib/tests/fixtures.py 2010-06-26 01:07:16 +0000
+++ bzrlib/tests/fixtures.py 2011-02-11 06:11:19 +0000
@@ -97,3 +97,31 @@
97 def __exit__(self, exc_type, exc_val, exc_tb):97 def __exit__(self, exc_type, exc_val, exc_tb):
98 self._calls.append('__exit__')98 self._calls.append('__exit__')
99 return False # propogate exceptions.99 return False # propogate exceptions.
100
101
102def build_branch_with_non_ancestral_rev(branch_builder):
103 """Builds a branch with a rev not in the ancestry of the tip.
104
105 This is the revision graph::
106
107 rev-2
108 |
109 rev-1
110 |
111 (null)
112
113 The branch tip is 'rev-1'. 'rev-2' is present in the branch's repository,
114 but is not part of rev-1's ancestry.
115
116 :param branch_builder: A BranchBuilder (e.g. from
117 TestCaseWithMemoryTransport.make_branch_builder).
118 :returns: the new branch
119 """
120 # Make a sequence of two commits
121 branch_builder.build_commit(message="Rev 1", rev_id='rev-1')
122 branch_builder.build_commit(message="Rev 2", rev_id='rev-2')
123 # Move the branch tip back to the first commit
124 source = branch_builder.get_branch()
125 source.set_last_revision_info(1, 'rev-1')
126 return source
127
100128
=== modified file 'bzrlib/tests/per_branch/test_pull.py'
--- bzrlib/tests/per_branch/test_pull.py 2010-12-01 01:07:39 +0000
+++ bzrlib/tests/per_branch/test_pull.py 2011-02-11 06:11:19 +0000
@@ -25,7 +25,11 @@
25 memorytree,25 memorytree,
26 revision,26 revision,
27 )27 )
28from bzrlib.tests import per_branch, TestNotApplicable28from bzrlib.tests import (
29 fixtures,
30 per_branch,
31 TestNotApplicable,
32 )
2933
3034
31class TestPull(per_branch.TestCaseWithBranch):35class TestPull(per_branch.TestCaseWithBranch):
@@ -144,17 +148,14 @@
144 builder = self.make_branch_builder('source')148 builder = self.make_branch_builder('source')
145 except errors.UninitializableFormat:149 except errors.UninitializableFormat:
146 raise TestNotApplicable('uninitializeable format')150 raise TestNotApplicable('uninitializeable format')
147 builder.build_commit(message="Rev 1", rev_id='rev-1')151 source = fixtures.build_branch_with_non_ancestral_rev(builder)
148 source = builder.get_branch()
149 target = source.bzrdir.sprout('target').open_branch()152 target = source.bzrdir.sprout('target').open_branch()
150 # Add a non-ancestry tag to source153 # Add a tag to the source, then pull from source
151 builder.build_commit(message="Rev 2", rev_id='rev-2')
152 try:154 try:
153 source.tags.set_tag('tag-a', 'rev-2')155 source.tags.set_tag('tag-a', 'rev-2')
154 except errors.TagsNotSupported:156 except errors.TagsNotSupported:
155 raise TestNotApplicable('format does not support tags.')157 raise TestNotApplicable('format does not support tags.')
156 source.set_last_revision_info(1, 'rev-1')158 source.tags.set_tag('tag-a', 'rev-2')
157 # Pull from source
158 target.pull(source)159 target.pull(source)
159 # The tag is present, and so is its revision.160 # The tag is present, and so is its revision.
160 self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))161 self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
@@ -167,19 +168,15 @@
167 builder = self.make_branch_builder('source')168 builder = self.make_branch_builder('source')
168 except errors.UninitializableFormat:169 except errors.UninitializableFormat:
169 raise TestNotApplicable('uninitializeable format')170 raise TestNotApplicable('uninitializeable format')
170 builder.build_commit(message="Rev 1", rev_id='rev-1')171 source = fixtures.build_branch_with_non_ancestral_rev(builder)
171 source = builder.get_branch()
172 target = source.bzrdir.sprout('target').open_branch()172 target = source.bzrdir.sprout('target').open_branch()
173 # Add a non-ancestry tag to source
174 builder.build_commit(message="Rev 2", rev_id='rev-2')
175 try:
176 source.tags.set_tag('tag-a', 'rev-2')
177 except errors.TagsNotSupported:
178 raise TestNotApplicable('format does not support tags.')
179 source.set_last_revision_info(1, 'rev-1')
180 # Add a new commit to the ancestry173 # Add a new commit to the ancestry
181 builder.build_commit(message="Rev 2 again", rev_id='rev-2-again')174 builder.build_commit(message="Rev 2 again", rev_id='rev-2-again')
182 # Pull from source175 # Add a tag to the source, then pull rev-2-again from source
176 try:
177 source.tags.set_tag('tag-a', 'rev-2')
178 except errors.TagsNotSupported:
179 raise TestNotApplicable('format does not support tags.')
183 target.pull(source, 'rev-2-again')180 target.pull(source, 'rev-2-again')
184 # The tag is present, and so is its revision.181 # The tag is present, and so is its revision.
185 self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))182 self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
186183
=== modified file 'bzrlib/tests/per_branch/test_stacking.py'
--- bzrlib/tests/per_branch/test_stacking.py 2011-01-13 01:02:53 +0000
+++ bzrlib/tests/per_branch/test_stacking.py 2011-02-11 06:11:19 +0000
@@ -23,7 +23,7 @@
23 errors,23 errors,
24 )24 )
25from bzrlib.revision import NULL_REVISION25from bzrlib.revision import NULL_REVISION
26from bzrlib.tests import TestNotApplicable, transport_util26from bzrlib.tests import fixtures, TestNotApplicable, transport_util
27from bzrlib.tests.per_branch import TestCaseWithBranch27from bzrlib.tests.per_branch import TestCaseWithBranch
2828
2929
@@ -176,17 +176,20 @@
176176
177 def test_unstack_fetches(self):177 def test_unstack_fetches(self):
178 """Removing the stacked-on branch pulls across all data"""178 """Removing the stacked-on branch pulls across all data"""
179 try:
180 builder = self.make_branch_builder('trunk')
181 except errors.UninitializableFormat:
182 raise TestNotApplicable('uninitializeable format')
179 # We have a mainline183 # We have a mainline
180 trunk_tree = self.make_branch_and_tree('mainline')184 trunk = fixtures.build_branch_with_non_ancestral_rev(builder)
181 trunk_revid = trunk_tree.commit('revision on mainline')185 mainline_revid = 'rev-1'
182 # and make branch from it which is stacked186 # and make branch from it which is stacked (with no tags)
183 try:187 try:
184 new_dir = trunk_tree.bzrdir.sprout(self.get_url('newbranch'),188 new_dir = trunk.bzrdir.sprout(self.get_url('newbranch'), stacked=True)
185 stacked=True)
186 except unstackable_format_errors, e:189 except unstackable_format_errors, e:
187 raise TestNotApplicable(e)190 raise TestNotApplicable(e)
188 # stacked repository191 # stacked repository
189 self.assertRevisionNotInRepository('newbranch', trunk_revid)192 self.assertRevisionNotInRepository('newbranch', mainline_revid)
190 # TODO: we'd like to commit in the stacked repository; that requires193 # TODO: we'd like to commit in the stacked repository; that requires
191 # some care (maybe a BranchBuilder) if it's remote and has no194 # some care (maybe a BranchBuilder) if it's remote and has no
192 # workingtree195 # workingtree
@@ -195,13 +198,21 @@
195 # now when we unstack that should implicitly fetch, to make sure that198 # now when we unstack that should implicitly fetch, to make sure that
196 # the branch will still work199 # the branch will still work
197 new_branch = new_dir.open_branch()200 new_branch = new_dir.open_branch()
201 try:
202 new_branch.tags.set_tag('tag-a', 'rev-2')
203 except errors.TagsNotSupported:
204 tags_supported = False
205 else:
206 tags_supported = True
198 new_branch.set_stacked_on_url(None)207 new_branch.set_stacked_on_url(None)
199 self.assertRevisionInRepository('newbranch', trunk_revid)208 self.assertRevisionInRepository('newbranch', mainline_revid)
200 # of course it's still in the mainline209 # of course it's still in the mainline
201 self.assertRevisionInRepository('mainline', trunk_revid)210 self.assertRevisionInRepository('trunk', mainline_revid)
211 if tags_supported:
212 # the tagged revision in trunk is now in newbranch too
213 self.assertRevisionInRepository('newbranch', 'rev-2')
202 # and now we're no longer stacked214 # and now we're no longer stacked
203 self.assertRaises(errors.NotStacked,215 self.assertRaises(errors.NotStacked, new_branch.get_stacked_on_url)
204 new_branch.get_stacked_on_url)
205216
206 def test_unstack_already_locked(self):217 def test_unstack_already_locked(self):
207 """Removing the stacked-on branch with an already write-locked branch218 """Removing the stacked-on branch with an already write-locked branch
208219
=== modified file 'bzrlib/tests/per_controldir/test_controldir.py'
--- bzrlib/tests/per_controldir/test_controldir.py 2011-02-07 04:14:29 +0000
+++ bzrlib/tests/per_controldir/test_controldir.py 2011-02-11 06:11:19 +0000
@@ -33,6 +33,7 @@
33 )33 )
34import bzrlib.revision34import bzrlib.revision
35from bzrlib.tests import (35from bzrlib.tests import (
36 fixtures,
36 ChrootedTestCase,37 ChrootedTestCase,
37 TestNotApplicable,38 TestNotApplicable,
38 TestSkipped,39 TestSkipped,
@@ -676,14 +677,11 @@
676 # when sprouting a branch all revisions named in the tags are copied677 # when sprouting a branch all revisions named in the tags are copied
677 # too.678 # too.
678 builder = self.make_branch_builder('source')679 builder = self.make_branch_builder('source')
679 builder.build_commit(message="Rev 1", rev_id='rev-1')680 source = fixtures.build_branch_with_non_ancestral_rev(builder)
680 builder.build_commit(message="Rev 2", rev_id='rev-2')
681 source = builder.get_branch()
682 try:681 try:
683 source.tags.set_tag('tag-a', 'rev-2')682 source.tags.set_tag('tag-a', 'rev-2')
684 except errors.TagsNotSupported:683 except errors.TagsNotSupported:
685 raise TestNotApplicable('Branch format does not support tags.')684 raise TestNotApplicable('Branch format does not support tags.')
686 source.set_last_revision_info(1, 'rev-1')
687 # Now source has a tag not in its ancestry. Sprout its controldir.685 # Now source has a tag not in its ancestry. Sprout its controldir.
688 dir = source.bzrdir686 dir = source.bzrdir
689 target = dir.sprout(self.get_url('target'))687 target = dir.sprout(self.get_url('target'))
690688
=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- doc/en/release-notes/bzr-2.4.txt 2011-02-10 16:30:54 +0000
+++ doc/en/release-notes/bzr-2.4.txt 2011-02-11 06:11:19 +0000
@@ -68,6 +68,10 @@
68 paths, however they may still print junk if not on a UTF-8 terminal.68 paths, however they may still print junk if not on a UTF-8 terminal.
69 (Martin [gz], #707954)69 (Martin [gz], #707954)
7070
71* ``bzr reconfigure --unstacked`` now copies revisions (and their
72 ancestors) named in tags into the unstacked repository, not just the
73 ancestry of the branch's tip. (Andrew Bennetts, #401646)
74
71* ``bzr serve`` no longer crashes when a server_started hook is installed and75* ``bzr serve`` no longer crashes when a server_started hook is installed and
72 IPv6 support is available on the system. (Jelmer Vernooij, #293697)76 IPv6 support is available on the system. (Jelmer Vernooij, #293697)
7377