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
1=== modified file 'bzrlib/branch.py'
2--- bzrlib/branch.py 2011-02-07 04:30:00 +0000
3+++ bzrlib/branch.py 2011-02-11 06:11:19 +0000
4@@ -880,13 +880,14 @@
5 # XXX: If you unstack a branch while it has a working tree
6 # with a pending merge, the pending-merged revisions will no
7 # longer be present. You can (probably) revert and remerge.
8- #
9- # XXX: This only fetches up to the tip of the repository; it
10- # doesn't bring across any tags. That's fairly consistent
11- # with how branch works, but perhaps not ideal.
12- self.repository.fetch(old_repository,
13- revision_id=self.last_revision(),
14- find_ghosts=True)
15+ try:
16+ tags_to_fetch = set(self.tags.get_reverse_tag_dict())
17+ except errors.TagsNotSupported:
18+ tags_to_fetch = set()
19+ fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
20+ old_repository, required_ids=[self.last_revision()],
21+ if_present_ids=tags_to_fetch, find_ghosts=True).execute()
22+ self.repository.fetch(old_repository, fetch_spec=fetch_spec)
23 finally:
24 old_repository.unlock()
25 finally:
26
27=== modified file 'bzrlib/tests/blackbox/test_branch.py'
28--- bzrlib/tests/blackbox/test_branch.py 2011-01-12 23:33:40 +0000
29+++ bzrlib/tests/blackbox/test_branch.py 2011-02-11 06:11:19 +0000
30@@ -28,6 +28,7 @@
31 from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
32 from bzrlib.tests import TestCaseWithTransport
33 from bzrlib.tests import (
34+ fixtures,
35 HardlinkFeature,
36 test_server,
37 )
38@@ -270,11 +271,8 @@
39
40 def test_branch_fetches_all_tags(self):
41 builder = self.make_branch_builder('source')
42- builder.build_commit(message="Rev 1", rev_id='rev-1')
43- builder.build_commit(message="Rev 2", rev_id='rev-2')
44- source = builder.get_branch()
45+ source = fixtures.build_branch_with_non_ancestral_rev(builder)
46 source.tags.set_tag('tag-a', 'rev-2')
47- source.set_last_revision_info(1, 'rev-1')
48 # Now source has a tag not in its ancestry. Make a branch from it.
49 self.run_bzr('branch source new-branch')
50 new_branch = branch.Branch.open('new-branch')
51@@ -466,12 +464,9 @@
52 def test_branch_from_branch_with_tags(self):
53 self.setup_smart_server_with_call_log()
54 builder = self.make_branch_builder('source')
55- builder.build_commit(message="Rev 1", rev_id='rev-1')
56- builder.build_commit(message="Rev 2", rev_id='rev-2')
57- source = builder.get_branch()
58+ source = fixtures.build_branch_with_non_ancestral_rev(builder)
59 source.tags.set_tag('tag-a', 'rev-2')
60 source.tags.set_tag('tag-missing', 'missing-rev')
61- source.set_last_revision_info(1, 'rev-1')
62 # Now source has a tag not in its ancestry. Make a branch from it.
63 self.reset_smart_call_log()
64 out, err = self.run_bzr(['branch', self.get_url('source'), 'target'])
65
66=== modified file 'bzrlib/tests/blackbox/test_pull.py'
67--- bzrlib/tests/blackbox/test_pull.py 2011-02-07 04:14:29 +0000
68+++ bzrlib/tests/blackbox/test_pull.py 2011-02-11 06:11:19 +0000
69@@ -29,7 +29,10 @@
70 from bzrlib.branch import Branch
71 from bzrlib.directory_service import directories
72 from bzrlib.osutils import pathjoin
73-from bzrlib.tests import TestCaseWithTransport
74+from bzrlib.tests import (
75+ fixtures,
76+ TestCaseWithTransport,
77+ )
78 from bzrlib.uncommit import uncommit
79 from bzrlib.workingtree import WorkingTree
80
81@@ -148,13 +151,9 @@
82 """
83 # Make a source, sprout a target off it
84 builder = self.make_branch_builder('source')
85- builder.build_commit(message="Rev 1", rev_id='rev-1')
86- source = builder.get_branch()
87+ source = fixtures.build_branch_with_non_ancestral_rev(builder)
88 target_bzrdir = source.bzrdir.sprout('target')
89- # Add a non-ancestry tag to source
90- builder.build_commit(message="Rev 2", rev_id='rev-2')
91 source.tags.set_tag('tag-a', 'rev-2')
92- source.set_last_revision_info(1, 'rev-1')
93 # Pull from source
94 self.run_bzr('pull -d target source')
95 target = target_bzrdir.open_branch()
96
97=== modified file 'bzrlib/tests/fixtures.py'
98--- bzrlib/tests/fixtures.py 2010-06-26 01:07:16 +0000
99+++ bzrlib/tests/fixtures.py 2011-02-11 06:11:19 +0000
100@@ -97,3 +97,31 @@
101 def __exit__(self, exc_type, exc_val, exc_tb):
102 self._calls.append('__exit__')
103 return False # propogate exceptions.
104+
105+
106+def build_branch_with_non_ancestral_rev(branch_builder):
107+ """Builds a branch with a rev not in the ancestry of the tip.
108+
109+ This is the revision graph::
110+
111+ rev-2
112+ |
113+ rev-1
114+ |
115+ (null)
116+
117+ The branch tip is 'rev-1'. 'rev-2' is present in the branch's repository,
118+ but is not part of rev-1's ancestry.
119+
120+ :param branch_builder: A BranchBuilder (e.g. from
121+ TestCaseWithMemoryTransport.make_branch_builder).
122+ :returns: the new branch
123+ """
124+ # Make a sequence of two commits
125+ branch_builder.build_commit(message="Rev 1", rev_id='rev-1')
126+ branch_builder.build_commit(message="Rev 2", rev_id='rev-2')
127+ # Move the branch tip back to the first commit
128+ source = branch_builder.get_branch()
129+ source.set_last_revision_info(1, 'rev-1')
130+ return source
131+
132
133=== modified file 'bzrlib/tests/per_branch/test_pull.py'
134--- bzrlib/tests/per_branch/test_pull.py 2010-12-01 01:07:39 +0000
135+++ bzrlib/tests/per_branch/test_pull.py 2011-02-11 06:11:19 +0000
136@@ -25,7 +25,11 @@
137 memorytree,
138 revision,
139 )
140-from bzrlib.tests import per_branch, TestNotApplicable
141+from bzrlib.tests import (
142+ fixtures,
143+ per_branch,
144+ TestNotApplicable,
145+ )
146
147
148 class TestPull(per_branch.TestCaseWithBranch):
149@@ -144,17 +148,14 @@
150 builder = self.make_branch_builder('source')
151 except errors.UninitializableFormat:
152 raise TestNotApplicable('uninitializeable format')
153- builder.build_commit(message="Rev 1", rev_id='rev-1')
154- source = builder.get_branch()
155+ source = fixtures.build_branch_with_non_ancestral_rev(builder)
156 target = source.bzrdir.sprout('target').open_branch()
157- # Add a non-ancestry tag to source
158- builder.build_commit(message="Rev 2", rev_id='rev-2')
159+ # Add a tag to the source, then pull from source
160 try:
161 source.tags.set_tag('tag-a', 'rev-2')
162 except errors.TagsNotSupported:
163 raise TestNotApplicable('format does not support tags.')
164- source.set_last_revision_info(1, 'rev-1')
165- # Pull from source
166+ source.tags.set_tag('tag-a', 'rev-2')
167 target.pull(source)
168 # The tag is present, and so is its revision.
169 self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
170@@ -167,19 +168,15 @@
171 builder = self.make_branch_builder('source')
172 except errors.UninitializableFormat:
173 raise TestNotApplicable('uninitializeable format')
174- builder.build_commit(message="Rev 1", rev_id='rev-1')
175- source = builder.get_branch()
176+ source = fixtures.build_branch_with_non_ancestral_rev(builder)
177 target = source.bzrdir.sprout('target').open_branch()
178- # Add a non-ancestry tag to source
179- builder.build_commit(message="Rev 2", rev_id='rev-2')
180- try:
181- source.tags.set_tag('tag-a', 'rev-2')
182- except errors.TagsNotSupported:
183- raise TestNotApplicable('format does not support tags.')
184- source.set_last_revision_info(1, 'rev-1')
185 # Add a new commit to the ancestry
186 builder.build_commit(message="Rev 2 again", rev_id='rev-2-again')
187- # Pull from source
188+ # Add a tag to the source, then pull rev-2-again from source
189+ try:
190+ source.tags.set_tag('tag-a', 'rev-2')
191+ except errors.TagsNotSupported:
192+ raise TestNotApplicable('format does not support tags.')
193 target.pull(source, 'rev-2-again')
194 # The tag is present, and so is its revision.
195 self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
196
197=== modified file 'bzrlib/tests/per_branch/test_stacking.py'
198--- bzrlib/tests/per_branch/test_stacking.py 2011-01-13 01:02:53 +0000
199+++ bzrlib/tests/per_branch/test_stacking.py 2011-02-11 06:11:19 +0000
200@@ -23,7 +23,7 @@
201 errors,
202 )
203 from bzrlib.revision import NULL_REVISION
204-from bzrlib.tests import TestNotApplicable, transport_util
205+from bzrlib.tests import fixtures, TestNotApplicable, transport_util
206 from bzrlib.tests.per_branch import TestCaseWithBranch
207
208
209@@ -176,17 +176,20 @@
210
211 def test_unstack_fetches(self):
212 """Removing the stacked-on branch pulls across all data"""
213+ try:
214+ builder = self.make_branch_builder('trunk')
215+ except errors.UninitializableFormat:
216+ raise TestNotApplicable('uninitializeable format')
217 # We have a mainline
218- trunk_tree = self.make_branch_and_tree('mainline')
219- trunk_revid = trunk_tree.commit('revision on mainline')
220- # and make branch from it which is stacked
221+ trunk = fixtures.build_branch_with_non_ancestral_rev(builder)
222+ mainline_revid = 'rev-1'
223+ # and make branch from it which is stacked (with no tags)
224 try:
225- new_dir = trunk_tree.bzrdir.sprout(self.get_url('newbranch'),
226- stacked=True)
227+ new_dir = trunk.bzrdir.sprout(self.get_url('newbranch'), stacked=True)
228 except unstackable_format_errors, e:
229 raise TestNotApplicable(e)
230 # stacked repository
231- self.assertRevisionNotInRepository('newbranch', trunk_revid)
232+ self.assertRevisionNotInRepository('newbranch', mainline_revid)
233 # TODO: we'd like to commit in the stacked repository; that requires
234 # some care (maybe a BranchBuilder) if it's remote and has no
235 # workingtree
236@@ -195,13 +198,21 @@
237 # now when we unstack that should implicitly fetch, to make sure that
238 # the branch will still work
239 new_branch = new_dir.open_branch()
240+ try:
241+ new_branch.tags.set_tag('tag-a', 'rev-2')
242+ except errors.TagsNotSupported:
243+ tags_supported = False
244+ else:
245+ tags_supported = True
246 new_branch.set_stacked_on_url(None)
247- self.assertRevisionInRepository('newbranch', trunk_revid)
248+ self.assertRevisionInRepository('newbranch', mainline_revid)
249 # of course it's still in the mainline
250- self.assertRevisionInRepository('mainline', trunk_revid)
251+ self.assertRevisionInRepository('trunk', mainline_revid)
252+ if tags_supported:
253+ # the tagged revision in trunk is now in newbranch too
254+ self.assertRevisionInRepository('newbranch', 'rev-2')
255 # and now we're no longer stacked
256- self.assertRaises(errors.NotStacked,
257- new_branch.get_stacked_on_url)
258+ self.assertRaises(errors.NotStacked, new_branch.get_stacked_on_url)
259
260 def test_unstack_already_locked(self):
261 """Removing the stacked-on branch with an already write-locked branch
262
263=== modified file 'bzrlib/tests/per_controldir/test_controldir.py'
264--- bzrlib/tests/per_controldir/test_controldir.py 2011-02-07 04:14:29 +0000
265+++ bzrlib/tests/per_controldir/test_controldir.py 2011-02-11 06:11:19 +0000
266@@ -33,6 +33,7 @@
267 )
268 import bzrlib.revision
269 from bzrlib.tests import (
270+ fixtures,
271 ChrootedTestCase,
272 TestNotApplicable,
273 TestSkipped,
274@@ -676,14 +677,11 @@
275 # when sprouting a branch all revisions named in the tags are copied
276 # too.
277 builder = self.make_branch_builder('source')
278- builder.build_commit(message="Rev 1", rev_id='rev-1')
279- builder.build_commit(message="Rev 2", rev_id='rev-2')
280- source = builder.get_branch()
281+ source = fixtures.build_branch_with_non_ancestral_rev(builder)
282 try:
283 source.tags.set_tag('tag-a', 'rev-2')
284 except errors.TagsNotSupported:
285 raise TestNotApplicable('Branch format does not support tags.')
286- source.set_last_revision_info(1, 'rev-1')
287 # Now source has a tag not in its ancestry. Sprout its controldir.
288 dir = source.bzrdir
289 target = dir.sprout(self.get_url('target'))
290
291=== modified file 'doc/en/release-notes/bzr-2.4.txt'
292--- doc/en/release-notes/bzr-2.4.txt 2011-02-10 16:30:54 +0000
293+++ doc/en/release-notes/bzr-2.4.txt 2011-02-11 06:11:19 +0000
294@@ -68,6 +68,10 @@
295 paths, however they may still print junk if not on a UTF-8 terminal.
296 (Martin [gz], #707954)
297
298+* ``bzr reconfigure --unstacked`` now copies revisions (and their
299+ ancestors) named in tags into the unstacked repository, not just the
300+ ancestry of the branch's tip. (Andrew Bennetts, #401646)
301+
302 * ``bzr serve`` no longer crashes when a server_started hook is installed and
303 IPv6 support is available on the system. (Jelmer Vernooij, #293697)
304