Rev 3289: Deprecate VersionedFile.get_parents, breaking pulling from a ghost containing knit or pack repository to weaves, which improves correctness and allows simplification of core code. in http://people.ubuntu.com/~robertc/baz2.0/versioned_files
Robert Collins
robertc at robertcollins.net
Wed Mar 19 04:39:11 GMT 2008
At http://people.ubuntu.com/~robertc/baz2.0/versioned_files
------------------------------------------------------------
revno: 3289
revision-id:robertc at robertcollins.net-20080319043904-7g4imzvybc7q9l8h
parent: robertc at robertcollins.net-20080318011335-oq6210j5dgu9rz7d
committer: Robert Collins <robertc at robertcollins.net>
branch nick: versionedfile.apicleanup
timestamp: Wed 2008-03-19 15:39:04 +1100
message:
Deprecate VersionedFile.get_parents, breaking pulling from a ghost containing knit or pack repository to weaves, which improves correctness and allows simplification of core code.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/bundle/serializer/v4.py v10.py-20070611062757-5ggj7k18s9dej0fr-1
bzrlib/fetch.py fetch.py-20050818234941-26fea6105696365d
bzrlib/knit.py knit.py-20051212171256-f056ac8f0fbe1bd9
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/multiparent.py __init__.py-20070410133617-n1jdhcc1n1mibarp-1
bzrlib/reconcile.py reweave_inventory.py-20051108164726-1e5e0934febac06e
bzrlib/repofmt/knitrepo.py knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
bzrlib/repofmt/weaverepo.py presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/interversionedfile_implementations/test_join.py test_join.py-20060302012326-9b5e9b0f0a03fedc
bzrlib/tests/repository_implementations/test_check_reconcile.py test_broken.py-20070928125406-62236394w0jpbpd6-2
bzrlib/tests/repository_implementations/test_iter_reverse_revision_history.py test_iter_reverse_re-20070217015036-spu7j5ggch7pbpyd-1
bzrlib/tests/test_bundle.py test.py-20050630184834-092aa401ab9f039c
bzrlib/tests/test_knit.py test_knit.py-20051212171302-95d4c00dd5f11f2b
bzrlib/tests/test_versionedfile.py test_versionedfile.py-20060222045249-db45c9ed14a1c2e5
bzrlib/versionedfile.py versionedfile.py-20060222045106-5039c71ee3b65490
bzrlib/weave.py knit.py-20050627021749-759c29984154256b
=== modified file 'NEWS'
--- a/NEWS 2008-03-16 16:58:03 +0000
+++ b/NEWS 2008-03-19 04:39:04 +0000
@@ -22,10 +22,20 @@
API BREAKS:
+ * Attempting to pull data from a ghost aware repository (e.g. knits) into a
+ non-ghost aware repository such as weaves will now fail if there are
+ ghosts. (Robert Collins)
+
+ * ``VersionedFile.get_parents`` is deprecated, please use
+ ``VersionedFile.get_parent_map``. (Robert Collins)
+
TESTING:
INTERNALS:
+ * ``VersionedFile`` now has a new method ``get_parent_map`` which, like
+ ``Graph.get_parent_map`` returns a dict of key:parents. (Robert Collins)
+
bzr 1.3rc1 2008-03-16
---------------------
=== modified file 'bzrlib/bundle/serializer/v4.py'
--- a/bzrlib/bundle/serializer/v4.py 2007-12-18 20:57:34 +0000
+++ b/bzrlib/bundle/serializer/v4.py 2008-03-19 04:39:04 +0000
@@ -327,7 +327,7 @@
if revision_id in self.base_ancestry:
continue
new_revision_ids.add(revision_id)
- pending.extend(vf.get_parents(revision_id))
+ pending.extend(vf.get_parent_map([revision_id])[revision_id])
yield vf, file_id, new_revision_ids
def write_files(self):
@@ -376,8 +376,9 @@
revision_ids = list(multiparent.topo_iter(vf, revision_ids))
mpdiffs = vf.make_mpdiffs(revision_ids)
sha1s = vf.get_sha1s(revision_ids)
+ parent_map = vf.get_parent_map(revision_ids)
for mpdiff, revision_id, sha1, in zip(mpdiffs, revision_ids, sha1s):
- parents = vf.get_parents(revision_id)
+ parents = parent_map[revision_id]
text = ''.join(mpdiff.to_patch())
self.bundle.add_multiparent_record(text, sha1, parents, repo_kind,
revision_id, file_id)
=== modified file 'bzrlib/fetch.py'
--- a/bzrlib/fetch.py 2008-01-17 05:30:53 +0000
+++ b/bzrlib/fetch.py 2008-03-19 04:39:04 +0000
@@ -356,12 +356,15 @@
parent_texts = {}
versionedfile = {}
to_store = self.target.weave_store
+ parent_map = self.source.get_graph().get_parent_map(revs)
for tree in self.iter_rev_trees(revs):
revision_id = tree.inventory.root.revision
root_id = tree.get_root_id()
- parents = inventory_weave.get_parents(revision_id)
+ parents = parent_map[revision_id]
+ if parents[0] == NULL_REVISION:
+ parents = ()
if root_id not in versionedfile:
- versionedfile[root_id] = to_store.get_weave_or_empty(root_id,
+ versionedfile[root_id] = to_store.get_weave_or_empty(root_id,
self.target.get_transaction())
_, _, parent_texts[root_id] = versionedfile[root_id].add_lines(
revision_id, parents, [], parent_texts)
=== modified file 'bzrlib/knit.py'
--- a/bzrlib/knit.py 2008-03-18 01:13:35 +0000
+++ b/bzrlib/knit.py 2008-03-19 04:39:04 +0000
@@ -720,7 +720,7 @@
def get_delta(self, version_id):
"""Get a delta for constructing version from some other version."""
self.check_not_reserved_id(version_id)
- parents = self.get_parents(version_id)
+ parents = self.get_parent_map([version_id])[version_id]
if len(parents):
parent = parents[0]
else:
@@ -977,11 +977,11 @@
self._index.check_versions_present(version_ids)
def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts,
- nostore_sha, random_id, check_content):
+ nostore_sha, random_id, check_content, left_matching_blocks):
"""See VersionedFile.add_lines_with_ghosts()."""
self._check_add(version_id, lines, random_id, check_content)
return self._add(version_id, lines, parents, self.delta,
- parent_texts, None, nostore_sha, random_id)
+ parent_texts, left_matching_blocks, nostore_sha, random_id)
def _add_lines(self, version_id, parents, lines, parent_texts,
left_matching_blocks, nostore_sha, random_id, check_content):
@@ -1265,7 +1265,7 @@
for version_id in version_ids:
try:
result[version_id] = tuple(lookup(version_id))
- except KeyError:
+ except (KeyError, RevisionNotPresent):
pass
return result
@@ -2828,9 +2828,10 @@
# do the join:
count = 0
total = len(version_list)
+ parent_map = self.source.get_parent_map(version_list)
for version_id in version_list:
pb.update("Converting to knit", count, total)
- parents = self.source.get_parents(version_id)
+ parents = parent_map[version_id]
# check that its will be a consistent copy:
for parent in parents:
# if source has the parent, we must already have it
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2008-03-14 16:23:28 +0000
+++ b/bzrlib/merge.py 2008-03-19 04:39:04 +0000
@@ -1403,7 +1403,7 @@
"""
if version_id not in self.uncommon:
return set()
- parents = self.vf.get_parents(version_id)
+ parents = self.vf.get_parent_map([version_id])[version_id]
if len(parents) == 0:
return set(range(len(self.vf.get_lines(version_id))))
new = None
=== modified file 'bzrlib/multiparent.py'
--- a/bzrlib/multiparent.py 2007-10-04 05:50:44 +0000
+++ b/bzrlib/multiparent.py 2008-03-19 04:39:04 +0000
@@ -23,6 +23,7 @@
from StringIO import StringIO
from bzrlib import (
+ errors,
patiencediff,
trace,
ui,
@@ -37,11 +38,12 @@
descendants = {}
if versions is None:
versions = vf.versions()
+ parents = vf.get_parent_map(versions)
def pending_parents(version):
- return [v for v in vf.get_parents(version) if v in versions and
+ return [v for v in parents[version] if v in versions and
v not in seen]
for version_id in versions:
- for parent_id in vf.get_parents(version_id):
+ for parent_id in parents[version_id]:
descendants.setdefault(parent_id, []).append(version_id)
cur = [v for v in versions if len(pending_parents(v)) == 0]
while len(cur) > 0:
@@ -508,7 +510,10 @@
self._parents[version_id] = parent_ids
def get_diff(self, version_id):
- return self._diffs[version_id]
+ try:
+ return self._diffs[version_id]
+ except KeyError:
+ raise errors.RevisionNotPresent(version_id, self)
def destroy(self):
self._diffs = {}
=== modified file 'bzrlib/reconcile.py'
--- a/bzrlib/reconcile.py 2007-11-27 23:39:22 +0000
+++ b/bzrlib/reconcile.py 2008-03-19 04:39:04 +0000
@@ -228,15 +228,15 @@
parents.append(parent)
else:
mutter('found ghost %s', parent)
- self._rev_graph[rev_id] = parents
+ self._rev_graph[rev_id] = parents
if self._parents_are_inconsistent(rev_id, parents):
self.inconsistent_parents += 1
mutter('Inconsistent inventory parents: id {%s} '
'inventory claims %r, '
'available parents are %r, '
'unavailable parents are %r',
- rev_id,
- set(self.inventory.get_parents(rev_id)),
+ rev_id,
+ set(self.inventory.get_parent_map([rev_id])[rev_id]),
set(parents),
set(rev.parent_ids).difference(set(parents)))
@@ -248,7 +248,7 @@
differences.
Otherwise only the ghost differences are evaluated.
"""
- weave_parents = self.inventory.get_parents(rev_id)
+ weave_parents = self.inventory.get_parent_map([rev_id])[rev_id]
weave_missing_old_ghosts = set(weave_parents) != set(parents)
first_parent_is_wrong = (
len(weave_parents) and len(parents) and
@@ -333,16 +333,20 @@
# we have topological order of revisions and non ghost parents ready.
self._setup_steps(len(self.revisions))
- for rev_id in TopoSorter(self.revisions.get_graph().items()).iter_topo_order():
- parents = self.revisions.get_parents(rev_id)
- # double check this really is in topological order.
- unavailable = [p for p in parents if p not in new_inventory_vf]
+ graph = self.revisions.get_graph()
+ parent_map = self.revisions.get_parent_map(graph.keys())
+ for rev_id in TopoSorter(graph.items()).iter_topo_order():
+ parents = parent_map[rev_id]
+ # double check this really is in topological order, ignoring existing ghosts.
+ unavailable = [p for p in parents if p not in new_inventory_vf and
+ p in self.revisions]
assert len(unavailable) == 0
# this entry has all the non ghost parents in the inventory
# file already.
self._reweave_step('adding inventories')
# ugly but needed, weaves are just way tooooo slow else.
- new_inventory_vf.add_lines(rev_id, parents, self.inventory.get_lines(rev_id))
+ new_inventory_vf.add_lines_with_ghosts(rev_id, parents,
+ self.inventory.get_lines(rev_id))
# if this worked, the set of new_inventory_vf.names should equal
# self.pending
@@ -412,7 +416,7 @@
elif version in versions_with_bad_parents:
parents = versions_with_bad_parents[version][1]
else:
- parents = vf.get_parents(version)
+ parents = vf.get_parent_map([version])[version]
new_parents[version] = parents
if not len(new_parents):
# No used versions, remove the VF.
=== modified file 'bzrlib/repofmt/knitrepo.py'
--- a/bzrlib/repofmt/knitrepo.py 2008-03-10 15:39:56 +0000
+++ b/bzrlib/repofmt/knitrepo.py 2008-03-19 04:39:04 +0000
@@ -269,13 +269,6 @@
vf = self._revision_store.get_revision_file(self.get_transaction())
return vf
- def _get_history_vf(self):
- """Get a versionedfile whose history graph reflects all revisions.
-
- For knit repositories, this is the revision knit.
- """
- return self._get_revision_vf()
-
def has_revisions(self, revision_ids):
"""See Repository.has_revisions()."""
result = set()
=== modified file 'bzrlib/repofmt/weaverepo.py'
--- a/bzrlib/repofmt/weaverepo.py 2008-02-12 02:38:27 +0000
+++ b/bzrlib/repofmt/weaverepo.py 2008-03-19 04:39:04 +0000
@@ -107,10 +107,11 @@
consistency and is only applicable to inventory-weave-for-ancestry
using repository formats & fetchers.
"""
- weave_parents = inventory.get_parents(revision.revision_id)
- weave_names = inventory.versions()
+ weave_parents = inventory.get_parent_map(
+ [revision.revision_id])[revision.revision_id]
+ parent_map = inventory.get_parent_map(revision.parent_ids)
for parent_id in revision.parent_ids:
- if parent_id in weave_names:
+ if parent_id in parent_map:
# this parent must not be a ghost.
if not parent_id in weave_parents:
# but it is a ghost
@@ -158,8 +159,7 @@
a_weave = self.get_inventory_weave()
all_revisions = self._eliminate_revisions_not_present(
a_weave.versions())
- entire_graph = dict([(node, tuple(a_weave.get_parents(node))) for
- node in all_revisions])
+ entire_graph = a_weave.get_parent_map(all_revisions)
if revision_id is None:
return entire_graph
elif revision_id not in entire_graph:
@@ -247,10 +247,11 @@
consistency and is only applicable to inventory-weave-for-ancestry
using repository formats & fetchers.
"""
- weave_parents = inventory.get_parents(revision.revision_id)
- weave_names = inventory.versions()
+ weave_parents = inventory.get_parent_map(
+ [revision.revision_id])[revision.revision_id]
+ parent_map = inventory.get_parent_map(revision.parent_ids)
for parent_id in revision.parent_ids:
- if parent_id in weave_names:
+ if parent_id in parent_map:
# this parent must not be a ghost.
if not parent_id in weave_parents:
# but it is a ghost
@@ -299,8 +300,7 @@
a_weave = self.get_inventory_weave()
all_revisions = self._eliminate_revisions_not_present(
a_weave.versions())
- entire_graph = dict([(node, tuple(a_weave.get_parents(node))) for
- node in all_revisions])
+ entire_graph = a_weave.get_parent_map(all_revisions)
if revision_id is None:
return entire_graph
elif revision_id not in entire_graph:
=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py 2008-03-14 10:55:37 +0000
+++ b/bzrlib/repository.py 2008-03-19 04:39:04 +0000
@@ -1607,26 +1607,19 @@
done.add(revision_id)
return result
- def _get_history_vf(self):
- """Get a versionedfile whose history graph reflects all revisions.
-
- For weave repositories, this is the inventory weave.
- """
- return self.get_inventory_weave()
-
def iter_reverse_revision_history(self, revision_id):
"""Iterate backwards through revision ids in the lefthand history
:param revision_id: The revision id to start with. All its lefthand
ancestors will be traversed.
"""
- if revision_id in (None, _mod_revision.NULL_REVISION):
- return
+ graph = self.get_graph()
next_id = revision_id
- versionedfile = self._get_history_vf()
while True:
+ if next_id in (None, _mod_revision.NULL_REVISION):
+ return
yield next_id
- parents = versionedfile.get_parents(next_id)
+ parents = graph.get_parent_map([next_id])[next_id]
if len(parents) == 0:
return
else:
@@ -3124,7 +3117,9 @@
"""
wrong_parents = {}
unused_versions = set()
- for num, revision_id in enumerate(weave.versions()):
+ versions = weave.versions()
+ parent_map = weave.get_parent_map(versions)
+ for num, revision_id in enumerate(versions):
try:
correct_parents = self.calculate_file_version_parents(
revision_id, file_id)
@@ -3133,7 +3128,7 @@
unused_versions.add(revision_id)
else:
try:
- knit_parents = tuple(weave.get_parents(revision_id))
+ knit_parents = tuple(parent_map[revision_id])
except errors.RevisionNotPresent:
knit_parents = None
if correct_parents != knit_parents:
=== modified file 'bzrlib/tests/interversionedfile_implementations/test_join.py'
--- a/bzrlib/tests/interversionedfile_implementations/test_join.py 2007-09-21 00:27:04 +0000
+++ b/bzrlib/tests/interversionedfile_implementations/test_join.py 2008-03-19 04:39:04 +0000
@@ -96,8 +96,7 @@
'v-1 v-2 v-3'.split())
self.assertEqualDiff(w1.get_text('v-3'),
'line 1\n')
- self.assertEqual(sorted(w1.get_parents('v-3')),
- ['v-1'])
+ self.assertEqual({'v-3':('v-1',)}, w1.get_parent_map(['v-3']))
ann = list(w1.annotate('v-3'))
self.assertEqual(len(ann), 1)
self.assertEqual(ann[0][0], 'v-1')
@@ -122,11 +121,11 @@
def verify_weave1(self, w1):
self.assertEqual(sorted(w1.versions()), ['v1', 'v2', 'v3'])
self.assertEqual(w1.get_lines('v1'), ['hello\n'])
- self.assertEqual([], w1.get_parents('v1'))
+ self.assertEqual({'v1':()}, w1.get_parent_map(['v1']))
self.assertEqual(w1.get_lines('v2'), ['hello\n', 'world\n'])
- self.assertEqual(['v1'], w1.get_parents('v2'))
+ self.assertEqual({'v2':('v1',)}, w1.get_parent_map(['v2']))
self.assertEqual(w1.get_lines('v3'), ['hello\n', 'cruel\n', 'world\n'])
- self.assertEqual(['v2'], w1.get_parents('v3'))
+ self.assertEqual({'v3':('v2',)}, w1.get_parent_map(['v3']))
def test_join_source_has_less_parents_preserves_parents(self):
# when the target has a text with more parent info, join
@@ -138,7 +137,7 @@
t.add_lines('base', [], [])
t.add_lines('text', ['base'], [])
t.join(s)
- self.assertEqual(['base'], t.get_parents('text'))
+ self.assertEqual({'text':('base',)}, t.get_parent_map(['text']))
def test_join_with_ghosts(self):
"""Join that inserts parents of an existing revision.
@@ -167,7 +166,7 @@
self.assertEqual(['v1', 'v2', 'v3', 'x1',], sorted(w1.versions()))
self.assertEqual('line from x1\n', w1.get_text('x1'))
self.assertEqual(['hello\n', 'world\n'], w1.get_lines('v2'))
- self.assertEqual(['v1'], w1.get_parents('v2'))
+ self.assertEqual({'v2':('v1',)}, w1.get_parent_map(['v2']))
def test_join_with_ignore_missing_versions(self):
# test that ignore_missing=True makes a listed but absent version id
@@ -182,7 +181,7 @@
eq(sorted(w1.versions()), ['v1', 'v2', 'v3', 'x1'])
eq(w1.get_text('x1'), 'line from x1\n')
eq(w1.get_lines('v2'), ['hello\n', 'world\n'])
- eq(w1.get_parents('v2'), ['v1'])
+ self.assertEqual({'v2':('v1',)}, w1.get_parent_map(['v2']))
def build_source_weave(self, name, *pattern):
w = self.get_source(name)
@@ -232,25 +231,32 @@
# try filling target with ghosts and filling in reverse -
target.add_lines_with_ghosts('notbase', ['base'], [])
- source.join(target)
+ try:
+ source.join(target)
+ except errors.RevisionNotPresent:
+ # can't join a ghost containing target onto a non-ghost supporting
+ # source.
+ self.assertFalse(source_ghosts)
+ return
+ else:
+ self.assertTrue(source_ghosts)
# legacy apis should behave
self.assertEqual(['notbase'], source.get_ancestry(['notbase']))
- self.assertEqual([], source.get_parents('notbase'))
self.assertEqual({'notbase':()}, source.get_graph())
self.assertFalse(source.has_version('base'))
- if source_ghosts:
- # ghost data should have been preserved
- self.assertEqual(['base', 'notbase'], source.get_ancestry_with_ghosts(['notbase']))
- self.assertEqual(['base'], source.get_parents_with_ghosts('notbase'))
- self.assertEqual({'notbase':['base']}, source.get_graph_with_ghosts())
- self.assertTrue(source.has_ghost('base'))
+ # ghost data should have been preserved
+ self.assertEqual(['base', 'notbase'], source.get_ancestry_with_ghosts(['notbase']))
+ self.assertEqual(['base'], source.get_parents_with_ghosts('notbase'))
+ self.assertEqual({'notbase':('base',)}, source.get_parent_map(['notbase']))
+ self.assertEqual({'notbase':['base']}, source.get_graph_with_ghosts())
+ self.assertTrue(source.has_ghost('base'))
# if we add something that is fills out what is a ghost, then
# when joining into a ghost aware join it should flesh out the ghosts.
source.add_lines('base', [], [])
target.join(source, version_ids=['base'])
self.assertEqual(['base', 'notbase'], target.get_ancestry(['notbase']))
- self.assertEqual(['base'], target.get_parents('notbase'))
+ self.assertEqual({'notbase':('base',)}, target.get_parent_map(['notbase']))
self.assertEqual({'base':(),
'notbase':('base', ),
},
=== modified file 'bzrlib/tests/repository_implementations/test_check_reconcile.py'
--- a/bzrlib/tests/repository_implementations/test_check_reconcile.py 2007-11-15 02:07:37 +0000
+++ b/bzrlib/tests/repository_implementations/test_check_reconcile.py 2008-03-19 04:39:04 +0000
@@ -114,8 +114,8 @@
"Format does not support text parent reconciliation")
def file_parents(self, repo, revision_id):
- return tuple(repo.weave_store.get_weave('a-file-id',
- repo.get_transaction()).get_parents(revision_id))
+ return repo.weave_store.get_weave('a-file-id',
+ repo.get_transaction()).get_parent_map([revision_id])[revision_id]
def assertFileVersionAbsent(self, repo, revision_id):
self.assertFalse(repo.weave_store.get_weave('a-file-id',
=== modified file 'bzrlib/tests/repository_implementations/test_iter_reverse_revision_history.py'
--- a/bzrlib/tests/repository_implementations/test_iter_reverse_revision_history.py 2007-09-25 08:14:12 +0000
+++ b/bzrlib/tests/repository_implementations/test_iter_reverse_revision_history.py 2008-03-19 04:39:04 +0000
@@ -90,7 +90,8 @@
def test_is_generator(self):
tree = self.create_linear_history()
repo = tree.branch.repository
-
+ repo.lock_read()
+ self.addCleanup(repo.unlock)
rev_history = repo.iter_reverse_revision_history('rev4')
self.assertEqual('rev4', rev_history.next())
self.assertEqual('rev3', rev_history.next())
@@ -100,7 +101,11 @@
def assertRevHistoryList(self, expected, repo, revision_id):
"""Assert the return values of iter_reverse_revision_history."""
- actual = list(repo.iter_reverse_revision_history(revision_id))
+ repo.lock_read()
+ try:
+ actual = list(repo.iter_reverse_revision_history(revision_id))
+ finally:
+ repo.unlock()
self.assertEqual(expected, actual)
def test_linear_history(self):
@@ -119,7 +124,6 @@
def test_revision_ids_are_utf8(self):
tree = self.create_linear_history_with_utf8()
repo = tree.branch.repository
-
self.assertRevHistoryList(['rev-\xc3\xa5', 'rev-\xc2\xb5'],
repo, 'rev-\xc3\xa5')
=== modified file 'bzrlib/tests/test_bundle.py'
--- a/bzrlib/tests/test_bundle.py 2007-12-29 22:42:51 +0000
+++ b/bzrlib/tests/test_bundle.py 2008-03-19 04:39:04 +0000
@@ -1339,7 +1339,8 @@
self.assertEqual('contents2\nstatic\n', vf.get_text('rev2'))
rtree = target_repo.revision_tree('rev2')
inventory_vf = target_repo.get_inventory_weave()
- self.assertEqual(['rev1'], inventory_vf.get_parents('rev2'))
+ self.assertEqual({'rev2':('rev1',)},
+ inventory_vf.get_parent_map(['rev2']))
self.assertEqual('changed file',
target_repo.get_revision('rev2').message)
=== modified file 'bzrlib/tests/test_knit.py'
--- a/bzrlib/tests/test_knit.py 2008-02-26 22:26:00 +0000
+++ b/bzrlib/tests/test_knit.py 2008-03-19 04:39:04 +0000
@@ -1221,8 +1221,8 @@
"""Store in knit with parents"""
k = self.make_test_knit()
self.add_stock_one_and_one_a(k)
- self.assertEquals(k.get_parents('text-1'), [])
- self.assertEquals(k.get_parents('text-1a'), ['text-1'])
+ self.assertEqual({'text-1':(), 'text-1a':('text-1',)},
+ k.get_parent_map(['text-1', 'text-1a']))
def test_ancestry(self):
"""Store in knit with parents"""
@@ -1485,7 +1485,7 @@
# and when reading it revid3 should now appear.
knit = KnitVersionedFile('test', get_transport('.'), access_mode='r')
self.assertEqual(['revid', 'revid2', 'revid3'], knit.versions())
- self.assertEqual(['revid2'], knit.get_parents('revid3'))
+ self.assertEqual({'revid3':('revid2',)}, knit.get_parent_map(['revid3']))
def test_delay_create(self):
"""Test that passing delay_create=True creates files late"""
@@ -2385,14 +2385,6 @@
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip'))
self.assertEqual(['fulltext'], index.get_options('parent'))
- def test_get_parents(self):
- # get_parents ignores ghosts
- index = self.two_graph_index()
- self.assertEqual(('tail', ), index.get_parents('parent'))
- # and errors on ghosts.
- self.assertRaises(errors.RevisionNotPresent,
- index.get_parents, 'ghost')
-
def test_get_parents_with_ghosts(self):
index = self.two_graph_index()
self.assertEqual(('tail', 'ghost'), index.get_parents_with_ghosts('parent'))
@@ -2660,13 +2652,6 @@
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip'))
self.assertEqual(['fulltext'], index.get_options('parent'))
- def test_get_parents(self):
- index = self.two_graph_index()
- self.assertEqual((), index.get_parents('parent'))
- # and errors on ghosts.
- self.assertRaises(errors.RevisionNotPresent,
- index.get_parents, 'ghost')
-
def test_get_parents_with_ghosts(self):
index = self.two_graph_index()
self.assertEqual((), index.get_parents_with_ghosts('parent'))
=== modified file 'bzrlib/tests/test_versionedfile.py'
--- a/bzrlib/tests/test_versionedfile.py 2008-03-18 01:13:35 +0000
+++ b/bzrlib/tests/test_versionedfile.py 2008-03-19 04:39:04 +0000
@@ -39,6 +39,7 @@
KnitAnnotateFactory,
KnitPlainFactory,
)
+from bzrlib.symbol_versioning import one_three
from bzrlib.tests import TestCaseWithMemoryTransport, TestSkipped
from bzrlib.tests.http_utils import TestCaseWithWebserver
from bzrlib.trace import mutter
@@ -240,7 +241,7 @@
new_vf = self.get_file('bar')
for version in multiparent.topo_iter(vf):
mpdiff = vf.make_mpdiffs([version])[0]
- new_vf.add_mpdiffs([(version, vf.get_parents(version),
+ new_vf.add_mpdiffs([(version, vf.get_parent_map([version])[version],
vf.get_sha1(version), mpdiff)])
self.assertEqualDiff(vf.get_text(version),
new_vf.get_text(version))
@@ -370,8 +371,7 @@
def verify_file(f):
self.assertEquals(f.get_lines('r1'), f.get_lines('r0'))
self.assertEquals(f.get_lines('r1'), ['a\n', 'b\n'])
- self.assertEquals(f.get_parents('r1'), ['r0'])
-
+ self.assertEqual({'r1':('r0',)}, f.get_parent_map(['r1']))
self.assertRaises(RevisionNotPresent,
f.clone_text, 'r2', 'rX', [])
self.assertRaises(RevisionAlreadyPresent,
@@ -453,10 +453,10 @@
f.add_lines('r2', [], ['a\n', 'b\n'])
f.add_lines('r3', [], ['a\n', 'b\n'])
f.add_lines('m', ['r0', 'r1', 'r2', 'r3'], ['a\n', 'b\n'])
- self.assertEquals(f.get_parents('m'), ['r0', 'r1', 'r2', 'r3'])
-
+ self.assertEqual(['r0', 'r1', 'r2', 'r3'],
+ self.applyDeprecated(one_three, f.get_parents, 'm'))
self.assertRaises(RevisionNotPresent,
- f.get_parents, 'y')
+ self.applyDeprecated, one_three, f.get_parents, 'y')
def test_get_parent_map(self):
f = self.get_file()
@@ -640,7 +640,8 @@
# has_version
# - these are ghost unaware and must not be reflect ghosts
self.assertEqual(['notbxbfse'], vf.get_ancestry('notbxbfse'))
- self.assertEqual([], vf.get_parents('notbxbfse'))
+ self.assertEqual([],
+ self.applyDeprecated(one_three, vf.get_parents, 'notbxbfse'))
self.assertEqual({'notbxbfse':()}, vf.get_graph())
self.assertFalse(vf.has_version(parent_id_utf8))
# we have _with_ghost apis to give us ghost information.
@@ -652,7 +653,8 @@
# results of the prior apis
vf.add_lines(parent_id_utf8, [], [])
self.assertEqual([parent_id_utf8, 'notbxbfse'], vf.get_ancestry(['notbxbfse']))
- self.assertEqual([parent_id_utf8], vf.get_parents('notbxbfse'))
+ self.assertEqual({'notbxbfse':(parent_id_utf8,)},
+ vf.get_parent_map(['notbxbfse']))
self.assertEqual({parent_id_utf8:(),
'notbxbfse':(parent_id_utf8, ),
},
@@ -865,12 +867,16 @@
def test_get_parents(self):
self.setup_abcde()
- self.assertEqual(['A'], self.plan_merge_vf.get_parents('B'))
- self.assertEqual(['C'], self.plan_merge_vf.get_parents('D'))
- self.assertEqual(['B', 'D'], self.plan_merge_vf.get_parents('E:'))
- error = self.assertRaises(errors.RevisionNotPresent,
- self.plan_merge_vf.get_parents, 'F')
- self.assertContainsRe(str(error), '{F} not present in "root"')
+ self.assertEqual({'B':('A',)}, self.plan_merge_vf.get_parent_map(['B']))
+ self.assertEqual({'D':('C',)}, self.plan_merge_vf.get_parent_map(['D']))
+ self.assertEqual({'E:':('B', 'D')},
+ self.plan_merge_vf.get_parent_map(['E:']))
+ self.assertEqual({}, self.plan_merge_vf.get_parent_map(['F']))
+ self.assertEqual({
+ 'B':('A',),
+ 'D':('C',),
+ 'E:':('B', 'D'),
+ }, self.plan_merge_vf.get_parent_map(['B', 'D', 'E:', 'F']))
def test_get_lines(self):
self.setup_abcde()
=== modified file 'bzrlib/versionedfile.py'
--- a/bzrlib/versionedfile.py 2008-03-18 01:13:35 +0000
+++ b/bzrlib/versionedfile.py 2008-03-19 04:39:04 +0000
@@ -36,6 +36,7 @@
from cStringIO import StringIO
from bzrlib.inter import InterObject
+from bzrlib.symbol_versioning import *
from bzrlib.textmerge import TextMerge
@@ -128,17 +129,17 @@
def add_lines_with_ghosts(self, version_id, parents, lines,
parent_texts=None, nostore_sha=None, random_id=False,
- check_content=True):
+ check_content=True, left_matching_blocks=None):
"""Add lines to the versioned file, allowing ghosts to be present.
This takes the same parameters as add_lines and returns the same.
"""
self._check_write_ok()
return self._add_lines_with_ghosts(version_id, parents, lines,
- parent_texts, nostore_sha, random_id, check_content)
+ parent_texts, nostore_sha, random_id, check_content, left_matching_blocks)
def _add_lines_with_ghosts(self, version_id, parents, lines, parent_texts,
- nostore_sha, random_id, check_content):
+ nostore_sha, random_id, check_content, left_matching_blocks):
"""Helper to do class specific add_lines_with_ghosts."""
raise NotImplementedError(self.add_lines_with_ghosts)
@@ -213,15 +214,25 @@
def make_mpdiffs(self, version_ids):
"""Create multiparent diffs for specified versions."""
knit_versions = set()
+ knit_versions.update(version_ids)
+ parent_map = self.get_parent_map(version_ids)
for version_id in version_ids:
- knit_versions.add(version_id)
- knit_versions.update(self.get_parents(version_id))
+ try:
+ knit_versions.update(parent_map[version_id])
+ except KeyError:
+ raise RevisionNotPresent(version_id, self)
+ # We need to filter out ghosts, because we can't diff against them.
+ knit_versions = set(self.get_parent_map(knit_versions).keys())
lines = dict(zip(knit_versions,
self._get_lf_split_line_list(knit_versions)))
diffs = []
for version_id in version_ids:
target = lines[version_id]
- parents = [lines[p] for p in self.get_parents(version_id)]
+ try:
+ parents = [lines[p] for p in parent_map[version_id] if p in
+ knit_versions]
+ except KeyError:
+ raise RevisionNotPresent(version_id, self)
if len(parents) > 0:
left_parent_blocks = self._extract_blocks(version_id,
parents[0], target)
@@ -251,8 +262,9 @@
for version, parent_ids, expected_sha1, mpdiff in records:
needed_parents.update(p for p in parent_ids
if not mpvf.has_version(p))
- for parent_id, lines in zip(needed_parents,
- self._get_lf_split_line_list(needed_parents)):
+ present_parents = set(self.get_parent_map(needed_parents).keys())
+ for parent_id, lines in zip(present_parents,
+ self._get_lf_split_line_list(present_parents)):
mpvf.add_version(lines, parent_id, [])
for (version, parent_ids, expected_sha1, mpdiff), lines in\
zip(records, mpvf.get_line_list(versions)):
@@ -261,8 +273,16 @@
mpvf.get_diff(parent_ids[0]).num_lines()))
else:
left_matching_blocks = None
- _, _, version_text = self.add_lines(version, parent_ids, lines,
- vf_parents, left_matching_blocks=left_matching_blocks)
+ try:
+ _, _, version_text = self.add_lines_with_ghosts(version,
+ parent_ids, lines, vf_parents,
+ left_matching_blocks=left_matching_blocks)
+ except NotImplementedError:
+ # The vf can't handle ghosts, so add lines normally, which will
+ # (reasonably) fail if there are ghosts in the data.
+ _, _, version_text = self.add_lines(version,
+ parent_ids, lines, vf_parents,
+ left_matching_blocks=left_matching_blocks)
vf_parents[version] = version_text
for (version, parent_ids, expected_sha1, mpdiff), sha1 in\
zip(records, self.get_sha1s(versions)):
@@ -379,6 +399,7 @@
"""
raise NotImplementedError(self.get_parent_map)
+ @deprecated_method(one_three)
def get_parents(self, version_id):
"""Return version names for parents of a version.
@@ -471,11 +492,7 @@
The order is undefined, allowing for different optimisations in
the underlying implementation.
"""
- for version_id in version_ids:
- try:
- yield version_id, tuple(self.get_parents(version_id))
- except errors.RevisionNotPresent:
- pass
+ return self.get_parent_map(version_ids).iteritems()
def transaction_finished(self):
"""The transaction that this file was opened in has finished.
@@ -567,7 +584,7 @@
raise ValueError('Parents may not be None')
if lines is None:
raise ValueError('Lines may not be None')
- self._parents[version_id] = parents
+ self._parents[version_id] = tuple(parents)
self._lines[version_id] = lines
def get_lines(self, version_id):
@@ -610,18 +627,23 @@
ancestry.update(self.get_ancestry(parent, topo_sorted=False))
return ancestry
- def get_parents(self, version_id):
- """See VersionedFile.get_parents"""
- parents = self._parents.get(version_id)
- if parents is not None:
- return parents
+ def get_parent_map(self, version_ids):
+ """See VersionedFile.get_parent_map"""
+ result = {}
+ pending = set(version_ids)
+ for key in version_ids:
+ try:
+ result[key] = self._parents[key]
+ except KeyError:
+ pass
+ pending = pending - set(result.keys())
for versionedfile in self.fallback_versionedfiles:
- try:
- return versionedfile.get_parents(version_id)
- except errors.RevisionNotPresent:
- continue
- else:
- raise errors.RevisionNotPresent(version_id, self._file_id)
+ parents = versionedfile.get_parent_map(pending)
+ result.update(parents)
+ pending = pending - set(parents.keys())
+ if not pending:
+ return result
+ return result
def _get_graph(self):
from bzrlib.graph import (
@@ -772,10 +794,11 @@
# memory pressure reduction. RBC 20060313
# pb.update('Converting versioned data', 0, len(order))
total = len(order)
+ parent_map = self.source.get_parent_map(order)
for index, version in enumerate(order):
pb.update('Converting versioned data', index, total)
_, _, parent_text = target.add_lines(version,
- self.source.get_parents(version),
+ parent_map[version],
self.source.get_lines(version),
parent_texts=parent_texts)
parent_texts[version] = parent_text
=== modified file 'bzrlib/weave.py'
--- a/bzrlib/weave.py 2008-03-18 01:13:35 +0000
+++ b/bzrlib/weave.py 2008-03-19 04:39:04 +0000
@@ -768,8 +768,11 @@
version_ids = set(other.versions()).intersection(set(version_ids))
# pull in the referenced graph.
version_ids = other.get_ancestry(version_ids)
- pending_graph = [(version, other.get_parents(version)) for
- version in version_ids]
+ pending_parents = other.get_parent_map(version_ids)
+ pending_graph = pending_parents.items()
+ if len(pending_graph) != len(version_ids):
+ raise RevisionNotPresent(
+ set(version_ids) - pending_parents.keys(), self)
for name in topo_sort(pending_graph):
other_idx = other._name_map[name]
# returns True if we have it, False if we need it.
@@ -777,7 +780,6 @@
names_to_join.append((other_idx, name))
processed += 1
-
if pb and not msg:
msg = 'weave join'
More information about the bazaar-commits
mailing list