Rev 2481: Get merge_nested finally working: change nested tree iterators to take file_ids, and ensure the right branch is connected to in the merge logic. May not be suitable for shared repositories yet. in http://bazaar.launchpad.net/~bzr/bzr/dirstate
Robert Collins
robertc at robertcollins.net
Tue Mar 6 12:29:49 GMT 2007
At http://bazaar.launchpad.net/~bzr/bzr/dirstate
------------------------------------------------------------
revno: 2481
revision-id: robertc at robertcollins.net-20070306122818-xk0lc3l01ecl6vbc
parent: mbp at sourcefrog.net-20070306121306-n387xz1h5aguv1he
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate.dogfood
timestamp: Tue 2007-03-06 23:28:18 +1100
message:
Get merge_nested finally working: change nested tree iterators to take file_ids, and ensure the right branch is connected to in the merge logic. May not be suitable for shared repositories yet.
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/bzrdir.py bzrdir.py-20060131065624-156dfea39c4387cb
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/revisiontree.py revisiontree.py-20060724012533-bg8xyryhxd0o0i0h-1
bzrlib/tests/tree_implementations/test_tree.py test_tree.py-20061215160206-usu7lwcj8aq2n3br-1
bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2007-03-05 04:55:34 +0000
+++ b/bzrlib/branch.py 2007-03-06 12:28:18 +0000
@@ -687,12 +687,16 @@
# branch tip correctly, and seed it with history.
checkout_branch.pull(self, stop_revision=revision_id)
tree = checkout.create_workingtree(revision_id)
- for path, entry in tree.iter_reference_entries():
- path = tree.id2path(entry.file_id)
- reference_parent = self.reference_parent(entry.file_id, path)
- reference_parent.create_checkout(tree.abspath(path),
- entry.reference_revision,
- lightweight)
+ basis_tree = tree.basis_tree()
+ basis_tree.lock_read()
+ try:
+ for path, file_id in basis_tree.iter_references():
+ reference_parent = self.reference_parent(file_id, path)
+ reference_parent.create_checkout(tree.abspath(path),
+ basis_tree.get_reference_revision(file_id, path),
+ lightweight)
+ finally:
+ basis_tree.unlock()
return tree
def reference_parent(self, file_id, path):
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py 2007-03-06 07:24:20 +0000
+++ b/bzrlib/bzrdir.py 2007-03-06 12:28:18 +0000
@@ -768,19 +768,28 @@
wt = None
if recurse == 'down':
if wt is not None:
- entries = wt.iter_reference_entries()
+ basis = wt.basis_tree()
+ basis.lock_read()
+ subtrees = basis.iter_references()
recurse_branch = wt.branch
elif source_branch is not None:
- entries = source_branch.basis_tree().iter_reference_entries()
+ basis = source_branch.basis_tree()
+ basis.lock_read()
+ subtrees = basis.iter_references()
recurse_branch = source_branch
else:
- entries = []
- for path, entry in entries:
- target = urlutils.join(url, urlutils.escape(path))
- sublocation = source_branch.reference_parent(entry.file_id,
- path)
- sublocation.bzrdir.sprout(target, entry.reference_revision,
- force_new_repo=force_new_repo, recurse=recurse)
+ subtrees = []
+ basis = None
+ try:
+ for path, file_id in subtrees:
+ target = urlutils.join(url, urlutils.escape(path))
+ sublocation = source_branch.reference_parent(file_id, path)
+ sublocation.bzrdir.sprout(target,
+ basis.get_reference_revision(file_id, path),
+ force_new_repo=force_new_repo, recurse=recurse)
+ finally:
+ if basis is not None:
+ basis.unlock()
return result
=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py 2007-03-06 10:51:27 +0000
+++ b/bzrlib/inventory.py 2007-03-06 12:28:18 +0000
@@ -843,7 +843,8 @@
def _read_tree_state(self, path, work_tree):
"""Populate fields in the inventory entry from the given tree.
"""
- self.reference_revision = work_tree.get_reference_revision(self, path)
+ self.reference_revision = work_tree.get_reference_revision(
+ self.file_id, path)
def _forget_tree_state(self):
self.reference_revision = None
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2007-03-01 10:14:03 +0000
+++ b/bzrlib/merge.py 2007-03-06 12:28:18 +0000
@@ -298,6 +298,23 @@
merge = self.merge_type(pb=self._pb,
change_reporter=self.change_reporter,
**kwargs)
+ if self.recurse == 'down':
+ for path, file_id in self.this_tree.iter_references():
+ sub_tree = self.this_tree.get_nested_tree(file_id, path)
+ other_revision = self.other_tree.get_reference_revision(
+ file_id, path)
+ if other_revision == sub_tree.last_revision():
+ continue
+ sub_merge = Merger(sub_tree.branch, this_tree=sub_tree)
+ sub_merge.merge_type = self.merge_type
+ relpath = self.this_tree.relpath(path)
+ other_branch = self.other_branch.reference_parent(file_id, relpath)
+ sub_merge.set_other_revision(other_revision, other_branch)
+ base_revision = self.base_tree.get_reference_revision(file_id)
+ sub_merge.base_tree = \
+ sub_tree.branch.repository.revision_tree(base_revision)
+ sub_merge.do_merge()
+
finally:
if self.other_tree is not None:
self.other_tree.unlock()
@@ -310,26 +327,6 @@
else:
note("%d conflicts encountered." % len(merge.cooked_conflicts))
- if self.recurse == 'down':
- for path, entry in self.this_tree.iter_reference_entries():
- sub_tree = self.this_tree.get_nested_tree(entry, path)
- other_entry = self.other_tree.inventory[entry.file_id]
- other_revision = self.other_tree.get_reference_revision(
- other_entry, path)
- if other_revision == sub_tree.last_revision():
- continue
- sub_merge = Merger(sub_tree.branch, this_tree=sub_tree)
- sub_merge.merge_type = self.merge_type
- other_branch = self.other_branch.reference_parent(
- entry.file_id, path)
- sub_merge.set_other_revision(other_revision, other_branch)
- base_entry = self.base_tree.inventory[entry.file_id]
- base_revision = \
- self.base_tree.get_reference_revision(base_entry)
- sub_merge.base_tree = \
- sub_tree.branch.repository.revision_tree(base_revision)
- sub_merge.do_merge()
-
return len(merge.cooked_conflicts)
def regen_inventory(self, new_entries):
=== modified file 'bzrlib/revisiontree.py'
--- a/bzrlib/revisiontree.py 2007-03-01 07:56:56 +0000
+++ b/bzrlib/revisiontree.py 2007-03-06 12:28:18 +0000
@@ -128,8 +128,8 @@
ie = self._inventory[file_id]
return ie.symlink_target;
- def get_reference_revision(self, entry, path=None):
- return entry.reference_revision
+ def get_reference_revision(self, file_id, path=None):
+ return self.inventory[file_id].reference_revision
def get_root_id(self):
if self.inventory.root:
=== modified file 'bzrlib/tests/tree_implementations/test_tree.py'
--- a/bzrlib/tests/tree_implementations/test_tree.py 2007-03-05 04:15:38 +0000
+++ b/bzrlib/tests/tree_implementations/test_tree.py 2007-03-06 12:28:18 +0000
@@ -58,23 +58,16 @@
def test_get_reference_revision(self):
tree = self.create_nested()
- tree.lock_read()
- try:
- entry = tree.inventory['sub-root']
- finally:
- tree.unlock()
path = tree.id2path('sub-root')
- self.assertEqual('sub-1', tree.get_reference_revision(entry, path))
+ self.assertEqual('sub-1', tree.get_reference_revision('sub-root', path))
- def test_iter_reference_entries(self):
+ def test_iter_references(self):
tree = self.create_nested()
tree.lock_read()
- try:
- entry = tree.inventory['sub-root']
- finally:
- tree.unlock()
- self.assertEqual([entry], [e for p, e in
- tree.iter_reference_entries()])
+ self.addCleanup(tree.unlock)
+ entry = tree.inventory['sub-root']
+ self.assertEqual([(tree.abspath('subtree'), 'sub-root')],
+ list(tree.iter_references()))
def test_get_root_id(self):
# trees should return some kind of root id; it can be none
=== modified file 'bzrlib/tests/workingtree_implementations/test_commit.py'
--- a/bzrlib/tests/workingtree_implementations/test_commit.py 2007-03-06 10:51:27 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_commit.py 2007-03-06 12:28:18 +0000
@@ -234,8 +234,7 @@
sub_basis.lock_read()
self.addCleanup(sub_basis.unlock)
self.assertEqual(subsubtree.last_revision(),
- sub_basis.get_reference_revision(
- sub_basis.inventory[sub_basis.path2id('subtree')]))
+ sub_basis.get_reference_revision(basis.path2id('subtree')))
# the intermediate tree has changed, so should have had a commit
# take place.
self.assertNotEqual(None, subtree.last_revision())
@@ -245,8 +244,7 @@
basis.lock_read()
self.addCleanup(basis.unlock)
self.assertEqual(subtree.last_revision(),
- basis.get_reference_revision(
- basis.inventory[basis.path2id('subtree')]))
+ basis.get_reference_revision(basis.path2id('subtree')))
# the outer tree must have have changed too.
self.assertNotEqual(None, rev_id)
@@ -278,8 +276,7 @@
basis.lock_read()
self.addCleanup(basis.unlock)
self.assertEqual(subtree.last_revision(),
- basis.get_reference_revision(
- basis.inventory[basis.path2id('subtree')]))
+ basis.get_reference_revision(basis.path2id('subtree')))
self.assertNotEqual(rev_id, rev_id2)
=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py 2007-03-05 04:15:38 +0000
+++ b/bzrlib/tree.py 2007-03-06 12:28:18 +0000
@@ -177,16 +177,16 @@
return self.inventory.iter_entries_by_dir(
specific_file_ids=specific_file_ids)
- def iter_reference_entries(self):
+ def iter_references(self):
for path, entry in self.iter_entries_by_dir():
if entry.kind == 'tree-reference':
- yield path, entry
+ yield path, entry.file_id
def kind(self, file_id):
raise NotImplementedError("Tree subclass %s must implement kind"
% self.__class__.__name__)
- def get_reference_revision(self, entry, path=None):
+ def get_reference_revision(self, file_id, path=None):
raise NotImplementedError("Tree subclass %s must implement "
"get_reference_revision"
% self.__class__.__name__)
@@ -705,8 +705,8 @@
self.target.get_symlink_target(file_id)):
changed_content = True
elif from_kind == 'tree-reference':
- if (self.source.get_reference_revision(from_entry, from_path)
- != self.target.get_reference_revision(to_entry, to_path)):
+ if (self.source.get_reference_revision(file_id, from_path)
+ != self.target.get_reference_revision(file_id, to_path)):
changed_content = True
parent = (from_parent, to_entry.parent_id)
name = (from_name, to_entry.name)
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-03-06 10:29:01 +0000
+++ b/bzrlib/workingtree_4.py 2007-03-06 12:28:18 +0000
@@ -418,13 +418,14 @@
"""
return self.current_dirstate().get_parent_ids()
- def get_reference_revision(self, entry, path=None):
+ def get_reference_revision(self, file_id, path=None):
# referenced tree's revision is whatever's currently there
- return self.get_nested_tree(entry, path).last_revision()
+ return self.get_nested_tree(file_id, path).last_revision()
- def get_nested_tree(self, entry, path=None):
+ def get_nested_tree(self, file_id, path=None):
if path is None:
- path = self.id2path(entry.file_id)
+ path = self.id2path(file_id)
+ # else: check file_id is at path?
return WorkingTree.open(self.abspath(path))
@needs_read_lock
@@ -468,6 +469,18 @@
result.append(key[2])
return iter(result)
+ def iter_references(self):
+ for key, tree_details in self.current_dirstate()._iter_entries():
+ if tree_details[0][0] in ('a', 'r'): # absent, relocated
+ # not relevant to the working tree
+ continue
+ if not key[1]:
+ # the root is not a reference.
+ continue
+ path = pathjoin(self.basedir, key[0].decode('utf8'), key[1].decode('utf8'))
+ if self._kind(path) == 'tree-reference':
+ yield path, key[2]
+
@needs_read_lock
def kind(self, file_id):
"""Return the kind of a file.
@@ -478,6 +491,9 @@
relpath = self.id2path(file_id)
assert relpath != None, \
"path for id {%s} is None!" % file_id
+ return self._kind(relpath)
+
+ def _kind(self, relpath):
abspath = self.abspath(relpath)
kind = file_kind(abspath)
if kind == 'directory' and self._directory_is_tree_reference(relpath):
@@ -1403,8 +1419,8 @@
def get_file_text(self, file_id):
return ''.join(self.get_file_lines(file_id))
- def get_reference_revision(self, entry, path=None):
- return entry.reference_revision
+ def get_reference_revision(self, file_id, path=None):
+ return self.inventory[file_id].reference_revision
def get_symlink_target(self, file_id):
entry = self._get_entry(file_id=file_id)
More information about the bazaar-commits
mailing list