157
137
except NotImplementedError:
160
def test_add_reserved(self):
162
self.assertRaises(errors.ReservedId,
163
vf.add_lines, 'a:', [], ['a\n', 'b\n', 'c\n'])
165
def test_add_lines_nostoresha(self):
166
"""When nostore_sha is supplied using old content raises."""
168
empty_text = ('a', [])
169
sample_text_nl = ('b', ["foo\n", "bar\n"])
170
sample_text_no_nl = ('c', ["foo\n", "bar"])
172
for version, lines in (empty_text, sample_text_nl, sample_text_no_nl):
173
sha, _, _ = vf.add_lines(version, [], lines)
175
# we now have a copy of all the lines in the vf.
176
for sha, (version, lines) in zip(
177
shas, (empty_text, sample_text_nl, sample_text_no_nl)):
178
self.assertRaises(errors.ExistingContent,
179
vf.add_lines, version + "2", [], lines,
181
# and no new version should have been added.
182
self.assertRaises(errors.RevisionNotPresent, vf.get_lines,
185
def test_add_lines_with_ghosts_nostoresha(self):
186
"""When nostore_sha is supplied using old content raises."""
188
empty_text = ('a', [])
189
sample_text_nl = ('b', ["foo\n", "bar\n"])
190
sample_text_no_nl = ('c', ["foo\n", "bar"])
192
for version, lines in (empty_text, sample_text_nl, sample_text_no_nl):
193
sha, _, _ = vf.add_lines(version, [], lines)
195
# we now have a copy of all the lines in the vf.
196
# is the test applicable to this vf implementation?
198
vf.add_lines_with_ghosts('d', [], [])
199
except NotImplementedError:
200
raise TestSkipped("add_lines_with_ghosts is optional")
201
for sha, (version, lines) in zip(
202
shas, (empty_text, sample_text_nl, sample_text_no_nl)):
203
self.assertRaises(errors.ExistingContent,
204
vf.add_lines_with_ghosts, version + "2", [], lines,
206
# and no new version should have been added.
207
self.assertRaises(errors.RevisionNotPresent, vf.get_lines,
210
def test_add_lines_return_value(self):
211
# add_lines should return the sha1 and the text size.
213
empty_text = ('a', [])
214
sample_text_nl = ('b', ["foo\n", "bar\n"])
215
sample_text_no_nl = ('c', ["foo\n", "bar"])
216
# check results for the three cases:
217
for version, lines in (empty_text, sample_text_nl, sample_text_no_nl):
218
# the first two elements are the same for all versioned files:
219
# - the digest and the size of the text. For some versioned files
220
# additional data is returned in additional tuple elements.
221
result = vf.add_lines(version, [], lines)
222
self.assertEqual(3, len(result))
223
self.assertEqual((osutils.sha_strings(lines), sum(map(len, lines))),
225
# parents should not affect the result:
226
lines = sample_text_nl[1]
227
self.assertEqual((osutils.sha_strings(lines), sum(map(len, lines))),
228
vf.add_lines('d', ['b', 'c'], lines)[0:2])
230
def test_get_reserved(self):
232
self.assertRaises(errors.ReservedId, vf.get_texts, ['b:'])
233
self.assertRaises(errors.ReservedId, vf.get_lines, 'b:')
234
self.assertRaises(errors.ReservedId, vf.get_text, 'b:')
236
def test_make_mpdiffs(self):
237
from bzrlib import multiparent
238
vf = self.get_file('foo')
239
sha1s = self._setup_for_deltas(vf)
240
new_vf = self.get_file('bar')
241
for version in multiparent.topo_iter(vf):
242
mpdiff = vf.make_mpdiffs([version])[0]
243
new_vf.add_mpdiffs([(version, vf.get_parents(version),
244
vf.get_sha1(version), mpdiff)])
245
self.assertEqualDiff(vf.get_text(version),
246
new_vf.get_text(version))
140
def test_get_delta(self):
142
sha1s = self._setup_for_deltas(f)
143
expected_delta = (None, '6bfa09d82ce3e898ad4641ae13dd4fdb9cf0d76b', False,
144
[(0, 0, 1, [('base', 'line\n')])])
145
self.assertEqual(expected_delta, f.get_delta('base'))
147
text_name = 'chain1-'
148
for depth in range(26):
149
new_version = text_name + '%s' % depth
150
expected_delta = (next_parent, sha1s[depth],
152
[(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
153
self.assertEqual(expected_delta, f.get_delta(new_version))
154
next_parent = new_version
156
text_name = 'chain2-'
157
for depth in range(26):
158
new_version = text_name + '%s' % depth
159
expected_delta = (next_parent, sha1s[depth], False,
160
[(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
161
self.assertEqual(expected_delta, f.get_delta(new_version))
162
next_parent = new_version
163
# smoke test for eol support
164
expected_delta = ('base', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True, [])
165
self.assertEqual(['line'], f.get_lines('noeol'))
166
self.assertEqual(expected_delta, f.get_delta('noeol'))
168
def test_get_deltas(self):
170
sha1s = self._setup_for_deltas(f)
171
deltas = f.get_deltas(f.versions())
172
expected_delta = (None, '6bfa09d82ce3e898ad4641ae13dd4fdb9cf0d76b', False,
173
[(0, 0, 1, [('base', 'line\n')])])
174
self.assertEqual(expected_delta, deltas['base'])
176
text_name = 'chain1-'
177
for depth in range(26):
178
new_version = text_name + '%s' % depth
179
expected_delta = (next_parent, sha1s[depth],
181
[(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
182
self.assertEqual(expected_delta, deltas[new_version])
183
next_parent = new_version
185
text_name = 'chain2-'
186
for depth in range(26):
187
new_version = text_name + '%s' % depth
188
expected_delta = (next_parent, sha1s[depth], False,
189
[(depth + 1, depth + 1, 1, [(new_version, 'line\n')])])
190
self.assertEqual(expected_delta, deltas[new_version])
191
next_parent = new_version
192
# smoke tests for eol support
193
expected_delta = ('base', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True, [])
194
self.assertEqual(['line'], f.get_lines('noeol'))
195
self.assertEqual(expected_delta, deltas['noeol'])
196
# smoke tests for eol support - two noeol in a row same content
197
expected_deltas = (('noeol', '3ad7ee82dbd8f29ecba073f96e43e414b3f70a4d', True,
198
[(0, 1, 2, [(u'noeolsecond', 'line\n'), (u'noeolsecond', 'line\n')])]),
199
('noeol', '3ad7ee82dbd8f29ecba073f96e43e414b3f70a4d', True,
200
[(0, 0, 1, [('noeolsecond', 'line\n')]), (1, 1, 0, [])]))
201
self.assertEqual(['line\n', 'line'], f.get_lines('noeolsecond'))
202
self.assertTrue(deltas['noeolsecond'] in expected_deltas)
203
# two no-eol in a row, different content
204
expected_delta = ('noeolsecond', '8bb553a84e019ef1149db082d65f3133b195223b', True,
205
[(1, 2, 1, [(u'noeolnotshared', 'phone\n')])])
206
self.assertEqual(['line\n', 'phone'], f.get_lines('noeolnotshared'))
207
self.assertEqual(expected_delta, deltas['noeolnotshared'])
208
# eol folling a no-eol with content change
209
expected_delta = ('noeol', 'a61f6fb6cfc4596e8d88c34a308d1e724caf8977', False,
210
[(0, 1, 1, [(u'eol', 'phone\n')])])
211
self.assertEqual(['phone\n'], f.get_lines('eol'))
212
self.assertEqual(expected_delta, deltas['eol'])
213
# eol folling a no-eol with content change
214
expected_delta = ('noeol', '6bfa09d82ce3e898ad4641ae13dd4fdb9cf0d76b', False,
215
[(0, 1, 1, [(u'eolline', 'line\n')])])
216
self.assertEqual(['line\n'], f.get_lines('eolline'))
217
self.assertEqual(expected_delta, deltas['eolline'])
218
# eol with no parents
219
expected_delta = (None, '264f39cab871e4cfd65b3a002f7255888bb5ed97', True,
220
[(0, 0, 1, [(u'noeolbase', 'line\n')])])
221
self.assertEqual(['line'], f.get_lines('noeolbase'))
222
self.assertEqual(expected_delta, deltas['noeolbase'])
223
# eol with two parents, in inverse insertion order
224
expected_deltas = (('noeolbase', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True,
225
[(0, 1, 1, [(u'eolbeforefirstparent', 'line\n')])]),
226
('noeolbase', '264f39cab871e4cfd65b3a002f7255888bb5ed97', True,
227
[(0, 1, 1, [(u'eolbeforefirstparent', 'line\n')])]))
228
self.assertEqual(['line'], f.get_lines('eolbeforefirstparent'))
229
#self.assertTrue(deltas['eolbeforefirstparent'] in expected_deltas)
248
231
def _setup_for_deltas(self, f):
249
self.assertFalse(f.has_version('base'))
232
self.assertRaises(errors.RevisionNotPresent, f.get_delta, 'base')
250
233
# add texts that should trip the knit maximum delta chain threshold
251
234
# as well as doing parallel chains of data in knits.
252
235
# this is done by two chains of 25 insertions
498
538
"""Open the versioned file from disk again."""
499
539
raise NotImplementedError(self.reopen_file)
501
def test_iter_parents(self):
502
"""iter_parents returns the parents for many nodes."""
506
f.add_lines('r0', [], ['a\n', 'b\n'])
508
f.add_lines('r1', ['r0'], ['a\n', 'b\n'])
510
f.add_lines('r2', ['r1', 'r0'], ['a\n', 'b\n'])
512
# cases: each sample data individually:
513
self.assertEqual(set([('r0', ())]),
514
set(f.iter_parents(['r0'])))
515
self.assertEqual(set([('r1', ('r0', ))]),
516
set(f.iter_parents(['r1'])))
517
self.assertEqual(set([('r2', ('r1', 'r0'))]),
518
set(f.iter_parents(['r2'])))
519
# no nodes returned for a missing node
520
self.assertEqual(set(),
521
set(f.iter_parents(['missing'])))
522
# 1 node returned with missing nodes skipped
523
self.assertEqual(set([('r1', ('r0', ))]),
524
set(f.iter_parents(['ghost1', 'r1', 'ghost'])))
526
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
527
set(f.iter_parents(['r0', 'r1'])))
528
# 2 nodes returned, missing skipped
529
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
530
set(f.iter_parents(['a', 'r0', 'b', 'r1', 'c'])))
532
541
def test_iter_lines_added_or_present_in_versions(self):
533
542
# test that we get at least an equalset of the lines added by
534
543
# versions in the weave
535
544
# the ordering here is to make a tree so that dumb searches have
536
545
# more changes to muck up.
538
class InstrumentedProgress(progress.DummyProgress):
542
progress.DummyProgress.__init__(self)
545
def update(self, msg=None, current=None, total=None):
546
self.updates.append((msg, current, total))
548
546
vf = self.get_file()
549
547
# add a base to get included
550
548
vf.add_lines('base', [], ['base\n'])
616
636
self.assertRaises(NotImplementedError, vf.get_parents_with_ghosts, 'foo')
617
637
self.assertRaises(NotImplementedError, vf.get_graph_with_ghosts)
619
vf = self.reopen_file()
620
639
# test key graph related apis: getncestry, _graph, get_parents
622
641
# - these are ghost unaware and must not be reflect ghosts
623
self.assertEqual(['notbxbfse'], vf.get_ancestry('notbxbfse'))
624
self.assertEqual([], vf.get_parents('notbxbfse'))
625
self.assertEqual({'notbxbfse':()}, vf.get_graph())
626
self.assertFalse(vf.has_version(parent_id_utf8))
642
self.assertEqual([u'notbxbfse'], vf.get_ancestry(u'notbxbfse'))
643
self.assertEqual([], vf.get_parents(u'notbxbfse'))
644
self.assertEqual({u'notbxbfse':[]}, vf.get_graph())
645
self.assertFalse(vf.has_version(u'b\xbfse'))
627
646
# we have _with_ghost apis to give us ghost information.
628
self.assertEqual([parent_id_utf8, 'notbxbfse'], vf.get_ancestry_with_ghosts(['notbxbfse']))
629
self.assertEqual([parent_id_utf8], vf.get_parents_with_ghosts('notbxbfse'))
630
self.assertEqual({'notbxbfse':[parent_id_utf8]}, vf.get_graph_with_ghosts())
631
self.assertTrue(vf.has_ghost(parent_id_utf8))
647
self.assertEqual([u'b\xbfse', u'notbxbfse'], vf.get_ancestry_with_ghosts([u'notbxbfse']))
648
self.assertEqual([u'b\xbfse'], vf.get_parents_with_ghosts(u'notbxbfse'))
649
self.assertEqual({u'notbxbfse':[u'b\xbfse']}, vf.get_graph_with_ghosts())
650
self.assertTrue(vf.has_ghost(u'b\xbfse'))
632
651
# if we add something that is a ghost of another, it should correct the
633
652
# results of the prior apis
634
vf.add_lines(parent_id_utf8, [], [])
635
self.assertEqual([parent_id_utf8, 'notbxbfse'], vf.get_ancestry(['notbxbfse']))
636
self.assertEqual([parent_id_utf8], vf.get_parents('notbxbfse'))
637
self.assertEqual({parent_id_utf8:(),
638
'notbxbfse':(parent_id_utf8, ),
653
vf.add_lines(u'b\xbfse', [], [])
654
self.assertEqual([u'b\xbfse', u'notbxbfse'], vf.get_ancestry([u'notbxbfse']))
655
self.assertEqual([u'b\xbfse'], vf.get_parents(u'notbxbfse'))
656
self.assertEqual({u'b\xbfse':[],
657
u'notbxbfse':[u'b\xbfse'],
641
self.assertTrue(vf.has_version(parent_id_utf8))
660
self.assertTrue(vf.has_version(u'b\xbfse'))
642
661
# we have _with_ghost apis to give us ghost information.
643
self.assertEqual([parent_id_utf8, 'notbxbfse'],
644
vf.get_ancestry_with_ghosts(['notbxbfse']))
645
self.assertEqual([parent_id_utf8], vf.get_parents_with_ghosts('notbxbfse'))
646
self.assertEqual({parent_id_utf8:[],
647
'notbxbfse':[parent_id_utf8],
662
self.assertEqual([u'b\xbfse', u'notbxbfse'], vf.get_ancestry_with_ghosts([u'notbxbfse']))
663
self.assertEqual([u'b\xbfse'], vf.get_parents_with_ghosts(u'notbxbfse'))
664
self.assertEqual({u'b\xbfse':[],
665
u'notbxbfse':[u'b\xbfse'],
649
667
vf.get_graph_with_ghosts())
650
self.assertFalse(vf.has_ghost(parent_id_utf8))
668
self.assertFalse(vf.has_ghost(u'b\xbfse'))
652
670
def test_add_lines_with_ghosts_after_normal_revs(self):
653
671
# some versioned file formats allow lines to be added with parent