bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
1  | 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
2  | 
#
 | 
3  | 
# This program is free software; you can redistribute it and/or modify
 | 
|
4  | 
# it under the terms of the GNU General Public License as published by
 | 
|
5  | 
# the Free Software Foundation; either version 2 of the License, or
 | 
|
6  | 
# (at your option) any later version.
 | 
|
7  | 
#
 | 
|
8  | 
# This program is distributed in the hope that it will be useful,
 | 
|
9  | 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|
10  | 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|
11  | 
# GNU General Public License for more details.
 | 
|
12  | 
#
 | 
|
13  | 
# You should have received a copy of the GNU General Public License
 | 
|
14  | 
# along with this program; if not, write to the Free Software
 | 
|
15  | 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|
16  | 
||
17  | 
"""Tests for Knit data structure"""
 | 
|
18  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
19  | 
from cStringIO import StringIO  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
20  | 
import difflib  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
21  | 
import gzip  | 
22  | 
import sha  | 
|
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
23  | 
import sys  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
24  | 
|
| 
2196.2.5
by John Arbash Meinel
 Add an exception class when the knit index storage method is unknown, and properly test for it  | 
25  | 
from bzrlib import (  | 
26  | 
errors,  | 
|
| 
2484.1.5
by John Arbash Meinel
 Simplistic implementations of custom parsers for options and parents  | 
27  | 
generate_ids,  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
28  | 
knit,  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
29  | 
pack,  | 
| 
2196.2.5
by John Arbash Meinel
 Add an exception class when the knit index storage method is unknown, and properly test for it  | 
30  | 
    )
 | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
31  | 
from bzrlib.errors import (  | 
32  | 
RevisionAlreadyPresent,  | 
|
33  | 
KnitHeaderError,  | 
|
34  | 
RevisionNotPresent,  | 
|
35  | 
NoSuchFile,  | 
|
36  | 
    )
 | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
37  | 
from bzrlib.index import *  | 
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
38  | 
from bzrlib.knit import (  | 
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
39  | 
KnitContent,  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
40  | 
KnitGraphIndex,  | 
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
41  | 
KnitVersionedFile,  | 
42  | 
KnitPlainFactory,  | 
|
43  | 
KnitAnnotateFactory,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
44  | 
_KnitAccess,  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
45  | 
_KnitData,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
46  | 
_KnitIndex,  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
47  | 
_PackAccess,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
48  | 
WeaveToKnit,  | 
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
49  | 
KnitSequenceMatcher,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
50  | 
    )
 | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
51  | 
from bzrlib.osutils import split_lines  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
52  | 
from bzrlib.tests import (  | 
53  | 
Feature,  | 
|
54  | 
TestCase,  | 
|
55  | 
TestCaseWithMemoryTransport,  | 
|
56  | 
TestCaseWithTransport,  | 
|
57  | 
    )
 | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
58  | 
from bzrlib.transport import TransportLogger, get_transport  | 
| 
1563.2.13
by Robert Collins
 InterVersionedFile implemented.  | 
59  | 
from bzrlib.transport.memory import MemoryTransport  | 
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
60  | 
from bzrlib.weave import Weave  | 
61  | 
||
62  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
63  | 
class _CompiledKnitFeature(Feature):  | 
64  | 
||
65  | 
def _probe(self):  | 
|
66  | 
try:  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
67  | 
import bzrlib._knit_load_data_c  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
68  | 
except ImportError:  | 
69  | 
return False  | 
|
70  | 
return True  | 
|
71  | 
||
72  | 
def feature_name(self):  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
73  | 
return 'bzrlib._knit_load_data_c'  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
74  | 
|
75  | 
CompiledKnitFeature = _CompiledKnitFeature()  | 
|
76  | 
||
77  | 
||
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
78  | 
class KnitContentTests(TestCase):  | 
79  | 
||
80  | 
def test_constructor(self):  | 
|
81  | 
content = KnitContent([])  | 
|
82  | 
||
83  | 
def test_text(self):  | 
|
84  | 
content = KnitContent([])  | 
|
85  | 
self.assertEqual(content.text(), [])  | 
|
86  | 
||
87  | 
content = KnitContent([("origin1", "text1"), ("origin2", "text2")])  | 
|
88  | 
self.assertEqual(content.text(), ["text1", "text2"])  | 
|
89  | 
||
90  | 
def test_annotate(self):  | 
|
91  | 
content = KnitContent([])  | 
|
92  | 
self.assertEqual(content.annotate(), [])  | 
|
93  | 
||
94  | 
content = KnitContent([("origin1", "text1"), ("origin2", "text2")])  | 
|
95  | 
self.assertEqual(content.annotate(),  | 
|
96  | 
[("origin1", "text1"), ("origin2", "text2")])  | 
|
97  | 
||
98  | 
def test_annotate_iter(self):  | 
|
99  | 
content = KnitContent([])  | 
|
100  | 
it = content.annotate_iter()  | 
|
101  | 
self.assertRaises(StopIteration, it.next)  | 
|
102  | 
||
103  | 
content = KnitContent([("origin1", "text1"), ("origin2", "text2")])  | 
|
104  | 
it = content.annotate_iter()  | 
|
105  | 
self.assertEqual(it.next(), ("origin1", "text1"))  | 
|
106  | 
self.assertEqual(it.next(), ("origin2", "text2"))  | 
|
107  | 
self.assertRaises(StopIteration, it.next)  | 
|
108  | 
||
109  | 
def test_copy(self):  | 
|
110  | 
content = KnitContent([("origin1", "text1"), ("origin2", "text2")])  | 
|
111  | 
copy = content.copy()  | 
|
112  | 
self.assertIsInstance(copy, KnitContent)  | 
|
113  | 
self.assertEqual(copy.annotate(),  | 
|
114  | 
[("origin1", "text1"), ("origin2", "text2")])  | 
|
115  | 
||
116  | 
def test_line_delta(self):  | 
|
117  | 
content1 = KnitContent([("", "a"), ("", "b")])  | 
|
118  | 
content2 = KnitContent([("", "a"), ("", "a"), ("", "c")])  | 
|
119  | 
self.assertEqual(content1.line_delta(content2),  | 
|
120  | 
[(1, 2, 2, [("", "a"), ("", "c")])])  | 
|
121  | 
||
122  | 
def test_line_delta_iter(self):  | 
|
123  | 
content1 = KnitContent([("", "a"), ("", "b")])  | 
|
124  | 
content2 = KnitContent([("", "a"), ("", "a"), ("", "c")])  | 
|
125  | 
it = content1.line_delta_iter(content2)  | 
|
126  | 
self.assertEqual(it.next(), (1, 2, 2, [("", "a"), ("", "c")]))  | 
|
127  | 
self.assertRaises(StopIteration, it.next)  | 
|
128  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
129  | 
|
130  | 
class MockTransport(object):  | 
|
131  | 
||
132  | 
def __init__(self, file_lines=None):  | 
|
133  | 
self.file_lines = file_lines  | 
|
134  | 
self.calls = []  | 
|
| 
2196.2.3
by John Arbash Meinel
 Update tests and code to pass after merging bzr.dev  | 
135  | 
        # We have no base directory for the MockTransport
 | 
136  | 
self.base = ''  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
137  | 
|
138  | 
def get(self, filename):  | 
|
139  | 
if self.file_lines is None:  | 
|
140  | 
raise NoSuchFile(filename)  | 
|
141  | 
else:  | 
|
142  | 
return StringIO("\n".join(self.file_lines))  | 
|
143  | 
||
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
144  | 
def readv(self, relpath, offsets):  | 
145  | 
fp = self.get(relpath)  | 
|
146  | 
for offset, size in offsets:  | 
|
147  | 
fp.seek(offset)  | 
|
148  | 
yield offset, fp.read(size)  | 
|
149  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
150  | 
def __getattr__(self, name):  | 
151  | 
def queue_call(*args, **kwargs):  | 
|
152  | 
self.calls.append((name, args, kwargs))  | 
|
153  | 
return queue_call  | 
|
154  | 
||
155  | 
||
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
156  | 
class KnitRecordAccessTestsMixin(object):  | 
157  | 
"""Tests for getting and putting knit records."""  | 
|
158  | 
||
159  | 
def assertAccessExists(self, access):  | 
|
160  | 
"""Ensure the data area for access has been initialised/exists."""  | 
|
161  | 
raise NotImplementedError(self.assertAccessExists)  | 
|
162  | 
||
163  | 
def test_add_raw_records(self):  | 
|
164  | 
"""Add_raw_records adds records retrievable later."""  | 
|
165  | 
access = self.get_access()  | 
|
166  | 
memos = access.add_raw_records([10], '1234567890')  | 
|
167  | 
self.assertEqual(['1234567890'], list(access.get_raw_records(memos)))  | 
|
168  | 
||
169  | 
def test_add_several_raw_records(self):  | 
|
170  | 
"""add_raw_records with many records and read some back."""  | 
|
171  | 
access = self.get_access()  | 
|
172  | 
memos = access.add_raw_records([10, 2, 5], '12345678901234567')  | 
|
173  | 
self.assertEqual(['1234567890', '12', '34567'],  | 
|
174  | 
list(access.get_raw_records(memos)))  | 
|
175  | 
self.assertEqual(['1234567890'],  | 
|
176  | 
list(access.get_raw_records(memos[0:1])))  | 
|
177  | 
self.assertEqual(['12'],  | 
|
178  | 
list(access.get_raw_records(memos[1:2])))  | 
|
179  | 
self.assertEqual(['34567'],  | 
|
180  | 
list(access.get_raw_records(memos[2:3])))  | 
|
181  | 
self.assertEqual(['1234567890', '34567'],  | 
|
182  | 
list(access.get_raw_records(memos[0:1] + memos[2:3])))  | 
|
183  | 
||
184  | 
def test_create(self):  | 
|
185  | 
"""create() should make a file on disk."""  | 
|
186  | 
access = self.get_access()  | 
|
187  | 
access.create()  | 
|
188  | 
self.assertAccessExists(access)  | 
|
189  | 
||
190  | 
def test_open_file(self):  | 
|
191  | 
"""open_file never errors."""  | 
|
192  | 
access = self.get_access()  | 
|
193  | 
access.open_file()  | 
|
194  | 
||
195  | 
||
196  | 
class TestKnitKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):  | 
|
197  | 
"""Tests for the .kndx implementation."""  | 
|
198  | 
||
199  | 
def assertAccessExists(self, access):  | 
|
200  | 
self.assertNotEqual(None, access.open_file())  | 
|
201  | 
||
202  | 
def get_access(self):  | 
|
203  | 
"""Get a .knit style access instance."""  | 
|
204  | 
access = _KnitAccess(self.get_transport(), "foo.knit", None, None,  | 
|
205  | 
False, False)  | 
|
206  | 
return access  | 
|
207  | 
||
208  | 
||
209  | 
class TestPackKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):  | 
|
210  | 
"""Tests for the pack based access."""  | 
|
211  | 
||
212  | 
def assertAccessExists(self, access):  | 
|
213  | 
        # as pack based access has no backing unless an index maps data, this
 | 
|
214  | 
        # is a no-op.
 | 
|
215  | 
        pass
 | 
|
216  | 
||
217  | 
def get_access(self):  | 
|
218  | 
return self._get_access()[0]  | 
|
219  | 
||
220  | 
def _get_access(self, packname='packfile', index='FOO'):  | 
|
221  | 
transport = self.get_transport()  | 
|
222  | 
def write_data(bytes):  | 
|
223  | 
transport.append_bytes(packname, bytes)  | 
|
224  | 
writer = pack.ContainerWriter(write_data)  | 
|
225  | 
writer.begin()  | 
|
226  | 
indices = {index:(transport, packname)}  | 
|
227  | 
access = _PackAccess(indices, writer=(writer, index))  | 
|
228  | 
return access, writer  | 
|
229  | 
||
230  | 
def test_read_from_several_packs(self):  | 
|
231  | 
access, writer = self._get_access()  | 
|
232  | 
memos = []  | 
|
233  | 
memos.extend(access.add_raw_records([10], '1234567890'))  | 
|
234  | 
writer.end()  | 
|
235  | 
access, writer = self._get_access('pack2', 'FOOBAR')  | 
|
236  | 
memos.extend(access.add_raw_records([5], '12345'))  | 
|
237  | 
writer.end()  | 
|
238  | 
access, writer = self._get_access('pack3', 'BAZ')  | 
|
239  | 
memos.extend(access.add_raw_records([5], 'alpha'))  | 
|
240  | 
writer.end()  | 
|
241  | 
transport = self.get_transport()  | 
|
242  | 
access = _PackAccess({"FOO":(transport, 'packfile'),  | 
|
243  | 
"FOOBAR":(transport, 'pack2'),  | 
|
244  | 
"BAZ":(transport, 'pack3')})  | 
|
245  | 
self.assertEqual(['1234567890', '12345', 'alpha'],  | 
|
246  | 
list(access.get_raw_records(memos)))  | 
|
247  | 
self.assertEqual(['1234567890'],  | 
|
248  | 
list(access.get_raw_records(memos[0:1])))  | 
|
249  | 
self.assertEqual(['12345'],  | 
|
250  | 
list(access.get_raw_records(memos[1:2])))  | 
|
251  | 
self.assertEqual(['alpha'],  | 
|
252  | 
list(access.get_raw_records(memos[2:3])))  | 
|
253  | 
self.assertEqual(['1234567890', 'alpha'],  | 
|
254  | 
list(access.get_raw_records(memos[0:1] + memos[2:3])))  | 
|
255  | 
||
256  | 
def test_set_writer(self):  | 
|
257  | 
"""The writer should be settable post construction."""  | 
|
258  | 
access = _PackAccess({})  | 
|
259  | 
transport = self.get_transport()  | 
|
260  | 
packname = 'packfile'  | 
|
261  | 
index = 'foo'  | 
|
262  | 
def write_data(bytes):  | 
|
263  | 
transport.append_bytes(packname, bytes)  | 
|
264  | 
writer = pack.ContainerWriter(write_data)  | 
|
265  | 
writer.begin()  | 
|
266  | 
access.set_writer(writer, index, (transport, packname))  | 
|
267  | 
memos = access.add_raw_records([10], '1234567890')  | 
|
268  | 
writer.end()  | 
|
269  | 
self.assertEqual(['1234567890'], list(access.get_raw_records(memos)))  | 
|
270  | 
||
271  | 
||
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
272  | 
class LowLevelKnitDataTests(TestCase):  | 
273  | 
||
274  | 
def create_gz_content(self, text):  | 
|
275  | 
sio = StringIO()  | 
|
276  | 
gz_file = gzip.GzipFile(mode='wb', fileobj=sio)  | 
|
277  | 
gz_file.write(text)  | 
|
278  | 
gz_file.close()  | 
|
279  | 
return sio.getvalue()  | 
|
280  | 
||
281  | 
def test_valid_knit_data(self):  | 
|
282  | 
sha1sum = sha.new('foo\nbar\n').hexdigest()  | 
|
283  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
|
284  | 
'foo\n'  | 
|
285  | 
'bar\n'  | 
|
286  | 
'end rev-id-1\n'  | 
|
287  | 
% (sha1sum,))  | 
|
288  | 
transport = MockTransport([gz_txt])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
289  | 
access = _KnitAccess(transport, 'filename', None, None, False, False)  | 
290  | 
data = _KnitData(access=access)  | 
|
291  | 
records = [('rev-id-1', (None, 0, len(gz_txt)))]  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
292  | 
|
293  | 
contents = data.read_records(records)  | 
|
294  | 
self.assertEqual({'rev-id-1':(['foo\n', 'bar\n'], sha1sum)}, contents)  | 
|
295  | 
||
296  | 
raw_contents = list(data.read_records_iter_raw(records))  | 
|
297  | 
self.assertEqual([('rev-id-1', gz_txt)], raw_contents)  | 
|
298  | 
||
299  | 
def test_not_enough_lines(self):  | 
|
300  | 
sha1sum = sha.new('foo\n').hexdigest()  | 
|
301  | 
        # record says 2 lines data says 1
 | 
|
302  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
|
303  | 
'foo\n'  | 
|
304  | 
'end rev-id-1\n'  | 
|
305  | 
% (sha1sum,))  | 
|
306  | 
transport = MockTransport([gz_txt])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
307  | 
access = _KnitAccess(transport, 'filename', None, None, False, False)  | 
308  | 
data = _KnitData(access=access)  | 
|
309  | 
records = [('rev-id-1', (None, 0, len(gz_txt)))]  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
310  | 
self.assertRaises(errors.KnitCorrupt, data.read_records, records)  | 
311  | 
||
312  | 
        # read_records_iter_raw won't detect that sort of mismatch/corruption
 | 
|
313  | 
raw_contents = list(data.read_records_iter_raw(records))  | 
|
314  | 
self.assertEqual([('rev-id-1', gz_txt)], raw_contents)  | 
|
315  | 
||
316  | 
def test_too_many_lines(self):  | 
|
317  | 
sha1sum = sha.new('foo\nbar\n').hexdigest()  | 
|
318  | 
        # record says 1 lines data says 2
 | 
