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