comparison mercurial/revlog.py @ 47153:f58a13c52726

revlog: split the `version` attribute into its two components The `revlog.version` attribute contained an integer coding 2 different informations: * the revlog version number * a bit field defining some specific feature of the revlog We now explicitly store the two components independently. This avoid exposing the implementation details all around the code and prepare for future revlog version that would encode the information in a different way. In the process we drop the `version` attribute from the interface. It was flagged for removal when that interface was created. Differential Revision: https://phab.mercurial-scm.org/D10565
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 03 May 2021 12:20:45 +0200
parents 84b176ad2860
children 47ffc754989a
comparison
equal deleted inserted replaced
47152:bc138f2a2e47 47153:f58a13c52726
449 if inst.errno != errno.ENOENT: 449 if inst.errno != errno.ENOENT:
450 raise 450 raise
451 451
452 versionflags = newversionflags 452 versionflags = newversionflags
453 453
454 self.version = versionflags 454 flags = self._format_flags = versionflags & ~0xFFFF
455 455 fmt = self._format_version = versionflags & 0xFFFF
456 flags = versionflags & ~0xFFFF
457 fmt = versionflags & 0xFFFF
458 456
459 if fmt == REVLOGV0: 457 if fmt == REVLOGV0:
460 if flags: 458 if flags:
461 raise error.RevlogError( 459 raise error.RevlogError(
462 _(b'unknown flags (%#04x) in version %d revlog %s') 460 _(b'unknown flags (%#04x) in version %d revlog %s')
517 use_rust_index = True 515 use_rust_index = True
518 else: 516 else:
519 use_rust_index = self.opener.options.get(b'rust.index') 517 use_rust_index = self.opener.options.get(b'rust.index')
520 518
521 self._parse_index = parse_index_v1 519 self._parse_index = parse_index_v1
522 if self.version == REVLOGV0: 520 if self._format_version == REVLOGV0:
523 self._parse_index = revlogv0.parse_index_v0 521 self._parse_index = revlogv0.parse_index_v0
524 elif fmt == REVLOGV2: 522 elif fmt == REVLOGV2:
525 self._parse_index = parse_index_v2 523 self._parse_index = parse_index_v2
526 elif devel_nodemap: 524 elif devel_nodemap:
527 self._parse_index = parse_index_v1_nodemap 525 self._parse_index = parse_index_v1_nodemap
1943 dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1]) 1941 dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1])
1944 if troffset <= self.start(r): 1942 if troffset <= self.start(r):
1945 trindex = r 1943 trindex = r
1946 1944
1947 with self._indexfp(b'w') as fp: 1945 with self._indexfp(b'w') as fp:
1948 self.version &= ~FLAG_INLINE_DATA 1946 self._format_flags &= ~FLAG_INLINE_DATA
1949 self._inline = False 1947 self._inline = False
1950 for i in self: 1948 for i in self:
1951 e = self.index.entry_binary(i) 1949 e = self.index.entry_binary(i)
1952 if i == 0: 1950 if i == 0:
1953 header = self.index.pack_header(self.version) 1951 header = self._format_flags | self._format_version
1952 header = self.index.pack_header(header)
1954 e = header + e 1953 e = header + e
1955 fp.write(e) 1954 fp.write(e)
1956 1955
1957 # the temp file replace the real index when we exit the context 1956 # the temp file replace the real index when we exit the context
1958 # manager 1957 # manager
2267 node, 2266 node,
2268 sidedata_offset, 2267 sidedata_offset,
2269 len(serialized_sidedata), 2268 len(serialized_sidedata),
2270 ) 2269 )
2271 2270
2272 if self.version & 0xFFFF != REVLOGV2: 2271 if self._format_version != REVLOGV2:
2273 e = e[:8] 2272 e = e[:8]
2274 2273
2275 self.index.append(e) 2274 self.index.append(e)
2276 entry = self.index.entry_binary(curr) 2275 entry = self.index.entry_binary(curr)
2277 if curr == 0: 2276 if curr == 0:
2278 header = self.index.pack_header(self.version) 2277 header = self._format_flags | self._format_version
2278 header = self.index.pack_header(header)
2279 entry = header + entry 2279 entry = header + entry
2280 self._writeentry( 2280 self._writeentry(
2281 transaction, 2281 transaction,
2282 ifh, 2282 ifh,
2283 dfh, 2283 dfh,
2305 end of the data file within a transaction, you can have cases where, for 2305 end of the data file within a transaction, you can have cases where, for
2306 example, rev `n` does not have sidedata while rev `n - 1` does, leading 2306 example, rev `n` does not have sidedata while rev `n - 1` does, leading
2307 to `n - 1`'s sidedata being written after `n`'s data. 2307 to `n - 1`'s sidedata being written after `n`'s data.
2308 2308
2309 TODO cache this in a docket file before getting out of experimental.""" 2309 TODO cache this in a docket file before getting out of experimental."""
2310 if self.version & 0xFFFF != REVLOGV2: 2310 if self._format_version != REVLOGV2:
2311 return self.end(prev) 2311 return self.end(prev)
2312 2312
2313 offset = 0 2313 offset = 0
2314 for rev, entry in enumerate(self.index): 2314 for rev, entry in enumerate(self.index):
2315 sidedata_end = entry[8] + entry[9] 2315 sidedata_end = entry[8] + entry[9]
2845 2845
2846 if addrevisioncb: 2846 if addrevisioncb:
2847 addrevisioncb(self, rev, node) 2847 addrevisioncb(self, rev, node)
2848 2848
2849 def censorrevision(self, tr, censornode, tombstone=b''): 2849 def censorrevision(self, tr, censornode, tombstone=b''):
2850 if (self.version & 0xFFFF) == REVLOGV0: 2850 if self._format_version == REVLOGV0:
2851 raise error.RevlogError( 2851 raise error.RevlogError(
2852 _(b'cannot censor with version %d revlogs') % self.version 2852 _(b'cannot censor with version %d revlogs')
2853 % self._format_version
2853 ) 2854 )
2854 2855
2855 censorrev = self.rev(censornode) 2856 censorrev = self.rev(censornode)
2856 tombstone = storageutil.packmeta({b'censored': tombstone}, b'') 2857 tombstone = storageutil.packmeta({b'censored': tombstone}, b'')
2857 2858
2873 target=self.target, 2874 target=self.target,
2874 indexfile=newindexfile, 2875 indexfile=newindexfile,
2875 datafile=newdatafile, 2876 datafile=newdatafile,
2876 censorable=True, 2877 censorable=True,
2877 ) 2878 )
2878 newrl.version = self.version 2879 newrl._format_version = self._format_version
2880 newrl._format_flags = self._format_flags
2879 newrl._generaldelta = self._generaldelta 2881 newrl._generaldelta = self._generaldelta
2880 newrl._parse_index = self._parse_index 2882 newrl._parse_index = self._parse_index
2881 2883
2882 for rev in self.revs(): 2884 for rev in self.revs():
2883 node = self.node(rev) 2885 node = self.node(rev)
2945 if dd: 2947 if dd:
2946 yield revlogproblem(error=_(b'data length off by %d bytes') % dd) 2948 yield revlogproblem(error=_(b'data length off by %d bytes') % dd)
2947 if di: 2949 if di:
2948 yield revlogproblem(error=_(b'index contains %d extra bytes') % di) 2950 yield revlogproblem(error=_(b'index contains %d extra bytes') % di)
2949 2951
2950 version = self.version & 0xFFFF 2952 version = self._format_version
2951 2953
2952 # The verifier tells us what version revlog we should be. 2954 # The verifier tells us what version revlog we should be.
2953 if version != state[b'expectedversion']: 2955 if version != state[b'expectedversion']:
2954 yield revlogproblem( 2956 yield revlogproblem(
2955 warning=_(b"warning: '%s' uses revlog format %d; expected %d") 2957 warning=_(b"warning: '%s' uses revlog format %d; expected %d")
3135 for i, e in enumerate(new_entries): 3137 for i, e in enumerate(new_entries):
3136 rev = startrev + i 3138 rev = startrev + i
3137 self.index.replace_sidedata_info(rev, e[8], e[9], e[0]) 3139 self.index.replace_sidedata_info(rev, e[8], e[9], e[0])
3138 packed = self.index.entry_binary(rev) 3140 packed = self.index.entry_binary(rev)
3139 if rev == 0: 3141 if rev == 0:
3140 header = self.index.pack_header(self.version) 3142 header = self._format_flags | self._format_version
3143 header = self.index.pack_header(header)
3141 packed = header + packed 3144 packed = header + packed
3142 fp.write(packed) 3145 fp.write(packed)