811 The first line is used to check if the cache is still valid. It is a series |
811 The first line is used to check if the cache is still valid. It is a series |
812 of key value pair. The following key are recognized: |
812 of key value pair. The following key are recognized: |
813 |
813 |
814 - tip-rev: the rev-num of the tip-most revision seen by this cache |
814 - tip-rev: the rev-num of the tip-most revision seen by this cache |
815 - tip-node: the node-id of the tip-most revision sen by this cache |
815 - tip-node: the node-id of the tip-most revision sen by this cache |
816 - filtered-hash: the hash of all filtered and obsolete revisions (before |
816 - filtered-hash: the hash of all filtered revisions (before tip-rev) |
|
817 ignored by this cache. |
|
818 - obsolete-hash: the hash of all non-filtered obsolete revisions (before |
817 tip-rev) ignored by this cache. |
819 tip-rev) ignored by this cache. |
818 |
820 |
819 The tip-rev is used to know how far behind the value in the file are |
821 The tip-rev is used to know how far behind the value in the file are |
820 compared to the current repository state. |
822 compared to the current repository state. |
821 |
823 |
822 The tip-node and filtered-hash are used to detect if this cache can be used |
824 The tip-node, filtered-hash and obsolete-hash are used to detect if this |
823 for this repository state at all. |
825 cache can be used for this repository state at all. |
824 |
826 |
825 The open/closed state is represented by a single letter 'o' or 'c'. |
827 The open/closed state is represented by a single letter 'o' or 'c'. |
826 This field can be used to avoid changelog reads when determining if a |
828 This field can be used to avoid changelog reads when determining if a |
827 branch head closes a branch or not. |
829 branch head closes a branch or not. |
828 """ |
830 """ |
829 |
831 |
830 _base_filename = b"branch3" |
832 _base_filename = b"branch3" |
|
833 _default_key_hashes = (None, None) |
831 |
834 |
832 def _write_header(self, fp) -> None: |
835 def _write_header(self, fp) -> None: |
833 cache_keys = { |
836 cache_keys = { |
834 b"tip-node": hex(self.tipnode), |
837 b"tip-node": hex(self.tipnode), |
835 b"tip-rev": b'%d' % self.tiprev, |
838 b"tip-rev": b'%d' % self.tiprev, |
836 } |
839 } |
837 if self.key_hashes: |
840 if self.key_hashes: |
838 cache_keys[b"filtered-hash"] = hex(self.key_hashes[0]) |
841 if self.key_hashes[0] is not None: |
|
842 cache_keys[b"filtered-hash"] = hex(self.key_hashes[0]) |
|
843 if self.key_hashes[1] is not None: |
|
844 cache_keys[b"obsolete-hash"] = hex(self.key_hashes[1]) |
839 pieces = (b"%s=%s" % i for i in sorted(cache_keys.items())) |
845 pieces = (b"%s=%s" % i for i in sorted(cache_keys.items())) |
840 fp.write(b" ".join(pieces) + b'\n') |
846 fp.write(b" ".join(pieces) + b'\n') |
841 |
847 |
842 @classmethod |
848 @classmethod |
843 def _load_header(cls, repo, lineiter): |
849 def _load_header(cls, repo, lineiter): |
844 header_line = next(lineiter) |
850 header_line = next(lineiter) |
845 pieces = header_line.rstrip(b'\n').split(b" ") |
851 pieces = header_line.rstrip(b'\n').split(b" ") |
846 cache_keys = dict(p.split(b'=', 1) for p in pieces) |
852 cache_keys = dict(p.split(b'=', 1) for p in pieces) |
847 |
853 |
848 args = {} |
854 args = {} |
|
855 filtered_hash = None |
|
856 obsolete_hash = None |
849 for k, v in cache_keys.items(): |
857 for k, v in cache_keys.items(): |
850 if k == b"tip-rev": |
858 if k == b"tip-rev": |
851 args["tiprev"] = int(v) |
859 args["tiprev"] = int(v) |
852 elif k == b"tip-node": |
860 elif k == b"tip-node": |
853 args["tipnode"] = bin(v) |
861 args["tipnode"] = bin(v) |
854 elif k == b"filtered-hash": |
862 elif k == b"filtered-hash": |
855 args["key_hashes"] = (bin(v),) |
863 filtered_hash = bin(v) |
|
864 elif k == b"obsolete-hash": |
|
865 obsolete_hash = bin(v) |
856 else: |
866 else: |
857 msg = b"unknown cache key: %r" % k |
867 msg = b"unknown cache key: %r" % k |
858 raise ValueError(msg) |
868 raise ValueError(msg) |
|
869 args["key_hashes"] = (filtered_hash, obsolete_hash) |
859 return args |
870 return args |
860 |
871 |
861 def _compute_key_hashes(self, repo) -> Tuple[bytes]: |
872 def _compute_key_hashes(self, repo) -> Tuple[bytes]: |
862 """return the cache key hashes that match this repoview state""" |
873 """return the cache key hashes that match this repoview state""" |
863 filtered_hash = scmutil.combined_filtered_and_obsolete_hash( |
874 return scmutil.filtered_and_obsolete_hash( |
864 repo, |
875 repo, |
865 self.tiprev, |
876 self.tiprev, |
866 needobsolete=True, |
|
867 ) |
877 ) |
868 if filtered_hash is None: |
|
869 return cast(Tuple[bytes], ()) |
|
870 else: |
|
871 return (filtered_hash,) |
|
872 |
878 |
873 |
879 |
874 class remotebranchcache(_BaseBranchCache): |
880 class remotebranchcache(_BaseBranchCache): |
875 """Branchmap info for a remote connection, should not write locally""" |
881 """Branchmap info for a remote connection, should not write locally""" |
876 |
882 |