Show More
@@ -290,6 +290,16 b' class revlog:' | |||||
290 |
|
290 | |||
291 | _flagserrorclass = error.RevlogError |
|
291 | _flagserrorclass = error.RevlogError | |
292 |
|
292 | |||
|
293 | @staticmethod | |||
|
294 | def is_inline_index(header_bytes): | |||
|
295 | header = INDEX_HEADER.unpack(header_bytes)[0] | |||
|
296 | ||||
|
297 | _format_flags = header & ~0xFFFF | |||
|
298 | _format_version = header & 0xFFFF | |||
|
299 | ||||
|
300 | features = FEATURES_BY_VERSION[_format_version] | |||
|
301 | return features[b'inline'](_format_flags) | |||
|
302 | ||||
293 | def __init__( |
|
303 | def __init__( | |
294 | self, |
|
304 | self, | |
295 | opener, |
|
305 | opener, |
@@ -16,6 +16,9 b' from .i18n import _' | |||||
16 | from .pycompat import getattr |
|
16 | from .pycompat import getattr | |
17 | from .thirdparty import attr |
|
17 | from .thirdparty import attr | |
18 | from .node import hex |
|
18 | from .node import hex | |
|
19 | from .revlogutils.constants import ( | |||
|
20 | INDEX_HEADER, | |||
|
21 | ) | |||
19 | from . import ( |
|
22 | from . import ( | |
20 | changelog, |
|
23 | changelog, | |
21 | error, |
|
24 | error, | |
@@ -23,6 +26,7 b' from . import (' | |||||
23 | manifest, |
|
26 | manifest, | |
24 | policy, |
|
27 | policy, | |
25 | pycompat, |
|
28 | pycompat, | |
|
29 | revlog as revlogmod, | |||
26 | util, |
|
30 | util, | |
27 | vfs as vfsmod, |
|
31 | vfs as vfsmod, | |
28 | ) |
|
32 | ) | |
@@ -619,44 +623,70 b' class RevlogStoreEntry(BaseStoreEntry):' | |||||
619 | copies=None, |
|
623 | copies=None, | |
620 | max_changeset=None, |
|
624 | max_changeset=None, | |
621 | ): |
|
625 | ): | |
622 | if repo is None or max_changeset is None: |
|
626 | if ( | |
623 | return super().get_streams( |
|
627 | repo is None | |
624 | repo=repo, |
|
628 | or max_changeset is None | |
625 | vfs=vfs, |
|
|||
626 | copies=copies, |
|
|||
627 | max_changeset=max_changeset, |
|
|||
628 | ) |
|
|||
629 | if any(k.endswith(b'.idx') for k in self._details.keys()): |
|
|||
630 | # This use revlog-v2, ignore for now |
|
629 | # This use revlog-v2, ignore for now | |
|
630 | or any(k.endswith(b'.idx') for k in self._details.keys()) | |||
|
631 | # This is not inline, no race expected | |||
|
632 | or b'.d' in self._details | |||
|
633 | ): | |||
631 | return super().get_streams( |
|
634 | return super().get_streams( | |
632 | repo=repo, |
|
635 | repo=repo, | |
633 | vfs=vfs, |
|
636 | vfs=vfs, | |
634 | copies=copies, |
|
637 | copies=copies, | |
635 | max_changeset=max_changeset, |
|
638 | max_changeset=max_changeset, | |
636 | ) |
|
639 | ) | |
637 | name_to_ext = {} |
|
640 | ||
638 | for ext in self._details.keys(): |
|
|||
639 | name_to_ext[self._path_prefix + ext] = ext |
|
|||
640 | name_to_size = {} |
|
641 | name_to_size = {} | |
641 | for f in self.files(): |
|
642 | for f in self.files(): | |
642 | name_to_size[f.unencoded_path] = f.file_size(None) |
|
643 | name_to_size[f.unencoded_path] = f.file_size(None) | |
|
644 | ||||
643 | stream = [ |
|
645 | stream = [ | |
644 | f.get_stream(vfs, copies) |
|
646 | f.get_stream(vfs, copies) | |
645 | for f in self.files() |
|
647 | for f in self.files() | |
646 |
if n |
|
648 | if not f.unencoded_path.endswith(b'.i') | |
647 | ] |
|
649 | ] | |
648 |
|
650 | |||
649 | is_inline = b'.d' not in self._details |
|
651 | index_path = self._path_prefix + b'.i' | |
650 |
|
652 | |||
651 | rl = self.get_revlog_instance(repo).get_revlog() |
|
653 | index_file = None | |
652 | rl_stream = rl.get_streams(max_changeset, force_inline=is_inline) |
|
654 | try: | |
|
655 | index_file = vfs(index_path) | |||
|
656 | header = index_file.read(INDEX_HEADER.size) | |||
|
657 | if revlogmod.revlog.is_inline_index(header): | |||
|
658 | size = name_to_size[index_path] | |||
653 |
|
659 | |||
654 | for name, s, size in rl_stream: |
|
660 | # no split underneath, just return the stream | |
655 | if name_to_size.get(name, 0) != size: |
|
661 | def get_stream(): | |
656 | msg = _(b"expected %d bytes but %d provided for %s") |
|
662 | fp = index_file | |
657 | msg %= name_to_size.get(name, 0), size, name |
|
663 | try: | |
658 | raise error.Abort(msg) |
|
664 | fp.seek(0) | |
659 | stream.extend(rl_stream) |
|
665 | yield None | |
|
666 | if size <= 65536: | |||
|
667 | yield fp.read(size) | |||
|
668 | else: | |||
|
669 | yield from util.filechunkiter(fp, limit=size) | |||
|
670 | finally: | |||
|
671 | fp.close() | |||
|
672 | ||||
|
673 | s = get_stream() | |||
|
674 | next(s) | |||
|
675 | index_file = None | |||
|
676 | stream.append((index_path, s, size)) | |||
|
677 | else: | |||
|
678 | rl = self.get_revlog_instance(repo).get_revlog() | |||
|
679 | rl_stream = rl.get_streams(max_changeset, force_inline=True) | |||
|
680 | for name, s, size in rl_stream: | |||
|
681 | if name_to_size.get(name, 0) != size: | |||
|
682 | msg = _(b"expected %d bytes but %d provided for %s") | |||
|
683 | msg %= name_to_size.get(name, 0), size, name | |||
|
684 | raise error.Abort(msg) | |||
|
685 | stream.extend(rl_stream) | |||
|
686 | finally: | |||
|
687 | if index_file is not None: | |||
|
688 | index_file.close() | |||
|
689 | ||||
660 | files = self.files() |
|
690 | files = self.files() | |
661 | assert len(stream) == len(files), ( |
|
691 | assert len(stream) == len(files), ( | |
662 | stream, |
|
692 | stream, |
General Comments 0
You need to be logged in to leave comments.
Login now