Rev 3529: Initial work on _entries_lca. in http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/merge_lca_multi

John Arbash Meinel john at arbash-meinel.com
Tue Jul 22 17:48:25 BST 2008


At http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/merge_lca_multi

------------------------------------------------------------
revno: 3529
revision-id: john at arbash-meinel.com-20080722164720-h66kbfwehfpcpyis
parent: john at arbash-meinel.com-20080722154417-qoc7kmrv0i4orptm
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: merge_lca_multi
timestamp: Tue 2008-07-22 11:47:20 -0500
message:
  Initial work on _entries_lca.
  
  At least get the basic API working, and track when a file is modified.
  
  I'm going to need a better test setup if I'm going to handle all the test cases in
  a way that can be actually understood.
-------------- next part --------------
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py	2008-07-22 15:44:17 +0000
+++ b/bzrlib/merge.py	2008-07-22 16:47:20 +0000
@@ -27,6 +27,7 @@
     patiencediff,
     registry,
     revision as _mod_revision,
+    tree as _mod_tree,
     )
 from bzrlib.branch import Branch
 from bzrlib.conflicts import ConflictList, Conflict
@@ -638,6 +639,50 @@
             result.append((file_id, changed, parents3, names3, executable3))
         return result
 
+    def _entries_lca(self):
+        """Gather data about files modified between multiple trees.
+
+        This compares OTHER versus all LCA trees, and for interesting entries,
+        it then compares with THIS and BASE.
+
+        For the multi-valued entries, the format will be (BASE, [lca1, lca2])
+        :return: [(file_id, changed, parents, names, executable)]
+            file_id     Simple file_id of the entry
+            changed     Boolean, True if the kind or contents changed
+                        else False
+            parents     ((base, [parent_id, in, lcas]), parent_id_other,
+                         parent_id_this)
+            names       ((base, [name, in, lcas]), name_in_other, name_in_this)
+            executable  ((base, [exec, in, lcas]), exec_in_other, exec_in_this)
+        """
+        result = []
+        walker = _mod_tree.MultiWalker(self.other_tree,
+                                       self._lca_trees.values())
+
+        for path, file_id, other_ie, lca_values in walker.iter_all():
+            # Is this modified at all from any of the other trees?
+            last_rev = other_ie.revision
+            for lca_path, ie in lca_values:
+                if ie.revision != last_rev:
+                    break
+            else: # Identical in all trees
+                continue
+            base_ie = self.base_tree.inventory[file_id]
+            this_ie = self.this_tree.inventory[file_id]
+            result.append((file_id, True,
+                           ((base_ie.parent_id,
+                            [ie.parent_id for path, ie in lca_values]),
+                            other_ie.parent_id, this_ie.parent_id),
+                           ((base_ie.name,
+                            [ie.name for path, ie in lca_values]),
+                            other_ie.name, this_ie.name),
+                           ((base_ie.executable,
+                            [ie.executable for path, ie in lca_values]),
+                            other_ie.executable, this_ie.executable)
+                          ))
+        return result
+
+
     def fix_root(self):
         try:
             self.tt.final_kind(self.tt.root)

=== modified file 'bzrlib/tests/test_merge.py'
--- a/bzrlib/tests/test_merge.py	2008-07-22 15:44:17 +0000
+++ b/bzrlib/tests/test_merge.py	2008-07-22 16:47:20 +0000
@@ -825,3 +825,58 @@
         merge_obj = merger.make_merger()
         self.assertIsInstance(merge_obj, UnsupportedLCATreesMerger)
         self.assertFalse('lca_trees' in merge_obj.kwargs)
+
+    def test__entries_lca_simple(self):
+        tree = self.make_branch_and_memory_tree('tree')
+        tree.lock_write()
+        self.addCleanup(tree.unlock)
+        tree.add('.')
+        tree.add(['a'], ['a-id'], ['file'])
+        tree.put_file_bytes_non_atomic('a-id', 'a\nb\nc\n')
+        tree.commit('A', rev_id='A-id')
+        tree.put_file_bytes_non_atomic('a-id', 'a\nb\nC\nc\n')
+        tree.commit('C', rev_id='C-id')
+        tree.branch.set_last_revision_info(1, 'A-id')
+        tree.set_parent_ids(['A-id'])
+        tree.put_file_bytes_non_atomic('a-id', 'a\nB\nb\nc\n')
+        tree.commit('B', rev_id='B-id')
+        tree.set_parent_ids(['B-id', 'C-id'])
+        tree.put_file_bytes_non_atomic('a-id', 'a\nB\nb\nC\nc\n')
+        tree.commit('D', rev_id='D-id')
+        tree.branch.set_last_revision_info(2, 'C-id')
+        tree.set_parent_ids(['C-id', 'B-id'])
+        tree.put_file_bytes_non_atomic('a-id', 'a\nB\nb\nC\nc\nE\n')
+        tree.commit('E', rev_id='E-id')
+        tree.branch.set_last_revision_info(2, 'D-id')
+        tree.set_parent_ids(['D-id'])
+
+        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
+            tree, 'E-id')
+        merger.merge_type = _mod_merge.Merge3Merger
+        merge_obj = merger.make_merger()
+
+        entries = list(merge_obj._entries_lca())
+        root_id = tree.path2id('')
+        self.assertEqual(['B-id', 'C-id'], sorted(merge_obj._lca_trees.keys()))
+
+        # (file_id, changed, parents, names, executable)
+        # BASE, lca1, lca2, OTHER, THIS
+        self.assertEqual([(root_id, True,
+                           ((None, [None, None]), None, None),
+                           ((u'', [u'', u'']), u'', u''),
+                           ((False, [False, False]), False, False)),
+                          ('a-id', True,
+                           ((root_id, [root_id, root_id]), root_id, root_id),
+                           ((u'a', [u'a', u'a']), u'a', u'a'),
+                           ((False, [False, False]), False, False)),
+                         ], entries)
+                         
+
+    # TODO: cases to test
+    #       simple criss-cross LCAS identical, BASE different
+    #       x-x changed from BASE but identical for all LCAs and tips
+    #       x-x file not in BASE
+    #       x-x file not in THIS
+    #       x-x OTHER deletes the file
+    #       x-x OTHER introduces the file
+    #       x-x LCAs differ, one in ancestry of other for a given file



More information about the bazaar-commits mailing list