Merge lp:~jelmer/brz/file-content-factory into lp:brz
- file-content-factory
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Merged |
---|---|
Approved by: | Jelmer Vernooij |
Approved revision: | no longer in the source branch. |
Merge reported by: | The Breezy Bot |
Merged at revision: | not available |
Proposed branch: | lp:~jelmer/brz/file-content-factory |
Merge into: | lp:brz |
Diff against target: |
878 lines (+197/-139) 14 files modified
breezy/_annotator_py.py (+1/-1) breezy/bzr/groupcompress.py (+20/-17) breezy/bzr/groupcompress_repo.py (+3/-3) breezy/bzr/knit.py (+55/-36) breezy/bzr/knitpack_repo.py (+2/-2) breezy/bzr/reconcile.py (+5/-5) breezy/bzr/smart/repository.py (+3/-1) breezy/bzr/versionedfile.py (+55/-18) breezy/bzr/vf_repository.py (+6/-12) breezy/bzr/weave.py (+5/-6) breezy/git/annotate.py (+7/-4) breezy/merge.py (+1/-2) breezy/plugins/weave_fmt/repository.py (+5/-5) breezy/tests/per_versionedfile.py (+29/-27) |
To merge this branch: | bzr merge lp:~jelmer/brz/file-content-factory |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij | Approve | ||
Review via email: mp+378072@code.launchpad.net |
Commit message
Add a 'lines' storage kind.
Description of the change
Add a 'lines' storage kind.
Avoid converting back and forth between fulltext and lines in various places.
To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) : | # |
review:
Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote : | # |
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote : | # |
Running landing tests failed
https:/
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote : | # |
Running landing tests failed
https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'breezy/_annotator_py.py' | |||
2 | --- breezy/_annotator_py.py 2019-03-02 21:46:18 +0000 | |||
3 | +++ breezy/_annotator_py.py 2020-01-25 16:26:49 +0000 | |||
4 | @@ -127,7 +127,7 @@ | |||
5 | 127 | if record.storage_kind == 'absent': | 127 | if record.storage_kind == 'absent': |
6 | 128 | raise errors.RevisionNotPresent(record.key, self._vf) | 128 | raise errors.RevisionNotPresent(record.key, self._vf) |
7 | 129 | this_key = record.key | 129 | this_key = record.key |
9 | 130 | lines = osutils.chunks_to_lines(record.get_bytes_as('chunked')) | 130 | lines = record.get_bytes_as('lines') |
10 | 131 | num_lines = len(lines) | 131 | num_lines = len(lines) |
11 | 132 | self._text_cache[this_key] = lines | 132 | self._text_cache[this_key] = lines |
12 | 133 | yield this_key, lines, num_lines | 133 | yield this_key, lines, num_lines |
13 | 134 | 134 | ||
14 | === modified file 'breezy/bzr/groupcompress.py' | |||
15 | --- breezy/bzr/groupcompress.py 2020-01-25 14:46:10 +0000 | |||
16 | +++ breezy/bzr/groupcompress.py 2020-01-25 16:26:49 +0000 | |||
17 | @@ -466,7 +466,7 @@ | |||
18 | 466 | return self._manager._wire_bytes() | 466 | return self._manager._wire_bytes() |
19 | 467 | else: | 467 | else: |
20 | 468 | return b'' | 468 | return b'' |
22 | 469 | if storage_kind in ('fulltext', 'chunked'): | 469 | if storage_kind in ('fulltext', 'chunked', 'lines'): |
23 | 470 | if self._bytes is None: | 470 | if self._bytes is None: |
24 | 471 | # Grab and cache the raw bytes for this entry | 471 | # Grab and cache the raw bytes for this entry |
25 | 472 | # and break the ref-cycle with _manager since we don't need it | 472 | # and break the ref-cycle with _manager since we don't need it |
26 | @@ -482,8 +482,10 @@ | |||
27 | 482 | # refcycle here, but instead in manager.get_record_stream() | 482 | # refcycle here, but instead in manager.get_record_stream() |
28 | 483 | if storage_kind == 'fulltext': | 483 | if storage_kind == 'fulltext': |
29 | 484 | return self._bytes | 484 | return self._bytes |
31 | 485 | else: | 485 | elif storage_kind == 'chunked': |
32 | 486 | return [self._bytes] | 486 | return [self._bytes] |
33 | 487 | else: | ||
34 | 488 | return osutils.split_lines(self._bytes) | ||
35 | 487 | raise errors.UnavailableRepresentation(self.key, storage_kind, | 489 | raise errors.UnavailableRepresentation(self.key, storage_kind, |
36 | 488 | self.storage_kind) | 490 | self.storage_kind) |
37 | 489 | 491 | ||
38 | @@ -566,9 +568,9 @@ | |||
39 | 566 | old_length = self._block._content_length | 568 | old_length = self._block._content_length |
40 | 567 | end_point = 0 | 569 | end_point = 0 |
41 | 568 | for factory in self._factories: | 570 | for factory in self._factories: |
43 | 569 | bytes = factory.get_bytes_as('fulltext') | 571 | chunks = factory.get_bytes_as('chunked') |
44 | 570 | (found_sha1, start_point, end_point, | 572 | (found_sha1, start_point, end_point, |
46 | 571 | type) = compressor.compress(factory.key, [bytes], factory.sha1) | 573 | type) = compressor.compress(factory.key, chunks, factory.sha1) |
47 | 572 | # Now update this factory with the new offsets, etc | 574 | # Now update this factory with the new offsets, etc |
48 | 573 | factory.sha1 = found_sha1 | 575 | factory.sha1 = found_sha1 |
49 | 574 | factory._start = start_point | 576 | factory._start = start_point |
50 | @@ -1369,7 +1371,7 @@ | |||
51 | 1369 | if keys is None: | 1371 | if keys is None: |
52 | 1370 | keys = self.keys() | 1372 | keys = self.keys() |
53 | 1371 | for record in self.get_record_stream(keys, 'unordered', True): | 1373 | for record in self.get_record_stream(keys, 'unordered', True): |
55 | 1372 | record.get_bytes_as('fulltext') | 1374 | record.get_bytes_as('chunked') |
56 | 1373 | else: | 1375 | else: |
57 | 1374 | return self.get_record_stream(keys, 'unordered', True) | 1376 | return self.get_record_stream(keys, 'unordered', True) |
58 | 1375 | 1377 | ||
59 | @@ -1670,8 +1672,8 @@ | |||
60 | 1670 | result[record.key] = record.sha1 | 1672 | result[record.key] = record.sha1 |
61 | 1671 | else: | 1673 | else: |
62 | 1672 | if record.storage_kind != 'absent': | 1674 | if record.storage_kind != 'absent': |
65 | 1673 | result[record.key] = osutils.sha_string( | 1675 | result[record.key] = osutils.sha_strings( |
66 | 1674 | record.get_bytes_as('fulltext')) | 1676 | record.get_bytes_as('chunked')) |
67 | 1675 | return result | 1677 | return result |
68 | 1676 | 1678 | ||
69 | 1677 | def insert_record_stream(self, stream): | 1679 | def insert_record_stream(self, stream): |
70 | @@ -1823,25 +1825,26 @@ | |||
71 | 1823 | self._index.add_records(nodes, random_id=random_id) | 1825 | self._index.add_records(nodes, random_id=random_id) |
72 | 1824 | continue | 1826 | continue |
73 | 1825 | try: | 1827 | try: |
75 | 1826 | bytes = record.get_bytes_as('fulltext') | 1828 | chunks = record.get_bytes_as('chunked') |
76 | 1827 | except errors.UnavailableRepresentation: | 1829 | except errors.UnavailableRepresentation: |
78 | 1828 | adapter_key = record.storage_kind, 'fulltext' | 1830 | adapter_key = record.storage_kind, 'chunked' |
79 | 1829 | adapter = get_adapter(adapter_key) | 1831 | adapter = get_adapter(adapter_key) |
81 | 1830 | bytes = adapter.get_bytes(record) | 1832 | chunks = adapter.get_bytes(record, 'chunked') |
82 | 1833 | chunks_len = sum(map(len, chunks)) | ||
83 | 1831 | if len(record.key) > 1: | 1834 | if len(record.key) > 1: |
84 | 1832 | prefix = record.key[0] | 1835 | prefix = record.key[0] |
85 | 1833 | soft = (prefix == last_prefix) | 1836 | soft = (prefix == last_prefix) |
86 | 1834 | else: | 1837 | else: |
87 | 1835 | prefix = None | 1838 | prefix = None |
88 | 1836 | soft = False | 1839 | soft = False |
91 | 1837 | if max_fulltext_len < len(bytes): | 1840 | if max_fulltext_len < chunks_len: |
92 | 1838 | max_fulltext_len = len(bytes) | 1841 | max_fulltext_len = chunks_len |
93 | 1839 | max_fulltext_prefix = prefix | 1842 | max_fulltext_prefix = prefix |
94 | 1840 | (found_sha1, start_point, end_point, | 1843 | (found_sha1, start_point, end_point, |
95 | 1841 | type) = self._compressor.compress(record.key, | 1844 | type) = self._compressor.compress(record.key, |
97 | 1842 | [bytes], record.sha1, soft=soft, | 1845 | chunks, record.sha1, soft=soft, |
98 | 1843 | nostore_sha=nostore_sha) | 1846 | nostore_sha=nostore_sha) |
100 | 1844 | # delta_ratio = float(len(bytes)) / (end_point - start_point) | 1847 | # delta_ratio = float(chunks_len) / (end_point - start_point) |
101 | 1845 | # Check if we want to continue to include that text | 1848 | # Check if we want to continue to include that text |
102 | 1846 | if (prefix == max_fulltext_prefix | 1849 | if (prefix == max_fulltext_prefix |
103 | 1847 | and end_point < 2 * max_fulltext_len): | 1850 | and end_point < 2 * max_fulltext_len): |
104 | @@ -1859,10 +1862,10 @@ | |||
105 | 1859 | if start_new_block: | 1862 | if start_new_block: |
106 | 1860 | self._compressor.pop_last() | 1863 | self._compressor.pop_last() |
107 | 1861 | flush() | 1864 | flush() |
109 | 1862 | max_fulltext_len = len(bytes) | 1865 | max_fulltext_len = chunks_len |
110 | 1863 | (found_sha1, start_point, end_point, | 1866 | (found_sha1, start_point, end_point, |
111 | 1864 | type) = self._compressor.compress( | 1867 | type) = self._compressor.compress( |
113 | 1865 | record.key, [bytes], record.sha1) | 1868 | record.key, chunks, record.sha1) |
114 | 1866 | if record.key[-1] is None: | 1869 | if record.key[-1] is None: |
115 | 1867 | key = record.key[:-1] + (b'sha1:' + found_sha1,) | 1870 | key = record.key[:-1] + (b'sha1:' + found_sha1,) |
116 | 1868 | else: | 1871 | else: |
117 | @@ -1915,7 +1918,7 @@ | |||
118 | 1915 | pb.update('Walking content', key_idx, total) | 1918 | pb.update('Walking content', key_idx, total) |
119 | 1916 | if record.storage_kind == 'absent': | 1919 | if record.storage_kind == 'absent': |
120 | 1917 | raise errors.RevisionNotPresent(key, self) | 1920 | raise errors.RevisionNotPresent(key, self) |
122 | 1918 | lines = osutils.split_lines(record.get_bytes_as('fulltext')) | 1921 | lines = record.get_bytes_as('lines') |
123 | 1919 | for line in lines: | 1922 | for line in lines: |
124 | 1920 | yield line, key | 1923 | yield line, key |
125 | 1921 | if pb is not None: | 1924 | if pb is not None: |
126 | 1922 | 1925 | ||
127 | === modified file 'breezy/bzr/groupcompress_repo.py' | |||
128 | --- breezy/bzr/groupcompress_repo.py 2019-10-19 22:53:54 +0000 | |||
129 | +++ breezy/bzr/groupcompress_repo.py 2020-01-25 16:26:49 +0000 | |||
130 | @@ -698,9 +698,9 @@ | |||
131 | 698 | % (chk_inv.revision_id, p_id_map.key()[0], | 698 | % (chk_inv.revision_id, p_id_map.key()[0], |
132 | 699 | canon_p_id_map.key()[0])) | 699 | canon_p_id_map.key()[0])) |
133 | 700 | self._data_changed = True | 700 | self._data_changed = True |
137 | 701 | yield versionedfile.ChunkedContentFactory(record.key, | 701 | yield versionedfile.ChunkedContentFactory( |
138 | 702 | record.parents, record.sha1, | 702 | record.key, record.parents, record.sha1, canonical_inv.to_lines(), |
139 | 703 | canonical_inv.to_lines()) | 703 | chunks_are_lines=True) |
140 | 704 | # We have finished processing all of the inventory records, we | 704 | # We have finished processing all of the inventory records, we |
141 | 705 | # don't need these sets anymore | 705 | # don't need these sets anymore |
142 | 706 | return _filtered_inv_stream() | 706 | return _filtered_inv_stream() |
143 | 707 | 707 | ||
144 | === modified file 'breezy/bzr/knit.py' | |||
145 | --- breezy/bzr/knit.py 2020-01-25 04:20:44 +0000 | |||
146 | +++ breezy/bzr/knit.py 2020-01-25 16:26:49 +0000 | |||
147 | @@ -223,7 +223,10 @@ | |||
148 | 223 | class FTAnnotatedToUnannotated(KnitAdapter): | 223 | class FTAnnotatedToUnannotated(KnitAdapter): |
149 | 224 | """An adapter from FT annotated knits to unannotated ones.""" | 224 | """An adapter from FT annotated knits to unannotated ones.""" |
150 | 225 | 225 | ||
152 | 226 | def get_bytes(self, factory): | 226 | def get_bytes(self, factory, target_storage_kind): |
153 | 227 | if target_storage_kind != 'knit-ft-gz': | ||
154 | 228 | raise errors.UnavailableRepresentation( | ||
155 | 229 | factory.key, target_storage_kind, factory.storage_kind) | ||
156 | 227 | annotated_compressed_bytes = factory._raw_record | 230 | annotated_compressed_bytes = factory._raw_record |
157 | 228 | rec, contents = \ | 231 | rec, contents = \ |
158 | 229 | self._data._parse_record_unchecked(annotated_compressed_bytes) | 232 | self._data._parse_record_unchecked(annotated_compressed_bytes) |
159 | @@ -236,7 +239,10 @@ | |||
160 | 236 | class DeltaAnnotatedToUnannotated(KnitAdapter): | 239 | class DeltaAnnotatedToUnannotated(KnitAdapter): |
161 | 237 | """An adapter for deltas from annotated to unannotated.""" | 240 | """An adapter for deltas from annotated to unannotated.""" |
162 | 238 | 241 | ||
164 | 239 | def get_bytes(self, factory): | 242 | def get_bytes(self, factory, target_storage_kind): |
165 | 243 | if target_storage_kind != 'knit-delta-gz': | ||
166 | 244 | raise errors.UnavailableRepresentation( | ||
167 | 245 | factory.key, target_storage_kind, factory.storage_kind) | ||
168 | 240 | annotated_compressed_bytes = factory._raw_record | 246 | annotated_compressed_bytes = factory._raw_record |
169 | 241 | rec, contents = \ | 247 | rec, contents = \ |
170 | 242 | self._data._parse_record_unchecked(annotated_compressed_bytes) | 248 | self._data._parse_record_unchecked(annotated_compressed_bytes) |
171 | @@ -250,19 +256,24 @@ | |||
172 | 250 | class FTAnnotatedToFullText(KnitAdapter): | 256 | class FTAnnotatedToFullText(KnitAdapter): |
173 | 251 | """An adapter from FT annotated knits to unannotated ones.""" | 257 | """An adapter from FT annotated knits to unannotated ones.""" |
174 | 252 | 258 | ||
176 | 253 | def get_bytes(self, factory): | 259 | def get_bytes(self, factory, target_storage_kind): |
177 | 254 | annotated_compressed_bytes = factory._raw_record | 260 | annotated_compressed_bytes = factory._raw_record |
178 | 255 | rec, contents = \ | 261 | rec, contents = \ |
179 | 256 | self._data._parse_record_unchecked(annotated_compressed_bytes) | 262 | self._data._parse_record_unchecked(annotated_compressed_bytes) |
180 | 257 | content, delta = self._annotate_factory.parse_record(factory.key[-1], | 263 | content, delta = self._annotate_factory.parse_record(factory.key[-1], |
181 | 258 | contents, factory._build_details, None) | 264 | contents, factory._build_details, None) |
183 | 259 | return b''.join(content.text()) | 265 | if target_storage_kind == 'fulltext': |
184 | 266 | return b''.join(content.text()) | ||
185 | 267 | elif target_storage_kind in ('chunked', 'lines'): | ||
186 | 268 | return content.text() | ||
187 | 269 | raise errors.UnavailableRepresentation( | ||
188 | 270 | factory.key, target_storage_kind, factory.storage_kind) | ||
189 | 260 | 271 | ||
190 | 261 | 272 | ||
191 | 262 | class DeltaAnnotatedToFullText(KnitAdapter): | 273 | class DeltaAnnotatedToFullText(KnitAdapter): |
192 | 263 | """An adapter for deltas from annotated to unannotated.""" | 274 | """An adapter for deltas from annotated to unannotated.""" |
193 | 264 | 275 | ||
195 | 265 | def get_bytes(self, factory): | 276 | def get_bytes(self, factory, target_storage_kind): |
196 | 266 | annotated_compressed_bytes = factory._raw_record | 277 | annotated_compressed_bytes = factory._raw_record |
197 | 267 | rec, contents = \ | 278 | rec, contents = \ |
198 | 268 | self._data._parse_record_unchecked(annotated_compressed_bytes) | 279 | self._data._parse_record_unchecked(annotated_compressed_bytes) |
199 | @@ -273,32 +284,42 @@ | |||
200 | 273 | [compression_parent], 'unordered', True)) | 284 | [compression_parent], 'unordered', True)) |
201 | 274 | if basis_entry.storage_kind == 'absent': | 285 | if basis_entry.storage_kind == 'absent': |
202 | 275 | raise errors.RevisionNotPresent(compression_parent, self._basis_vf) | 286 | raise errors.RevisionNotPresent(compression_parent, self._basis_vf) |
205 | 276 | basis_chunks = basis_entry.get_bytes_as('chunked') | 287 | basis_lines = basis_entry.get_bytes_as('lines') |
204 | 277 | basis_lines = osutils.chunks_to_lines(basis_chunks) | ||
206 | 278 | # Manually apply the delta because we have one annotated content and | 288 | # Manually apply the delta because we have one annotated content and |
207 | 279 | # one plain. | 289 | # one plain. |
208 | 280 | basis_content = PlainKnitContent(basis_lines, compression_parent) | 290 | basis_content = PlainKnitContent(basis_lines, compression_parent) |
209 | 281 | basis_content.apply_delta(delta, rec[1]) | 291 | basis_content.apply_delta(delta, rec[1]) |
210 | 282 | basis_content._should_strip_eol = factory._build_details[1] | 292 | basis_content._should_strip_eol = factory._build_details[1] |
212 | 283 | return b''.join(basis_content.text()) | 293 | |
213 | 294 | if target_storage_kind == 'fulltext': | ||
214 | 295 | return b''.join(basis_content.text()) | ||
215 | 296 | elif target_storage_kind in ('chunked', 'lines'): | ||
216 | 297 | return basis_content.text() | ||
217 | 298 | raise errors.UnavailableRepresentation( | ||
218 | 299 | factory.key, target_storage_kind, factory.storage_kind) | ||
219 | 284 | 300 | ||
220 | 285 | 301 | ||
221 | 286 | class FTPlainToFullText(KnitAdapter): | 302 | class FTPlainToFullText(KnitAdapter): |
222 | 287 | """An adapter from FT plain knits to unannotated ones.""" | 303 | """An adapter from FT plain knits to unannotated ones.""" |
223 | 288 | 304 | ||
225 | 289 | def get_bytes(self, factory): | 305 | def get_bytes(self, factory, target_storage_kind): |
226 | 290 | compressed_bytes = factory._raw_record | 306 | compressed_bytes = factory._raw_record |
227 | 291 | rec, contents = \ | 307 | rec, contents = \ |
228 | 292 | self._data._parse_record_unchecked(compressed_bytes) | 308 | self._data._parse_record_unchecked(compressed_bytes) |
229 | 293 | content, delta = self._plain_factory.parse_record(factory.key[-1], | 309 | content, delta = self._plain_factory.parse_record(factory.key[-1], |
230 | 294 | contents, factory._build_details, None) | 310 | contents, factory._build_details, None) |
232 | 295 | return b''.join(content.text()) | 311 | if target_storage_kind == 'fulltext': |
233 | 312 | return b''.join(content.text()) | ||
234 | 313 | elif target_storage_kind in ('chunked', 'lines'): | ||
235 | 314 | return content.text() | ||
236 | 315 | raise errors.UnavailableRepresentation( | ||
237 | 316 | factory.key, target_storage_kind, factory.storage_kind) | ||
238 | 296 | 317 | ||
239 | 297 | 318 | ||
240 | 298 | class DeltaPlainToFullText(KnitAdapter): | 319 | class DeltaPlainToFullText(KnitAdapter): |
241 | 299 | """An adapter for deltas from annotated to unannotated.""" | 320 | """An adapter for deltas from annotated to unannotated.""" |
242 | 300 | 321 | ||
244 | 301 | def get_bytes(self, factory): | 322 | def get_bytes(self, factory, target_storage_kind): |
245 | 302 | compressed_bytes = factory._raw_record | 323 | compressed_bytes = factory._raw_record |
246 | 303 | rec, contents = \ | 324 | rec, contents = \ |
247 | 304 | self._data._parse_record_unchecked(compressed_bytes) | 325 | self._data._parse_record_unchecked(compressed_bytes) |
248 | @@ -309,14 +330,18 @@ | |||
249 | 309 | [compression_parent], 'unordered', True)) | 330 | [compression_parent], 'unordered', True)) |
250 | 310 | if basis_entry.storage_kind == 'absent': | 331 | if basis_entry.storage_kind == 'absent': |
251 | 311 | raise errors.RevisionNotPresent(compression_parent, self._basis_vf) | 332 | raise errors.RevisionNotPresent(compression_parent, self._basis_vf) |
254 | 312 | basis_chunks = basis_entry.get_bytes_as('chunked') | 333 | basis_lines = basis_entry.get_bytes_as('lines') |
253 | 313 | basis_lines = osutils.chunks_to_lines(basis_chunks) | ||
255 | 314 | basis_content = PlainKnitContent(basis_lines, compression_parent) | 334 | basis_content = PlainKnitContent(basis_lines, compression_parent) |
256 | 315 | # Manually apply the delta because we have one annotated content and | 335 | # Manually apply the delta because we have one annotated content and |
257 | 316 | # one plain. | 336 | # one plain. |
258 | 317 | content, _ = self._plain_factory.parse_record(rec[1], contents, | 337 | content, _ = self._plain_factory.parse_record(rec[1], contents, |
259 | 318 | factory._build_details, basis_content) | 338 | factory._build_details, basis_content) |
261 | 319 | return b''.join(content.text()) | 339 | if target_storage_kind == 'fulltext': |
262 | 340 | return b''.join(content.text()) | ||
263 | 341 | elif target_storage_kind in ('chunked', 'lines'): | ||
264 | 342 | return content.text() | ||
265 | 343 | raise errors.UnavailableRepresentation( | ||
266 | 344 | factory.key, target_storage_kind, factory.storage_kind) | ||
267 | 320 | 345 | ||
268 | 321 | 346 | ||
269 | 322 | class KnitContentFactory(ContentFactory): | 347 | class KnitContentFactory(ContentFactory): |
270 | @@ -381,19 +406,15 @@ | |||
271 | 381 | self._create_network_bytes() | 406 | self._create_network_bytes() |
272 | 382 | return self._network_bytes | 407 | return self._network_bytes |
273 | 383 | if ('-ft-' in self.storage_kind | 408 | if ('-ft-' in self.storage_kind |
276 | 384 | and storage_kind in ('chunked', 'fulltext')): | 409 | and storage_kind in ('chunked', 'fulltext', 'lines')): |
277 | 385 | adapter_key = (self.storage_kind, 'fulltext') | 410 | adapter_key = (self.storage_kind, storage_kind) |
278 | 386 | adapter_factory = adapter_registry.get(adapter_key) | 411 | adapter_factory = adapter_registry.get(adapter_key) |
279 | 387 | adapter = adapter_factory(None) | 412 | adapter = adapter_factory(None) |
285 | 388 | bytes = adapter.get_bytes(self) | 413 | return adapter.get_bytes(self, storage_kind) |
281 | 389 | if storage_kind == 'chunked': | ||
282 | 390 | return [bytes] | ||
283 | 391 | else: | ||
284 | 392 | return bytes | ||
286 | 393 | if self._knit is not None: | 414 | if self._knit is not None: |
287 | 394 | # Not redundant with direct conversion above - that only handles | 415 | # Not redundant with direct conversion above - that only handles |
288 | 395 | # fulltext cases. | 416 | # fulltext cases. |
290 | 396 | if storage_kind == 'chunked': | 417 | if storage_kind in ('chunked', 'lines'): |
291 | 397 | return self._knit.get_lines(self.key[0]) | 418 | return self._knit.get_lines(self.key[0]) |
292 | 398 | elif storage_kind == 'fulltext': | 419 | elif storage_kind == 'fulltext': |
293 | 399 | return self._knit.get_text(self.key[0]) | 420 | return self._knit.get_text(self.key[0]) |
294 | @@ -435,9 +456,9 @@ | |||
295 | 435 | # all the keys etc are contained in the bytes returned in the | 456 | # all the keys etc are contained in the bytes returned in the |
296 | 436 | # first record. | 457 | # first record. |
297 | 437 | return b'' | 458 | return b'' |
299 | 438 | if storage_kind in ('chunked', 'fulltext'): | 459 | if storage_kind in ('chunked', 'fulltext', 'lines'): |
300 | 439 | chunks = self._generator._get_one_work(self.key).text() | 460 | chunks = self._generator._get_one_work(self.key).text() |
302 | 440 | if storage_kind == 'chunked': | 461 | if storage_kind in ('chunked', 'lines'): |
303 | 441 | return chunks | 462 | return chunks |
304 | 442 | else: | 463 | else: |
305 | 443 | return b''.join(chunks) | 464 | return b''.join(chunks) |
306 | @@ -1708,7 +1729,7 @@ | |||
307 | 1708 | except KeyError: | 1729 | except KeyError: |
308 | 1709 | adapter_key = (record.storage_kind, "knit-ft-gz") | 1730 | adapter_key = (record.storage_kind, "knit-ft-gz") |
309 | 1710 | adapter = get_adapter(adapter_key) | 1731 | adapter = get_adapter(adapter_key) |
311 | 1711 | bytes = adapter.get_bytes(record) | 1732 | bytes = adapter.get_bytes(record, adapter_key[1]) |
312 | 1712 | else: | 1733 | else: |
313 | 1713 | # It's a knit record, it has a _raw_record field (even if | 1734 | # It's a knit record, it has a _raw_record field (even if |
314 | 1714 | # it was reconstituted from a network stream). | 1735 | # it was reconstituted from a network stream). |
315 | @@ -1745,9 +1766,8 @@ | |||
316 | 1745 | buffered = True | 1766 | buffered = True |
317 | 1746 | if not buffered: | 1767 | if not buffered: |
318 | 1747 | self._index.add_records([index_entry]) | 1768 | self._index.add_records([index_entry]) |
322 | 1748 | elif record.storage_kind == 'chunked': | 1769 | elif record.storage_kind in ('chunked', 'file'): |
323 | 1749 | self.add_lines(record.key, parents, | 1770 | self.add_lines(record.key, parents, record.get_bytes_as('lines')) |
321 | 1750 | osutils.chunks_to_lines(record.get_bytes_as('chunked'))) | ||
324 | 1751 | else: | 1771 | else: |
325 | 1752 | # Not suitable for direct insertion as a | 1772 | # Not suitable for direct insertion as a |
326 | 1753 | # delta, either because it's not the right format, or this | 1773 | # delta, either because it's not the right format, or this |
327 | @@ -1757,12 +1777,11 @@ | |||
328 | 1757 | self._access.flush() | 1777 | self._access.flush() |
329 | 1758 | try: | 1778 | try: |
330 | 1759 | # Try getting a fulltext directly from the record. | 1779 | # Try getting a fulltext directly from the record. |
332 | 1760 | bytes = record.get_bytes_as('fulltext') | 1780 | lines = record.get_bytes_as('lines') |
333 | 1761 | except errors.UnavailableRepresentation: | 1781 | except errors.UnavailableRepresentation: |
335 | 1762 | adapter_key = record.storage_kind, 'fulltext' | 1782 | adapter_key = record.storage_kind, 'lines' |
336 | 1763 | adapter = get_adapter(adapter_key) | 1783 | adapter = get_adapter(adapter_key) |
339 | 1764 | bytes = adapter.get_bytes(record) | 1784 | lines = adapter.get_bytes(record, 'lines') |
338 | 1765 | lines = split_lines(bytes) | ||
340 | 1766 | try: | 1785 | try: |
341 | 1767 | self.add_lines(record.key, parents, lines) | 1786 | self.add_lines(record.key, parents, lines) |
342 | 1768 | except errors.RevisionAlreadyPresent: | 1787 | except errors.RevisionAlreadyPresent: |
343 | @@ -2107,7 +2126,7 @@ | |||
344 | 2107 | if key in self.nonlocal_keys: | 2126 | if key in self.nonlocal_keys: |
345 | 2108 | record = next(self.get_record_stream()) | 2127 | record = next(self.get_record_stream()) |
346 | 2109 | # Create a content object on the fly | 2128 | # Create a content object on the fly |
348 | 2110 | lines = osutils.chunks_to_lines(record.get_bytes_as('chunked')) | 2129 | lines = record.get_bytes_as('lines') |
349 | 2111 | return PlainKnitContent(lines, record.key) | 2130 | return PlainKnitContent(lines, record.key) |
350 | 2112 | else: | 2131 | else: |
351 | 2113 | # local keys we can ask for directly | 2132 | # local keys we can ask for directly |
352 | @@ -2198,9 +2217,9 @@ | |||
353 | 2198 | if component_id in self._contents_map: | 2217 | if component_id in self._contents_map: |
354 | 2199 | content = self._contents_map[component_id] | 2218 | content = self._contents_map[component_id] |
355 | 2200 | else: | 2219 | else: |
359 | 2201 | content, delta = self._factory.parse_record(key[-1], | 2220 | content, delta = self._factory.parse_record( |
360 | 2202 | record, record_details, content, | 2221 | key[-1], record, record_details, content, |
361 | 2203 | copy_base_content=multiple_versions) | 2222 | copy_base_content=multiple_versions) |
362 | 2204 | if multiple_versions: | 2223 | if multiple_versions: |
363 | 2205 | self._contents_map[component_id] = content | 2224 | self._contents_map[component_id] = content |
364 | 2206 | 2225 | ||
365 | 2207 | 2226 | ||
366 | === modified file 'breezy/bzr/knitpack_repo.py' | |||
367 | --- breezy/bzr/knitpack_repo.py 2020-01-11 17:50:28 +0000 | |||
368 | +++ breezy/bzr/knitpack_repo.py 2020-01-25 16:26:49 +0000 | |||
369 | @@ -1092,8 +1092,8 @@ | |||
370 | 1092 | raise errors.BzrError('Mismatched key parent %r:%r' % | 1092 | raise errors.BzrError('Mismatched key parent %r:%r' % |
371 | 1093 | (key, parent_keys)) | 1093 | (key, parent_keys)) |
372 | 1094 | parents.append(parent_key[1]) | 1094 | parents.append(parent_key[1]) |
375 | 1095 | text_lines = osutils.split_lines(next(repo.texts.get_record_stream( | 1095 | text_lines = next(repo.texts.get_record_stream( |
376 | 1096 | [key], 'unordered', True)).get_bytes_as('fulltext')) | 1096 | [key], 'unordered', True)).get_bytes_as('lines') |
377 | 1097 | output_texts.add_lines(key, parent_keys, text_lines, | 1097 | output_texts.add_lines(key, parent_keys, text_lines, |
378 | 1098 | random_id=True, check_content=False) | 1098 | random_id=True, check_content=False) |
379 | 1099 | # 5) check that nothing inserted has a reference outside the keyspace. | 1099 | # 5) check that nothing inserted has a reference outside the keyspace. |
380 | 1100 | 1100 | ||
381 | === modified file 'breezy/bzr/reconcile.py' | |||
382 | --- breezy/bzr/reconcile.py 2018-11-30 12:39:04 +0000 | |||
383 | +++ breezy/bzr/reconcile.py 2020-01-25 16:26:49 +0000 | |||
384 | @@ -35,7 +35,7 @@ | |||
385 | 35 | from ..i18n import gettext | 35 | from ..i18n import gettext |
386 | 36 | from ..trace import mutter | 36 | from ..trace import mutter |
387 | 37 | from ..tsort import topo_sort | 37 | from ..tsort import topo_sort |
389 | 38 | from .versionedfile import AdapterFactory, FulltextContentFactory | 38 | from .versionedfile import AdapterFactory, ChunkedContentFactory |
390 | 39 | 39 | ||
391 | 40 | 40 | ||
392 | 41 | class VersionedFileRepoReconciler(object): | 41 | class VersionedFileRepoReconciler(object): |
393 | @@ -152,8 +152,8 @@ | |||
394 | 152 | # The check for the left most parent only handles knit | 152 | # The check for the left most parent only handles knit |
395 | 153 | # compressors, but this code only applies to knit and weave | 153 | # compressors, but this code only applies to knit and weave |
396 | 154 | # repositories anyway. | 154 | # repositories anyway. |
399 | 155 | bytes = record.get_bytes_as('fulltext') | 155 | chunks = record.get_bytes_as('chunked') |
400 | 156 | yield FulltextContentFactory(record.key, wanted_parents, record.sha1, bytes) | 156 | yield ChunkedContentFactory(record.key, wanted_parents, record.sha1, chunks) |
401 | 157 | else: | 157 | else: |
402 | 158 | adapted_record = AdapterFactory( | 158 | adapted_record = AdapterFactory( |
403 | 159 | record.key, wanted_parents, record) | 159 | record.key, wanted_parents, record) |
404 | @@ -344,10 +344,10 @@ | |||
405 | 344 | 344 | ||
406 | 345 | def fix_parents(stream): | 345 | def fix_parents(stream): |
407 | 346 | for record in stream: | 346 | for record in stream: |
409 | 347 | bytes = record.get_bytes_as('fulltext') | 347 | chunks = record.get_bytes_as('chunked') |
410 | 348 | new_key = (new_file_id, record.key[-1]) | 348 | new_key = (new_file_id, record.key[-1]) |
411 | 349 | parents = new_parents[new_key] | 349 | parents = new_parents[new_key] |
413 | 350 | yield FulltextContentFactory(new_key, parents, record.sha1, bytes) | 350 | yield ChunkedContentFactory(new_key, parents, record.sha1, chunks) |
414 | 351 | stream = self.repo.texts.get_record_stream( | 351 | stream = self.repo.texts.get_record_stream( |
415 | 352 | needed_keys, 'topological', True) | 352 | needed_keys, 'topological', True) |
416 | 353 | self.repo._remove_file_id(new_file_id) | 353 | self.repo._remove_file_id(new_file_id) |
417 | 354 | 354 | ||
418 | === modified file 'breezy/bzr/smart/repository.py' | |||
419 | --- breezy/bzr/smart/repository.py 2019-02-15 18:57:38 +0000 | |||
420 | +++ breezy/bzr/smart/repository.py 2020-01-25 16:26:49 +0000 | |||
421 | @@ -1270,7 +1270,9 @@ | |||
422 | 1270 | inv_delta = inv._make_delta(prev_inv) | 1270 | inv_delta = inv._make_delta(prev_inv) |
423 | 1271 | lines = serializer.delta_to_lines( | 1271 | lines = serializer.delta_to_lines( |
424 | 1272 | prev_inv.revision_id, inv.revision_id, inv_delta) | 1272 | prev_inv.revision_id, inv.revision_id, inv_delta) |
426 | 1273 | yield ChunkedContentFactory(inv.revision_id, None, None, lines) | 1273 | yield ChunkedContentFactory( |
427 | 1274 | inv.revision_id, None, None, lines, | ||
428 | 1275 | chunks_are_lines=True) | ||
429 | 1274 | prev_inv = inv | 1276 | prev_inv = inv |
430 | 1275 | 1277 | ||
431 | 1276 | def body_stream(self, repository, ordering, revids): | 1278 | def body_stream(self, repository, ordering, revids): |
432 | 1277 | 1279 | ||
433 | === modified file 'breezy/bzr/versionedfile.py' | |||
434 | --- breezy/bzr/versionedfile.py 2020-01-11 17:50:28 +0000 | |||
435 | +++ breezy/bzr/versionedfile.py 2020-01-25 16:26:49 +0000 | |||
436 | @@ -56,20 +56,19 @@ | |||
437 | 56 | 56 | ||
438 | 57 | 57 | ||
439 | 58 | adapter_registry = Registry() | 58 | adapter_registry = Registry() |
440 | 59 | adapter_registry.register_lazy(('knit-delta-gz', 'fulltext'), 'breezy.bzr.knit', | ||
441 | 60 | 'DeltaPlainToFullText') | ||
442 | 61 | adapter_registry.register_lazy(('knit-ft-gz', 'fulltext'), 'breezy.bzr.knit', | ||
443 | 62 | 'FTPlainToFullText') | ||
444 | 63 | adapter_registry.register_lazy(('knit-annotated-delta-gz', 'knit-delta-gz'), | 59 | adapter_registry.register_lazy(('knit-annotated-delta-gz', 'knit-delta-gz'), |
445 | 64 | 'breezy.bzr.knit', 'DeltaAnnotatedToUnannotated') | 60 | 'breezy.bzr.knit', 'DeltaAnnotatedToUnannotated') |
446 | 65 | adapter_registry.register_lazy(('knit-annotated-delta-gz', 'fulltext'), | ||
447 | 66 | 'breezy.bzr.knit', 'DeltaAnnotatedToFullText') | ||
448 | 67 | adapter_registry.register_lazy(('knit-annotated-ft-gz', 'knit-ft-gz'), | 61 | adapter_registry.register_lazy(('knit-annotated-ft-gz', 'knit-ft-gz'), |
449 | 68 | 'breezy.bzr.knit', 'FTAnnotatedToUnannotated') | 62 | 'breezy.bzr.knit', 'FTAnnotatedToUnannotated') |
454 | 69 | adapter_registry.register_lazy(('knit-annotated-ft-gz', 'fulltext'), | 63 | for target_storage_kind in ('fulltext', 'chunked', 'lines'): |
455 | 70 | 'breezy.bzr.knit', 'FTAnnotatedToFullText') | 64 | adapter_registry.register_lazy(('knit-delta-gz', target_storage_kind), 'breezy.bzr.knit', |
456 | 71 | # adapter_registry.register_lazy(('knit-annotated-ft-gz', 'chunked'), | 65 | 'DeltaPlainToFullText') |
457 | 72 | # 'breezy.bzr.knit', 'FTAnnotatedToChunked') | 66 | adapter_registry.register_lazy(('knit-ft-gz', target_storage_kind), 'breezy.bzr.knit', |
458 | 67 | 'FTPlainToFullText') | ||
459 | 68 | adapter_registry.register_lazy(('knit-annotated-ft-gz', target_storage_kind), | ||
460 | 69 | 'breezy.bzr.knit', 'FTAnnotatedToFullText') | ||
461 | 70 | adapter_registry.register_lazy(('knit-annotated-delta-gz', target_storage_kind), | ||
462 | 71 | 'breezy.bzr.knit', 'DeltaAnnotatedToFullText') | ||
463 | 73 | 72 | ||
464 | 74 | 73 | ||
465 | 75 | class ContentFactory(object): | 74 | class ContentFactory(object): |
466 | @@ -110,21 +109,27 @@ | |||
467 | 110 | :ivar parents: A tuple of parent keys for self.key. If the object has | 109 | :ivar parents: A tuple of parent keys for self.key. If the object has |
468 | 111 | no parent information, None (as opposed to () for an empty list of | 110 | no parent information, None (as opposed to () for an empty list of |
469 | 112 | parents). | 111 | parents). |
470 | 112 | :ivar chunks_are_lines: Whether chunks are lines. | ||
471 | 113 | """ | 113 | """ |
472 | 114 | 114 | ||
474 | 115 | def __init__(self, key, parents, sha1, chunks): | 115 | def __init__(self, key, parents, sha1, chunks, chunks_are_lines=None): |
475 | 116 | """Create a ContentFactory.""" | 116 | """Create a ContentFactory.""" |
476 | 117 | self.sha1 = sha1 | 117 | self.sha1 = sha1 |
477 | 118 | self.storage_kind = 'chunked' | 118 | self.storage_kind = 'chunked' |
478 | 119 | self.key = key | 119 | self.key = key |
479 | 120 | self.parents = parents | 120 | self.parents = parents |
480 | 121 | self._chunks = chunks | 121 | self._chunks = chunks |
481 | 122 | self._chunks_are_lines = chunks_are_lines | ||
482 | 122 | 123 | ||
483 | 123 | def get_bytes_as(self, storage_kind): | 124 | def get_bytes_as(self, storage_kind): |
484 | 124 | if storage_kind == 'chunked': | 125 | if storage_kind == 'chunked': |
485 | 125 | return self._chunks | 126 | return self._chunks |
486 | 126 | elif storage_kind == 'fulltext': | 127 | elif storage_kind == 'fulltext': |
487 | 127 | return b''.join(self._chunks) | 128 | return b''.join(self._chunks) |
488 | 129 | elif storage_kind == 'lines': | ||
489 | 130 | if self._chunks_are_lines: | ||
490 | 131 | return self._chunks | ||
491 | 132 | return list(osutils.chunks_to_lines(self._chunks)) | ||
492 | 128 | raise errors.UnavailableRepresentation(self.key, storage_kind, | 133 | raise errors.UnavailableRepresentation(self.key, storage_kind, |
493 | 129 | self.storage_kind) | 134 | self.storage_kind) |
494 | 130 | 135 | ||
495 | @@ -160,6 +165,38 @@ | |||
496 | 160 | return self._text | 165 | return self._text |
497 | 161 | elif storage_kind == 'chunked': | 166 | elif storage_kind == 'chunked': |
498 | 162 | return [self._text] | 167 | return [self._text] |
499 | 168 | elif storage_kind == 'lines': | ||
500 | 169 | return osutils.split_lines(self._text) | ||
501 | 170 | raise errors.UnavailableRepresentation(self.key, storage_kind, | ||
502 | 171 | self.storage_kind) | ||
503 | 172 | |||
504 | 173 | |||
505 | 174 | class FileContentFactory(ContentFactory): | ||
506 | 175 | """File-based content factory. | ||
507 | 176 | """ | ||
508 | 177 | |||
509 | 178 | def __init__(self, key, parents, fileobj): | ||
510 | 179 | self.key = key | ||
511 | 180 | self.parents = parents | ||
512 | 181 | self.file = fileobj | ||
513 | 182 | self.storage_kind = 'file' | ||
514 | 183 | self._sha1 = None | ||
515 | 184 | |||
516 | 185 | @property | ||
517 | 186 | def sha1(self): | ||
518 | 187 | if self._sha1 is None: | ||
519 | 188 | self.file.seek(0) | ||
520 | 189 | self._size, self._sha1 = osutils.size_sha_file(self.file) | ||
521 | 190 | return self._sha1 | ||
522 | 191 | |||
523 | 192 | def get_bytes_as(self, storage_kind): | ||
524 | 193 | self.file.seek(0) | ||
525 | 194 | if storage_kind == 'fulltext': | ||
526 | 195 | return self.file.read() | ||
527 | 196 | elif storage_kind == 'chunked': | ||
528 | 197 | return list(osutils.file_iterator(self.file)) | ||
529 | 198 | elif storage_kind == 'lines': | ||
530 | 199 | return self.file.readlines() | ||
531 | 163 | raise errors.UnavailableRepresentation(self.key, storage_kind, | 200 | raise errors.UnavailableRepresentation(self.key, storage_kind, |
532 | 164 | self.storage_kind) | 201 | self.storage_kind) |
533 | 165 | 202 | ||
534 | @@ -1030,13 +1067,11 @@ | |||
535 | 1030 | if not mpvf.has_version(p)) | 1067 | if not mpvf.has_version(p)) |
536 | 1031 | # It seems likely that adding all the present parents as fulltexts can | 1068 | # It seems likely that adding all the present parents as fulltexts can |
537 | 1032 | # easily exhaust memory. | 1069 | # easily exhaust memory. |
538 | 1033 | chunks_to_lines = osutils.chunks_to_lines | ||
539 | 1034 | for record in self.get_record_stream(needed_parents, 'unordered', | 1070 | for record in self.get_record_stream(needed_parents, 'unordered', |
540 | 1035 | True): | 1071 | True): |
541 | 1036 | if record.storage_kind == 'absent': | 1072 | if record.storage_kind == 'absent': |
542 | 1037 | continue | 1073 | continue |
545 | 1038 | mpvf.add_version(chunks_to_lines(record.get_bytes_as('chunked')), | 1074 | mpvf.add_version(record.get_bytes_as('lines'), record.key, []) |
544 | 1039 | record.key, []) | ||
546 | 1040 | for (key, parent_keys, expected_sha1, mpdiff), lines in zip( | 1075 | for (key, parent_keys, expected_sha1, mpdiff), lines in zip( |
547 | 1041 | records, mpvf.get_line_list(versions)): | 1076 | records, mpvf.get_line_list(versions)): |
548 | 1042 | if len(parent_keys) == 1: | 1077 | if len(parent_keys) == 1: |
549 | @@ -1546,7 +1581,9 @@ | |||
550 | 1546 | lines = self._lines[key] | 1581 | lines = self._lines[key] |
551 | 1547 | parents = self._parents[key] | 1582 | parents = self._parents[key] |
552 | 1548 | pending.remove(key) | 1583 | pending.remove(key) |
554 | 1549 | yield ChunkedContentFactory(key, parents, None, lines) | 1584 | yield ChunkedContentFactory( |
555 | 1585 | key, parents, None, lines, | ||
556 | 1586 | chunks_are_lines=True) | ||
557 | 1550 | for versionedfile in self.fallback_versionedfiles: | 1587 | for versionedfile in self.fallback_versionedfiles: |
558 | 1551 | for record in versionedfile.get_record_stream( | 1588 | for record in versionedfile.get_record_stream( |
559 | 1552 | pending, 'unordered', True): | 1589 | pending, 'unordered', True): |
560 | @@ -1775,9 +1812,9 @@ | |||
561 | 1775 | if lines is not None: | 1812 | if lines is not None: |
562 | 1776 | if not isinstance(lines, list): | 1813 | if not isinstance(lines, list): |
563 | 1777 | raise AssertionError | 1814 | raise AssertionError |
567 | 1778 | yield ChunkedContentFactory((k,), None, | 1815 | yield ChunkedContentFactory( |
568 | 1779 | sha1=osutils.sha_strings(lines), | 1816 | (k,), None, sha1=osutils.sha_strings(lines), |
569 | 1780 | chunks=lines) | 1817 | chunks=lines, chunks_are_lines=True) |
570 | 1781 | else: | 1818 | else: |
571 | 1782 | yield AbsentContentFactory((k,)) | 1819 | yield AbsentContentFactory((k,)) |
572 | 1783 | 1820 | ||
573 | 1784 | 1821 | ||
574 | === modified file 'breezy/bzr/vf_repository.py' | |||
575 | --- breezy/bzr/vf_repository.py 2020-01-20 00:03:54 +0000 | |||
576 | +++ breezy/bzr/vf_repository.py 2020-01-25 16:26:49 +0000 | |||
577 | @@ -853,8 +853,8 @@ | |||
578 | 853 | """Check a single text from this repository.""" | 853 | """Check a single text from this repository.""" |
579 | 854 | if kind == 'inventories': | 854 | if kind == 'inventories': |
580 | 855 | rev_id = record.key[0] | 855 | rev_id = record.key[0] |
583 | 856 | inv = self._deserialise_inventory(rev_id, | 856 | inv = self._deserialise_inventory( |
584 | 857 | record.get_bytes_as('fulltext')) | 857 | rev_id, record.get_bytes_as('fulltext')) |
585 | 858 | if last_object is not None: | 858 | if last_object is not None: |
586 | 859 | delta = inv._make_delta(last_object) | 859 | delta = inv._make_delta(last_object) |
587 | 860 | for old_path, path, file_id, ie in delta: | 860 | for old_path, path, file_id, ie in delta: |
588 | @@ -880,14 +880,9 @@ | |||
589 | 880 | """Check a single text.""" | 880 | """Check a single text.""" |
590 | 881 | # Check it is extractable. | 881 | # Check it is extractable. |
591 | 882 | # TODO: check length. | 882 | # TODO: check length. |
600 | 883 | if record.storage_kind == 'chunked': | 883 | chunks = record.get_bytes_as('chunked') |
601 | 884 | chunks = record.get_bytes_as(record.storage_kind) | 884 | sha1 = osutils.sha_strings(chunks) |
602 | 885 | sha1 = osutils.sha_strings(chunks) | 885 | length = sum(map(len, chunks)) |
595 | 886 | length = sum(map(len, chunks)) | ||
596 | 887 | else: | ||
597 | 888 | content = record.get_bytes_as('fulltext') | ||
598 | 889 | sha1 = osutils.sha_string(content) | ||
599 | 890 | length = len(content) | ||
603 | 891 | if item_data and sha1 != item_data[1]: | 886 | if item_data and sha1 != item_data[1]: |
604 | 892 | checker._report_items.append( | 887 | checker._report_items.append( |
605 | 893 | 'sha1 mismatch: %s has sha1 %s expected %s referenced by %s' % | 888 | 'sha1 mismatch: %s has sha1 %s expected %s referenced by %s' % |
606 | @@ -1197,9 +1192,8 @@ | |||
607 | 1197 | stream = self.inventories.get_record_stream(keys, 'unordered', True) | 1192 | stream = self.inventories.get_record_stream(keys, 'unordered', True) |
608 | 1198 | for record in stream: | 1193 | for record in stream: |
609 | 1199 | if record.storage_kind != 'absent': | 1194 | if record.storage_kind != 'absent': |
611 | 1200 | chunks = record.get_bytes_as('chunked') | 1195 | lines = record.get_bytes_as('lines') |
612 | 1201 | revid = record.key[-1] | 1196 | revid = record.key[-1] |
613 | 1202 | lines = osutils.chunks_to_lines(chunks) | ||
614 | 1203 | for line in lines: | 1197 | for line in lines: |
615 | 1204 | yield line, revid | 1198 | yield line, revid |
616 | 1205 | 1199 | ||
617 | 1206 | 1200 | ||
618 | === modified file 'breezy/bzr/weave.py' | |||
619 | --- breezy/bzr/weave.py 2019-03-02 21:46:18 +0000 | |||
620 | +++ breezy/bzr/weave.py 2020-01-25 16:26:49 +0000 | |||
621 | @@ -179,7 +179,7 @@ | |||
622 | 179 | def get_bytes_as(self, storage_kind): | 179 | def get_bytes_as(self, storage_kind): |
623 | 180 | if storage_kind == 'fulltext': | 180 | if storage_kind == 'fulltext': |
624 | 181 | return self._weave.get_text(self.key[-1]) | 181 | return self._weave.get_text(self.key[-1]) |
626 | 182 | elif storage_kind == 'chunked': | 182 | elif storage_kind in ('chunked', 'lines'): |
627 | 183 | return self._weave.get_lines(self.key[-1]) | 183 | return self._weave.get_lines(self.key[-1]) |
628 | 184 | else: | 184 | else: |
629 | 185 | raise UnavailableRepresentation(self.key, storage_kind, 'fulltext') | 185 | raise UnavailableRepresentation(self.key, storage_kind, 'fulltext') |
630 | @@ -422,20 +422,19 @@ | |||
631 | 422 | raise RevisionNotPresent([record.key[0]], self) | 422 | raise RevisionNotPresent([record.key[0]], self) |
632 | 423 | # adapt to non-tuple interface | 423 | # adapt to non-tuple interface |
633 | 424 | parents = [parent[0] for parent in record.parents] | 424 | parents = [parent[0] for parent in record.parents] |
636 | 425 | if (record.storage_kind == 'fulltext' or | 425 | if record.storage_kind in ('fulltext', 'chunked', 'lines'): |
635 | 426 | record.storage_kind == 'chunked'): | ||
637 | 427 | self.add_lines( | 426 | self.add_lines( |
638 | 428 | record.key[0], parents, | 427 | record.key[0], parents, |
640 | 429 | osutils.chunks_to_lines(record.get_bytes_as('chunked'))) | 428 | record.get_bytes_as('lines')) |
641 | 430 | else: | 429 | else: |
643 | 431 | adapter_key = record.storage_kind, 'fulltext' | 430 | adapter_key = record.storage_kind, 'lines' |
644 | 432 | try: | 431 | try: |
645 | 433 | adapter = adapters[adapter_key] | 432 | adapter = adapters[adapter_key] |
646 | 434 | except KeyError: | 433 | except KeyError: |
647 | 435 | adapter_factory = adapter_registry.get(adapter_key) | 434 | adapter_factory = adapter_registry.get(adapter_key) |
648 | 436 | adapter = adapter_factory(self) | 435 | adapter = adapter_factory(self) |
649 | 437 | adapters[adapter_key] = adapter | 436 | adapters[adapter_key] = adapter |
651 | 438 | lines = split_lines(adapter.get_bytes(record)) | 437 | lines = adapter.get_bytes(record, 'lines') |
652 | 439 | try: | 438 | try: |
653 | 440 | self.add_lines(record.key[0], parents, lines) | 439 | self.add_lines(record.key[0], parents, lines) |
654 | 441 | except RevisionAlreadyPresent: | 440 | except RevisionAlreadyPresent: |
655 | 442 | 441 | ||
656 | === modified file 'breezy/git/annotate.py' | |||
657 | --- breezy/git/annotate.py 2019-10-20 23:46:25 +0000 | |||
658 | +++ breezy/git/annotate.py 2020-01-25 16:26:49 +0000 | |||
659 | @@ -22,6 +22,7 @@ | |||
660 | 22 | tree_lookup_path, | 22 | tree_lookup_path, |
661 | 23 | ) | 23 | ) |
662 | 24 | 24 | ||
663 | 25 | from .. import osutils | ||
664 | 25 | from ..errors import ( | 26 | from ..errors import ( |
665 | 26 | NoSuchRevision, | 27 | NoSuchRevision, |
666 | 27 | UnavailableRepresentation, | 28 | UnavailableRepresentation, |
667 | @@ -32,7 +33,7 @@ | |||
668 | 32 | ) | 33 | ) |
669 | 33 | 34 | ||
670 | 34 | 35 | ||
672 | 35 | class GitFulltextContentFactory(object): | 36 | class GitBlobContentFactory(object): |
673 | 36 | """Static data content factory. | 37 | """Static data content factory. |
674 | 37 | 38 | ||
675 | 38 | This takes a fulltext when created and just returns that during | 39 | This takes a fulltext when created and just returns that during |
676 | @@ -52,17 +53,19 @@ | |||
677 | 52 | """Create a ContentFactory.""" | 53 | """Create a ContentFactory.""" |
678 | 53 | self.store = store | 54 | self.store = store |
679 | 54 | self.key = (path, revision) | 55 | self.key = (path, revision) |
681 | 55 | self.storage_kind = 'fulltext' | 56 | self.storage_kind = 'git-blob' |
682 | 56 | self.parents = None | 57 | self.parents = None |
683 | 57 | self.blob_id = blob_id | 58 | self.blob_id = blob_id |
684 | 58 | 59 | ||
685 | 59 | def get_bytes_as(self, storage_kind): | 60 | def get_bytes_as(self, storage_kind): |
686 | 60 | if storage_kind == 'fulltext': | 61 | if storage_kind == 'fulltext': |
687 | 61 | return self.store[self.blob_id].as_raw_string() | 62 | return self.store[self.blob_id].as_raw_string() |
688 | 63 | elif storage_kind == 'lines': | ||
689 | 64 | return osutils.chunks_to_lines(self.store[self.blob_id].as_raw_chunks()) | ||
690 | 62 | elif storage_kind == 'chunked': | 65 | elif storage_kind == 'chunked': |
691 | 63 | return self.store[self.blob_id].as_raw_chunks() | 66 | return self.store[self.blob_id].as_raw_chunks() |
692 | 64 | raise UnavailableRepresentation(self.key, storage_kind, | 67 | raise UnavailableRepresentation(self.key, storage_kind, |
694 | 65 | 'fulltext') | 68 | self.storage_kind) |
695 | 66 | 69 | ||
696 | 67 | 70 | ||
697 | 68 | class GitAbsentContentFactory(object): | 71 | class GitAbsentContentFactory(object): |
698 | @@ -153,5 +156,5 @@ | |||
699 | 153 | except KeyError: | 156 | except KeyError: |
700 | 154 | yield GitAbsentContentFactory(store, path, text_revision) | 157 | yield GitAbsentContentFactory(store, path, text_revision) |
701 | 155 | else: | 158 | else: |
703 | 156 | yield GitFulltextContentFactory( | 159 | yield GitBlobContentFactory( |
704 | 157 | store, path, text_revision, blob_sha) | 160 | store, path, text_revision, blob_sha) |
705 | 158 | 161 | ||
706 | === modified file 'breezy/merge.py' | |||
707 | --- breezy/merge.py 2020-01-18 16:14:28 +0000 | |||
708 | +++ breezy/merge.py 2020-01-25 16:26:49 +0000 | |||
709 | @@ -2007,8 +2007,7 @@ | |||
710 | 2007 | for record in self.vf.get_record_stream(keys, 'unordered', True): | 2007 | for record in self.vf.get_record_stream(keys, 'unordered', True): |
711 | 2008 | if record.storage_kind == 'absent': | 2008 | if record.storage_kind == 'absent': |
712 | 2009 | raise errors.RevisionNotPresent(record.key, self.vf) | 2009 | raise errors.RevisionNotPresent(record.key, self.vf) |
715 | 2010 | result[record.key[-1]] = osutils.chunks_to_lines( | 2010 | result[record.key[-1]] = record.get_bytes_as('lines') |
714 | 2011 | record.get_bytes_as('chunked')) | ||
716 | 2012 | return result | 2011 | return result |
717 | 2013 | 2012 | ||
718 | 2014 | def plan_merge(self): | 2013 | def plan_merge(self): |
719 | 2015 | 2014 | ||
720 | === modified file 'breezy/plugins/weave_fmt/repository.py' | |||
721 | --- breezy/plugins/weave_fmt/repository.py 2018-11-12 01:41:38 +0000 | |||
722 | +++ breezy/plugins/weave_fmt/repository.py 2020-01-25 16:26:49 +0000 | |||
723 | @@ -628,19 +628,19 @@ | |||
724 | 628 | if record.storage_kind == 'absent': | 628 | if record.storage_kind == 'absent': |
725 | 629 | raise errors.RevisionNotPresent([record.key[0]], self) | 629 | raise errors.RevisionNotPresent([record.key[0]], self) |
726 | 630 | # adapt to non-tuple interface | 630 | # adapt to non-tuple interface |
728 | 631 | if record.storage_kind == 'fulltext': | 631 | if record.storage_kind in ('fulltext', 'chunks', 'lines'): |
729 | 632 | self.add_lines(record.key, None, | 632 | self.add_lines(record.key, None, |
731 | 633 | osutils.split_lines(record.get_bytes_as('fulltext'))) | 633 | record.get_bytes_as('lines')) |
732 | 634 | else: | 634 | else: |
734 | 635 | adapter_key = record.storage_kind, 'fulltext' | 635 | adapter_key = record.storage_kind, 'lines' |
735 | 636 | try: | 636 | try: |
736 | 637 | adapter = adapters[adapter_key] | 637 | adapter = adapters[adapter_key] |
737 | 638 | except KeyError: | 638 | except KeyError: |
738 | 639 | adapter_factory = adapter_registry.get(adapter_key) | 639 | adapter_factory = adapter_registry.get(adapter_key) |
739 | 640 | adapter = adapter_factory(self) | 640 | adapter = adapter_factory(self) |
740 | 641 | adapters[adapter_key] = adapter | 641 | adapters[adapter_key] = adapter |
743 | 642 | lines = osutils.split_lines(adapter.get_bytes( | 642 | lines = adapter.get_bytes( |
744 | 643 | record, record.get_bytes_as(record.storage_kind))) | 643 | record, record.get_bytes_as(record.storage_kind)) |
745 | 644 | try: | 644 | try: |
746 | 645 | self.add_lines(record.key, None, lines) | 645 | self.add_lines(record.key, None, lines) |
747 | 646 | except errors.RevisionAlreadyPresent: | 646 | except errors.RevisionAlreadyPresent: |
748 | 647 | 647 | ||
749 | === modified file 'breezy/tests/per_versionedfile.py' | |||
750 | --- breezy/tests/per_versionedfile.py 2019-06-16 15:54:33 +0000 | |||
751 | +++ breezy/tests/per_versionedfile.py 2020-01-25 16:26:49 +0000 | |||
752 | @@ -1214,7 +1214,11 @@ | |||
753 | 1214 | # Each is source_kind, requested_kind, adapter class | 1214 | # Each is source_kind, requested_kind, adapter class |
754 | 1215 | scenarios = [ | 1215 | scenarios = [ |
755 | 1216 | ('knit-delta-gz', 'fulltext', _mod_knit.DeltaPlainToFullText), | 1216 | ('knit-delta-gz', 'fulltext', _mod_knit.DeltaPlainToFullText), |
756 | 1217 | ('knit-delta-gz', 'lines', _mod_knit.DeltaPlainToFullText), | ||
757 | 1218 | ('knit-delta-gz', 'chunked', _mod_knit.DeltaPlainToFullText), | ||
758 | 1217 | ('knit-ft-gz', 'fulltext', _mod_knit.FTPlainToFullText), | 1219 | ('knit-ft-gz', 'fulltext', _mod_knit.FTPlainToFullText), |
759 | 1220 | ('knit-ft-gz', 'lines', _mod_knit.FTPlainToFullText), | ||
760 | 1221 | ('knit-ft-gz', 'chunked', _mod_knit.FTPlainToFullText), | ||
761 | 1218 | ('knit-annotated-delta-gz', 'knit-delta-gz', | 1222 | ('knit-annotated-delta-gz', 'knit-delta-gz', |
762 | 1219 | _mod_knit.DeltaAnnotatedToUnannotated), | 1223 | _mod_knit.DeltaAnnotatedToUnannotated), |
763 | 1220 | ('knit-annotated-delta-gz', 'fulltext', | 1224 | ('knit-annotated-delta-gz', 'fulltext', |
764 | @@ -1223,6 +1227,10 @@ | |||
765 | 1223 | _mod_knit.FTAnnotatedToUnannotated), | 1227 | _mod_knit.FTAnnotatedToUnannotated), |
766 | 1224 | ('knit-annotated-ft-gz', 'fulltext', | 1228 | ('knit-annotated-ft-gz', 'fulltext', |
767 | 1225 | _mod_knit.FTAnnotatedToFullText), | 1229 | _mod_knit.FTAnnotatedToFullText), |
768 | 1230 | ('knit-annotated-ft-gz', 'lines', | ||
769 | 1231 | _mod_knit.FTAnnotatedToFullText), | ||
770 | 1232 | ('knit-annotated-ft-gz', 'chunked', | ||
771 | 1233 | _mod_knit.FTAnnotatedToFullText), | ||
772 | 1226 | ] | 1234 | ] |
773 | 1227 | for source, requested, klass in scenarios: | 1235 | for source, requested, klass in scenarios: |
774 | 1228 | adapter_factory = versionedfile.adapter_registry.get( | 1236 | adapter_factory = versionedfile.adapter_registry.get( |
775 | @@ -1235,16 +1243,16 @@ | |||
776 | 1235 | transport = self.get_transport() | 1243 | transport = self.get_transport() |
777 | 1236 | return make_file_factory(annotated, mapper)(transport) | 1244 | return make_file_factory(annotated, mapper)(transport) |
778 | 1237 | 1245 | ||
780 | 1238 | def helpGetBytes(self, f, ft_adapter, delta_adapter): | 1246 | def helpGetBytes(self, f, ft_name, ft_adapter, delta_name, delta_adapter): |
781 | 1239 | """Grab the interested adapted texts for tests.""" | 1247 | """Grab the interested adapted texts for tests.""" |
782 | 1240 | # origin is a fulltext | 1248 | # origin is a fulltext |
783 | 1241 | entries = f.get_record_stream([(b'origin',)], 'unordered', False) | 1249 | entries = f.get_record_stream([(b'origin',)], 'unordered', False) |
784 | 1242 | base = next(entries) | 1250 | base = next(entries) |
786 | 1243 | ft_data = ft_adapter.get_bytes(base) | 1251 | ft_data = ft_adapter.get_bytes(base, ft_name) |
787 | 1244 | # merged is both a delta and multiple parents. | 1252 | # merged is both a delta and multiple parents. |
788 | 1245 | entries = f.get_record_stream([(b'merged',)], 'unordered', False) | 1253 | entries = f.get_record_stream([(b'merged',)], 'unordered', False) |
789 | 1246 | merged = next(entries) | 1254 | merged = next(entries) |
791 | 1247 | delta_data = delta_adapter.get_bytes(merged) | 1255 | delta_data = delta_adapter.get_bytes(merged, delta_name) |
792 | 1248 | return ft_data, delta_data | 1256 | return ft_data, delta_data |
793 | 1249 | 1257 | ||
794 | 1250 | def test_deannotation_noeol(self): | 1258 | def test_deannotation_noeol(self): |
795 | @@ -1252,10 +1260,9 @@ | |||
796 | 1252 | # we need a full text, and a delta | 1260 | # we need a full text, and a delta |
797 | 1253 | f = self.get_knit() | 1261 | f = self.get_knit() |
798 | 1254 | get_diamond_files(f, 1, trailing_eol=False) | 1262 | get_diamond_files(f, 1, trailing_eol=False) |
803 | 1255 | ft_data, delta_data = self.helpGetBytes(f, | 1263 | ft_data, delta_data = self.helpGetBytes( |
804 | 1256 | _mod_knit.FTAnnotatedToUnannotated( | 1264 | f, 'knit-ft-gz', _mod_knit.FTAnnotatedToUnannotated(None), |
805 | 1257 | None), | 1265 | 'knit-delta-gz', _mod_knit.DeltaAnnotatedToUnannotated(None)) |
802 | 1258 | _mod_knit.DeltaAnnotatedToUnannotated(None)) | ||
806 | 1259 | self.assertEqual( | 1266 | self.assertEqual( |
807 | 1260 | b'version origin 1 b284f94827db1fa2970d9e2014f080413b547a7e\n' | 1267 | b'version origin 1 b284f94827db1fa2970d9e2014f080413b547a7e\n' |
808 | 1261 | b'origin\n' | 1268 | b'origin\n' |
809 | @@ -1271,10 +1278,9 @@ | |||
810 | 1271 | # we need a full text, and a delta | 1278 | # we need a full text, and a delta |
811 | 1272 | f = self.get_knit() | 1279 | f = self.get_knit() |
812 | 1273 | get_diamond_files(f, 1) | 1280 | get_diamond_files(f, 1) |
817 | 1274 | ft_data, delta_data = self.helpGetBytes(f, | 1281 | ft_data, delta_data = self.helpGetBytes( |
818 | 1275 | _mod_knit.FTAnnotatedToUnannotated( | 1282 | f, 'knit-ft-gz', _mod_knit.FTAnnotatedToUnannotated(None), |
819 | 1276 | None), | 1283 | 'knit-delta-gz', _mod_knit.DeltaAnnotatedToUnannotated(None)) |
816 | 1277 | _mod_knit.DeltaAnnotatedToUnannotated(None)) | ||
820 | 1278 | self.assertEqual( | 1284 | self.assertEqual( |
821 | 1279 | b'version origin 1 00e364d235126be43292ab09cb4686cf703ddc17\n' | 1285 | b'version origin 1 00e364d235126be43292ab09cb4686cf703ddc17\n' |
822 | 1280 | b'origin\n' | 1286 | b'origin\n' |
823 | @@ -1293,10 +1299,9 @@ | |||
824 | 1293 | # Reconstructing a full text requires a backing versioned file, and it | 1299 | # Reconstructing a full text requires a backing versioned file, and it |
825 | 1294 | # must have the base lines requested from it. | 1300 | # must have the base lines requested from it. |
826 | 1295 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) | 1301 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) |
831 | 1296 | ft_data, delta_data = self.helpGetBytes(f, | 1302 | ft_data, delta_data = self.helpGetBytes( |
832 | 1297 | _mod_knit.FTAnnotatedToFullText( | 1303 | f, 'fulltext', _mod_knit.FTAnnotatedToFullText(None), |
833 | 1298 | None), | 1304 | 'fulltext', _mod_knit.DeltaAnnotatedToFullText(logged_vf)) |
830 | 1299 | _mod_knit.DeltaAnnotatedToFullText(logged_vf)) | ||
834 | 1300 | self.assertEqual(b'origin', ft_data) | 1305 | self.assertEqual(b'origin', ft_data) |
835 | 1301 | self.assertEqual(b'base\nleft\nright\nmerged', delta_data) | 1306 | self.assertEqual(b'base\nleft\nright\nmerged', delta_data) |
836 | 1302 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', | 1307 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', |
837 | @@ -1310,10 +1315,9 @@ | |||
838 | 1310 | # Reconstructing a full text requires a backing versioned file, and it | 1315 | # Reconstructing a full text requires a backing versioned file, and it |
839 | 1311 | # must have the base lines requested from it. | 1316 | # must have the base lines requested from it. |
840 | 1312 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) | 1317 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) |
845 | 1313 | ft_data, delta_data = self.helpGetBytes(f, | 1318 | ft_data, delta_data = self.helpGetBytes( |
846 | 1314 | _mod_knit.FTAnnotatedToFullText( | 1319 | f, 'fulltext', _mod_knit.FTAnnotatedToFullText(None), |
847 | 1315 | None), | 1320 | 'fulltext', _mod_knit.DeltaAnnotatedToFullText(logged_vf)) |
844 | 1316 | _mod_knit.DeltaAnnotatedToFullText(logged_vf)) | ||
848 | 1317 | self.assertEqual(b'origin\n', ft_data) | 1321 | self.assertEqual(b'origin\n', ft_data) |
849 | 1318 | self.assertEqual(b'base\nleft\nright\nmerged\n', delta_data) | 1322 | self.assertEqual(b'base\nleft\nright\nmerged\n', delta_data) |
850 | 1319 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', | 1323 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', |
851 | @@ -1330,10 +1334,9 @@ | |||
852 | 1330 | # Reconstructing a full text requires a backing versioned file, and it | 1334 | # Reconstructing a full text requires a backing versioned file, and it |
853 | 1331 | # must have the base lines requested from it. | 1335 | # must have the base lines requested from it. |
854 | 1332 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) | 1336 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) |
859 | 1333 | ft_data, delta_data = self.helpGetBytes(f, | 1337 | ft_data, delta_data = self.helpGetBytes( |
860 | 1334 | _mod_knit.FTPlainToFullText( | 1338 | f, 'fulltext', _mod_knit.FTPlainToFullText(None), |
861 | 1335 | None), | 1339 | 'fulltext', _mod_knit.DeltaPlainToFullText(logged_vf)) |
858 | 1336 | _mod_knit.DeltaPlainToFullText(logged_vf)) | ||
862 | 1337 | self.assertEqual(b'origin\n', ft_data) | 1340 | self.assertEqual(b'origin\n', ft_data) |
863 | 1338 | self.assertEqual(b'base\nleft\nright\nmerged\n', delta_data) | 1341 | self.assertEqual(b'base\nleft\nright\nmerged\n', delta_data) |
864 | 1339 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', | 1342 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', |
865 | @@ -1350,10 +1353,9 @@ | |||
866 | 1350 | # Reconstructing a full text requires a backing versioned file, and it | 1353 | # Reconstructing a full text requires a backing versioned file, and it |
867 | 1351 | # must have the base lines requested from it. | 1354 | # must have the base lines requested from it. |
868 | 1352 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) | 1355 | logged_vf = versionedfile.RecordingVersionedFilesDecorator(f) |
873 | 1353 | ft_data, delta_data = self.helpGetBytes(f, | 1356 | ft_data, delta_data = self.helpGetBytes( |
874 | 1354 | _mod_knit.FTPlainToFullText( | 1357 | f, 'fulltext', _mod_knit.FTPlainToFullText(None), |
875 | 1355 | None), | 1358 | 'fulltext', _mod_knit.DeltaPlainToFullText(logged_vf)) |
872 | 1356 | _mod_knit.DeltaPlainToFullText(logged_vf)) | ||
876 | 1357 | self.assertEqual(b'origin', ft_data) | 1359 | self.assertEqual(b'origin', ft_data) |
877 | 1358 | self.assertEqual(b'base\nleft\nright\nmerged', delta_data) | 1360 | self.assertEqual(b'base\nleft\nright\nmerged', delta_data) |
878 | 1359 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', | 1361 | self.assertEqual([('get_record_stream', [(b'left',)], 'unordered', |
Running landing tests failed /ci.breezy- vcs.org/ job/brz/ job/brz- land/650/
https:/