Mercurial > public > mercurial-scm > hg
comparison mercurial/revlog.py @ 46718:ba8e508a8e69
sidedata-exchange: rewrite sidedata on-the-fly whenever possible
When a A exchanges with B, the difference of their supported sidedata categories
is made, and the responsibility is always with the client to generated it:
- If A pushes to B and B requires category `foo` that A does not have, A
will need to generate it when sending it to B.
- If A pulls from B and A needs category `foo`, it will generate `foo`
before the end of the transaction.
- Any category that is not required is removed. If peers are not compatible,
abort.
It is forbidden to rewrite sidedata for a rev that already has sidedata, since
that would introduce unreachable (garbage) data in the data file, something
we're not prepared for yet.
Differential Revision: https://phab.mercurial-scm.org/D10032
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Fri, 19 Feb 2021 11:24:50 +0100 |
parents | c8bb7b89179e |
children | 49fd21f32695 |
comparison
equal
deleted
inserted
replaced
46717:502e795b55ac | 46718:ba8e508a8e69 |
---|---|
3203 d[b'storedsize'] = sum( | 3203 d[b'storedsize'] = sum( |
3204 self.opener.stat(path).st_size for path in self.files() | 3204 self.opener.stat(path).st_size for path in self.files() |
3205 ) | 3205 ) |
3206 | 3206 |
3207 return d | 3207 return d |
3208 | |
3209 def rewrite_sidedata(self, helpers, startrev, endrev): | |
3210 if self.version & 0xFFFF != REVLOGV2: | |
3211 return | |
3212 # inline are not yet supported because they suffer from an issue when | |
3213 # rewriting them (since it's not an append-only operation). | |
3214 # See issue6485. | |
3215 assert not self._inline | |
3216 if not helpers[1] and not helpers[2]: | |
3217 # Nothing to generate or remove | |
3218 return | |
3219 | |
3220 new_entries = [] | |
3221 # append the new sidedata | |
3222 with self._datafp(b'a+') as fp: | |
3223 # Maybe this bug still exists, see revlog._writeentry | |
3224 fp.seek(0, os.SEEK_END) | |
3225 current_offset = fp.tell() | |
3226 for rev in range(startrev, endrev + 1): | |
3227 entry = self.index[rev] | |
3228 new_sidedata = storageutil.run_sidedata_helpers( | |
3229 store=self, | |
3230 sidedata_helpers=helpers, | |
3231 sidedata={}, | |
3232 rev=rev, | |
3233 ) | |
3234 | |
3235 serialized_sidedata = sidedatautil.serialize_sidedata( | |
3236 new_sidedata | |
3237 ) | |
3238 if entry[8] != 0 or entry[9] != 0: | |
3239 # rewriting entries that already have sidedata is not | |
3240 # supported yet, because it introduces garbage data in the | |
3241 # revlog. | |
3242 msg = "Rewriting existing sidedata is not supported yet" | |
3243 raise error.Abort(msg) | |
3244 entry = entry[:8] | |
3245 entry += (current_offset, len(serialized_sidedata)) | |
3246 | |
3247 fp.write(serialized_sidedata) | |
3248 new_entries.append(entry) | |
3249 current_offset += len(serialized_sidedata) | |
3250 | |
3251 # rewrite the new index entries | |
3252 with self._indexfp(b'w+') as fp: | |
3253 fp.seek(startrev * self._io.size) | |
3254 for i, entry in enumerate(new_entries): | |
3255 rev = startrev + i | |
3256 self.index.replace_sidedata_info(rev, entry[8], entry[9]) | |
3257 packed = self._io.packentry(entry, self.node, self.version, rev) | |
3258 fp.write(packed) |