|
319  | 
gz_txt = self.create_gz_content('version rev-id-1 1 %s\n'  | 
|
320  | 
'foo\n'  | 
|
321  | 
'bar\n'  | 
|
322  | 
'end rev-id-1\n'  | 
|
323  | 
% (sha1sum,))  | 
|
324  | 
transport = MockTransport([gz_txt])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
325  | 
access = _KnitAccess(transport, 'filename', None, None, False, False)  | 
326  | 
data = _KnitData(access=access)  | 
|
327  | 
records = [('rev-id-1', (None, 0, len(gz_txt)))]  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
328  | 
self.assertRaises(errors.KnitCorrupt, data.read_records, records)  | 
329  | 
||
330  | 
        # read_records_iter_raw won't detect that sort of mismatch/corruption
 | 
|
331  | 
raw_contents = list(data.read_records_iter_raw(records))  | 
|
332  | 
self.assertEqual([('rev-id-1', gz_txt)], raw_contents)  | 
|
333  | 
||
334  | 
def test_mismatched_version_id(self):  | 
|
335  | 
sha1sum = sha.new('foo\nbar\n').hexdigest()  | 
|
336  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
|
337  | 
'foo\n'  | 
|
338  | 
'bar\n'  | 
|
339  | 
'end rev-id-1\n'  | 
|
340  | 
% (sha1sum,))  | 
|
341  | 
transport = MockTransport([gz_txt])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
342  | 
access = _KnitAccess(transport, 'filename', None, None, False, False)  | 
343  | 
data = _KnitData(access=access)  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
344  | 
        # We are asking for rev-id-2, but the data is rev-id-1
 | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
345  | 
records = [('rev-id-2', (None, 0, len(gz_txt)))]  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
346  | 
self.assertRaises(errors.KnitCorrupt, data.read_records, records)  | 
347  | 
||
348  | 
        # read_records_iter_raw will notice if we request the wrong version.
 | 
|
349  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
350  | 
data.read_records_iter_raw(records))  | 
|
351  | 
||
352  | 
def test_uncompressed_data(self):  | 
|
353  | 
sha1sum = sha.new('foo\nbar\n').hexdigest()  | 
|
354  | 
txt = ('version rev-id-1 2 %s\n'  | 
|
355  | 
'foo\n'  | 
|
356  | 
'bar\n'  | 
|
357  | 
'end rev-id-1\n'  | 
|
358  | 
% (sha1sum,))  | 
|
359  | 
transport = MockTransport([txt])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
360  | 
access = _KnitAccess(transport, 'filename', None, None, False, False)  | 
361  | 
data = _KnitData(access=access)  | 
|
362  | 
records = [('rev-id-1', (None, 0, len(txt)))]  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
363  | 
|
364  | 
        # We don't have valid gzip data ==> corrupt
 | 
|
365  | 
self.assertRaises(errors.KnitCorrupt, data.read_records, records)  | 
|
366  | 
||
367  | 
        # read_records_iter_raw will notice the bad data
 | 
|
368  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
369  | 
data.read_records_iter_raw(records))  | 
|
370  | 
||
371  | 
def test_corrupted_data(self):  | 
|
372  | 
sha1sum = sha.new('foo\nbar\n').hexdigest()  | 
|
373  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
|
374  | 
'foo\n'  | 
|
375  | 
'bar\n'  | 
|
376  | 
'end rev-id-1\n'  | 
|
377  | 
% (sha1sum,))  | 
|
378  | 
        # Change 2 bytes in the middle to \xff
 | 
|
379  | 
gz_txt = gz_txt[:10] + '\xff\xff' + gz_txt[12:]  | 
|
380  | 
transport = MockTransport([gz_txt])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
381  | 
access = _KnitAccess(transport, 'filename', None, None, False, False)  | 
382  | 
data = _KnitData(access=access)  | 
|
383  | 
records = [('rev-id-1', (None, 0, len(gz_txt)))]  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
384  | 
|
385  | 
self.assertRaises(errors.KnitCorrupt, data.read_records, records)  | 
|
386  | 
||
387  | 
        # read_records_iter_raw will notice if we request the wrong version.
 | 
|
388  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
389  | 
data.read_records_iter_raw(records))  | 
|
390  | 
||
391  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
392  | 
class LowLevelKnitIndexTests(TestCase):  | 
393  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
394  | 
def get_knit_index(self, *args, **kwargs):  | 
395  | 
orig = knit._load_data  | 
|
396  | 
def reset():  | 
|
397  | 
knit._load_data = orig  | 
|
398  | 
self.addCleanup(reset)  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
399  | 
from bzrlib._knit_load_data_py import _load_data_py  | 
400  | 
knit._load_data = _load_data_py  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
401  | 
return _KnitIndex(*args, **kwargs)  | 
402  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
403  | 
def test_no_such_file(self):  | 
404  | 
transport = MockTransport()  | 
|
405  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
406  | 
self.assertRaises(NoSuchFile, self.get_knit_index,  | 
407  | 
transport, "filename", "r")  | 
|
408  | 
self.assertRaises(NoSuchFile, self.get_knit_index,  | 
|
409  | 
transport, "filename", "w", create=False)  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
410  | 
|
411  | 
def test_create_file(self):  | 
|
412  | 
transport = MockTransport()  | 
|
413  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
414  | 
index = self.get_knit_index(transport, "filename", "w",  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
415  | 
file_mode="wb", create=True)  | 
416  | 
self.assertEqual(  | 
|
417  | 
("put_bytes_non_atomic",  | 
|
418  | 
("filename", index.HEADER), {"mode": "wb"}),  | 
|
419  | 
transport.calls.pop(0))  | 
|
420  | 
||
421  | 
def test_delay_create_file(self):  | 
|
422  | 
transport = MockTransport()  | 
|
423  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
424  | 
index = self.get_knit_index(transport, "filename", "w",  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
425  | 
create=True, file_mode="wb", create_parent_dir=True,  | 
426  | 
delay_create=True, dir_mode=0777)  | 
|
427  | 
self.assertEqual([], transport.calls)  | 
|
428  | 
||
429  | 
index.add_versions([])  | 
|
430  | 
name, (filename, f), kwargs = transport.calls.pop(0)  | 
|
431  | 
self.assertEqual("put_file_non_atomic", name)  | 
|
432  | 
self.assertEqual(  | 
|
433  | 
{"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"},  | 
|
434  | 
kwargs)  | 
|
435  | 
self.assertEqual("filename", filename)  | 
|
436  | 
self.assertEqual(index.HEADER, f.read())  | 
|
437  | 
||
438  | 
index.add_versions([])  | 
|
439  | 
self.assertEqual(("append_bytes", ("filename", ""), {}),  | 
|
440  | 
transport.calls.pop(0))  | 
|
441  | 
||
442  | 
def test_read_utf8_version_id(self):  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
443  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
444  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
445  | 
transport = MockTransport([  | 
446  | 
_KnitIndex.HEADER,  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
447  | 
'%s option 0 1 :' % (utf8_revision_id,)  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
448  | 
            ])
 | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
449  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
450  | 
        # _KnitIndex is a private class, and deals in utf8 revision_ids, not
 | 
451  | 
        # Unicode revision_ids.
 | 
|
452  | 
self.assertTrue(index.has_version(utf8_revision_id))  | 
|
453  | 
self.assertFalse(index.has_version(unicode_revision_id))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
454  | 
|
455  | 
def test_read_utf8_parents(self):  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
456  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
457  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
458  | 
transport = MockTransport([  | 
459  | 
_KnitIndex.HEADER,  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
460  | 
"version option 0 1 .%s :" % (utf8_revision_id,)  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
461  | 
            ])
 | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
