Rev 4544: bring in the stack code. in http://bzr.arbash-meinel.com/branches/bzr/lp/1.18-stack-and-annotate-393366
John Arbash Meinel
john at arbash-meinel.com
Fri Jul 24 21:47:20 BST 2009
At http://bzr.arbash-meinel.com/branches/bzr/lp/1.18-stack-and-annotate-393366
------------------------------------------------------------
revno: 4544 [merge]
revision-id: john at arbash-meinel.com-20090724204717-ivzgkj7ofsxmbb9r
parent: john at arbash-meinel.com-20090724204628-eht2xokax2btghaz
parent: john at arbash-meinel.com-20090723000258-qwc6tacl2kw3itqi
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 1.18-stack-and-annotate-393366
timestamp: Fri 2009-07-24 15:47:17 -0500
message:
bring in the stack code.
added:
bzrlib/tests/per_repository/test_merge_directive.py test_send.py-20090717144100-x6fgufcynx6yu5b6-1
modified:
bzrlib/bundle/serializer/v4.py v10.py-20070611062757-5ggj7k18s9dej0fr-1
bzrlib/chk_map.py chk_map.py-20081001014447-ue6kkuhofvdecvxa-1
bzrlib/chk_serializer.py chk_serializer.py-20081002064345-2tofdfj2eqq01h4b-1
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/send.py send.py-20090521192735-j7cdb33ykmtmzx4w-1
bzrlib/tests/per_repository/__init__.py __init__.py-20060131092037-9564957a7d4a841b
bzrlib/tests/test_bundle.py test.py-20050630184834-092aa401ab9f039c
-------------- next part --------------
=== modified file 'bzrlib/bundle/serializer/v4.py'
--- a/bzrlib/bundle/serializer/v4.py 2009-06-10 03:56:49 +0000
+++ b/bzrlib/bundle/serializer/v4.py 2009-07-22 22:02:47 +0000
@@ -147,7 +147,7 @@
body
"""
- def __init__(self, fileobj, stream_input=True):
+ def __init__(self, fileobj, stream_input=False):
"""Constructor
:param fileobj: a file containing a bzip-encoded container
@@ -318,9 +318,66 @@
revision_order = [key[-1] for key in multiparent.topo_iter_keys(inv_vf,
self.revision_keys)]
if self.target is not None and self.target in self.revision_ids:
+ # Make sure the target is always the last entry
revision_order.remove(self.target)
revision_order.append(self.target)
- self._add_mp_records_keys('inventory', inv_vf, [(revid,) for revid in revision_order])
+ if self.repository._serializer.support_altered_by_hack:
+ self._add_mp_records_keys('inventory', inv_vf,
+ [(revid,) for revid in revision_order])
+ else:
+ self._add_inventory_mpdiffs_from_serializer(revision_order)
+ self._add_revision_texts(revision_order)
+
+ def _add_inventory_mpdiffs_from_serializer(self, revision_order):
+ inventory_key_order = [(r,) for r in revision_order]
+ parent_map = self.repository.inventories.get_parent_map(
+ inventory_key_order)
+ missing_keys = set(inventory_key_order).difference(parent_map)
+ if missing_keys:
+ raise errors.RevisionNotPresent(list(missing_keys)[0],
+ self.repository.inventories)
+ inv_to_str = self.repository._serializer.write_inventory_to_string
+ # Make sure that we grab the parent texts first
+ just_parents = set()
+ map(just_parents.update, parent_map.itervalues())
+ just_parents.difference_update(parent_map)
+ # Ignore ghost parents
+ if _mod_revision.NULL_REVISION in just_parents:
+ import pdb; pdb.set_trace()
+ present_parents = self.repository.inventories.get_parent_map(
+ just_parents)
+ ghost_keys = just_parents.difference(present_parents)
+ needed_inventories = list(present_parents) + inventory_key_order
+ needed_inventories = [k[-1] for k in needed_inventories]
+ all_lines = {}
+ for inv in self.repository.iter_inventories(needed_inventories):
+ revision_id = inv.revision_id
+ key = (revision_id,)
+ as_bytes = inv_to_str(inv)
+ # The sha1 is validated as the xml/textual form, not as the
+ # form-in-the-repository
+ sha1 = osutils.sha_string(as_bytes)
+ as_lines = osutils.split_lines(as_bytes)
+ del as_bytes
+ all_lines[key] = as_lines
+ if key in just_parents:
+ # We don't transmit those entries
+ continue
+ # Create an mpdiff for this text, and add it to the output
+ parent_keys = parent_map[key]
+ # See the comment in VF.make_mpdiffs about how this effects
+ # ordering when there are ghosts present. I think we have a latent
+ # bug
+ parent_lines = [all_lines[p_key] for p_key in parent_keys
+ if p_key not in ghost_keys]
+ diff = multiparent.MultiParent.from_lines(
+ as_lines, parent_lines)
+ text = ''.join(diff.to_patch())
+ parent_ids = [k[-1] for k in parent_keys]
+ self.bundle.add_multiparent_record(text, sha1, parent_ids,
+ 'inventory', revision_id, None)
+
+ def _add_revision_texts(self, revision_order):
parent_map = self.repository.get_parent_map(revision_order)
revision_to_str = self.repository._serializer.write_revision_to_string
revisions = self.repository.get_revisions(revision_order)
@@ -544,16 +601,30 @@
versionedfile.add_mpdiffs(vf_records)
def _install_inventory_records(self, records):
- if self._info['serializer'] == self._repository._serializer.format_num:
+ if (self._info['serializer'] == self._repository._serializer.format_num
+ and self._repository._serializer.support_altered_by_hack):
return self._install_mp_records_keys(self._repository.inventories,
records)
for key, metadata, bytes in records:
revision_id = key[-1]
parent_ids = metadata['parents']
- parents = [self._repository.get_inventory(p)
- for p in parent_ids]
+ # Note that this assumes the local ghosts are identical to the
+ # ghosts in the source. But the Bundle serialization format doesn't
+ # record any info that would help us figure that stuff out.
+ # We start by going directly to the inventory vf, because the
+ # revisions have not been installed yet, so repo.get_parent_map
+ # would think that more things are ghosts than really are.
+ parent_keys = [(r,) for r in parent_ids]
+ present_parent_map = self._repository.inventories.get_parent_map(
+ parent_keys)
+ present_parent_ids = [p_id for p_id in parent_ids
+ if (p_id,) in present_parent_map]
+ # TODO: This doesn't do any sort of caching, etc, so expect it to
+ # perform rather poorly.
+ parent_invs = list(self._repository.iter_inventories(
+ present_parent_ids))
p_texts = [self._source_serializer.write_inventory_to_string(p)
- for p in parents]
+ for p in parent_invs]
target_lines = multiparent.MultiParent.from_patch(bytes).to_lines(
p_texts)
sha1 = osutils.sha_strings(target_lines)
=== modified file 'bzrlib/chk_map.py'
--- a/bzrlib/chk_map.py 2009-07-16 23:28:49 +0000
+++ b/bzrlib/chk_map.py 2009-07-24 20:47:17 +0000
@@ -60,6 +60,9 @@
# We are caching bytes so len(value) is perfectly accurate
_page_cache = lru_cache.LRUSizeCache(_PAGE_CACHE_SIZE)
+def clear_cache():
+ _page_cache.clear()
+
# If a ChildNode falls below this many bytes, we check for a remap
_INTERESTING_NEW_SIZE = 50
# If a ChildNode shrinks by more than this amount, we check for a remap
=== modified file 'bzrlib/chk_serializer.py'
--- a/bzrlib/chk_serializer.py 2009-07-01 10:46:27 +0000
+++ b/bzrlib/chk_serializer.py 2009-07-22 20:22:21 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2008 Canonical Ltd
+# Copyright (C) 2008, 2009 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,8 +21,8 @@
cache_utf8,
inventory,
revision as _mod_revision,
- xml5,
xml6,
+ xml7,
)
@@ -131,7 +131,7 @@
return self.read_revision_from_string(f.read())
-class CHKSerializerSubtree(BEncodeRevisionSerializer1, xml6.Serializer_v6):
+class CHKSerializerSubtree(BEncodeRevisionSerializer1, xml7.Serializer_v7):
"""A CHKInventory based serializer that supports tree references"""
supported_kinds = set(['file', 'directory', 'symlink', 'tree-reference'])
@@ -152,14 +152,14 @@
return inventory.TreeReference(file_id, name, parent_id, revision,
reference_revision)
else:
- return xml6.Serializer_v6._unpack_entry(self, elt)
+ return xml7.Serializer_v7._unpack_entry(self, elt)
def __init__(self, node_size, search_key_name):
self.maximum_size = node_size
self.search_key_name = search_key_name
-class CHKSerializer(xml5.Serializer_v5):
+class CHKSerializer(xml6.Serializer_v6):
"""A CHKInventory based serializer with 'plain' behaviour."""
format_num = '9'
=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py 2009-07-20 10:14:42 +0000
+++ b/bzrlib/repository.py 2009-07-24 20:47:17 +0000
@@ -2212,6 +2212,7 @@
"""
if ((None in revision_ids)
or (_mod_revision.NULL_REVISION in revision_ids)):
+ import pdb; pdb.set_trace()
raise ValueError('cannot get null revision inventory')
return self._iter_inventories(revision_ids)
=== modified file 'bzrlib/send.py'
--- a/bzrlib/send.py 2009-07-15 07:32:26 +0000
+++ b/bzrlib/send.py 2009-07-17 14:41:02 +0000
@@ -77,6 +77,9 @@
submit_branch)
if mail_to is None or format is None:
+ # TODO: jam 20090716 we open the submit_branch here, but we *don't*
+ # pass it down into the format creation, so it will have to
+ # open it again
submit_br = Branch.open(submit_branch)
submit_config = submit_br.get_config()
if mail_to is None:
@@ -126,7 +129,6 @@
if revision_id == NULL_REVISION:
raise errors.BzrCommandError('No revisions to submit.')
if format is None:
- # TODO: Query submit branch for its preferred format
format = format_registry.get()
directive = format(branch, revision_id, submit_branch,
public_branch, no_patch, no_bundle, message, base_revision_id)
=== modified file 'bzrlib/tests/per_repository/__init__.py'
--- a/bzrlib/tests/per_repository/__init__.py 2009-07-10 06:45:04 +0000
+++ b/bzrlib/tests/per_repository/__init__.py 2009-07-22 17:22:06 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2008 Canonical Ltd
+# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
# Authors: Robert Collins <robert.collins at canonical.com>
# and others
#
@@ -867,6 +867,7 @@
'test_has_revisions',
'test_is_write_locked',
'test_iter_reverse_revision_history',
+ 'test_merge_directive',
'test_pack',
'test_reconcile',
'test_refresh_data',
=== added file 'bzrlib/tests/per_repository/test_merge_directive.py'
--- a/bzrlib/tests/per_repository/test_merge_directive.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/per_repository/test_merge_directive.py 2009-07-22 17:22:06 +0000
@@ -0,0 +1,73 @@
+# Copyright (C) 2009 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+"""Tests for how merge directives interact with various repository formats.
+
+Bundles contain the serialized form, so changes in serialization based on
+repository effects the final bundle.
+"""
+
+from bzrlib import (
+ chk_map,
+ errors,
+ merge_directive,
+ tests,
+ )
+
+from bzrlib.tests.per_repository import TestCaseWithRepository
+
+
+class TestMergeDirective(TestCaseWithRepository):
+
+ def make_two_branches(self):
+ builder = self.make_branch_builder('source')
+ builder.start_series()
+ builder.build_snapshot('A', None, [
+ ('add', ('', 'root-id', 'directory', None)),
+ ('add', ('f', 'f-id', 'file', 'initial content\n')),
+ ])
+ builder.build_snapshot('B', 'A', [
+ ('modify', ('f-id', 'new content\n')),
+ ])
+ builder.finish_series()
+ b1 = builder.get_branch()
+ b2 = b1.bzrdir.sprout('target', revision_id='A').open_branch()
+ return b1, b2
+
+ def create_merge_directive(self, source_branch, submit_url):
+ return merge_directive.MergeDirective2.from_objects(
+ source_branch.repository,
+ source_branch.last_revision(),
+ time=1247775710, timezone=0,
+ target_branch=submit_url)
+
+ def test_create_merge_directive(self):
+ source_branch, target_branch = self.make_two_branches()
+ directive = self.create_merge_directive(source_branch,
+ target_branch.base)
+ self.assertIsInstance(directive, merge_directive.MergeDirective2)
+
+
+ def test_create_and_install_directive(self):
+ source_branch, target_branch = self.make_two_branches()
+ directive = self.create_merge_directive(source_branch,
+ target_branch.base)
+ chk_map.clear_cache()
+ directive.install_revisions(target_branch.repository)
+ rt = target_branch.repository.revision_tree('B')
+ rt.lock_read()
+ self.assertEqualDiff('new content\n', rt.get_file_text('f-id'))
+ rt.unlock()
=== modified file 'bzrlib/tests/test_bundle.py'
--- a/bzrlib/tests/test_bundle.py 2009-07-20 04:26:55 +0000
+++ b/bzrlib/tests/test_bundle.py 2009-07-24 20:47:17 +0000
@@ -50,6 +50,22 @@
from bzrlib.transform import TreeTransform
+def get_text(vf, key):
+ """Get the fulltext for a given revision id that is present in the vf"""
+ stream = vf.get_record_stream([key], 'unordered', True)
+ record = stream.next()
+ return record.get_bytes_as('fulltext')
+
+
+def get_inventory_text(repo, revision_id):
+ """Get the fulltext for the inventory at revision id"""
+ repo.lock_read()
+ try:
+ return get_text(repo.inventories, (revision_id,))
+ finally:
+ repo.unlock()
+
+
class MockTree(object):
def __init__(self):
from bzrlib.inventory import InventoryDirectory, ROOT_ID
@@ -558,8 +574,9 @@
self.tree1 = self.make_branch_and_tree('b1')
self.b1 = self.tree1.branch
- open('b1/one', 'wb').write('one\n')
- self.tree1.add('one')
+ self.build_tree_contents([('b1/one', 'one\n')])
+ self.tree1.add('one', 'one-id')
+ self.tree1.set_root_id('root-id')
self.tree1.commit('add one', rev_id='a at cset-0-1')
bundle = self.get_valid_bundle('null:', 'a at cset-0-1')
@@ -576,8 +593,8 @@
, 'b1/sub/sub/'
, 'b1/sub/sub/nonempty.txt'
])
- open('b1/sub/sub/emptyfile.txt', 'wb').close()
- open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
+ self.build_tree_contents([('b1/sub/sub/emptyfile.txt', ''),
+ ('b1/dir/nolastnewline.txt', 'bloop')])
tt = TreeTransform(self.tree1)
tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
tt.apply()
@@ -616,7 +633,8 @@
bundle = self.get_valid_bundle('a at cset-0-2', 'a at cset-0-3')
self.assertRaises((errors.TestamentMismatch,
- errors.VersionedFileInvalidChecksum), self.get_invalid_bundle,
+ errors.VersionedFileInvalidChecksum,
+ errors.BadBundle), self.get_invalid_bundle,
'a at cset-0-2', 'a at cset-0-3')
# Check a rollup bundle
bundle = self.get_valid_bundle('null:', 'a at cset-0-3')
@@ -646,9 +664,10 @@
verbose=False)
bundle = self.get_valid_bundle('a at cset-0-5', 'a at cset-0-6')
other = self.get_checkout('a at cset-0-5')
- tree1_inv = self.tree1.branch.repository.get_inventory_xml(
- 'a at cset-0-5')
- tree2_inv = other.branch.repository.get_inventory_xml('a at cset-0-5')
+ tree1_inv = get_inventory_text(self.tree1.branch.repository,
+ 'a at cset-0-5')
+ tree2_inv = get_inventory_text(other.branch.repository,
+ 'a at cset-0-5')
self.assertEqualDiff(tree1_inv, tree2_inv)
other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
other.commit('rename file', rev_id='a at cset-0-6b')
@@ -1317,7 +1336,7 @@
new_text = self.get_raw(StringIO(''.join(bundle_txt)))
new_text = new_text.replace('<file file_id="exe-1"',
'<file executable="y" file_id="exe-1"')
- new_text = new_text.replace('B222', 'B237')
+ new_text = new_text.replace('B260', 'B275')
bundle_txt = StringIO()
bundle_txt.write(serializer._get_bundle_header('4'))
bundle_txt.write('\n')
@@ -1429,6 +1448,200 @@
return 'metaweave'
+class V4_2aBundleTester(V4BundleTester):
+
+ def bzrdir_format(self):
+ return '2a'
+
+ def get_invalid_bundle(self, base_rev_id, rev_id):
+ """Create a bundle from base_rev_id -> rev_id in built-in branch.
+ Munge the text so that it's invalid.
+
+ :return: The in-memory bundle
+ """
+ from bzrlib.bundle import serializer
+ bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
+ new_text = self.get_raw(StringIO(''.join(bundle_txt)))
+ # We are going to be replacing some text to set the executable bit on a
+ # file. Make sure the text replacement actually works correctly.
+ self.assertContainsRe(new_text, '(?m)B244\n\ni 1\n<inventory')
+ new_text = new_text.replace('<file file_id="exe-1"',
+ '<file executable="y" file_id="exe-1"')
+ new_text = new_text.replace('B244', 'B259')
+ bundle_txt = StringIO()
+ bundle_txt.write(serializer._get_bundle_header('4'))
+ bundle_txt.write('\n')
+ bundle_txt.write(new_text.encode('bz2'))
+ bundle_txt.seek(0)
+ bundle = read_bundle(bundle_txt)
+ self.valid_apply_bundle(base_rev_id, bundle)
+ return bundle
+
+ def make_merged_branch(self):
+ builder = self.make_branch_builder('source')
+ builder.start_series()
+ builder.build_snapshot('a at cset-0-1', None, [
+ ('add', ('', 'root-id', 'directory', None)),
+ ('add', ('file', 'file-id', 'file', 'original content\n')),
+ ])
+ builder.build_snapshot('a at cset-0-2a', ['a at cset-0-1'], [
+ ('modify', ('file-id', 'new-content\n')),
+ ])
+ builder.build_snapshot('a at cset-0-2b', ['a at cset-0-1'], [
+ ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
+ ])
+ builder.build_snapshot('a at cset-0-3', ['a at cset-0-2a', 'a at cset-0-2b'], [
+ ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
+ ])
+ builder.finish_series()
+ self.b1 = builder.get_branch()
+ self.b1.lock_read()
+ self.addCleanup(self.b1.unlock)
+
+ def make_bundle_just_inventories(self, base_revision_id,
+ target_revision_id,
+ revision_ids):
+ sio = StringIO()
+ writer = v4.BundleWriteOperation(base_revision_id, target_revision_id,
+ self.b1.repository, sio)
+ writer.bundle.begin()
+ writer._add_inventory_mpdiffs_from_serializer(revision_ids)
+ writer.bundle.end()
+ sio.seek(0)
+ return sio
+
+ def test_single_inventory_multiple_parents_as_xml(self):
+ self.make_merged_branch()
+ sio = self.make_bundle_just_inventories('a at cset-0-1', 'a at cset-0-3',
+ ['a at cset-0-3'])
+ reader = v4.BundleReader(sio, stream_input=False)
+ records = list(reader.iter_records())
+ self.assertEqual(1, len(records))
+ (bytes, metadata, repo_kind, revision_id,
+ file_id) = records[0]
+ self.assertIs(None, file_id)
+ self.assertEqual('a at cset-0-3', revision_id)
+ self.assertEqual('inventory', repo_kind)
+ self.assertEqual({'parents': ['a at cset-0-2a', 'a at cset-0-2b'],
+ 'sha1': '09c53b0c4de0895e11a2aacc34fef60a6e70865c',
+ 'storage_kind': 'mpdiff',
+ }, metadata)
+ # We should have an mpdiff that takes some lines from both parents.
+ self.assertEqualDiff(
+ 'i 1\n'
+ '<inventory format="10" revision_id="a at cset-0-3">\n'
+ '\n'
+ 'c 0 1 1 2\n'
+ 'c 1 3 3 2\n', bytes)
+
+ def test_single_inv_no_parents_as_xml(self):
+ self.make_merged_branch()
+ sio = self.make_bundle_just_inventories('null:', 'a at cset-0-1',
+ ['a at cset-0-1'])
+ reader = v4.BundleReader(sio, stream_input=False)
+ records = list(reader.iter_records())
+ self.assertEqual(1, len(records))
+ (bytes, metadata, repo_kind, revision_id,
+ file_id) = records[0]
+ self.assertIs(None, file_id)
+ self.assertEqual('a at cset-0-1', revision_id)
+ self.assertEqual('inventory', repo_kind)
+ self.assertEqual({'parents': [],
+ 'sha1': 'a13f42b142d544aac9b085c42595d304150e31a2',
+ 'storage_kind': 'mpdiff',
+ }, metadata)
+ # We should have an mpdiff that takes some lines from both parents.
+ self.assertEqualDiff(
+ 'i 4\n'
+ '<inventory format="10" revision_id="a at cset-0-1">\n'
+ '<directory file_id="root-id" name=""'
+ ' revision="a at cset-0-1" />\n'
+ '<file file_id="file-id" name="file" parent_id="root-id"'
+ ' revision="a at cset-0-1"'
+ ' text_sha1="09c2f8647e14e49e922b955c194102070597c2d1"'
+ ' text_size="17" />\n'
+ '</inventory>\n'
+ '\n', bytes)
+
+ def test_multiple_inventories_as_xml(self):
+ self.make_merged_branch()
+ sio = self.make_bundle_just_inventories('a at cset-0-1', 'a at cset-0-3',
+ ['a at cset-0-2a', 'a at cset-0-2b', 'a at cset-0-3'])
+ reader = v4.BundleReader(sio, stream_input=False)
+ records = list(reader.iter_records())
+ self.assertEqual(3, len(records))
+ revision_ids = [rev_id for b, m, k, rev_id, f in records]
+ self.assertEqual(['a at cset-0-2a', 'a at cset-0-2b', 'a at cset-0-3'],
+ revision_ids)
+ metadata_2a = records[0][1]
+ self.assertEqual({'parents': ['a at cset-0-1'],
+ 'sha1': '1e105886d62d510763e22885eec733b66f5f09bf',
+ 'storage_kind': 'mpdiff',
+ }, metadata_2a)
+ metadata_2b = records[1][1]
+ self.assertEqual({'parents': ['a at cset-0-1'],
+ 'sha1': 'f03f12574bdb5ed2204c28636c98a8547544ccd8',
+ 'storage_kind': 'mpdiff',
+ }, metadata_2b)
+ metadata_3 = records[2][1]
+ self.assertEqual({'parents': ['a at cset-0-2a', 'a at cset-0-2b'],
+ 'sha1': '09c53b0c4de0895e11a2aacc34fef60a6e70865c',
+ 'storage_kind': 'mpdiff',
+ }, metadata_3)
+ bytes_2a = records[0][0]
+ self.assertEqualDiff(
+ 'i 1\n'
+ '<inventory format="10" revision_id="a at cset-0-2a">\n'
+ '\n'
+ 'c 0 1 1 1\n'
+ 'i 1\n'
+ '<file file_id="file-id" name="file" parent_id="root-id"'
+ ' revision="a at cset-0-2a"'
+ ' text_sha1="50f545ff40e57b6924b1f3174b267ffc4576e9a9"'
+ ' text_size="12" />\n'
+ '\n'
+ 'c 0 3 3 1\n', bytes_2a)
+ bytes_2b = records[1][0]
+ self.assertEqualDiff(
+ 'i 1\n'
+ '<inventory format="10" revision_id="a at cset-0-2b">\n'
+ '\n'
+ 'c 0 1 1 2\n'
+ 'i 1\n'
+ '<file file_id="file2-id" name="other-file" parent_id="root-id"'
+ ' revision="a at cset-0-2b"'
+ ' text_sha1="b46c0c8ea1e5ef8e46fc8894bfd4752a88ec939e"'
+ ' text_size="14" />\n'
+ '\n'
+ 'c 0 3 4 1\n', bytes_2b)
+ bytes_3 = records[2][0]
+ self.assertEqualDiff(
+ 'i 1\n'
+ '<inventory format="10" revision_id="a at cset-0-3">\n'
+ '\n'
+ 'c 0 1 1 2\n'
+ 'c 1 3 3 2\n', bytes_3)
+
+ def test_creating_bundle_preserves_chk_pages(self):
+ self.make_merged_branch()
+ target = self.b1.bzrdir.sprout('target',
+ revision_id='a at cset-0-2a').open_branch()
+ bundle_txt, rev_ids = self.create_bundle_text('a at cset-0-2a',
+ 'a at cset-0-3')
+ self.assertEqual(['a at cset-0-2b', 'a at cset-0-3'], rev_ids)
+ bundle = read_bundle(bundle_txt)
+ target.lock_write()
+ self.addCleanup(target.unlock)
+ install_bundle(target.repository, bundle)
+ inv1 = self.b1.repository.inventories.get_record_stream([
+ ('a at cset-0-3',)], 'unordered',
+ True).next().get_bytes_as('fulltext')
+ inv2 = target.repository.inventories.get_record_stream([
+ ('a at cset-0-3',)], 'unordered',
+ True).next().get_bytes_as('fulltext')
+ self.assertEqualDiff(inv1, inv2)
+
+
class MungedBundleTester(object):
def build_test_bundle(self):
More information about the bazaar-commits
mailing list