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