462  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
463  | 
self.assertEqual([utf8_revision_id],  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
464  | 
index.get_parents_with_ghosts("version"))  | 
465  | 
||
466  | 
def test_read_ignore_corrupted_lines(self):  | 
|
467  | 
transport = MockTransport([  | 
|
468  | 
_KnitIndex.HEADER,  | 
|
469  | 
"corrupted",  | 
|
470  | 
"corrupted options 0 1 .b .c ",  | 
|
471  | 
            "version options 0 1 :"
 | 
|
472  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
473  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
474  | 
self.assertEqual(1, index.num_versions())  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
475  | 
self.assertTrue(index.has_version("version"))  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
476  | 
|
477  | 
def test_read_corrupted_header(self):  | 
|
| 
2196.2.3
by John Arbash Meinel
 Update tests and code to pass after merging bzr.dev  | 
478  | 
transport = MockTransport(['not a bzr knit index header\n'])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
479  | 
self.assertRaises(KnitHeaderError,  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
480  | 
self.get_knit_index, transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
481  | 
|
482  | 
def test_read_duplicate_entries(self):  | 
|
483  | 
transport = MockTransport([  | 
|
484  | 
_KnitIndex.HEADER,  | 
|
485  | 
"parent options 0 1 :",  | 
|
486  | 
"version options1 0 1 0 :",  | 
|
487  | 
"version options2 1 2 .other :",  | 
|
488  | 
            "version options3 3 4 0 .other :"
 | 
|
489  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
490  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
491  | 
self.assertEqual(2, index.num_versions())  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
492  | 
        # check that the index used is the first one written. (Specific
 | 
493  | 
        # to KnitIndex style indices.
 | 
|
494  | 
self.assertEqual("1", index._version_list_to_index(["version"]))  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
495  | 
self.assertEqual((None, 3, 4), index.get_position("version"))  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
496  | 
self.assertEqual(["options3"], index.get_options("version"))  | 
497  | 
self.assertEqual(["parent", "other"],  | 
|
498  | 
index.get_parents_with_ghosts("version"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
499  | 
|
500  | 
def test_read_compressed_parents(self):  | 
|
501  | 
transport = MockTransport([  | 
|
502  | 
_KnitIndex.HEADER,  | 
|
503  | 
"a option 0 1 :",  | 
|
504  | 
"b option 0 1 0 :",  | 
|
505  | 
"c option 0 1 1 0 :",  | 
|
506  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
507  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
508  | 
self.assertEqual(["a"], index.get_parents("b"))  | 
509  | 
self.assertEqual(["b", "a"], index.get_parents("c"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
510  | 
|
511  | 
def test_write_utf8_version_id(self):  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
512  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
513  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
514  | 
transport = MockTransport([  | 
515  | 
_KnitIndex.HEADER  | 
|
516  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
517  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
518  | 
index.add_version(utf8_revision_id, ["option"], (None, 0, 1), [])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
519  | 
self.assertEqual(("append_bytes", ("filename",  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
520  | 
"\n%s option 0 1 :" % (utf8_revision_id,)),  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
521  | 
            {}),
 | 
522  | 
transport.calls.pop(0))  | 
|
523  | 
||
524  | 
def test_write_utf8_parents(self):  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
525  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
526  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
527  | 
transport = MockTransport([  | 
528  | 
_KnitIndex.HEADER  | 
|
529  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
530  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
531  | 
index.add_version("version", ["option"], (None, 0, 1), [utf8_revision_id])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
532  | 
self.assertEqual(("append_bytes", ("filename",  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
533  | 
"\nversion option 0 1 .%s :" % (utf8_revision_id,)),  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
534  | 
            {}),
 | 
535  | 
transport.calls.pop(0))  | 
|
536  | 
||
537  | 
def test_get_graph(self):  | 
|
538  | 
transport = MockTransport()  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
539  | 
index = self.get_knit_index(transport, "filename", "w", create=True)  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
540  | 
self.assertEqual([], index.get_graph())  | 
541  | 
||
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
542  | 
index.add_version("a", ["option"], (None, 0, 1), ["b"])  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
543  | 
self.assertEqual([("a", ["b"])], index.get_graph())  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
544  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
545  | 
index.add_version("c", ["option"], (None, 0, 1), ["d"])  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
546  | 
self.assertEqual([("a", ["b"]), ("c", ["d"])],  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
547  | 
sorted(index.get_graph()))  | 
548  | 
||
549  | 
def test_get_ancestry(self):  | 
|
550  | 
transport = MockTransport([  | 
|
551  | 
_KnitIndex.HEADER,  | 
|
552  | 
"a option 0 1 :",  | 
|
553  | 
"b option 0 1 0 .e :",  | 
|
554  | 
"c option 0 1 1 0 :",  | 
|
555  | 
            "d option 0 1 2 .f :"
 | 
|
556  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
557  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
558  | 
|
559  | 
self.assertEqual([], index.get_ancestry([]))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
560  | 
self.assertEqual(["a"], index.get_ancestry(["a"]))  | 
561  | 
self.assertEqual(["a", "b"], index.get_ancestry(["b"]))  | 
|
562  | 
self.assertEqual(["a", "b", "c"], index.get_ancestry(["c"]))  | 
|
563  | 
self.assertEqual(["a", "b", "c", "d"], index.get_ancestry(["d"]))  | 
|
564  | 
self.assertEqual(["a", "b"], index.get_ancestry(["a", "b"]))  | 
|
565  | 
self.assertEqual(["a", "b", "c"], index.get_ancestry(["a", "c"]))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
566  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
567  | 
self.assertRaises(RevisionNotPresent, index.get_ancestry, ["e"])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
568  | 
|
569  | 
def test_get_ancestry_with_ghosts(self):  | 
|
570  | 
transport = MockTransport([  | 
|
571  | 
_KnitIndex.HEADER,  | 
|
572  | 
"a option 0 1 :",  | 
|
573  | 
"b option 0 1 0 .e :",  | 
|
574  | 
"c option 0 1 0 .f .g :",  | 
|
575  | 
            "d option 0 1 2 .h .j .k :"
 | 
|
576  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
577  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
578  | 
|
579  | 
self.assertEqual([], index.get_ancestry_with_ghosts([]))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
580  | 
self.assertEqual(["a"], index.get_ancestry_with_ghosts(["a"]))  | 
581  | 
self.assertEqual(["a", "e", "b"],  | 
|
582  | 
index.get_ancestry_with_ghosts(["b"]))  | 
|
583  | 
self.assertEqual(["a", "g", "f", "c"],  | 
|
584  | 
index.get_ancestry_with_ghosts(["c"]))  | 
|
585  | 
self.assertEqual(["a", "g", "f", "c", "k", "j", "h", "d"],  | 
|
586  | 
index.get_ancestry_with_ghosts(["d"]))  | 
|
587  | 
self.assertEqual(["a", "e", "b"],  | 
|
588  | 
index.get_ancestry_with_ghosts(["a", "b"]))  | 
|
589  | 
self.assertEqual(["a", "g", "f", "c"],  | 
|
590  | 
index.get_ancestry_with_ghosts(["a", "c"]))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
591  | 
self.assertEqual(  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
592  | 
["a", "g", "f", "c", "e", "b", "k", "j", "h", "d"],  | 
593  | 
index.get_ancestry_with_ghosts(["b", "d"]))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
594  | 
|
595  | 
self.assertRaises(RevisionNotPresent,  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
596  | 
index.get_ancestry_with_ghosts, ["e"])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
597  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
598  | 
def test_iter_parents(self):  | 
599  | 
transport = MockTransport()  | 
|
600  | 
index = self.get_knit_index(transport, "filename", "w", create=True)  | 
|
601  | 
        # no parents
 | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
602  | 
index.add_version('r0', ['option'], (None, 0, 1), [])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
603  | 
        # 1 parent
 | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
604  | 
index.add_version('r1', ['option'], (None, 0, 1), ['r0'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
605  | 
        # 2 parents
 | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
606  | 
index.add_version('r2', ['option'], (None, 0, 1), ['r1', 'r0'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
607  | 
        # XXX TODO a ghost
 | 
608  | 
        # cases: each sample data individually:
 | 
|
609  | 
self.assertEqual(set([('r0', ())]),  | 
|
610  | 
set(index.iter_parents(['r0'])))  | 
|
611  | 
self.assertEqual(set([('r1', ('r0', ))]),  | 
|
612  | 
set(index.iter_parents(['r1'])))  | 
|
613  | 
self.assertEqual(set([('r2', ('r1', 'r0'))]),  | 
|
614  | 
set(index.iter_parents(['r2'])))  | 
|
615  | 
        # no nodes returned for a missing node
 | 
|
616  | 
self.assertEqual(set(),  | 
|
617  | 
set(index.iter_parents(['missing'])))  | 
|
618  | 
        # 1 node returned with missing nodes skipped
 | 
|
619  | 
self.assertEqual(set([('r1', ('r0', ))]),  | 
|
620  | 
set(index.iter_parents(['ghost1', 'r1', 'ghost'])))  | 
|
621  | 
        # 2 nodes returned
 | 
|
622  | 
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),  | 
|
623  | 
set(index.iter_parents(['r0', 'r1'])))  | 
|
624  | 
        # 2 nodes returned, missing skipped
 | 
|
625  | 
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),  | 
|
626  | 
set(index.iter_parents(['a', 'r0', 'b', 'r1', 'c'])))  | 
|
627  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
628  | 
def test_num_versions(self):  | 
629  | 
transport = MockTransport([  | 
|
630  | 
_KnitIndex.HEADER  | 
|
631  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
632  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
633  | 
|
634  | 
self.assertEqual(0, index.num_versions())  | 
|
635  | 
self.assertEqual(0, len(index))  | 
|
636  | 
||
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
637  | 
index.add_version("a", ["option"], (None, 0, 1), [])  | 
638  | 
self.assertEqual(1, index.num_versions())  | 
|
639  | 
self.assertEqual(1, len(index))  | 
|
640  | 
||
641  | 
index.add_version("a", ["option2"], (None, 1, 2), [])  | 
|
642  | 
self.assertEqual(1, index.num_versions())  | 
|
643  | 
self.assertEqual(1, len(index))  | 
|
644  | 
||
645  | 
index.add_version("b", ["option"], (None, 0, 1), [])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
646  | 
self.assertEqual(2, index.num_versions())  | 
647  | 
self.assertEqual(2, len(index))  | 
|
648  | 
||
649  | 
def test_get_versions(self):  | 
|
650  | 
transport = MockTransport([  | 
|
651  | 
_KnitIndex.HEADER  | 
|
652  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
653  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
654  | 
|
655  | 
self.assertEqual([], index.get_versions())  | 
|
656  | 
||
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
657  | 
index.add_version("a", ["option"], (None, 0, 1), [])  | 
658  | 
self.assertEqual(["a"], index.get_versions())  | 
|
659  | 
||
660  | 
index.add_version("a", ["option"], (None, 0, 1), [])  | 
|
661  | 
self.assertEqual(["a"], index.get_versions())  | 
|
662  | 
||
663  | 
index.add_version("b", ["option"], (None, 0, 1), [])  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
664  | 
self.assertEqual(["a", "b"], index.get_versions())  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
665  | 
|
666  | 
def test_add_version(self):  | 
|
667  | 
transport = MockTransport([  | 
|
668  | 
_KnitIndex.HEADER  | 
|
669  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
670  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
671  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
672  | 
index.add_version("a", ["option"], (None, 0, 1), ["b"])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
673  | 
self.assertEqual(("append_bytes",  | 
674  | 
("filename", "\na option 0 1 .b :"),  | 
|
675  | 
{}), transport.calls.pop(0))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
676  | 
self.assertTrue(index.has_version("a"))  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
677  | 
self.assertEqual(1, index.num_versions())  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
678  | 
self.assertEqual((None, 0, 1), index.get_position("a"))  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
679  | 
self.assertEqual(["option"], index.get_options("a"))  | 
680  | 
self.assertEqual(["b"], index.get_parents_with_ghosts("a"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
681  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
682  | 
index.add_version("a", ["opt"], (None, 1, 2), ["c"])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
683  | 
self.assertEqual(("append_bytes",  | 
684  | 
("filename", "\na opt 1 2 .c :"),  | 
|
685  | 
{}), transport.calls.pop(0))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
686  | 
self.assertTrue(index.has_version("a"))  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
687  | 
self.assertEqual(1, index.num_versions())  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
688  | 
self.assertEqual((None, 1, 2), index.get_position("a"))  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
689  | 
self.assertEqual(["opt"], index.get_options("a"))  | 
690  | 
self.assertEqual(["c"], index.get_parents_with_ghosts("a"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
691  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
692  | 
index.add_version("b", ["option"], (None, 2, 3), ["a"])  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
693  | 
self.assertEqual(("append_bytes",  | 
694  | 
("filename", "\nb option 2 3 0 :"),  | 
|
695  | 
{}), transport.calls.pop(0))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
696  | 
self.assertTrue(index.has_version("b"))  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
697  | 
self.assertEqual(2, index.num_versions())  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
698  | 
self.assertEqual((None, 2, 3), index.get_position("b"))  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
699  | 
self.assertEqual(["option"], index.get_options("b"))  | 
700  | 
self.assertEqual(["a"], index.get_parents_with_ghosts("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
701  | 
|
702  | 
def test_add_versions(self):  | 
|
703  | 
transport = MockTransport([  | 
|
704  | 
_KnitIndex.HEADER  | 
|
705  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
706  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
707  | 
|
708  | 
index.add_versions([  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
709  | 
("a", ["option"], (None, 0, 1), ["b"]),  | 
710  | 
("a", ["opt"], (None, 1, 2), ["c"]),  | 
|
711  | 
("b", ["option"], (None, 2, 3), ["a"])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
712  | 
            ])
 | 
713  | 
self.assertEqual(("append_bytes", ("filename",  | 
|
714  | 
"\na option 0 1 .b :"  | 
|
715  | 
"\na opt 1 2 .c :"  | 
|
716  | 
"\nb option 2 3 0 :"  | 
|
717  | 
), {}), transport.calls.pop(0))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
718  | 
self.assertTrue(index.has_version("a"))  | 
719  | 
self.assertTrue(index.has_version("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
720  | 
self.assertEqual(2, index.num_versions())  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
721  | 
self.assertEqual((None, 1, 2), index.get_position("a"))  | 
722  | 
self.assertEqual((None, 2, 3), index.get_position("b"))  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
723  | 
self.assertEqual(["opt"], index.get_options("a"))  | 
724  | 
self.assertEqual(["option"], index.get_options("b"))  | 
|
725  | 
self.assertEqual(["c"], index.get_parents_with_ghosts("a"))  | 
|
726  | 
self.assertEqual(["a"], index.get_parents_with_ghosts("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
727  | 
|
728  | 
def test_delay_create_and_add_versions(self):  | 
|
729  | 
transport = MockTransport()  | 
|
730  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
731  | 
index = self.get_knit_index(transport, "filename", "w",  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
732  | 
create=True, file_mode="wb", create_parent_dir=True,  | 
733  | 
delay_create=True, dir_mode=0777)  | 
|
734  | 
self.assertEqual([], transport.calls)  | 
|
735  | 
||
736  | 
index.add_versions([  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
737  | 
("a", ["option"], (None, 0, 1), ["b"]),  | 
738  | 
("a", ["opt"], (None, 1, 2), ["c"]),  | 
|
739  | 
("b", ["option"], (None, 2, 3), ["a"])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
740  | 
            ])
 | 
741  | 
name, (filename, f), kwargs = transport.calls.pop(0)  | 
|
742  | 
self.assertEqual("put_file_non_atomic", name)  | 
|
743  | 
self.assertEqual(  | 
|
744  | 
{"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"},  | 
|
745  | 
kwargs)  | 
|
746  | 
self.assertEqual("filename", filename)  | 
|
747  | 
self.assertEqual(  | 
|
748  | 
index.HEADER +  | 
|
749  | 
"\na option 0 1 .b :"  | 
|
750  | 
"\na opt 1 2 .c :"  | 
|
751  | 
"\nb option 2 3 0 :",  | 
|
752  | 
f.read())  | 
|
753  | 
||
754  | 
def test_has_version(self):  | 
|
755  | 
transport = MockTransport([  | 
|
756  | 
_KnitIndex.HEADER,  | 
|
757  | 
            "a option 0 1 :"
 | 
|
758  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
759  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
760  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
761  | 
self.assertTrue(index.has_version("a"))  | 
762  | 
self.assertFalse(index.has_version("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
763  | 
|
764  | 
def test_get_position(self):  | 
|
765  | 
transport = MockTransport([  | 
|
766  | 
_KnitIndex.HEADER,  | 
|
767  | 
"a option 0 1 :",  | 
|
768  | 
            "b option 1 2 :"
 | 
|
769  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
770  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
771  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
772  | 
self.assertEqual((None, 0, 1), index.get_position("a"))  | 
773  | 
self.assertEqual((None, 1, 2), index.get_position("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
774  | 
|
775  | 
def test_get_method(self):  | 
|
776  | 
transport = MockTransport([  | 
|
777  | 
_KnitIndex.HEADER,  | 
|
778  | 
"a fulltext,unknown 0 1 :",  | 
|
779  | 
"b unknown,line-delta 1 2 :",  | 
|
780  | 
            "c bad 3 4 :"
 | 
|
781  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
782  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
783  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
784  | 
self.assertEqual("fulltext", index.get_method("a"))  | 
785  | 
self.assertEqual("line-delta", index.get_method("b"))  | 
|
786  | 
self.assertRaises(errors.KnitIndexUnknownMethod, index.get_method, "c")  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
787  | 
|
788  | 
def test_get_options(self):  | 
|
789  | 
transport = MockTransport([  | 
|
790  | 
_KnitIndex.HEADER,  | 
|
791  | 
"a opt1 0 1 :",  | 
|
792  | 
            "b opt2,opt3 1 2 :"
 | 
|
793  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
794  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
795  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
796  | 
self.assertEqual(["opt1"], index.get_options("a"))  | 
797  | 
self.assertEqual(["opt2", "opt3"], index.get_options("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
798  | 
|
799  | 
def test_get_parents(self):  | 
|
800  | 
transport = MockTransport([  | 
|
801  | 
_KnitIndex.HEADER,  | 
|
802  | 
"a option 0 1 :",  | 
|
803  | 
"b option 1 2 0 .c :",  | 
|
804  | 
            "c option 1 2 1 0 .e :"
 | 
|
805  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
806  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
807  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
808  | 
self.assertEqual([], index.get_parents("a"))  | 
809  | 
self.assertEqual(["a", "c"], index.get_parents("b"))  | 
|
810  | 
self.assertEqual(["b", "a"], index.get_parents("c"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
811  | 
|
812  | 
def test_get_parents_with_ghosts(self):  | 
|
813  | 
transport = MockTransport([  | 
|
814  | 
_KnitIndex.HEADER,  | 
|
815  | 
"a option 0 1 :",  | 
|
816  | 
"b option 1 2 0 .c :",  | 
|
817  | 
            "c option 1 2 1 0 .e :"
 | 
|
818  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
819  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
820  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
821  | 
self.assertEqual([], index.get_parents_with_ghosts("a"))  | 
822  | 
self.assertEqual(["a", "c"], index.get_parents_with_ghosts("b"))  | 
|
823  | 
self.assertEqual(["b", "a", "e"],  | 
|
824  | 
index.get_parents_with_ghosts("c"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
825  | 
|
826  | 
def test_check_versions_present(self):  | 
|
827  | 
transport = MockTransport([  | 
|
828  | 
_KnitIndex.HEADER,  | 
|
829  | 
"a option 0 1 :",  | 
|
830  | 
            "b option 0 1 :"
 | 
|
831  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
832  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
833  | 
|
834  | 
check = index.check_versions_present  | 
|
835  | 
||
836  | 
check([])  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
837  | 
check(["a"])  | 
838  | 
check(["b"])  | 
|
839  | 
check(["a", "b"])  | 
|
840  | 
self.assertRaises(RevisionNotPresent, check, ["c"])  | 
|
841  | 
self.assertRaises(RevisionNotPresent, check, ["a", "b", "c"])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
842  | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
843  | 
def test_impossible_parent(self):  | 
844  | 
"""Test we get KnitCorrupt if the parent couldn't possibly exist."""  | 
|
845  | 
transport = MockTransport([  | 
|
846  | 
_KnitIndex.HEADER,  | 
|
847  | 
"a option 0 1 :",  | 
|
848  | 
"b option 0 1 4 :" # We don't have a 4th record  | 
|
849  | 
            ])
 | 
|
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
850  | 
try:  | 
851  | 
self.assertRaises(errors.KnitCorrupt,  | 
|
852  | 
self.get_knit_index, transport, 'filename', 'r')  | 
|
853  | 
except TypeError, e:  | 
|
854  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
855  | 
' not exceptions.IndexError')  | 
|
856  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
857  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
858  | 
                                  ' raising new style exceptions with python'
 | 
|
859  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
860  | 
else:  | 
861  | 
                raise
 | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
862  | 
|
863  | 
def test_corrupted_parent(self):  | 
|
864  | 
transport = MockTransport([  | 
|
865  | 
_KnitIndex.HEADER,  | 
|
866  | 
"a option 0 1 :",  | 
|
867  | 
"b option 0 1 :",  | 
|
868  | 
"c option 0 1 1v :", # Can't have a parent of '1v'  | 
|
869  | 
            ])
 | 
|
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
870  | 
try:  | 
871  | 
self.assertRaises(errors.KnitCorrupt,  | 
|
872  | 
self.get_knit_index, transport, 'filename', 'r')  | 
|
873  | 
except TypeError, e:  | 
|
874  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
875  | 
' not exceptions.ValueError')  | 
|
876  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
877  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
878  | 
                                  ' raising new style exceptions with python'
 | 
|
879  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
880  | 
else:  | 
881  | 
                raise
 | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
882  | 
|
883  | 
def test_corrupted_parent_in_list(self):  | 
|
884  | 
transport = MockTransport([  | 
|
885  | 
_KnitIndex.HEADER,  | 
|
886  | 
"a option 0 1 :",  | 
|
887  | 
"b option 0 1 :",  | 
|
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
888  | 
"c option 0 1 1 v :", # Can't have a parent of 'v'  | 
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
889  | 
            ])
 | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
890  | 
try:  | 
891  | 
self.assertRaises(errors.KnitCorrupt,  | 
|
892  | 
self.get_knit_index, transport, 'filename', 'r')  | 
|
893  | 
except TypeError, e:  | 
|
894  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
895  | 
' not exceptions.ValueError')  | 
|
896  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
897  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
898  | 
                                  ' raising new style exceptions with python'
 | 
|
899  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
900  | 
else:  | 
901  | 
                raise
 | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
902  | 
|
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
903  | 
def test_invalid_position(self):  | 
904  | 
transport = MockTransport([  | 
|
905  | 
_KnitIndex.HEADER,  | 
|
906  | 
"a option 1v 1 :",  | 
|
907  | 
            ])
 | 
|
908  | 
try:  | 
|
909  | 
self.assertRaises(errors.KnitCorrupt,  | 
|
910  | 
self.get_knit_index, transport, 'filename', 'r')  | 
|
911  | 
except TypeError, e:  | 
|
912  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
913  | 
' not exceptions.ValueError')  | 
|
914  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
915  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
916  | 
                                  ' raising new style exceptions with python'
 | 
|
917  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
918  | 
else:  | 
919  | 
                raise
 | 
|
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
920  | 
|
921  | 
def test_invalid_size(self):  | 
|
922  | 
transport = MockTransport([  | 
|
923  | 
_KnitIndex.HEADER,  | 
|
924  | 
"a option 1 1v :",  | 
|
925  | 
            ])
 | 
|
926  | 
try:  | 
|
927  | 
self.assertRaises(errors.KnitCorrupt,  | 
|
928  | 
self.get_knit_index, transport, 'filename', 'r')  | 
|
929  | 
except TypeError, e:  | 
|
930  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
931  | 
' not exceptions.ValueError')  | 
|
932  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
933  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
934  | 
                                  ' raising new style exceptions with python'
 | 
|
935  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
936  | 
else:  | 
937  | 
                raise
 | 
|
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
938  | 
|
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
939  | 
def test_short_line(self):  | 
940  | 
transport = MockTransport([  | 
|
941  | 
_KnitIndex.HEADER,  | 
|
942  | 
"a option 0 10 :",  | 
|
943  | 
"b option 10 10 0", # This line isn't terminated, ignored  | 
|
944  | 
            ])
 | 
|
945  | 
index = self.get_knit_index(transport, "filename", "r")  | 
|
946  | 
self.assertEqual(['a'], index.get_versions())  | 
|
947  | 
||
948  | 
def test_skip_incomplete_record(self):  | 
|
949  | 
        # A line with bogus data should just be skipped
 | 
|
950  | 
transport = MockTransport([  | 
|
951  | 
_KnitIndex.HEADER,  | 
|
952  | 
"a option 0 10 :",  | 
|
953  | 
"b option 10 10 0", # This line isn't terminated, ignored  | 
|
954  | 
"c option 20 10 0 :", # Properly terminated, and starts with '\n'  | 
|
955  | 
            ])
 | 
|
956  | 
index = self.get_knit_index(transport, "filename", "r")  | 
|
957  | 
self.assertEqual(['a', 'c'], index.get_versions())  | 
|
958  | 
||
959  | 
def test_trailing_characters(self):  | 
|
960  | 
        # A line with bogus data should just be skipped
 | 
|
961  | 
transport = MockTransport([  | 
|
962  | 
_KnitIndex.HEADER,  | 
|
963  | 
"a option 0 10 :",  | 
|
964  | 
"b option 10 10 0 :a", # This line has extra trailing characters  | 
|
965  | 
"c option 20 10 0 :", # Properly terminated, and starts with '\n'  | 
|
966  | 
            ])
 | 
|
967  | 
index = self.get_knit_index(transport, "filename", "r")  | 
|
968  | 
self.assertEqual(['a', 'c'], index.get_versions())  | 
|
969  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
970  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
971  | 
class LowLevelKnitIndexTests_c(LowLevelKnitIndexTests):  | 
972  | 
||
973  | 
_test_needs_features = [CompiledKnitFeature]  | 
|
974  | 
||
975  | 
def get_knit_index(self, *args, **kwargs):  | 
|
976  | 
orig = knit._load_data  | 
|
977  | 
def reset():  | 
|
978  | 
knit._load_data = orig  | 
|
979  | 
self.addCleanup(reset)  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
980  | 
from bzrlib._knit_load_data_c import _load_data_c  | 
981  | 
knit._load_data = _load_data_c  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
982  | 
return _KnitIndex(*args, **kwargs)  | 
983  | 
||
984  | 
||
985  | 
||
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
986  | 
class KnitTests(TestCaseWithTransport):  | 
987  | 
"""Class containing knit test helper routines."""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
988  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
989  | 
def make_test_knit(self, annotate=False, delay_create=False, index=None):  | 
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
990  | 
if not annotate:  | 
991  | 
factory = KnitPlainFactory()  | 
|
992  | 
else:  | 
|
993  | 
factory = None  | 
|
| 
1946.2.1
by John Arbash Meinel
 2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories  | 
994  | 
return KnitVersionedFile('test', get_transport('.'), access_mode='w',  | 
995  | 
factory=factory, create=True,  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
996  | 
delay_create=delay_create, index=index)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
997  | 
|
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
998  | 
|
999  | 
class BasicKnitTests(KnitTests):  | 
|
1000  | 
||
1001  | 
def add_stock_one_and_one_a(self, k):  | 
|
1002  | 
k.add_lines('text-1', [], split_lines(TEXT_1))  | 
|
1003  | 
k.add_lines('text-1a', ['text-1'], split_lines(TEXT_1A))  | 
|
1004  | 
||
1005  | 
def test_knit_constructor(self):  | 
|
1006  | 
"""Construct empty k"""  | 
|
1007  | 
self.make_test_knit()  | 
|
1008  | 
||
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1009  | 
def test_make_explicit_index(self):  | 
1010  | 
"""We can supply an index to use."""  | 
|
1011  | 
knit = KnitVersionedFile('test', get_transport('.'),  | 
|
1012  | 
index='strangelove')  | 
|
1013  | 
self.assertEqual(knit._index, 'strangelove')  | 
|
1014  | 
||
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1015  | 
def test_knit_add(self):  | 
1016  | 
"""Store one text in knit and retrieve"""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1017  | 
k = self.make_test_knit()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1018  | 
k.add_lines('text-1', [], split_lines(TEXT_1))  | 
1019  | 
self.assertTrue(k.has_version('text-1'))  | 
|
1020  | 
self.assertEqualDiff(''.join(k.get_lines('text-1')), TEXT_1)  | 
|
1021  | 
||
1022  | 
def test_knit_reload(self):  | 
|
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1023  | 
        # test that the content in a reloaded knit is correct
 | 
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1024  | 
k = self.make_test_knit()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1025  | 
k.add_lines('text-1', [], split_lines(TEXT_1))  | 
1026  | 
del k  | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1027  | 
k2 = KnitVersionedFile('test', get_transport('.'), access_mode='r', factory=KnitPlainFactory(), create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1028  | 
self.assertTrue(k2.has_version('text-1'))  | 
1029  | 
self.assertEqualDiff(''.join(k2.get_lines('text-1')), TEXT_1)  | 
|
1030  | 
||
1031  | 
def test_knit_several(self):  | 
|
1032  | 
"""Store several texts in a knit"""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1033  | 
k = self.make_test_knit()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1034  | 
k.add_lines('text-1', [], split_lines(TEXT_1))  | 
1035  | 
k.add_lines('text-2', [], split_lines(TEXT_2))  | 
|
1036  | 
self.assertEqualDiff(''.join(k.get_lines('text-1')), TEXT_1)  | 
|
1037  | 
self.assertEqualDiff(''.join(k.get_lines('text-2')), TEXT_2)  | 
|
1038  | 
||
1039  | 
def test_repeated_add(self):  | 
|
1040  | 
"""Knit traps attempt to replace existing version"""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1041  | 
k = self.make_test_knit()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1042  | 
k.add_lines('text-1', [], split_lines(TEXT_1))  | 
1043  | 
self.assertRaises(RevisionAlreadyPresent,  | 
|
1044  | 
k.add_lines,  | 
|
1045  | 
'text-1', [], split_lines(TEXT_1))  | 
|
1046  | 
||
1047  | 
def test_empty(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1048  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1049  | 
k.add_lines('text-1', [], [])  | 
1050  | 
self.assertEquals(k.get_lines('text-1'), [])  | 
|
1051  | 
||
1052  | 
def test_incomplete(self):  | 
|
1053  | 
"""Test if texts without a ending line-end can be inserted and  | 
|
1054  | 
        extracted."""
 | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1055  | 
k = KnitVersionedFile('test', get_transport('.'), delta=False, create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1056  | 
k.add_lines('text-1', [], ['a\n', 'b' ])  | 
1057  | 
k.add_lines('text-2', ['text-1'], ['a\rb\n', 'b\n'])  | 
|
| 
1666.1.6
by Robert Collins
 Make knit the default format.  | 
1058  | 
        # reopening ensures maximum room for confusion
 | 
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1059  | 
k = KnitVersionedFile('test', get_transport('.'), delta=False, create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1060  | 
self.assertEquals(k.get_lines('text-1'), ['a\n', 'b' ])  | 
1061  | 
self.assertEquals(k.get_lines('text-2'), ['a\rb\n', 'b\n'])  | 
|
1062  | 
||
1063  | 
def test_delta(self):  | 
|
1064  | 
"""Expression of knit delta as lines"""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1065  | 
k = self.make_test_knit()  | 
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
1066  | 
        KnitContent
 | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1067  | 
td = list(line_delta(TEXT_1.splitlines(True),  | 
1068  | 
TEXT_1A.splitlines(True)))  | 
|
1069  | 
self.assertEqualDiff(''.join(td), delta_1_1a)  | 
|
1070  | 
out = apply_line_delta(TEXT_1.splitlines(True), td)  | 
|
1071  | 
self.assertEqualDiff(''.join(out), TEXT_1A)  | 
|
1072  | 
||
| 
2520.4.47
by Aaron Bentley
 Fix get_line_delta_blocks with eol  | 
1073  | 
def assertDerivedBlocksEqual(self, source, target, noeol=False):  | 
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
1074  | 
"""Assert that the derived matching blocks match real output"""  | 
1075  | 
source_lines = source.splitlines(True)  | 
|
1076  | 
target_lines = target.splitlines(True)  | 
|
| 
2520.4.47
by Aaron Bentley
 Fix get_line_delta_blocks with eol  | 
1077  | 
def nl(line):  | 
1078  | 
if noeol and not line.endswith('\n'):  | 
|
1079  | 
return line + '\n'  | 
|
1080  | 
else:  | 
|
1081  | 
return line  | 
|
1082  | 
source_content = KnitContent([(None, nl(l)) for l in source_lines])  | 
|
1083  | 
target_content = KnitContent([(None, nl(l)) for l in target_lines])  | 
|
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
1084  | 
line_delta = source_content.line_delta(target_content)  | 
| 
2520.4.47
by Aaron Bentley
 Fix get_line_delta_blocks with eol  | 
1085  | 
delta_blocks = list(KnitContent.get_line_delta_blocks(line_delta,  | 
1086  | 
source_lines, target_lines))  | 
|
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
1087  | 
matcher = KnitSequenceMatcher(None, source_lines, target_lines)  | 
| 
2520.4.47
by Aaron Bentley
 Fix get_line_delta_blocks with eol  | 
1088  | 
matcher_blocks = list(list(matcher.get_matching_blocks()))  | 
1089  | 
self.assertEqual(matcher_blocks, delta_blocks)  | 
|
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
1090  | 
|
1091  | 
def test_get_line_delta_blocks(self):  | 
|
1092  | 
self.assertDerivedBlocksEqual('a\nb\nc\n', 'q\nc\n')  | 
|
1093  | 
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1)  | 
|
1094  | 
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1A)  | 
|
1095  | 
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1B)  | 
|
1096  | 
self.assertDerivedBlocksEqual(TEXT_1B, TEXT_1A)  | 
|
1097  | 
self.assertDerivedBlocksEqual(TEXT_1A, TEXT_1B)  | 
|
1098  | 
self.assertDerivedBlocksEqual(TEXT_1A, '')  | 
|
1099  | 
self.assertDerivedBlocksEqual('', TEXT_1A)  | 
|
1100  | 
self.assertDerivedBlocksEqual('', '')  | 
|
| 
2520.4.47
by Aaron Bentley
 Fix get_line_delta_blocks with eol  | 
1101  | 
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd')  | 
1102  | 
||
1103  | 
def test_get_line_delta_blocks_noeol(self):  | 
|
| 
2520.4.48
by Aaron Bentley
 Support getting blocks from knit deltas with no final EOL  | 
1104  | 
"""Handle historical knit deltas safely  | 
1105  | 
||
1106  | 
        Some existing knit deltas don't consider the last line to differ
 | 
|
1107  | 
        when the only difference whether it has a final newline.
 | 
|
1108  | 
||
1109  | 
        New knit deltas appear to always consider the last line to differ
 | 
|
1110  | 
        in this case.
 | 
|
1111  | 
        """
 | 
|
| 
2520.4.47
by Aaron Bentley
 Fix get_line_delta_blocks with eol  | 
1112  | 
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd\n', noeol=True)  | 
1113  | 
self.assertDerivedBlocksEqual('a\nb\nc\nd\n', 'a\nb\nc', noeol=True)  | 
|
| 
2520.4.48
by Aaron Bentley
 Support getting blocks from knit deltas with no final EOL  | 
1114  | 
self.assertDerivedBlocksEqual('a\nb\nc\n', 'a\nb\nc', noeol=True)  | 
1115  | 
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\n', noeol=True)  | 
|
| 
2520.4.41
by Aaron Bentley
 Accelerate mpdiff generation  | 
1116  | 
|
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1117  | 
def test_add_with_parents(self):  | 
1118  | 
"""Store in knit with parents"""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1119  | 
k = self.make_test_knit()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1120  | 
self.add_stock_one_and_one_a(k)  | 
1121  | 
self.assertEquals(k.get_parents('text-1'), [])  | 
|
1122  | 
self.assertEquals(k.get_parents('text-1a'), ['text-1'])  | 
|
1123  | 
||
1124  | 
def test_ancestry(self):  | 
|
1125  | 
"""Store in knit with parents"""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1126  | 
k = self.make_test_knit()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1127  | 
self.add_stock_one_and_one_a(k)  | 
1128  | 
self.assertEquals(set(k.get_ancestry(['text-1a'])), set(['text-1a', 'text-1']))  | 
|
1129  | 
||
1130  | 
def test_add_delta(self):  | 
|
1131  | 
"""Store in knit with parents"""  | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1132  | 
k = KnitVersionedFile('test', get_transport('.'), factory=KnitPlainFactory(),  | 
| 
1563.2.25
by Robert Collins
 Merge in upstream.  | 
1133  | 
delta=True, create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1134  | 
self.add_stock_one_and_one_a(k)  | 
| 
1596.2.7
by Robert Collins
 Remove the requirement for reannotation in knit joins.  | 
1135  | 
k.clear_cache()  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1136  | 
self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A)  | 
1137  | 
||
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1138  | 
def test_add_delta_knit_graph_index(self):  | 
1139  | 
"""Does adding work with a KnitGraphIndex."""  | 
|
1140  | 
index = InMemoryGraphIndex(2)  | 
|
1141  | 
knit_index = KnitGraphIndex(index, add_callback=index.add_nodes,  | 
|
1142  | 
deltas=True)  | 
|
1143  | 
k = KnitVersionedFile('test', get_transport('.'),  | 
|
1144  | 
delta=True, create=True, index=knit_index)  | 
|
1145  | 
self.add_stock_one_and_one_a(k)  | 
|
1146  | 
k.clear_cache()  | 
|
1147  | 
self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A)  | 
|
1148  | 
        # check the index had the right data added.
 | 
|
1149  | 
self.assertEqual(set([  | 
|
| 
2624.2.14
by Robert Collins
 Add source index to the index iteration API to allow mapping back to the origin of retrieved data.  | 
1150  | 
(index, ('text-1', ), ' 0 127', ((), ())),  | 
1151  | 
(index, ('text-1a', ), ' 127 140', ((('text-1', ),), (('text-1', ),))),  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1152  | 
]), set(index.iter_all_entries()))  | 
1153  | 
        # we should not have a .kndx file
 | 
|
1154  | 
self.assertFalse(get_transport('.').has('test.kndx'))  | 
|
1155  | 
||
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1156  | 
def test_annotate(self):  | 
1157  | 
"""Annotations"""  | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1158  | 
k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(),  | 
| 
1563.2.25
by Robert Collins
 Merge in upstream.  | 
1159  | 
delta=True, create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1160  | 
self.insert_and_test_small_annotate(k)  | 
1161  | 
||
1162  | 
def insert_and_test_small_annotate(self, k):  | 
|
1163  | 
"""test annotation with k works correctly."""  | 
|
1164  | 
k.add_lines('text-1', [], ['a\n', 'b\n'])  | 
|
1165  | 
k.add_lines('text-2', ['text-1'], ['a\n', 'c\n'])  | 
|
1166  | 
||
1167  | 
origins = k.annotate('text-2')  | 
|
1168  | 
self.assertEquals(origins[0], ('text-1', 'a\n'))  | 
|
1169  | 
self.assertEquals(origins[1], ('text-2', 'c\n'))  | 
|
1170  | 
||
1171  | 
def test_annotate_fulltext(self):  | 
|
1172  | 
"""Annotations"""  | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1173  | 
k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(),  | 
| 
1563.2.25
by Robert Collins
 Merge in upstream.  | 
1174  | 
delta=False, create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1175  | 
self.insert_and_test_small_annotate(k)  | 
1176  | 
||
1177  | 
def test_annotate_merge_1(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1178  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1179  | 
k.add_lines('text-a1', [], ['a\n', 'b\n'])  | 
1180  | 
k.add_lines('text-a2', [], ['d\n', 'c\n'])  | 
|
1181  | 
k.add_lines('text-am', ['text-a1', 'text-a2'], ['d\n', 'b\n'])  | 
|
1182  | 
origins = k.annotate('text-am')  | 
|
1183  | 
self.assertEquals(origins[0], ('text-a2', 'd\n'))  | 
|
1184  | 
self.assertEquals(origins[1], ('text-a1', 'b\n'))  | 
|
1185  | 
||
1186  | 
def test_annotate_merge_2(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1187  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1188  | 
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n'])  | 
1189  | 
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n'])  | 
|
1190  | 
k.add_lines('text-am', ['text-a1', 'text-a2'], ['a\n', 'y\n', 'c\n'])  | 
|
1191  | 
origins = k.annotate('text-am')  | 
|
1192  | 
self.assertEquals(origins[0], ('text-a1', 'a\n'))  | 
|
1193  | 
self.assertEquals(origins[1], ('text-a2', 'y\n'))  | 
|
1194  | 
self.assertEquals(origins[2], ('text-a1', 'c\n'))  | 
|
1195  | 
||
1196  | 
def test_annotate_merge_9(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1197  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1198  | 
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n'])  | 
1199  | 
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n'])  | 
|
1200  | 
k.add_lines('text-am', ['text-a1', 'text-a2'], ['k\n', 'y\n', 'c\n'])  | 
|
1201  | 
origins = k.annotate('text-am')  | 
|
1202  | 
self.assertEquals(origins[0], ('text-am', 'k\n'))  | 
|
1203  | 
self.assertEquals(origins[1], ('text-a2', 'y\n'))  | 
|
1204  | 
self.assertEquals(origins[2], ('text-a1', 'c\n'))  | 
|
1205  | 
||
1206  | 
def test_annotate_merge_3(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1207  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1208  | 
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n'])  | 
1209  | 
k.add_lines('text-a2', [] ,['x\n', 'y\n', 'z\n'])  | 
|
1210  | 
k.add_lines('text-am', ['text-a1', 'text-a2'], ['k\n', 'y\n', 'z\n'])  | 
|
1211  | 
origins = k.annotate('text-am')  | 
|
1212  | 
self.assertEquals(origins[0], ('text-am', 'k\n'))  | 
|
1213  | 
self.assertEquals(origins[1], ('text-a2', 'y\n'))  | 
|
1214  | 
self.assertEquals(origins[2], ('text-a2', 'z\n'))  | 
|
1215  | 
||
1216  | 
def test_annotate_merge_4(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1217  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1218  | 
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n'])  | 
1219  | 
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n'])  | 
|
1220  | 
k.add_lines('text-a3', ['text-a1'], ['a\n', 'b\n', 'p\n'])  | 
|
1221  | 
k.add_lines('text-am', ['text-a2', 'text-a3'], ['a\n', 'b\n', 'z\n'])  | 
|
1222  | 
origins = k.annotate('text-am')  | 
|
1223  | 
self.assertEquals(origins[0], ('text-a1', 'a\n'))  | 
|
1224  | 
self.assertEquals(origins[1], ('text-a1', 'b\n'))  | 
|
1225  | 
self.assertEquals(origins[2], ('text-a2', 'z\n'))  | 
|
1226  | 
||
1227  | 
def test_annotate_merge_5(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1228  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1229  | 
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n'])  | 
1230  | 
k.add_lines('text-a2', [], ['d\n', 'e\n', 'f\n'])  | 
|
1231  | 
k.add_lines('text-a3', [], ['x\n', 'y\n', 'z\n'])  | 
|
1232  | 
k.add_lines('text-am',  | 
|
1233  | 
['text-a1', 'text-a2', 'text-a3'],  | 
|
1234  | 
['a\n', 'e\n', 'z\n'])  | 
|
1235  | 
origins = k.annotate('text-am')  | 
|
1236  | 
self.assertEquals(origins[0], ('text-a1', 'a\n'))  | 
|
1237  | 
self.assertEquals(origins[1], ('text-a2', 'e\n'))  | 
|
1238  | 
self.assertEquals(origins[2], ('text-a3', 'z\n'))  | 
|
1239  | 
||
1240  | 
def test_annotate_file_cherry_pick(self):  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1241  | 
k = self.make_test_knit(True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1242  | 
k.add_lines('text-1', [], ['a\n', 'b\n', 'c\n'])  | 
1243  | 
k.add_lines('text-2', ['text-1'], ['d\n', 'e\n', 'f\n'])  | 
|
1244  | 
k.add_lines('text-3', ['text-2', 'text-1'], ['a\n', 'b\n', 'c\n'])  | 
|
1245  | 
origins = k.annotate('text-3')  | 
|
1246  | 
self.assertEquals(origins[0], ('text-1', 'a\n'))  | 
|
1247  | 
self.assertEquals(origins[1], ('text-1', 'b\n'))  | 
|
1248  | 
self.assertEquals(origins[2], ('text-1', 'c\n'))  | 
|
1249  | 
||
1250  | 
def test_knit_join(self):  | 
|
1251  | 
"""Store in knit with parents"""  | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1252  | 
k1 = KnitVersionedFile('test1', get_transport('.'), factory=KnitPlainFactory(), create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1253  | 
k1.add_lines('text-a', [], split_lines(TEXT_1))  | 
1254  | 
k1.add_lines('text-b', ['text-a'], split_lines(TEXT_1))  | 
|
1255  | 
||
1256  | 
k1.add_lines('text-c', [], split_lines(TEXT_1))  | 
|
1257  | 
k1.add_lines('text-d', ['text-c'], split_lines(TEXT_1))  | 
|
1258  | 
||
1259  | 
k1.add_lines('text-m', ['text-b', 'text-d'], split_lines(TEXT_1))  | 
|
1260  | 
||
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1261  | 
k2 = KnitVersionedFile('test2', get_transport('.'), factory=KnitPlainFactory(), create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1262  | 
count = k2.join(k1, version_ids=['text-m'])  | 
1263  | 
self.assertEquals(count, 5)  | 
|
1264  | 
self.assertTrue(k2.has_version('text-a'))  | 
|
1265  | 
self.assertTrue(k2.has_version('text-c'))  | 
|
1266  | 
||
1267  | 
def test_reannotate(self):  | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1268  | 
k1 = KnitVersionedFile('knit1', get_transport('.'),  | 
| 
1563.2.25
by Robert Collins
 Merge in upstream.  | 
1269  | 
factory=KnitAnnotateFactory(), create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1270  | 
        # 0
 | 
1271  | 
k1.add_lines('text-a', [], ['a\n', 'b\n'])  | 
|
1272  | 
        # 1
 | 
|
1273  | 
k1.add_lines('text-b', ['text-a'], ['a\n', 'c\n'])  | 
|
1274  | 
||
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1275  | 
k2 = KnitVersionedFile('test2', get_transport('.'),  | 
| 
1563.2.25
by Robert Collins
 Merge in upstream.  | 
1276  | 
factory=KnitAnnotateFactory(), create=True)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1277  | 
k2.join(k1, version_ids=['text-b'])  | 
1278  | 
||
1279  | 
        # 2
 | 
|
1280  | 
k1.add_lines('text-X', ['text-b'], ['a\n', 'b\n'])  | 
|
1281  | 
        # 2
 | 
|
1282  | 
k2.add_lines('text-c', ['text-b'], ['z\n', 'c\n'])  | 
|
1283  | 
        # 3
 | 
|
1284  | 
k2.add_lines('text-Y', ['text-b'], ['b\n', 'c\n'])  | 
|
1285  | 
||
1286  | 
        # test-c will have index 3
 | 
|
1287  | 
k1.join(k2, version_ids=['text-c'])  | 
|
1288  | 
||
1289  | 
lines = k1.get_lines('text-c')  | 
|
1290  | 
self.assertEquals(lines, ['z\n', 'c\n'])  | 
|
1291  | 
||
1292  | 
origins = k1.annotate('text-c')  | 
|
| 
1594.2.24
by Robert Collins
 Make use of the transaction finalisation warning support to implement in-knit caching.  | 
1293  | 
self.assertEquals(origins[0], ('text-c', 'z\n'))  | 
1294  | 
self.assertEquals(origins[1], ('text-b', 'c\n'))  | 
|
1295  | 
||
| 
1756.3.4
by Aaron Bentley
 Fix bug getting texts when line deltas were reused  | 
1296  | 
def test_get_line_delta_texts(self):  | 
1297  | 
"""Make sure we can call get_texts on text with reused line deltas"""  | 
|
1298  | 
k1 = KnitVersionedFile('test1', get_transport('.'),  | 
|
1299  | 
factory=KnitPlainFactory(), create=True)  | 
|
1300  | 
for t in range(3):  | 
|
1301  | 
if t == 0:  | 
|
1302  | 
parents = []  | 
|
1303  | 
else:  | 
|
1304  | 
parents = ['%d' % (t-1)]  | 
|
1305  | 
k1.add_lines('%d' % t, parents, ['hello\n'] * t)  | 
|
1306  | 
k1.get_texts(('%d' % t) for t in range(3))  | 
|
| 
1594.3.1
by Robert Collins
 Merge transaction finalisation and ensure iter_lines_added_or_present in knits does a old-to-new read in the knit.  | 
1307  | 
|
1308  | 
def test_iter_lines_reads_in_order(self):  | 
|
1309  | 
t = MemoryTransport()  | 
|
1310  | 
instrumented_t = TransportLogger(t)  | 
|
1311  | 
k1 = KnitVersionedFile('id', instrumented_t, create=True, delta=True)  | 
|
1312  | 
self.assertEqual([('id.kndx',)], instrumented_t._calls)  | 
|
1313  | 
        # add texts with no required ordering
 | 
|
1314  | 
k1.add_lines('base', [], ['text\n'])  | 
|
1315  | 
k1.add_lines('base2', [], ['text2\n'])  | 
|
1316  | 
k1.clear_cache()  | 
|
1317  | 
instrumented_t._calls = []  | 
|
1318  | 
        # request a last-first iteration
 | 
|
1319  | 
results = list(k1.iter_lines_added_or_present_in_versions(['base2', 'base']))  | 
|
| 
1628.1.2
by Robert Collins
 More knit micro-optimisations.  | 
1320  | 
self.assertEqual([('id.knit', [(0, 87), (87, 89)])], instrumented_t._calls)  | 
| 
1594.3.1
by Robert Collins
 Merge transaction finalisation and ensure iter_lines_added_or_present in knits does a old-to-new read in the knit.  | 
1321  | 
self.assertEqual(['text\n', 'text2\n'], results)  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1322  | 
|
| 
1563.2.13
by Robert Collins
 InterVersionedFile implemented.  | 
1323  | 
def test_create_empty_annotated(self):  | 
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1324  | 
k1 = self.make_test_knit(True)  | 
| 
1563.2.13
by Robert Collins
 InterVersionedFile implemented.  | 
1325  | 
        # 0
 | 
1326  | 
k1.add_lines('text-a', [], ['a\n', 'b\n'])  | 
|
1327  | 
k2 = k1.create_empty('t', MemoryTransport())  | 
|
1328  | 
self.assertTrue(isinstance(k2.factory, KnitAnnotateFactory))  | 
|
1329  | 
self.assertEqual(k1.delta, k2.delta)  | 
|
1330  | 
        # the generic test checks for empty content and file class
 | 
|
1331  | 
||
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1332  | 
def test_knit_format(self):  | 
1333  | 
        # this tests that a new knit index file has the expected content
 | 
|
1334  | 
        # and that is writes the data we expect as records are added.
 | 
|
1335  | 
knit = self.make_test_knit(True)  | 
|
| 
1946.2.1
by John Arbash Meinel
 2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories  | 
1336  | 
        # Now knit files are not created until we first add data to them
 | 
| 
1666.1.6
by Robert Collins
 Make knit the default format.  | 
1337  | 
self.assertFileEqual("# bzr knit index 8\n", 'test.kndx')  | 
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1338  | 
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n'])  | 
1339  | 
self.assertFileEqual(  | 
|
| 
1666.1.6
by Robert Collins
 Make knit the default format.  | 
1340  | 
"# bzr knit index 8\n"  | 
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1341  | 
"\n"  | 
1342  | 
"revid fulltext 0 84 .a_ghost :",  | 
|
1343  | 
'test.kndx')  | 
|
1344  | 
knit.add_lines_with_ghosts('revid2', ['revid'], ['a\n'])  | 
|
1345  | 
self.assertFileEqual(  | 
|
| 
1666.1.6
by Robert Collins
 Make knit the default format.  | 
1346  | 
"# bzr knit index 8\n"  | 
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1347  | 
"\nrevid fulltext 0 84 .a_ghost :"  | 
1348  | 
"\nrevid2 line-delta 84 82 0 :",  | 
|
1349  | 
'test.kndx')  | 
|
1350  | 
        # we should be able to load this file again
 | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1351  | 
knit = KnitVersionedFile('test', get_transport('.'), access_mode='r')  | 
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1352  | 
self.assertEqual(['revid', 'revid2'], knit.versions())  | 
1353  | 
        # write a short write to the file and ensure that its ignored
 | 
|
| 
2484.1.23
by John Arbash Meinel
 When we append a new line, don't use text mode  | 
1354  | 
indexfile = file('test.kndx', 'ab')  | 
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1355  | 
indexfile.write('\nrevid3 line-delta 166 82 1 2 3 4 5 .phwoar:demo ')  | 
1356  | 
indexfile.close()  | 
|
1357  | 
        # we should be able to load this file again
 | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1358  | 
knit = KnitVersionedFile('test', get_transport('.'), access_mode='w')  | 
| 
1654.1.5
by Robert Collins
 Merge partial index write support for knits, adding a test case per review comments.  | 
1359  | 
self.assertEqual(['revid', 'revid2'], knit.versions())  | 
1360  | 
        # and add a revision with the same id the failed write had
 | 
|
1361  | 
knit.add_lines('revid3', ['revid2'], ['a\n'])  | 
|
1362  | 
        # and when reading it revid3 should now appear.
 | 
|
| 
1685.1.39
by John Arbash Meinel
 Updating test_knit to not instantiate a LocalTransport directly.  | 
1363  | 
knit = KnitVersionedFile('test', get_transport('.'), access_mode='r')  | 
| 
1654.1.5
by Robert Collins
 Merge partial index write support for knits, adding a test case per review comments.  | 
1364  | 
self.assertEqual(['revid', 'revid2', 'revid3'], knit.versions())  | 
1365  | 
self.assertEqual(['revid2'], knit.get_parents('revid3'))  | 
|
1366  | 
||
| 
1946.2.1
by John Arbash Meinel
 2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories  | 
1367  | 
def test_delay_create(self):  | 
1368  | 
"""Test that passing delay_create=True creates files late"""  | 
|
1369  | 
knit = self.make_test_knit(annotate=True, delay_create=True)  | 
|
1370  | 
self.failIfExists('test.knit')  | 
|
1371  | 
self.failIfExists('test.kndx')  | 
|
1372  | 
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n'])  | 
|
1373  | 
self.failUnlessExists('test.knit')  | 
|
1374  | 
self.assertFileEqual(  | 
|
1375  | 
"# bzr knit index 8\n"  | 
|
1376  | 
"\n"  | 
|
1377  | 
"revid fulltext 0 84 .a_ghost :",  | 
|
1378  | 
'test.kndx')  | 
|
1379  | 
||
| 
1946.2.2
by John Arbash Meinel
 test delay_create does the right thing  | 
1380  | 
def test_create_parent_dir(self):  | 
1381  | 
"""create_parent_dir can create knits in nonexistant dirs"""  | 
|
1382  | 
        # Has no effect if we don't set 'delay_create'
 | 
|
1383  | 
trans = get_transport('.')  | 
|
1384  | 
self.assertRaises(NoSuchFile, KnitVersionedFile, 'dir/test',  | 
|
1385  | 
trans, access_mode='w', factory=None,  | 
|
1386  | 
create=True, create_parent_dir=True)  | 
|
1387  | 
        # Nothing should have changed yet
 | 
|
1388  | 
knit = KnitVersionedFile('dir/test', trans, access_mode='w',  | 
|
1389  | 
factory=None, create=True,  | 
|
1390  | 
create_parent_dir=True,  | 
|
1391  | 
delay_create=True)  | 
|
1392  | 
self.failIfExists('dir/test.knit')  | 
|
1393  | 
self.failIfExists('dir/test.kndx')  | 
|
1394  | 
self.failIfExists('dir')  | 
|
1395  | 
knit.add_lines('revid', [], ['a\n'])  | 
|
1396  | 
self.failUnlessExists('dir')  | 
|
1397  | 
self.failUnlessExists('dir/test.knit')  | 
|
1398  | 
self.assertFileEqual(  | 
|
1399  | 
"# bzr knit index 8\n"  | 
|
1400  | 
"\n"  | 
|
1401  | 
"revid fulltext 0 84 :",  | 
|
1402  | 
'dir/test.kndx')  | 
|
1403  | 
||
| 
1946.2.13
by John Arbash Meinel
 Test that passing modes does the right thing for knits.  | 
1404  | 
def test_create_mode_700(self):  | 
1405  | 
trans = get_transport('.')  | 
|
1406  | 
if not trans._can_roundtrip_unix_modebits():  | 
|
1407  | 
            # Can't roundtrip, so no need to run this test
 | 
|
1408  | 
            return
 | 
|
1409  | 
knit = KnitVersionedFile('dir/test', trans, access_mode='w',  | 
|
1410  | 
factory=None, create=True,  | 
|
1411  | 
create_parent_dir=True,  | 
|
1412  | 
delay_create=True,  | 
|
1413  | 
file_mode=0600,  | 
|
1414  | 
dir_mode=0700)  | 
|
1415  | 
knit.add_lines('revid', [], ['a\n'])  | 
|
1416  | 
self.assertTransportMode(trans, 'dir', 0700)  | 
|
1417  | 
self.assertTransportMode(trans, 'dir/test.knit', 0600)  | 
|
1418  | 
self.assertTransportMode(trans, 'dir/test.kndx', 0600)  | 
|
1419  | 
||
1420  | 
def test_create_mode_770(self):  | 
|
1421  | 
trans = get_transport('.')  | 
|
1422  | 
if not trans._can_roundtrip_unix_modebits():  | 
|
1423  | 
            # Can't roundtrip, so no need to run this test
 | 
|
1424  | 
            return
 | 
|
1425  | 
knit = KnitVersionedFile('dir/test', trans, access_mode='w',  | 
|
1426  | 
factory=None, create=True,  | 
|
1427  | 
create_parent_dir=True,  | 
|
1428  | 
delay_create=True,  | 
|
1429  | 
file_mode=0660,  | 
|
1430  | 
dir_mode=0770)  | 
|
1431  | 
knit.add_lines('revid', [], ['a\n'])  | 
|
1432  | 
self.assertTransportMode(trans, 'dir', 0770)  | 
|
1433  | 
self.assertTransportMode(trans, 'dir/test.knit', 0660)  | 
|
1434  | 
self.assertTransportMode(trans, 'dir/test.kndx', 0660)  | 
|
1435  | 
||
1436  | 
def test_create_mode_777(self):  | 
|
1437  | 
trans = get_transport('.')  | 
|
1438  | 
if not trans._can_roundtrip_unix_modebits():  | 
|
1439  | 
            # Can't roundtrip, so no need to run this test
 | 
|
1440  | 
            return
 | 
|
1441  | 
knit = KnitVersionedFile('dir/test', trans, access_mode='w',  | 
|
1442  | 
factory=None, create=True,  | 
|
1443  | 
create_parent_dir=True,  | 
|
1444  | 
delay_create=True,  | 
|
1445  | 
file_mode=0666,  | 
|
1446  | 
dir_mode=0777)  | 
|
1447  | 
knit.add_lines('revid', [], ['a\n'])  | 
|
1448  | 
self.assertTransportMode(trans, 'dir', 0777)  | 
|
1449  | 
self.assertTransportMode(trans, 'dir/test.knit', 0666)  | 
|
1450  | 
self.assertTransportMode(trans, 'dir/test.kndx', 0666)  | 
|
1451  | 
||
| 
1664.2.1
by Aaron Bentley
 Start work on plan_merge test  | 
1452  | 
def test_plan_merge(self):  | 
1453  | 
my_knit = self.make_test_knit(annotate=True)  | 
|
1454  | 
my_knit.add_lines('text1', [], split_lines(TEXT_1))  | 
|
1455  | 
my_knit.add_lines('text1a', ['text1'], split_lines(TEXT_1A))  | 
|
1456  | 
my_knit.add_lines('text1b', ['text1'], split_lines(TEXT_1B))  | 
|
| 
1664.2.3
by Aaron Bentley
 Add failing test case  | 
1457  | 
plan = list(my_knit.plan_merge('text1a', 'text1b'))  | 
| 
1664.2.6
by Aaron Bentley
 Got plan-merge passing tests  | 
1458  | 
for plan_line, expected_line in zip(plan, AB_MERGE):  | 
1459  | 
self.assertEqual(plan_line, expected_line)  | 
|
| 
1641.1.2
by Robert Collins
 Change knit index files to be robust in the presence of partial writes.  | 
1460  | 
|
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1461  | 
|
1462  | 
TEXT_1 = """\  | 
|
1463  | 
Banana cup cakes:
 | 
|
1464  | 
||
1465  | 
- bananas
 | 
|
1466  | 
- eggs
 | 
|
1467  | 
- broken tea cups
 | 
|
1468  | 
"""
 | 
|
1469  | 
||
1470  | 
TEXT_1A = """\  | 
|
1471  | 
Banana cup cake recipe
 | 
|
1472  | 
(serves 6)
 | 
|
1473  | 
||
1474  | 
- bananas
 | 
|
1475  | 
- eggs
 | 
|
1476  | 
- broken tea cups
 | 
|
1477  | 
- self-raising flour
 | 
|
1478  | 
"""
 | 
|
1479  | 
||
| 
1664.2.1
by Aaron Bentley
 Start work on plan_merge test  | 
1480  | 
TEXT_1B = """\  | 
1481  | 
Banana cup cake recipe
 | 
|
1482  | 
||
1483  | 
- bananas (do not use plantains!!!)
 | 
|
1484  | 
- broken tea cups
 | 
|
1485  | 
- flour
 | 
|
1486  | 
"""
 | 
|
1487  | 
||
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1488  | 
delta_1_1a = """\  | 
1489  | 
0,1,2
 | 
|
1490  | 
Banana cup cake recipe
 | 
|
1491  | 
(serves 6)
 | 
|
1492  | 
5,5,1
 | 
|
1493  | 
- self-raising flour
 | 
|
1494  | 
"""
 | 
|
1495  | 
||
1496  | 
TEXT_2 = """\  | 
|
1497  | 
Boeuf bourguignon
 | 
|
1498  | 
||
1499  | 
- beef
 | 
|
1500  | 
- red wine
 | 
|
1501  | 
- small onions
 | 
|
1502  | 
- carrot
 | 
|
1503  | 
- mushrooms
 | 
|
1504  | 
"""
 | 
|
1505  | 
||
| 
1664.2.3
by Aaron Bentley
 Add failing test case  | 
1506  | 
AB_MERGE_TEXT="""unchanged|Banana cup cake recipe  | 
1507  | 
new-a|(serves 6)
 | 
|
1508  | 
unchanged|
 | 
|
1509  | 
killed-b|- bananas
 | 
|
1510  | 
killed-b|- eggs
 | 
|
1511  | 
new-b|- bananas (do not use plantains!!!)
 | 
|
1512  | 
unchanged|- broken tea cups
 | 
|
1513  | 
new-a|- self-raising flour
 | 
|
| 
1664.2.6
by Aaron Bentley
 Got plan-merge passing tests  | 
1514  | 
new-b|- flour
 | 
1515  | 
"""
 | 
|
| 
1664.2.3
by Aaron Bentley
 Add failing test case  | 
1516  | 
AB_MERGE=[tuple(l.split('|')) for l in AB_MERGE_TEXT.splitlines(True)]  | 
1517  | 
||
1518  | 
||
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
1519  | 
def line_delta(from_lines, to_lines):  | 
1520  | 
"""Generate line-based delta from one text to another"""  | 
|
1521  | 
s = difflib.SequenceMatcher(None, from_lines, to_lines)  | 
|
1522  | 
for op in s.get_opcodes():  | 
|
1523  | 
if op[0] == 'equal':  | 
|
1524  | 
            continue
 | 
|
1525  | 
yield '%d,%d,%d\n' % (op[1], op[2], op[4]-op[3])  | 
|
1526  | 
for i in range(op[3], op[4]):  | 
|
1527  | 
yield to_lines[i]  | 
|
1528  | 
||
1529  | 
||
1530  | 
def apply_line_delta(basis_lines, delta_lines):  | 
|
1531  | 
"""Apply a line-based perfect diff  | 
|
1532  | 
    
 | 
|
1533  | 
    basis_lines -- text to apply the patch to
 | 
|
1534  | 
    delta_lines -- diff instructions and content
 | 
|
1535  | 
    """
 | 
|
1536  | 
out = basis_lines[:]  | 
|
1537  | 
i = 0  | 
|
1538  | 
offset = 0  | 
|
1539  | 
while i < len(delta_lines):  | 
|
1540  | 
l = delta_lines[i]  | 
|
1541  | 
a, b, c = map(long, l.split(','))  | 
|
1542  | 
i = i + 1  | 
|
1543  | 
out[offset+a:offset+b] = delta_lines[i:i+c]  | 
|
1544  | 
i = i + c  | 
|
1545  | 
offset = offset + (b - a) + c  | 
|
1546  | 
return out  | 
|
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
1547  | 
|
1548  | 
||
1549  | 
class TestWeaveToKnit(KnitTests):  | 
|
1550  | 
||
1551  | 
def test_weave_to_knit_matches(self):  | 
|
1552  | 
        # check that the WeaveToKnit is_compatible function
 | 
|
1553  | 
        # registers True for a Weave to a Knit.
 | 
|
1554  | 
w = Weave()  | 
|
1555  | 
k = self.make_test_knit()  | 
|
1556  | 
self.failUnless(WeaveToKnit.is_compatible(w, k))  | 
|
1557  | 
self.failIf(WeaveToKnit.is_compatible(k, w))  | 
|
1558  | 
self.failIf(WeaveToKnit.is_compatible(w, w))  | 
|
1559  | 
self.failIf(WeaveToKnit.is_compatible(k, k))  | 
|
| 
1863.1.1
by John Arbash Meinel
 Allow Versioned files to do caching if explicitly asked, and implement for Knit  | 
1560  | 
|
1561  | 
||
1562  | 
class TestKnitCaching(KnitTests):  | 
|
1563  | 
||
1564  | 
def create_knit(self, cache_add=False):  | 
|
1565  | 
k = self.make_test_knit(True)  | 
|
1566  | 
if cache_add:  | 
|
1567  | 
k.enable_cache()  | 
|
1568  | 
||
1569  | 
k.add_lines('text-1', [], split_lines(TEXT_1))  | 
|
1570  | 
k.add_lines('text-2', [], split_lines(TEXT_2))  | 
|
1571  | 
return k  | 
|
1572  | 
||
1573  | 
def test_no_caching(self):  | 
|
1574  | 
k = self.create_knit()  | 
|
1575  | 
        # Nothing should be cached without setting 'enable_cache'
 | 
|
1576  | 
self.assertEqual({}, k._data._cache)  | 
|
1577  | 
||
1578  | 
def test_cache_add_and_clear(self):  | 
|
1579  | 
k = self.create_knit(True)  | 
|
1580  | 
||
1581  | 
self.assertEqual(['text-1', 'text-2'], sorted(k._data._cache.keys()))  | 
|
1582  | 
||
1583  | 
k.clear_cache()  | 
|
1584  | 
self.assertEqual({}, k._data._cache)  | 
|
1585  | 
||
1586  | 
def test_cache_data_read_raw(self):  | 
|
1587  | 
k = self.create_knit()  | 
|
1588  | 
||
1589  | 
        # Now cache and read
 | 
|
1590  | 
k.enable_cache()  | 
|
1591  | 
||
1592  | 
def read_one_raw(version):  | 
|
1593  | 
pos_map = k._get_components_positions([version])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1594  | 
method, index_memo, next = pos_map[version]  | 
1595  | 
lst = list(k._data.read_records_iter_raw([(version, index_memo)]))  | 
|
| 
1863.1.1
by John Arbash Meinel
 Allow Versioned files to do caching if explicitly asked, and implement for Knit  | 
1596  | 
self.assertEqual(1, len(lst))  | 
1597  | 
return lst[0]  | 
|
1598  | 
||
1599  | 
val = read_one_raw('text-1')  | 
|
| 
1863.1.8
by John Arbash Meinel
 Removing disk-backed-cache  | 
1600  | 
self.assertEqual({'text-1':val[1]}, k._data._cache)  | 
| 
1863.1.1
by John Arbash Meinel
 Allow Versioned files to do caching if explicitly asked, and implement for Knit  | 
1601  | 
|
1602  | 
k.clear_cache()  | 
|
1603  | 
        # After clear, new reads are not cached
 | 
|
1604  | 
self.assertEqual({}, k._data._cache)  | 
|
1605  | 
||
1606  | 
val2 = read_one_raw('text-1')  | 
|
1607  | 
self.assertEqual(val, val2)  | 
|
1608  | 
self.assertEqual({}, k._data._cache)  | 
|
1609  | 
||
1610  | 
def test_cache_data_read(self):  | 
|
1611  | 
k = self.create_knit()  | 
|
1612  | 
||
1613  | 
def read_one(version):  | 
|
1614  | 
pos_map = k._get_components_positions([version])  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1615  | 
method, index_memo, next = pos_map[version]  | 
1616  | 
lst = list(k._data.read_records_iter([(version, index_memo)]))  | 
|
| 
1863.1.1
by John Arbash Meinel
 Allow Versioned files to do caching if explicitly asked, and implement for Knit  | 
1617  | 
self.assertEqual(1, len(lst))  | 
1618  | 
return lst[0]  | 
|
1619  | 
||
1620  | 
        # Now cache and read
 | 
|
1621  | 
k.enable_cache()  | 
|
1622  | 
||
1623  | 
val = read_one('text-2')  | 
|
1624  | 
self.assertEqual(['text-2'], k._data._cache.keys())  | 
|
1625  | 
self.assertEqual('text-2', val[0])  | 
|
1626  | 
content, digest = k._data._parse_record('text-2',  | 
|
1627  | 
k._data._cache['text-2'])  | 
|
1628  | 
self.assertEqual(content, val[1])  | 
|
1629  | 
self.assertEqual(digest, val[2])  | 
|
1630  | 
||
1631  | 
k.clear_cache()  | 
|
1632  | 
self.assertEqual({}, k._data._cache)  | 
|
1633  | 
||
1634  | 
val2 = read_one('text-2')  | 
|
1635  | 
self.assertEqual(val, val2)  | 
|
1636  | 
self.assertEqual({}, k._data._cache)  | 
|
1637  | 
||
1638  | 
def test_cache_read(self):  | 
|
1639  | 
k = self.create_knit()  | 
|
1640  | 
k.enable_cache()  | 
|
1641  | 
||
1642  | 
text = k.get_text('text-1')  | 
|
1643  | 
self.assertEqual(TEXT_1, text)  | 
|
1644  | 
self.assertEqual(['text-1'], k._data._cache.keys())  | 
|
1645  | 
||
1646  | 
k.clear_cache()  | 
|
1647  | 
self.assertEqual({}, k._data._cache)  | 
|
1648  | 
||
1649  | 
text = k.get_text('text-1')  | 
|
1650  | 
self.assertEqual(TEXT_1, text)  | 
|
1651  | 
self.assertEqual({}, k._data._cache)  | 
|
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1652  | 
|
1653  | 
||
1654  | 
class TestKnitIndex(KnitTests):  | 
|
1655  | 
||
1656  | 
def test_add_versions_dictionary_compresses(self):  | 
|
1657  | 
"""Adding versions to the index should update the lookup dict"""  | 
|
1658  | 
knit = self.make_test_knit()  | 
|
1659  | 
idx = knit._index  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1660  | 
idx.add_version('a-1', ['fulltext'], (None, 0, 0), [])  | 
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1661  | 
self.check_file_contents('test.kndx',  | 
1662  | 
'# bzr knit index 8\n'  | 
|
1663  | 
'\n'  | 
|
1664  | 
            'a-1 fulltext 0 0  :'
 | 
|
1665  | 
            )
 | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1666  | 
idx.add_versions([('a-2', ['fulltext'], (None, 0, 0), ['a-1']),  | 
1667  | 
('a-3', ['fulltext'], (None, 0, 0), ['a-2']),  | 
|
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1668  | 
                         ])
 | 
1669  | 
self.check_file_contents('test.kndx',  | 
|
1670  | 
'# bzr knit index 8\n'  | 
|
1671  | 
'\n'  | 
|
1672  | 
'a-1 fulltext 0 0 :\n'  | 
|
1673  | 
'a-2 fulltext 0 0 0 :\n'  | 
|
1674  | 
            'a-3 fulltext 0 0 1 :'
 | 
|
1675  | 
            )
 | 
|
1676  | 
self.assertEqual(['a-1', 'a-2', 'a-3'], idx._history)  | 
|
1677  | 
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0),  | 
|
1678  | 
'a-2':('a-2', ['fulltext'], 0, 0, ['a-1'], 1),  | 
|
1679  | 
'a-3':('a-3', ['fulltext'], 0, 0, ['a-2'], 2),  | 
|
1680  | 
}, idx._cache)  | 
|
1681  | 
||
1682  | 
def test_add_versions_fails_clean(self):  | 
|
1683  | 
"""If add_versions fails in the middle, it restores a pristine state.  | 
|
1684  | 
||
1685  | 
        Any modifications that are made to the index are reset if all versions
 | 
|
1686  | 
        cannot be added.
 | 
|
1687  | 
        """
 | 
|
1688  | 
        # This cheats a little bit by passing in a generator which will
 | 
|
1689  | 
        # raise an exception before the processing finishes
 | 
|
1690  | 
        # Other possibilities would be to have an version with the wrong number
 | 
|
1691  | 
        # of entries, or to make the backing transport unable to write any
 | 
|
1692  | 
        # files.
 | 
|
1693  | 
||
1694  | 
knit = self.make_test_knit()  | 
|
1695  | 
idx = knit._index  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1696  | 
idx.add_version('a-1', ['fulltext'], (None, 0, 0), [])  | 
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1697  | 
|
1698  | 
class StopEarly(Exception):  | 
|
1699  | 
            pass
 | 
|
1700  | 
||
1701  | 
def generate_failure():  | 
|
1702  | 
"""Add some entries and then raise an exception"""  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1703  | 
yield ('a-2', ['fulltext'], (None, 0, 0), ['a-1'])  | 
1704  | 
yield ('a-3', ['fulltext'], (None, 0, 0), ['a-2'])  | 
|
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1705  | 
raise StopEarly()  | 
1706  | 
||
1707  | 
        # Assert the pre-condition
 | 
|
1708  | 
self.assertEqual(['a-1'], idx._history)  | 
|
1709  | 
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0)}, idx._cache)  | 
|
1710  | 
||
1711  | 
self.assertRaises(StopEarly, idx.add_versions, generate_failure())  | 
|
1712  | 
||
1713  | 
        # And it shouldn't be modified
 | 
|
1714  | 
self.assertEqual(['a-1'], idx._history)  | 
|
1715  | 
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0)}, idx._cache)  | 
|
| 
2171.1.1
by John Arbash Meinel
 Knit index files should ignore empty indexes rather than consider them corrupt.  | 
1716  | 
|
1717  | 
def test_knit_index_ignores_empty_files(self):  | 
|
1718  | 
        # There was a race condition in older bzr, where a ^C at the right time
 | 
|
1719  | 
        # could leave an empty .kndx file, which bzr would later claim was a
 | 
|
1720  | 
        # corrupted file since the header was not present. In reality, the file
 | 
|
1721  | 
        # just wasn't created, so it should be ignored.
 | 
|
1722  | 
t = get_transport('.')  | 
|
1723  | 
t.put_bytes('test.kndx', '')  | 
|
1724  | 
||
1725  | 
knit = self.make_test_knit()  | 
|
1726  | 
||
1727  | 
def test_knit_index_checks_header(self):  | 
|
1728  | 
t = get_transport('.')  | 
|
1729  | 
t.put_bytes('test.kndx', '# not really a knit header\n\n')  | 
|
1730  | 
||
| 
2196.2.1
by John Arbash Meinel
 Merge Dmitry's optimizations and minimize the actual diff.  | 
1731  | 
self.assertRaises(KnitHeaderError, self.make_test_knit)  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1732  | 
|
1733  | 
||
1734  | 
class TestGraphIndexKnit(KnitTests):  | 
|
1735  | 
"""Tests for knits using a GraphIndex rather than a KnitIndex."""  | 
|
1736  | 
||
1737  | 
def make_g_index(self, name, ref_lists=0, nodes=[]):  | 
|
1738  | 
builder = GraphIndexBuilder(ref_lists)  | 
|
1739  | 
for node, references, value in nodes:  | 
|
1740  | 
builder.add_node(node, references, value)  | 
|
1741  | 
stream = builder.finish()  | 
|
1742  | 
trans = self.get_transport()  | 
|
1743  | 
trans.put_file(name, stream)  | 
|
1744  | 
return GraphIndex(trans, name)  | 
|
1745  | 
||
1746  | 
def two_graph_index(self, deltas=False, catch_adds=False):  | 
|
1747  | 
"""Build a two-graph index.  | 
|
1748  | 
||
1749  | 
        :param deltas: If true, use underlying indices with two node-ref
 | 
|
1750  | 
            lists and 'parent' set to a delta-compressed against tail.
 | 
|
1751  | 
        """
 | 
|
1752  | 
        # build a complex graph across several indices.
 | 
|
1753  | 
if deltas:  | 
|
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1754  | 
            # delta compression inn the index
 | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1755  | 
index1 = self.make_g_index('1', 2, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1756  | 
(('tip', ), 'N0 100', ([('parent', )], [], )),  | 
1757  | 
(('tail', ), '', ([], []))])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1758  | 
index2 = self.make_g_index('2', 2, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1759  | 
(('parent', ), ' 100 78', ([('tail', ), ('ghost', )], [('tail', )])),  | 
1760  | 
(('separate', ), '', ([], []))])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1761  | 
else:  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1762  | 
            # just blob location and graph in the index.
 | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1763  | 
index1 = self.make_g_index('1', 1, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1764  | 
(('tip', ), 'N0 100', ([('parent', )], )),  | 
1765  | 
(('tail', ), '', ([], ))])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1766  | 
index2 = self.make_g_index('2', 1, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1767  | 
(('parent', ), ' 100 78', ([('tail', ), ('ghost', )], )),  | 
1768  | 
(('separate', ), '', ([], ))])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1769  | 
combined_index = CombinedGraphIndex([index1, index2])  | 
1770  | 
if catch_adds:  | 
|
1771  | 
self.combined_index = combined_index  | 
|
1772  | 
self.caught_entries = []  | 
|
1773  | 
add_callback = self.catch_add  | 
|
1774  | 
else:  | 
|
1775  | 
add_callback = None  | 
|
1776  | 
return KnitGraphIndex(combined_index, deltas=deltas,  | 
|
1777  | 
add_callback=add_callback)  | 
|
1778  | 
||
1779  | 
def test_get_graph(self):  | 
|
1780  | 
index = self.two_graph_index()  | 
|
1781  | 
self.assertEqual(set([  | 
|
1782  | 
('tip', ('parent', )),  | 
|
1783  | 
('tail', ()),  | 
|
1784  | 
('parent', ('tail', 'ghost')),  | 
|
1785  | 
('separate', ()),  | 
|
1786  | 
]), set(index.get_graph()))  | 
|
1787  | 
||
1788  | 
def test_get_ancestry(self):  | 
|
1789  | 
        # get_ancestry is defined as eliding ghosts, not erroring.
 | 
|
1790  | 
index = self.two_graph_index()  | 
|
1791  | 
self.assertEqual([], index.get_ancestry([]))  | 
|
1792  | 
self.assertEqual(['separate'], index.get_ancestry(['separate']))  | 
|
1793  | 
self.assertEqual(['tail'], index.get_ancestry(['tail']))  | 
|
1794  | 
self.assertEqual(['tail', 'parent'], index.get_ancestry(['parent']))  | 
|
1795  | 
self.assertEqual(['tail', 'parent', 'tip'], index.get_ancestry(['tip']))  | 
|
1796  | 
self.assertTrue(index.get_ancestry(['tip', 'separate']) in  | 
|
1797  | 
(['tail', 'parent', 'tip', 'separate'],  | 
|
1798  | 
['separate', 'tail', 'parent', 'tip'],  | 
|
1799  | 
            ))
 | 
|
1800  | 
        # and without topo_sort
 | 
|
1801  | 
self.assertEqual(set(['separate']),  | 
|
1802  | 
set(index.get_ancestry(['separate'], topo_sorted=False)))  | 
|
1803  | 
self.assertEqual(set(['tail']),  | 
|
1804  | 
set(index.get_ancestry(['tail'], topo_sorted=False)))  | 
|
1805  | 
self.assertEqual(set(['tail', 'parent']),  | 
|
1806  | 
set(index.get_ancestry(['parent'], topo_sorted=False)))  | 
|
1807  | 
self.assertEqual(set(['tail', 'parent', 'tip']),  | 
|
1808  | 
set(index.get_ancestry(['tip'], topo_sorted=False)))  | 
|
1809  | 
self.assertEqual(set(['separate', 'tail', 'parent', 'tip']),  | 
|
1810  | 
set(index.get_ancestry(['tip', 'separate'])))  | 
|
1811  | 
        # asking for a ghost makes it go boom.
 | 
|
1812  | 
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry, ['ghost'])  | 
|
1813  | 
||
1814  | 
def test_get_ancestry_with_ghosts(self):  | 
|
1815  | 
index = self.two_graph_index()  | 
|
1816  | 
self.assertEqual([], index.get_ancestry_with_ghosts([]))  | 
|
1817  | 
self.assertEqual(['separate'], index.get_ancestry_with_ghosts(['separate']))  | 
|
1818  | 
self.assertEqual(['tail'], index.get_ancestry_with_ghosts(['tail']))  | 
|
1819  | 
self.assertTrue(index.get_ancestry_with_ghosts(['parent']) in  | 
|
1820  | 
(['tail', 'ghost', 'parent'],  | 
|
1821  | 
['ghost', 'tail', 'parent'],  | 
|
1822  | 
            ))
 | 
|
1823  | 
self.assertTrue(index.get_ancestry_with_ghosts(['tip']) in  | 
|
1824  | 
(['tail', 'ghost', 'parent', 'tip'],  | 
|
1825  | 
['ghost', 'tail', 'parent', 'tip'],  | 
|
1826  | 
            ))
 | 
|
1827  | 
self.assertTrue(index.get_ancestry_with_ghosts(['tip', 'separate']) in  | 
|
1828  | 
(['tail', 'ghost', 'parent', 'tip', 'separate'],  | 
|
1829  | 
['ghost', 'tail', 'parent', 'tip', 'separate'],  | 
|
1830  | 
['separate', 'tail', 'ghost', 'parent', 'tip'],  | 
|
1831  | 
['separate', 'ghost', 'tail', 'parent', 'tip'],  | 
|
1832  | 
            ))
 | 
|
1833  | 
        # asking for a ghost makes it go boom.
 | 
|
1834  | 
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry_with_ghosts, ['ghost'])  | 
|
1835  | 
||
1836  | 
def test_num_versions(self):  | 
|
1837  | 
index = self.two_graph_index()  | 
|
1838  | 
self.assertEqual(4, index.num_versions())  | 
|
1839  | 
||
1840  | 
def test_get_versions(self):  | 
|
1841  | 
index = self.two_graph_index()  | 
|
1842  | 
self.assertEqual(set(['tail', 'tip', 'parent', 'separate']),  | 
|
1843  | 
set(index.get_versions()))  | 
|
1844  | 
||
1845  | 
def test_has_version(self):  | 
|
1846  | 
index = self.two_graph_index()  | 
|
1847  | 
self.assertTrue(index.has_version('tail'))  | 
|
1848  | 
self.assertFalse(index.has_version('ghost'))  | 
|
1849  | 
||
1850  | 
def test_get_position(self):  | 
|
1851  | 
index = self.two_graph_index()  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1852  | 
self.assertEqual((index._graph_index._indices[0], 0, 100), index.get_position('tip'))  | 
1853  | 
self.assertEqual((index._graph_index._indices[1], 100, 78), index.get_position('parent'))  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1854  | 
|
1855  | 
def test_get_method_deltas(self):  | 
|
1856  | 
index = self.two_graph_index(deltas=True)  | 
|
1857  | 
self.assertEqual('fulltext', index.get_method('tip'))  | 
|
1858  | 
self.assertEqual('line-delta', index.get_method('parent'))  | 
|
1859  | 
||
1860  | 
def test_get_method_no_deltas(self):  | 
|
1861  | 
        # check that the parent-history lookup is ignored with deltas=False.
 | 
|
1862  | 
index = self.two_graph_index(deltas=False)  | 
|
1863  | 
self.assertEqual('fulltext', index.get_method('tip'))  | 
|
1864  | 
self.assertEqual('fulltext', index.get_method('parent'))  | 
|
1865  | 
||
1866  | 
def test_get_options_deltas(self):  | 
|
1867  | 
index = self.two_graph_index(deltas=True)  | 
|
| 
2658.2.1
by Robert Collins
 Fix mismatch between KnitGraphIndex and KnitIndex in get_options.  | 
1868  | 
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip'))  | 
1869  | 
self.assertEqual(['line-delta'], index.get_options('parent'))  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1870  | 
|
1871  | 
def test_get_options_no_deltas(self):  | 
|
1872  | 
        # check that the parent-history lookup is ignored with deltas=False.
 | 
|
1873  | 
index = self.two_graph_index(deltas=False)  | 
|
| 
2658.2.1
by Robert Collins
 Fix mismatch between KnitGraphIndex and KnitIndex in get_options.  | 
1874  | 
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip'))  | 
1875  | 
self.assertEqual(['fulltext'], index.get_options('parent'))  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1876  | 
|
1877  | 
def test_get_parents(self):  | 
|
1878  | 
        # get_parents ignores ghosts
 | 
|
1879  | 
index = self.two_graph_index()  | 
|
1880  | 
self.assertEqual(('tail', ), index.get_parents('parent'))  | 
|
1881  | 
        # and errors on ghosts.
 | 
|
1882  | 
self.assertRaises(errors.RevisionNotPresent,  | 
|
1883  | 
index.get_parents, 'ghost')  | 
|
1884  | 
||
1885  | 
def test_get_parents_with_ghosts(self):  | 
|
1886  | 
index = self.two_graph_index()  | 
|
1887  | 
self.assertEqual(('tail', 'ghost'), index.get_parents_with_ghosts('parent'))  | 
|
1888  | 
        # and errors on ghosts.
 | 
|
1889  | 
self.assertRaises(errors.RevisionNotPresent,  | 
|
1890  | 
index.get_parents_with_ghosts, 'ghost')  | 
|
1891  | 
||
1892  | 
def test_check_versions_present(self):  | 
|
1893  | 
        # ghosts should not be considered present
 | 
|
1894  | 
index = self.two_graph_index()  | 
|
1895  | 
self.assertRaises(RevisionNotPresent, index.check_versions_present,  | 
|
1896  | 
['ghost'])  | 
|
1897  | 
self.assertRaises(RevisionNotPresent, index.check_versions_present,  | 
|
1898  | 
['tail', 'ghost'])  | 
|
1899  | 
index.check_versions_present(['tail', 'separate'])  | 
|
1900  | 
||
1901  | 
def catch_add(self, entries):  | 
|
1902  | 
self.caught_entries.append(entries)  | 
|
1903  | 
||
1904  | 
def test_add_no_callback_errors(self):  | 
|
1905  | 
index = self.two_graph_index()  | 
|
1906  | 
self.assertRaises(errors.ReadOnlyError, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1907  | 
'new', 'fulltext,no-eol', (None, 50, 60), ['separate'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1908  | 
|
1909  | 
def test_add_version_smoke(self):  | 
|
1910  | 
index = self.two_graph_index(catch_adds=True)  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1911  | 
index.add_version('new', 'fulltext,no-eol', (None, 50, 60), ['separate'])  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1912  | 
self.assertEqual([[(('new', ), 'N50 60', ((('separate',),),))]],  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1913  | 
self.caught_entries)  | 
1914  | 
||
1915  | 
def test_add_version_delta_not_delta_index(self):  | 
|
1916  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1917  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1918  | 
'new', 'no-eol,line-delta', (None, 0, 100), ['parent'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1919  | 
self.assertEqual([], self.caught_entries)  | 
1920  | 
||
1921  | 
def test_add_version_same_dup(self):  | 
|
1922  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1923  | 
        # options can be spelt two different ways
 | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1924  | 
index.add_version('tip', 'fulltext,no-eol', (None, 0, 100), ['parent'])  | 
1925  | 
index.add_version('tip', 'no-eol,fulltext', (None, 0, 100), ['parent'])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1926  | 
        # but neither should have added data.
 | 
1927  | 
self.assertEqual([[], []], self.caught_entries)  | 
|
1928  | 
||
1929  | 
def test_add_version_different_dup(self):  | 
|
1930  | 
index = self.two_graph_index(deltas=True, catch_adds=True)  | 
|
1931  | 
        # change options
 | 
|
1932  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1933  | 
'tip', 'no-eol,line-delta', (None, 0, 100), ['parent'])  | 
1934  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
1935  | 
'tip', 'line-delta,no-eol', (None, 0, 100), ['parent'])  | 
|
1936  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
1937  | 
'tip', 'fulltext', (None, 0, 100), ['parent'])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1938  | 
        # position/length
 | 
1939  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1940  | 
'tip', 'fulltext,no-eol', (None, 50, 100), ['parent'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1941  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1942  | 
'tip', 'fulltext,no-eol', (None, 0, 1000), ['parent'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1943  | 
        # parents
 | 
1944  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1945  | 
'tip', 'fulltext,no-eol', (None, 0, 100), [])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1946  | 
self.assertEqual([], self.caught_entries)  | 
1947  | 
||
1948  | 
def test_add_versions_nodeltas(self):  | 
|
1949  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1950  | 
index.add_versions([  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1951  | 
('new', 'fulltext,no-eol', (None, 50, 60), ['separate']),  | 
1952  | 
('new2', 'fulltext', (None, 0, 6), ['new']),  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1953  | 
                ])
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1954  | 
self.assertEqual([(('new', ), 'N50 60', ((('separate',),),)),  | 
1955  | 
(('new2', ), ' 0 6', ((('new',),),))],  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1956  | 
sorted(self.caught_entries[0]))  | 
1957  | 
self.assertEqual(1, len(self.caught_entries))  | 
|
1958  | 
||
1959  | 
def test_add_versions_deltas(self):  | 
|
1960  | 
index = self.two_graph_index(deltas=True, catch_adds=True)  | 
|
1961  | 
index.add_versions([  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1962  | 
('new', 'fulltext,no-eol', (None, 50, 60), ['separate']),  | 
1963  | 
('new2', 'line-delta', (None, 0, 6), ['new']),  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1964  | 
                ])
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1965  | 
self.assertEqual([(('new', ), 'N50 60', ((('separate',),), ())),  | 
1966  | 
(('new2', ), ' 0 6', ((('new',),), (('new',),), ))],  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1967  | 
sorted(self.caught_entries[0]))  | 
1968  | 
self.assertEqual(1, len(self.caught_entries))  | 
|
1969  | 
||
1970  | 
def test_add_versions_delta_not_delta_index(self):  | 
|
1971  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1972  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1973  | 
[('new', 'no-eol,line-delta', (None, 0, 100), ['parent'])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1974  | 
self.assertEqual([], self.caught_entries)  | 
1975  | 
||
1976  | 
def test_add_versions_same_dup(self):  | 
|
1977  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1978  | 
        # options can be spelt two different ways
 | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1979  | 
index.add_versions([('tip', 'fulltext,no-eol', (None, 0, 100), ['parent'])])  | 
1980  | 
index.add_versions([('tip', 'no-eol,fulltext', (None, 0, 100), ['parent'])])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1981  | 
        # but neither should have added data.
 | 
1982  | 
self.assertEqual([[], []], self.caught_entries)  | 
|
1983  | 
||
1984  | 
def test_add_versions_different_dup(self):  | 
|
1985  | 
index = self.two_graph_index(deltas=True, catch_adds=True)  | 
|
1986  | 
        # change options
 | 
|
1987  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1988  | 
[('tip', 'no-eol,line-delta', (None, 0, 100), ['parent'])])  | 
1989  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
1990  | 
[('tip', 'line-delta,no-eol', (None, 0, 100), ['parent'])])  | 
|
1991  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
1992  | 
[('tip', 'fulltext', (None, 0, 100), ['parent'])])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1993  | 
        # position/length
 | 
1994  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1995  | 
[('tip', 'fulltext,no-eol', (None, 50, 100), ['parent'])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1996  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
1997  | 
[('tip', 'fulltext,no-eol', (None, 0, 1000), ['parent'])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
1998  | 
        # parents
 | 
1999  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2000  | 
[('tip', 'fulltext,no-eol', (None, 0, 100), [])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2001  | 
        # change options in the second record
 | 
2002  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2003  | 
[('tip', 'fulltext,no-eol', (None, 0, 100), ['parent']),  | 
2004  | 
('tip', 'no-eol,line-delta', (None, 0, 100), ['parent'])])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2005  | 
self.assertEqual([], self.caught_entries)  | 
2006  | 
||
2007  | 
def test_iter_parents(self):  | 
|
2008  | 
index1 = self.make_g_index('1', 1, [  | 
|
2009  | 
        # no parents
 | 
|
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2010  | 
(('r0', ), 'N0 100', ([], )),  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2011  | 
        # 1 parent
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2012  | 
(('r1', ), '', ([('r0', )], ))])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2013  | 
index2 = self.make_g_index('2', 1, [  | 
2014  | 
        # 2 parents
 | 
|
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2015  | 
(('r2', ), 'N0 100', ([('r1', ), ('r0', )], )),  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2016  | 
            ])
 | 
2017  | 
combined_index = CombinedGraphIndex([index1, index2])  | 
|
2018  | 
index = KnitGraphIndex(combined_index)  | 
|
2019  | 
        # XXX TODO a ghost
 | 
|
2020  | 
        # cases: each sample data individually:
 | 
|
2021  | 
self.assertEqual(set([('r0', ())]),  | 
|
2022  | 
set(index.iter_parents(['r0'])))  | 
|
2023  | 
self.assertEqual(set([('r1', ('r0', ))]),  | 
|
2024  | 
set(index.iter_parents(['r1'])))  | 
|
2025  | 
self.assertEqual(set([('r2', ('r1', 'r0'))]),  | 
|
2026  | 
set(index.iter_parents(['r2'])))  | 
|
2027  | 
        # no nodes returned for a missing node
 | 
|
2028  | 
self.assertEqual(set(),  | 
|
2029  | 
set(index.iter_parents(['missing'])))  | 
|
2030  | 
        # 1 node returned with missing nodes skipped
 | 
|
2031  | 
self.assertEqual(set([('r1', ('r0', ))]),  | 
|
2032  | 
set(index.iter_parents(['ghost1', 'r1', 'ghost'])))  | 
|
2033  | 
        # 2 nodes returned
 | 
|
2034  | 
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),  | 
|
2035  | 
set(index.iter_parents(['r0', 'r1'])))  | 
|
2036  | 
        # 2 nodes returned, missing skipped
 | 
|
2037  | 
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),  | 
|
2038  | 
set(index.iter_parents(['a', 'r0', 'b', 'r1', 'c'])))  | 
|
2039  | 
||
2040  | 
||
2041  | 
class TestNoParentsGraphIndexKnit(KnitTests):  | 
|
2042  | 
"""Tests for knits using KnitGraphIndex with no parents."""  | 
|
2043  | 
||
2044  | 
def make_g_index(self, name, ref_lists=0, nodes=[]):  | 
|
2045  | 
builder = GraphIndexBuilder(ref_lists)  | 
|
2046  | 
for node, references in nodes:  | 
|
2047  | 
builder.add_node(node, references)  | 
|
2048  | 
stream = builder.finish()  | 
|
2049  | 
trans = self.get_transport()  | 
|
2050  | 
trans.put_file(name, stream)  | 
|
2051  | 
return GraphIndex(trans, name)  | 
|
2052  | 
||
2053  | 
def test_parents_deltas_incompatible(self):  | 
|
2054  | 
index = CombinedGraphIndex([])  | 
|
2055  | 
self.assertRaises(errors.KnitError, KnitGraphIndex, index,  | 
|
2056  | 
deltas=True, parents=False)  | 
|
2057  | 
||
2058  | 
def two_graph_index(self, catch_adds=False):  | 
|
2059  | 
"""Build a two-graph index.  | 
|
2060  | 
||
2061  | 
        :param deltas: If true, use underlying indices with two node-ref
 | 
|
2062  | 
            lists and 'parent' set to a delta-compressed against tail.
 | 
|
2063  | 
        """
 | 
|
2064  | 
        # put several versions in the index.
 | 
|
2065  | 
index1 = self.make_g_index('1', 0, [  | 
|
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2066  | 
(('tip', ), 'N0 100'),  | 
2067  | 
(('tail', ), '')])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2068  | 
index2 = self.make_g_index('2', 0, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2069  | 
(('parent', ), ' 100 78'),  | 
2070  | 
(('separate', ), '')])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2071  | 
combined_index = CombinedGraphIndex([index1, index2])  | 
2072  | 
if catch_adds:  | 
|
2073  | 
self.combined_index = combined_index  | 
|
2074  | 
self.caught_entries = []  | 
|
2075  | 
add_callback = self.catch_add  | 
|
2076  | 
else:  | 
|
2077  | 
add_callback = None  | 
|
2078  | 
return KnitGraphIndex(combined_index, parents=False,  | 
|
2079  | 
add_callback=add_callback)  | 
|
2080  | 
||
2081  | 
def test_get_graph(self):  | 
|
2082  | 
index = self.two_graph_index()  | 
|
2083  | 
self.assertEqual(set([  | 
|
2084  | 
('tip', ()),  | 
|
2085  | 
('tail', ()),  | 
|
2086  | 
('parent', ()),  | 
|
2087  | 
('separate', ()),  | 
|
2088  | 
]), set(index.get_graph()))  | 
|
2089  | 
||
2090  | 
def test_get_ancestry(self):  | 
|
2091  | 
        # with no parents, ancestry is always just the key.
 | 
|
2092  | 
index = self.two_graph_index()  | 
|
2093  | 
self.assertEqual([], index.get_ancestry([]))  | 
|
2094  | 
self.assertEqual(['separate'], index.get_ancestry(['separate']))  | 
|
2095  | 
self.assertEqual(['tail'], index.get_ancestry(['tail']))  | 
|
2096  | 
self.assertEqual(['parent'], index.get_ancestry(['parent']))  | 
|
2097  | 
self.assertEqual(['tip'], index.get_ancestry(['tip']))  | 
|
2098  | 
self.assertTrue(index.get_ancestry(['tip', 'separate']) in  | 
|
2099  | 
(['tip', 'separate'],  | 
|
2100  | 
['separate', 'tip'],  | 
|
2101  | 
            ))
 | 
|
2102  | 
        # asking for a ghost makes it go boom.
 | 
|
2103  | 
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry, ['ghost'])  | 
|
2104  | 
||
2105  | 
def test_get_ancestry_with_ghosts(self):  | 
|
2106  | 
index = self.two_graph_index()  | 
|
2107  | 
self.assertEqual([], index.get_ancestry_with_ghosts([]))  | 
|
2108  | 
self.assertEqual(['separate'], index.get_ancestry_with_ghosts(['separate']))  | 
|
2109  | 
self.assertEqual(['tail'], index.get_ancestry_with_ghosts(['tail']))  | 
|
2110  | 
self.assertEqual(['parent'], index.get_ancestry_with_ghosts(['parent']))  | 
|
2111  | 
self.assertEqual(['tip'], index.get_ancestry_with_ghosts(['tip']))  | 
|
2112  | 
self.assertTrue(index.get_ancestry_with_ghosts(['tip', 'separate']) in  | 
|
2113  | 
(['tip', 'separate'],  | 
|
2114  | 
['separate', 'tip'],  | 
|
2115  | 
            ))
 | 
|
2116  | 
        # asking for a ghost makes it go boom.
 | 
|
2117  | 
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry_with_ghosts, ['ghost'])  | 
|
2118  | 
||
2119  | 
def test_num_versions(self):  | 
|
2120  | 
index = self.two_graph_index()  | 
|
2121  | 
self.assertEqual(4, index.num_versions())  | 
|
2122  | 
||
2123  | 
def test_get_versions(self):  | 
|
2124  | 
index = self.two_graph_index()  | 
|
2125  | 
self.assertEqual(set(['tail', 'tip', 'parent', 'separate']),  | 
|
2126  | 
set(index.get_versions()))  | 
|
2127  | 
||
2128  | 
def test_has_version(self):  | 
|
2129  | 
index = self.two_graph_index()  | 
|
2130  | 
self.assertTrue(index.has_version('tail'))  | 
|
2131  | 
self.assertFalse(index.has_version('ghost'))  | 
|
2132  | 
||
2133  | 
def test_get_position(self):  | 
|
2134  | 
index = self.two_graph_index()  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2135  | 
self.assertEqual((index._graph_index._indices[0], 0, 100), index.get_position('tip'))  | 
2136  | 
self.assertEqual((index._graph_index._indices[1], 100, 78), index.get_position('parent'))  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2137  | 
|
2138  | 
def test_get_method(self):  | 
|
2139  | 
index = self.two_graph_index()  | 
|
2140  | 
self.assertEqual('fulltext', index.get_method('tip'))  | 
|
| 
2658.2.1
by Robert Collins
 Fix mismatch between KnitGraphIndex and KnitIndex in get_options.  | 
2141  | 
self.assertEqual(['fulltext'], index.get_options('parent'))  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2142  | 
|
2143  | 
def test_get_options(self):  | 
|
2144  | 
index = self.two_graph_index()  | 
|
| 
2658.2.1
by Robert Collins
 Fix mismatch between KnitGraphIndex and KnitIndex in get_options.  | 
2145  | 
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip'))  | 
2146  | 
self.assertEqual(['fulltext'], index.get_options('parent'))  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2147  | 
|
2148  | 
def test_get_parents(self):  | 
|
2149  | 
index = self.two_graph_index()  | 
|
2150  | 
self.assertEqual((), index.get_parents('parent'))  | 
|
2151  | 
        # and errors on ghosts.
 | 
|
2152  | 
self.assertRaises(errors.RevisionNotPresent,  | 
|
2153  | 
index.get_parents, 'ghost')  | 
|
2154  | 
||
2155  | 
def test_get_parents_with_ghosts(self):  | 
|
2156  | 
index = self.two_graph_index()  | 
|
2157  | 
self.assertEqual((), index.get_parents_with_ghosts('parent'))  | 
|
2158  | 
        # and errors on ghosts.
 | 
|
2159  | 
self.assertRaises(errors.RevisionNotPresent,  | 
|
2160  | 
index.get_parents_with_ghosts, 'ghost')  | 
|
2161  | 
||
2162  | 
def test_check_versions_present(self):  | 
|
2163  | 
index = self.two_graph_index()  | 
|
2164  | 
self.assertRaises(RevisionNotPresent, index.check_versions_present,  | 
|
2165  | 
['missing'])  | 
|
2166  | 
self.assertRaises(RevisionNotPresent, index.check_versions_present,  | 
|
2167  | 
['tail', 'missing'])  | 
|
2168  | 
index.check_versions_present(['tail', 'separate'])  | 
|
2169  | 
||
2170  | 
def catch_add(self, entries):  | 
|
2171  | 
self.caught_entries.append(entries)  | 
|
2172  | 
||
2173  | 
def test_add_no_callback_errors(self):  | 
|
2174  | 
index = self.two_graph_index()  | 
|
2175  | 
self.assertRaises(errors.ReadOnlyError, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2176  | 
'new', 'fulltext,no-eol', (None, 50, 60), ['separate'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2177  | 
|
2178  | 
def test_add_version_smoke(self):  | 
|
2179  | 
index = self.two_graph_index(catch_adds=True)  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2180  | 
index.add_version('new', 'fulltext,no-eol', (None, 50, 60), [])  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2181  | 
self.assertEqual([[(('new', ), 'N50 60')]],  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2182  | 
self.caught_entries)  | 
2183  | 
||
2184  | 
def test_add_version_delta_not_delta_index(self):  | 
|
2185  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2186  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2187  | 
'new', 'no-eol,line-delta', (None, 0, 100), [])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2188  | 
self.assertEqual([], self.caught_entries)  | 
2189  | 
||
2190  | 
def test_add_version_same_dup(self):  | 
|
2191  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2192  | 
        # options can be spelt two different ways
 | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2193  | 
index.add_version('tip', 'fulltext,no-eol', (None, 0, 100), [])  | 
2194  | 
index.add_version('tip', 'no-eol,fulltext', (None, 0, 100), [])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2195  | 
        # but neither should have added data.
 | 
2196  | 
self.assertEqual([[], []], self.caught_entries)  | 
|
2197  | 
||
2198  | 
def test_add_version_different_dup(self):  | 
|
2199  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2200  | 
        # change options
 | 
|
2201  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2202  | 
'tip', 'no-eol,line-delta', (None, 0, 100), [])  | 
2203  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
2204  | 
'tip', 'line-delta,no-eol', (None, 0, 100), [])  | 
|
2205  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
2206  | 
'tip', 'fulltext', (None, 0, 100), [])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2207  | 
        # position/length
 | 
2208  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2209  | 
'tip', 'fulltext,no-eol', (None, 50, 100), [])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2210  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2211  | 
'tip', 'fulltext,no-eol', (None, 0, 1000), [])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2212  | 
        # parents
 | 
2213  | 
self.assertRaises(errors.KnitCorrupt, index.add_version,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2214  | 
'tip', 'fulltext,no-eol', (None, 0, 100), ['parent'])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2215  | 
self.assertEqual([], self.caught_entries)  | 
2216  | 
||
2217  | 
def test_add_versions(self):  | 
|
2218  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2219  | 
index.add_versions([  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2220  | 
('new', 'fulltext,no-eol', (None, 50, 60), []),  | 
2221  | 
('new2', 'fulltext', (None, 0, 6), []),  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2222  | 
                ])
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
2223  | 
self.assertEqual([(('new', ), 'N50 60'), (('new2', ), ' 0 6')],  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2224  | 
sorted(self.caught_entries[0]))  | 
2225  | 
self.assertEqual(1, len(self.caught_entries))  | 
|
2226  | 
||
2227  | 
def test_add_versions_delta_not_delta_index(self):  | 
|
2228  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2229  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2230  | 
[('new', 'no-eol,line-delta', (None, 0, 100), ['parent'])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2231  | 
self.assertEqual([], self.caught_entries)  | 
2232  | 
||
2233  | 
def test_add_versions_parents_not_parents_index(self):  | 
|
2234  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2235  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2236  | 
[('new', 'no-eol,fulltext', (None, 0, 100), ['parent'])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2237  | 
self.assertEqual([], self.caught_entries)  | 
2238  | 
||
2239  | 
def test_add_versions_same_dup(self):  | 
|
2240  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2241  | 
        # options can be spelt two different ways
 | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2242  | 
index.add_versions([('tip', 'fulltext,no-eol', (None, 0, 100), [])])  | 
2243  | 
index.add_versions([('tip', 'no-eol,fulltext', (None, 0, 100), [])])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2244  | 
        # but neither should have added data.
 | 
2245  | 
self.assertEqual([[], []], self.caught_entries)  | 
|
2246  | 
||
2247  | 
def test_add_versions_different_dup(self):  | 
|
2248  | 
index = self.two_graph_index(catch_adds=True)  | 
|
2249  | 
        # change options
 | 
|
2250  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2251  | 
[('tip', 'no-eol,line-delta', (None, 0, 100), [])])  | 
2252  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
2253  | 
[('tip', 'line-delta,no-eol', (None, 0, 100), [])])  | 
|
2254  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
2255  | 
[('tip', 'fulltext', (None, 0, 100), [])])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2256  | 
        # position/length
 | 
2257  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2258  | 
[('tip', 'fulltext,no-eol', (None, 50, 100), [])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2259  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2260  | 
[('tip', 'fulltext,no-eol', (None, 0, 1000), [])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2261  | 
        # parents
 | 
2262  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2263  | 
[('tip', 'fulltext,no-eol', (None, 0, 100), ['parent'])])  | 
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2264  | 
        # change options in the second record
 | 
2265  | 
self.assertRaises(errors.KnitCorrupt, index.add_versions,  | 
|
| 
2670.2.2
by Robert Collins
 * In ``bzrlib.knit`` the internal interface has been altered to use  | 
2266  | 
[('tip', 'fulltext,no-eol', (None, 0, 100), []),  | 
2267  | 
('tip', 'no-eol,line-delta', (None, 0, 100), [])])  | 
|
| 
2625.8.1
by Robert Collins
 LIBRARY API BREAKS:  | 
2268  | 
self.assertEqual([], self.caught_entries)  | 
2269  | 
||
2270  | 
def test_iter_parents(self):  | 
|
2271  | 
index = self.two_graph_index()  | 
|
2272  | 
self.assertEqual(set([  | 
|
2273  | 
('tip', ()), ('tail', ()), ('parent', ()), ('separate', ())  | 
|
2274  | 
            ]),
 | 
|
2275  | 
set(index.iter_parents(['tip', 'tail', 'ghost', 'parent', 'separate'])))  | 
|
2276  | 
self.assertEqual(set([('tip', ())]),  | 
|
2277  | 
set(index.iter_parents(['tip'])))  | 
|
2278  | 
self.assertEqual(set(),  | 
|
2279  | 
set(index.iter_parents([])))  |