132
144
altered by all revisions it contains, which means that it needs both
133
145
the inventory for any revision it has, and the inventories of all that
134
146
revision's parents.
148
However, we should also skip any revisions which are ghosts in the
136
to_repo = self.make_to_repository('to')
137
if not to_repo._format.supports_external_lookups:
151
if not self.repository_format_to.supports_external_lookups:
138
152
raise TestNotApplicable("Need stacking support in the target.")
139
153
builder = self.make_branch_builder('branch')
140
154
builder.start_series()
141
155
builder.build_snapshot('base', None, [
142
('add', ('', 'root-id', 'directory', ''))])
143
builder.build_snapshot('left', ['base'], [])
144
builder.build_snapshot('right', ['base'], [])
145
builder.build_snapshot('merge', ['left', 'right'], [])
156
('add', ('', 'root-id', 'directory', '')),
157
('add', ('file', 'file-id', 'file', 'content\n'))])
158
builder.build_snapshot('left', ['base'], [
159
('modify', ('file-id', 'left content\n'))])
160
builder.build_snapshot('right', ['base'], [
161
('modify', ('file-id', 'right content\n'))])
162
builder.build_snapshot('merge', ['left', 'right'], [
163
('modify', ('file-id', 'left and right content\n'))])
146
164
builder.finish_series()
147
165
branch = builder.get_branch()
148
166
repo = self.make_to_repository('trunk')
161
179
self.assertEqual(
162
180
set([('left',), ('right',), ('merge',)]),
163
181
unstacked_repo.inventories.keys())
182
# And the basis inventories have been copied correctly
184
self.addCleanup(trunk.unlock)
185
left_tree, right_tree = trunk.repository.revision_trees(
187
stacked_branch.lock_read()
188
self.addCleanup(stacked_branch.unlock)
190
stacked_right_tree) = stacked_branch.repository.revision_trees(
192
self.assertEqual(left_tree.inventory, stacked_left_tree.inventory)
193
self.assertEqual(right_tree.inventory, stacked_right_tree.inventory)
195
# Finally, it's not enough to see that the basis inventories are
196
# present. The texts introduced in merge (and only those) should be
197
# present, and also generating a stream should succeed without blowing
199
self.assertTrue(unstacked_repo.has_revision('merge'))
200
expected_texts = set([('file-id', 'merge')])
201
if stacked_branch.repository.texts.get_parent_map([('root-id',
203
# If a (root-id,merge) text exists, it should be in the stacked
205
expected_texts.add(('root-id', 'merge'))
206
self.assertEqual(expected_texts, unstacked_repo.texts.keys())
207
self.assertCanStreamRevision(unstacked_repo, 'merge')
209
def assertCanStreamRevision(self, repo, revision_id):
210
exclude_keys = set(repo.all_revision_ids()) - set([revision_id])
211
search = SearchResult([revision_id], exclude_keys, 1, [revision_id])
212
source = repo._get_source(repo._format)
213
for substream_kind, substream in source.get_stream(search):
214
# Consume the substream
217
def test_fetch_across_stacking_boundary_ignores_ghost(self):
218
if not self.repository_format_to.supports_external_lookups:
219
raise TestNotApplicable("Need stacking support in the target.")
220
to_repo = self.make_to_repository('to')
221
builder = self.make_branch_builder('branch')
222
builder.start_series()
223
builder.build_snapshot('base', None, [
224
('add', ('', 'root-id', 'directory', '')),
225
('add', ('file', 'file-id', 'file', 'content\n'))])
226
builder.build_snapshot('second', ['base'], [
227
('modify', ('file-id', 'second content\n'))])
228
builder.build_snapshot('third', ['second', 'ghost'], [
229
('modify', ('file-id', 'third content\n'))])
230
builder.finish_series()
231
branch = builder.get_branch()
232
repo = self.make_to_repository('trunk')
233
trunk = repo.bzrdir.create_branch()
234
trunk.repository.fetch(branch.repository, 'second')
235
repo = self.make_to_repository('stacked')
236
stacked_branch = repo.bzrdir.create_branch()
237
stacked_branch.set_stacked_on_url(trunk.base)
238
stacked_branch.repository.fetch(branch.repository, 'third')
239
unstacked_repo = stacked_branch.bzrdir.open_repository()
240
unstacked_repo.lock_read()
241
self.addCleanup(unstacked_repo.unlock)
242
self.assertFalse(unstacked_repo.has_revision('second'))
243
self.assertFalse(unstacked_repo.has_revision('ghost'))
245
set([('second',), ('third',)]),
246
unstacked_repo.inventories.keys())
247
# And the basis inventories have been copied correctly
249
self.addCleanup(trunk.unlock)
250
second_tree = trunk.repository.revision_tree('second')
251
stacked_branch.lock_read()
252
self.addCleanup(stacked_branch.unlock)
253
stacked_second_tree = stacked_branch.repository.revision_tree('second')
254
self.assertEqual(second_tree.inventory, stacked_second_tree.inventory)
255
# Finally, it's not enough to see that the basis inventories are
256
# present. The texts introduced in merge (and only those) should be
257
# present, and also generating a stream should succeed without blowing
259
self.assertTrue(unstacked_repo.has_revision('third'))
260
expected_texts = set([('file-id', 'third')])
261
if stacked_branch.repository.texts.get_parent_map([('root-id',
263
# If a (root-id,third) text exists, it should be in the stacked
265
expected_texts.add(('root-id', 'third'))
266
self.assertEqual(expected_texts, unstacked_repo.texts.keys())
267
self.assertCanStreamRevision(unstacked_repo, 'third')
165
269
def test_fetch_missing_basis_text(self):
166
270
"""If fetching a delta, we should die if a basis is not present."""