Rev 3575: Add the ability to force a basis for a revision. in http://bzr.arbash-meinel.com/branches/bzr/1.7-dev/branch_builder
John Arbash Meinel
john at arbash-meinel.com
Tue Jul 22 19:48:27 BST 2008
At http://bzr.arbash-meinel.com/branches/bzr/1.7-dev/branch_builder
------------------------------------------------------------
revno: 3575
revision-id: john at arbash-meinel.com-20080722184724-as3agicle15r1szy
parent: john at arbash-meinel.com-20080722181225-nx1dwfmb4wky600x
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: branch_builder
timestamp: Tue 2008-07-22 13:47:24 -0500
message:
Add the ability to force a basis for a revision.
This includes the ability to merge in another tree, though it won't
actually *do* the merge under the covers.
You have to manually set what you want the texts to be like.
-------------- next part --------------
=== modified file 'bzrlib/branchbuilder.py'
--- a/bzrlib/branchbuilder.py 2008-07-22 18:12:25 +0000
+++ b/bzrlib/branchbuilder.py 2008-07-22 18:47:24 +0000
@@ -61,9 +61,23 @@
tree.unlock()
def build_snapshot(self, parent_ids, revision_id, actions):
+ if parent_ids is not None:
+ self._branch.lock_write()
+ try:
+ base_id = parent_ids[0]
+ # Unfortunately, this is the only real way to get the revno
+ cur_revno, cur_revision_id = self._branch.last_revision_info()
+ g = self._branch.repository.get_graph()
+ new_revno = g.find_distance_to_null(base_id,
+ [(cur_revision_id, cur_revno)])
+ self._branch.set_last_revision_info(new_revno, base_id)
+ finally:
+ self._branch.unlock()
tree = memorytree.MemoryTree.create_on_branch(self._branch)
tree.lock_write()
try:
+ if parent_ids is not None:
+ tree.set_parent_ids(parent_ids)
# Unfortunately, MemoryTree.add(directory) just creates an
# inventory entry. And the only public function to create a
# directory is MemoryTree.mkdir() which creates the directory, but
=== modified file 'bzrlib/tests/test_branchbuilder.py'
--- a/bzrlib/tests/test_branchbuilder.py 2008-07-22 18:12:25 +0000
+++ b/bzrlib/tests/test_branchbuilder.py 2008-07-22 18:47:24 +0000
@@ -178,3 +178,82 @@
builder = self.build_a_rev()
self.assertRaises(errors.UnknownBuildAction,
builder.build_snapshot, None, 'B-id', [('weirdo', ('foo',))])
+
+ # TODO: rename a file/directory, but rename isn't supported by the
+ # MemoryTree api yet, so for now we wait until it is used
+
+ def test_set_parent(self):
+ builder = self.build_a_rev()
+ builder.build_snapshot(['A-id'], 'B-id',
+ [('modify', ('a-id', 'new\ncontent\n'))])
+ builder.build_snapshot(['A-id'], 'C-id',
+ [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))])
+ # We should now have a graph:
+ # A
+ # |\
+ # C B
+ # And not A => B => C
+ repo = builder.get_branch().repository
+ repo.lock_read()
+ self.addCleanup(repo.unlock)
+ self.assertEqual({'B-id': ('A-id',), 'C-id': ('A-id',)},
+ repo.get_parent_map(['B-id', 'C-id']))
+ b_tree = repo.revision_tree('B-id')
+ self.assertTreeShape([(u'', 'a-root-id', 'directory'),
+ (u'a', 'a-id', 'file'),
+ ], b_tree)
+ self.assertEqual('new\ncontent\n', b_tree.get_file_text('a-id'))
+
+ # We should still be using the content from A in C, not from B
+ c_tree = repo.revision_tree('C-id')
+ self.assertTreeShape([(u'', 'a-root-id', 'directory'),
+ (u'a', 'a-id', 'file'),
+ (u'c', 'c-id', 'file'),
+ ], c_tree)
+ self.assertEqual('contents', c_tree.get_file_text('a-id'))
+ self.assertEqual('alt\ncontent\n', c_tree.get_file_text('c-id'))
+
+ def test_set_merge_parent(self):
+ builder = self.build_a_rev()
+ builder.build_snapshot(['A-id'], 'B-id',
+ [('add', ('b', 'b-id', 'file', 'b\ncontent\n'))])
+ builder.build_snapshot(['A-id'], 'C-id',
+ [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))])
+ builder.build_snapshot(['B-id', 'C-id'], 'D-id', [])
+ repo = builder.get_branch().repository
+ repo.lock_read()
+ self.addCleanup(repo.unlock)
+ self.assertEqual({'B-id': ('A-id',), 'C-id': ('A-id',),
+ 'D-id': ('B-id', 'C-id')},
+ repo.get_parent_map(['B-id', 'C-id', 'D-id']))
+ d_tree = repo.revision_tree('D-id')
+ # Note: by default a merge node does *not* pull in the changes from the
+ # merged tree, you have to supply it yourself.
+ self.assertTreeShape([(u'', 'a-root-id', 'directory'),
+ (u'a', 'a-id', 'file'),
+ (u'b', 'b-id', 'file'),
+ ], d_tree)
+
+ def test_set_merge_parent_and_contents(self):
+ builder = self.build_a_rev()
+ builder.build_snapshot(['A-id'], 'B-id',
+ [('add', ('b', 'b-id', 'file', 'b\ncontent\n'))])
+ builder.build_snapshot(['A-id'], 'C-id',
+ [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))])
+ builder.build_snapshot(['B-id', 'C-id'], 'D-id',
+ [('add', ('c', 'c-id', 'file', 'alt\ncontent\n'))])
+ repo = builder.get_branch().repository
+ repo.lock_read()
+ self.addCleanup(repo.unlock)
+ self.assertEqual({'B-id': ('A-id',), 'C-id': ('A-id',),
+ 'D-id': ('B-id', 'C-id')},
+ repo.get_parent_map(['B-id', 'C-id', 'D-id']))
+ d_tree = repo.revision_tree('D-id')
+ self.assertTreeShape([(u'', 'a-root-id', 'directory'),
+ (u'a', 'a-id', 'file'),
+ (u'b', 'b-id', 'file'),
+ (u'c', 'c-id', 'file'),
+ ], d_tree)
+ # Because we copied the exact text into *this* tree, the 'c' file
+ # should look like it was not modified in the merge
+ self.assertEqual('C-id', d_tree.inventory['c-id'].revision)
More information about the bazaar-commits
mailing list