Rev 3794: CommitBuilder.record_iter_changes handles merged directories. in http://people.ubuntu.com/~robertc/baz2.0/commit-iterchanges

Robert Collins robertc at robertcollins.net
Tue Dec 2 02:43:44 GMT 2008


At http://people.ubuntu.com/~robertc/baz2.0/commit-iterchanges

------------------------------------------------------------
revno: 3794
revision-id: robertc at robertcollins.net-20081202024339-47ae2uuhqfdbiw8z
parent: robertc at robertcollins.net-20081202015850-izprtzmz0sxm0q19
committer: Robert Collins <robertc at robertcollins.net>
branch nick: commit-iterchanges
timestamp: Tue 2008-12-02 13:43:39 +1100
message:
  CommitBuilder.record_iter_changes handles merged directories.
modified:
  bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/per_repository/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2008-08-09 00:45:30 +0000
+++ b/bzrlib/inventory.py	2008-12-02 02:43:39 +0000
@@ -981,6 +981,24 @@
                         child_dirs.append((child_relpath+'/', child_ie))
             stack.extend(reversed(child_dirs))
 
+    def make_delta(self, old):
+        """Make an inventory delta from two inventories."""
+        old_ids = set(old)
+        new_ids = set(self)
+        adds = new_ids - old_ids
+        deletes = old_ids - new_ids
+        common = old_ids.intersection(new_ids)
+        delta = []
+        for file_id in deletes:
+            delta.append((old.id2path(file_id), None, file_id, None))
+        for file_id in adds:
+            delta.append((None, self.id2path(file_id), file_id, self[file_id]))
+        for file_id in common:
+            if old[file_id] != self[file_id]:
+                delta.append((old.id2path(file_id), self.id2path(file_id),
+                    file_id, self[file_id]))
+        return delta
+
     def make_entry(self, kind, name, parent_id, file_id=None):
         """Simple thunk to bzrlib.inventory.make_entry."""
         return make_entry(kind, name, parent_id, file_id)

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2008-12-02 01:58:50 +0000
+++ b/bzrlib/repository.py	2008-12-02 02:43:39 +0000
@@ -536,25 +536,43 @@
             revtrees = list(self.repository.revision_trees(self.parents))
             repo_basis = revtrees[0]
             for revtree in revtrees[1:]:
-                for change in _make_delta(basis_tree, revtree):
+                for change in revtree.inventory.make_delta(basis_tree.inventory):
                     if change[1] is None:
                         # Deleted
                         continue
                     if change[2] not in merged_ids:
                         if change[0] is not None:
-                            merged_ids[change[2]] = set([change[3].revision,
-                                repo_basis[change[2]].revision])
+                            merged_ids[change[2]] = [
+                                repo_basis.inventory[change[2]].revision,
+                                change[3].revision]
                         else:
-                            merged_ids[change[2]] = set([change[3].revision])
+                            merged_ids[change[2]] = [change[3].revision]
                     else:
-                        merged_ids[change[2]].add(change[3].revision)
+                        merged_ids[change[2]].append(change[3].revision)
         else:
             merged_ids = {}
         changes= {}
         for change in iter_changes:
+            # This probably looks up in basis_inv way to much.
             changes[change[0]] = change, merged_ids.get(
-                change[0], set([basis_inv[change[0]].revision]))
+                change[0], [basis_inv[change[0]].revision])
         unchanged_merged = set(merged_ids) - set(changes)
+        for file_id in unchanged_merged:
+            # Record a merged version with the current content from basis.
+            # NB:XXX: We are reconstructing path information we had, this
+            # should be preserved instead.
+            # inv delta  change: (file_id, (path_in_source, path_in_target),
+            #   changed_content, versioned, parent, name, kind,
+            #   executable)
+            basis_entry = basis_inv[file_id]
+            change = (file_id,
+                (basis_inv.id2path(file_id), tree.id2path(file_id)),
+                False, (True, True),
+                (basis_entry.parent_id, basis_entry.parent_id),
+                (basis_entry.name, basis_entry.name),
+                (basis_entry.kind, basis_entry.kind),
+                (basis_entry.executable, basis_entry.executable))
+            changes[file_id] = (change, merged_ids[file_id])
         # changes contains tuples with the change and a set of inventory
         # candidates for the file.
         # inv delta is:
@@ -568,7 +586,13 @@
                 file_id = change[0]
                 entry = _entry_factory[kind](file_id, change[5][1],
                     change[4][1])
-                heads = self._heads(change[0], head_candidates)
+                head_set = self._heads(change[0], set(head_candidates))
+                heads = []
+                # Preserve ordering.
+                for head_candidate in head_candidates:
+                    if head_candidate in head_set:
+                        heads.append(head_candidate)
+                        head_set.remove(head_candidate)
                 # Populate the entry
                 if change[2]:
                     # From disk.
@@ -615,8 +639,10 @@
                         entry.symlink_target = basis_inv[file_id].symlink_target
                         self._add_text_to_weave(change[0], [], heads, None)
                     elif kind == 'directory':
-                        # Nothing to set.
-                        self._add_text_to_weave(change[0], [], heads, None)
+                        # Nothing to set on the entry.
+                        # XXX: split into the Root and nonRoot versions.
+                        if change[1][1] != '' or self.repository.supports_rich_root():
+                            self._add_text_to_weave(change[0], [], heads, None)
                     elif kind == 'tree-reference':
                         import pdb;pdb.set_trace()
                     else:

=== modified file 'bzrlib/tests/per_repository/test_commit_builder.py'
--- a/bzrlib/tests/per_repository/test_commit_builder.py	2008-12-02 01:58:50 +0000
+++ b/bzrlib/tests/per_repository/test_commit_builder.py	2008-12-02 02:43:39 +0000
@@ -837,13 +837,16 @@
         tree.rename_one(name, 'new_' + name)
         return tree.commit('')
 
-    def _commit_sprout_rename_merge(self, tree1, name, expect_fs_hash=False):
+    def _commit_sprout_rename_merge(self, tree1, name, expect_fs_hash=False,
+        mini_commit=None):
         rev1, tree2 = self._commit_sprout(tree1, name)
         # change both sides equally
         rev2 = self._rename_in_tree(tree1, name)
         rev3 = self._rename_in_tree(tree2, name)
         tree1.merge_from_branch(tree2.branch)
-        rev4 = self.mini_commit(tree1, 'new_' + name, 'new_' + name,
+        if mini_commit is None:
+            mini_commit = self.mini_commit
+        rev4 = mini_commit(tree1, 'new_' + name, 'new_' + name,
             expect_fs_hash=expect_fs_hash)
         tree3, = self._get_revtrees(tree1, [rev4])
         self.assertEqual(rev4, tree3.inventory[name + 'id'].revision)
@@ -861,6 +864,13 @@
         self.build_tree(['t1/dir/'])
         self._commit_sprout_rename_merge(tree1, 'dir')
 
+    def test_last_modified_revision_after_merge_dir_changes_ric(self):
+        # merge a dir changes the last modified.
+        tree1 = self.make_branch_and_tree('t1')
+        self.build_tree(['t1/dir/'])
+        self._commit_sprout_rename_merge(tree1, 'dir',
+            mini_commit=self.mini_commit_record_iter_changes)
+
     def test_last_modified_revision_after_merge_file_changes(self):
         # merge a file changes the last modified.
         tree1 = self.make_branch_and_tree('t1')




More information about the bazaar-commits mailing list