Rev 3525: Update the lca_multi_way logic so that it can handle when bases supersede eachother for a given entry. in http://bzr.arbash-meinel.com/branches/bzr/1.6-dev/merge3_per_file

John Arbash Meinel john at arbash-meinel.com
Mon Jun 30 19:19:47 BST 2008


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

------------------------------------------------------------
revno: 3525
revision-id: john at arbash-meinel.com-20080630181914-tbo6tazaxj50185c
parent: john at arbash-meinel.com-20080626235243-d1sli6ayrssk7bym
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: merge3_per_file
timestamp: Mon 2008-06-30 13:19:14 -0500
message:
  Update the lca_multi_way logic so that it can handle when bases supersede eachother for a given entry.
-------------- next part --------------
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py	2008-06-26 23:52:43 +0000
+++ b/bzrlib/merge.py	2008-06-30 18:19:14 +0000
@@ -640,7 +640,7 @@
             changed     boolean indicating whether the file contents
                         or kind were changed versus any base
             parents     parent ids for ([bases], other, this)
-            names       names for ([bases], other, this)
+            names       names for ((unique_lca_base, [lca_bases]), other, this)
             executable  execute-bit values for ([bases], other, this)
         """
         bases_values = {}
@@ -706,18 +706,25 @@
         # Now we should have an entry in each base tree, and an entry for this
         # and other
         result = []
+        unique_lca_inventory = self.base_tree.inventory
         assert not all_file_ids.symmetric_difference(file_id_ordering)
         for file_id in file_id_ordering:
+            unique_lca_base = get_info_from_inventory(file_id,
+                                                      unique_lca_inventory)
+            try:
+                unique_lca_base_ie = self.base_tree.inventory[file_id]
+            except errors.NoSuchId:
+                unique_lca_base_ie = None
             base_tuples = [base[file_id] for base in bases_values.itervalues()]
             changed = all_changed.get(file_id, False)
             this_tuple = this_values[file_id]
             other_tuple = other_values[file_id]
-            parents = ([b[0] for b in base_tuples], other_tuple[0],
-                       this_tuple[0])
-            names = ([b[1] for b in base_tuples], other_tuple[1],
-                     this_tuple[1])
-            executable = ([b[2] for b in base_tuples], other_tuple[2],
-                          this_tuple[2])
+            parents = ((unique_lca_base[0], [b[0] for b in base_tuples]),
+                       other_tuple[0], this_tuple[0])
+            names = ((unique_lca_base[1], [b[1] for b in base_tuples]),
+                     other_tuple[1], this_tuple[1])
+            executable = ((unique_lca_base[2], [b[2] for b in base_tuples]),
+                          other_tuple[2], this_tuple[2])
             result.append((file_id, changed, parents, names, executable))
         return result
 
@@ -821,25 +828,38 @@
         :return: One of 'this', 'conflict', or 'other'
             indicating which one should be taken, or that there was a conflict.
         """
-        base_first = bases[0]
-        for base in bases[1:]:
-            # XXX: This is not technically correct. A value does not always
-            #      supersede None. Sometimes you get None because someone
-            #      deleted an object. The correct resolution would probably be
-            #      to recurse back into the LCA of these bases until we get
-            #      some sort of convergance. (Eventually you always reach NULL
-            #      where everything is None). That would let us know if this
-            #      None is a "didn't exist yet" or a "deleted".
-            if base is not None and base_first != base:
-                break
-        else: # All the bases are identical, we can just use 3-way
-            return Merge3Merger._three_way(base_first, other, this)
+        # Either nothing changed or "Ambiguous clean merge" -- both sides have
+        # made the same change. Either way, nothing to merge.
+        if other == this:
+            return "this"
+        unique_lca_base_value, lca_bases_value = bases
+
+        # Check if the lca's agree, so that we can just use standard 3-way
+        # merge logic.
+        # TODO: This is a shortcut for figuring out if one of the LCA values
+        #       supercedes another. However, it is using a shortcut based on
+        #       unique_lca. It is possible that a value should supersede even
+        #       though it isn't available here.
+        interesting_values = []
+        for base_value in lca_bases_value:
+            if (base_value != unique_lca_base_value
+                and base_value not in interesting_values):
+                interesting_values.append(base_value)
+
+        if len(interesting_values) == 0:
+            import pdb; pdb.set_trace()
+            # All of them == the value in the unique base, just use it.
+            return Merge3Merger._three_way(unique_lca_base_value, other, this)
+        elif len(interesting_values) == 1:
+            import pdb; pdb.set_trace()
+            # There was only 1 interesting value (not equal to unique base)
+            # So again we can collapse
+            return Merge3Merger._three_way(interesting_values[0], other, this)
+        import pdb; pdb.set_trace()
+
         # If we got this far, we have variation in what the common ancestors
         # think is the correct value for this path.
 
-        # "Ambiguous clean merge" -- both sides have made the same change.
-        if other == this:
-            return "this"
         # Punt at this point, we might be able to work something out, but for
         # now, just conflict
         # TODO: Consider the ramifications of something like:
@@ -849,6 +869,7 @@
         #           return "other"
         #       Also, if *both* are in 'bases' is this a conflict? Arguably
         #       both sides have chosen to supersede the base value.
+        #       This could be seen as a "annotation" merge for scalars
         return "conflict"
 
     @staticmethod
@@ -1585,7 +1606,7 @@
                 break
             elif len(next_lcas) > 2:
                 # Fall back to grabbing all of the ancestry for this entry
-                warning('Found more than to Least Common Ancestors'
+                warning('Found more than two Least Common Ancestors'
                         ' falling back to full ancestry. For %s',
                         self.vf)
                 cur_lcas = next_lcas



More information about the bazaar-commits mailing list