##// END OF EJS Templates
sidedata: enable sidedata computers to optionally rewrite flags...
Raphaël Gomès -
r47844:223b4723 default
parent child Browse files
Show More
@@ -503,14 +503,14 b' static PyObject *index_append(indexObjec'
503 inside the transaction that creates the given revision. */
503 inside the transaction that creates the given revision. */
504 static PyObject *index_replace_sidedata_info(indexObject *self, PyObject *args)
504 static PyObject *index_replace_sidedata_info(indexObject *self, PyObject *args)
505 {
505 {
506 uint64_t sidedata_offset;
506 uint64_t offset_flags, sidedata_offset;
507 int rev;
507 int rev;
508 Py_ssize_t sidedata_comp_len;
508 Py_ssize_t sidedata_comp_len;
509 char *data;
509 char *data;
510 #if LONG_MAX == 0x7fffffffL
510 #if LONG_MAX == 0x7fffffffL
511 const char *const sidedata_format = PY23("nKi", "nKi");
511 const char *const sidedata_format = PY23("nKiK", "nKiK");
512 #else
512 #else
513 const char *const sidedata_format = PY23("nki", "nki");
513 const char *const sidedata_format = PY23("nkik", "nkik");
514 #endif
514 #endif
515
515
516 if (self->hdrsize == v1_hdrsize || self->inlined) {
516 if (self->hdrsize == v1_hdrsize || self->inlined) {
@@ -525,7 +525,7 b' static PyObject *index_replace_sidedata_'
525 }
525 }
526
526
527 if (!PyArg_ParseTuple(args, sidedata_format, &rev, &sidedata_offset,
527 if (!PyArg_ParseTuple(args, sidedata_format, &rev, &sidedata_offset,
528 &sidedata_comp_len))
528 &sidedata_comp_len, &offset_flags))
529 return NULL;
529 return NULL;
530
530
531 if (rev < 0 || rev >= index_length(self)) {
531 if (rev < 0 || rev >= index_length(self)) {
@@ -542,6 +542,7 b' static PyObject *index_replace_sidedata_'
542 /* Find the newly added node, offset from the "already on-disk" length
542 /* Find the newly added node, offset from the "already on-disk" length
543 */
543 */
544 data = self->added + self->hdrsize * (rev - self->length);
544 data = self->added + self->hdrsize * (rev - self->length);
545 putbe64(offset_flags, data);
545 putbe64(sidedata_offset, data + 64);
546 putbe64(sidedata_offset, data + 64);
546 putbe32(sidedata_comp_len, data + 72);
547 putbe32(sidedata_comp_len, data + 72);
547
548
@@ -1856,7 +1856,7 b' class ilocalrepositorymain(interfaceutil'
1856 def savecommitmessage(text):
1856 def savecommitmessage(text):
1857 pass
1857 pass
1858
1858
1859 def register_sidedata_computer(kind, category, keys, computer):
1859 def register_sidedata_computer(kind, category, keys, computer, flags):
1860 pass
1860 pass
1861
1861
1862 def register_wanted_sidedata(category):
1862 def register_wanted_sidedata(category):
@@ -3370,9 +3370,9 b' class localrepository(object):'
3370 return
3370 return
3371 self._wanted_sidedata.add(pycompat.bytestr(category))
3371 self._wanted_sidedata.add(pycompat.bytestr(category))
3372
3372
3373 def register_sidedata_computer(self, kind, category, keys, computer):
3373 def register_sidedata_computer(self, kind, category, keys, computer, flags):
3374 if kind not in revlogconst.ALL_KINDS:
3374 if kind not in revlogconst.ALL_KINDS:
3375 msg = _(b"unexpected revlog kind %r.")
3375 msg = _(b"unexpected revlog kind '%s'.")
3376 raise error.ProgrammingError(msg % kind)
3376 raise error.ProgrammingError(msg % kind)
3377 category = pycompat.bytestr(category)
3377 category = pycompat.bytestr(category)
3378 if category in self._sidedata_computers.get(kind, []):
3378 if category in self._sidedata_computers.get(kind, []):
@@ -3381,7 +3381,7 b' class localrepository(object):'
3381 )
3381 )
3382 raise error.ProgrammingError(msg % category)
3382 raise error.ProgrammingError(msg % category)
3383 self._sidedata_computers.setdefault(kind, {})
3383 self._sidedata_computers.setdefault(kind, {})
3384 self._sidedata_computers[kind][category] = (keys, computer)
3384 self._sidedata_computers[kind][category] = (keys, computer, flags)
3385
3385
3386
3386
3387 # used to avoid circular references so destructors work
3387 # used to avoid circular references so destructors work
@@ -820,7 +820,9 b' def _getsidedata(srcrepo, rev):'
820
820
821
821
822 def copies_sidedata_computer(repo, revlog, rev, existing_sidedata):
822 def copies_sidedata_computer(repo, revlog, rev, existing_sidedata):
823 return _getsidedata(repo, rev)[0]
823 sidedata, has_copies_info = _getsidedata(repo, rev)
824 flags_to_add = sidedataflag.REVIDX_HASCOPIESINFO if has_copies_info else 0
825 return sidedata, (flags_to_add, 0)
824
826
825
827
826 def set_sidedata_spec_for_repo(repo):
828 def set_sidedata_spec_for_repo(repo):
@@ -831,6 +833,7 b' def set_sidedata_spec_for_repo(repo):'
831 sidedatamod.SD_FILES,
833 sidedatamod.SD_FILES,
832 (sidedatamod.SD_FILES,),
834 (sidedatamod.SD_FILES,),
833 copies_sidedata_computer,
835 copies_sidedata_computer,
836 sidedataflag.REVIDX_HASCOPIESINFO,
834 )
837 )
835
838
836
839
@@ -268,7 +268,9 b' class Index2Mixin(object):'
268 index_format = revlog_constants.INDEX_ENTRY_V2
268 index_format = revlog_constants.INDEX_ENTRY_V2
269 null_item = (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid, 0, 0)
269 null_item = (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid, 0, 0)
270
270
271 def replace_sidedata_info(self, i, sidedata_offset, sidedata_length):
271 def replace_sidedata_info(
272 self, i, sidedata_offset, sidedata_length, offset_flags
273 ):
272 """
274 """
273 Replace an existing index entry's sidedata offset and length with new
275 Replace an existing index entry's sidedata offset and length with new
274 ones.
276 ones.
@@ -283,7 +285,8 b' class Index2Mixin(object):'
283 if i >= self._lgt:
285 if i >= self._lgt:
284 packed = _pack(sidedata_format, sidedata_offset, sidedata_length)
286 packed = _pack(sidedata_format, sidedata_offset, sidedata_length)
285 old = self._extra[i - self._lgt]
287 old = self._extra[i - self._lgt]
286 new = old[:64] + packed + old[64 + packed_size :]
288 offset_flags = struct.pack(b">Q", offset_flags)
289 new = offset_flags + old[8:64] + packed + old[64 + packed_size :]
287 self._extra[i - self._lgt] = new
290 self._extra[i - self._lgt] = new
288 else:
291 else:
289 msg = b"cannot rewrite entries outside of this transaction"
292 msg = b"cannot rewrite entries outside of this transaction"
@@ -3105,7 +3105,7 b' class revlog(object):'
3105 current_offset = fp.tell()
3105 current_offset = fp.tell()
3106 for rev in range(startrev, endrev + 1):
3106 for rev in range(startrev, endrev + 1):
3107 entry = self.index[rev]
3107 entry = self.index[rev]
3108 new_sidedata = storageutil.run_sidedata_helpers(
3108 new_sidedata, flags = storageutil.run_sidedata_helpers(
3109 store=self,
3109 store=self,
3110 sidedata_helpers=helpers,
3110 sidedata_helpers=helpers,
3111 sidedata={},
3111 sidedata={},
@@ -3121,7 +3121,11 b' class revlog(object):'
3121 # revlog.
3121 # revlog.
3122 msg = b"Rewriting existing sidedata is not supported yet"
3122 msg = b"Rewriting existing sidedata is not supported yet"
3123 raise error.Abort(msg)
3123 raise error.Abort(msg)
3124 entry = entry[:8]
3124
3125 # Apply (potential) flags to add and to remove after running
3126 # the sidedata helpers
3127 new_offset_flags = entry[0] | flags[0] & ~flags[1]
3128 entry = (new_offset_flags,) + entry[1:8]
3125 entry += (current_offset, len(serialized_sidedata))
3129 entry += (current_offset, len(serialized_sidedata))
3126
3130
3127 fp.write(serialized_sidedata)
3131 fp.write(serialized_sidedata)
@@ -3131,9 +3135,9 b' class revlog(object):'
3131 # rewrite the new index entries
3135 # rewrite the new index entries
3132 with self._indexfp(b'w+') as fp:
3136 with self._indexfp(b'w+') as fp:
3133 fp.seek(startrev * self.index.entry_size)
3137 fp.seek(startrev * self.index.entry_size)
3134 for i, entry in enumerate(new_entries):
3138 for i, e in enumerate(new_entries):
3135 rev = startrev + i
3139 rev = startrev + i
3136 self.index.replace_sidedata_info(rev, entry[8], entry[9])
3140 self.index.replace_sidedata_info(rev, e[8], e[9], e[0])
3137 packed = self.index.entry_binary(rev)
3141 packed = self.index.entry_binary(rev)
3138 if rev == 0:
3142 if rev == 0:
3139 header = self.index.pack_header(self.version)
3143 header = self.index.pack_header(self.version)
@@ -366,12 +366,17 b' def emitrevisions('
366 If not None, means that sidedata should be included.
366 If not None, means that sidedata should be included.
367 A dictionary of revlog type to tuples of `(repo, computers, removers)`:
367 A dictionary of revlog type to tuples of `(repo, computers, removers)`:
368 * `repo` is used as an argument for computers
368 * `repo` is used as an argument for computers
369 * `computers` is a list of `(category, (keys, computer)` that
369 * `computers` is a list of `(category, (keys, computer, flags)` that
370 compute the missing sidedata categories that were asked:
370 compute the missing sidedata categories that were asked:
371 * `category` is the sidedata category
371 * `category` is the sidedata category
372 * `keys` are the sidedata keys to be affected
372 * `keys` are the sidedata keys to be affected
373 * `flags` is a bitmask (an integer) of flags to remove when
374 removing the category.
373 * `computer` is the function `(repo, store, rev, sidedata)` that
375 * `computer` is the function `(repo, store, rev, sidedata)` that
374 returns a new sidedata dict.
376 returns a tuple of
377 `(new sidedata dict, (flags to add, flags to remove))`.
378 For example, it will return `({}, (0, 1 << 15))` to return no
379 sidedata, with no flags to add and one flag to remove.
375 * `removers` will remove the keys corresponding to the categories
380 * `removers` will remove the keys corresponding to the categories
376 that are present, but not needed.
381 that are present, but not needed.
377 If both `computers` and `removers` are empty, sidedata are simply not
382 If both `computers` and `removers` are empty, sidedata are simply not
@@ -491,12 +496,13 b' def emitrevisions('
491 available.add(rev)
496 available.add(rev)
492
497
493 serialized_sidedata = None
498 serialized_sidedata = None
499 sidedata_flags = (0, 0)
494 if sidedata_helpers:
500 if sidedata_helpers:
495 sidedata = store.sidedata(rev)
501 old_sidedata = store.sidedata(rev)
496 sidedata = run_sidedata_helpers(
502 sidedata, sidedata_flags = run_sidedata_helpers(
497 store=store,
503 store=store,
498 sidedata_helpers=sidedata_helpers,
504 sidedata_helpers=sidedata_helpers,
499 sidedata=sidedata,
505 sidedata=old_sidedata,
500 rev=rev,
506 rev=rev,
501 )
507 )
502 if sidedata:
508 if sidedata:
@@ -507,6 +513,8 b' def emitrevisions('
507 if serialized_sidedata:
513 if serialized_sidedata:
508 # Advertise that sidedata exists to the other side
514 # Advertise that sidedata exists to the other side
509 protocol_flags |= CG_FLAG_SIDEDATA
515 protocol_flags |= CG_FLAG_SIDEDATA
516 # Computers and removers can return flags to add and/or remove
517 flags = flags | sidedata_flags[0] & ~sidedata_flags[1]
510
518
511 yield resultcls(
519 yield resultcls(
512 node=node,
520 node=node,
@@ -535,12 +543,17 b' def run_sidedata_helpers(store, sidedata'
535 """
543 """
536 repo, sd_computers, sd_removers = sidedata_helpers
544 repo, sd_computers, sd_removers = sidedata_helpers
537 kind = store.revlog_kind
545 kind = store.revlog_kind
538 for _keys, sd_computer in sd_computers.get(kind, []):
546 flags_to_add = 0
539 sidedata = sd_computer(repo, store, rev, sidedata)
547 flags_to_remove = 0
540 for keys, _computer in sd_removers.get(kind, []):
548 for _keys, sd_computer, _flags in sd_computers.get(kind, []):
549 sidedata, flags = sd_computer(repo, store, rev, sidedata)
550 flags_to_add |= flags[0]
551 flags_to_remove |= flags[1]
552 for keys, _computer, flags in sd_removers.get(kind, []):
541 for key in keys:
553 for key in keys:
542 sidedata.pop(key, None)
554 sidedata.pop(key, None)
543 return sidedata
555 flags_to_remove |= flags
556 return sidedata, (flags_to_add, flags_to_remove)
544
557
545
558
546 def deltaiscensored(delta, baserev, baselenfn):
559 def deltaiscensored(delta, baserev, baselenfn):
@@ -16,13 +16,15 b' import struct'
16 from mercurial.revlogutils import sidedata as sidedatamod
16 from mercurial.revlogutils import sidedata as sidedatamod
17 from mercurial.revlogutils import constants
17 from mercurial.revlogutils import constants
18
18
19 NO_FLAGS = (0, 0) # hoot
20
19
21
20 def compute_sidedata_1(repo, revlog, rev, sidedata, text=None):
22 def compute_sidedata_1(repo, revlog, rev, sidedata, text=None):
21 sidedata = sidedata.copy()
23 sidedata = sidedata.copy()
22 if text is None:
24 if text is None:
23 text = revlog.revision(rev)
25 text = revlog.revision(rev)
24 sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text))
26 sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text))
25 return sidedata
27 return sidedata, NO_FLAGS
26
28
27
29
28 def compute_sidedata_2(repo, revlog, rev, sidedata, text=None):
30 def compute_sidedata_2(repo, revlog, rev, sidedata, text=None):
@@ -31,7 +33,7 b' def compute_sidedata_2(repo, revlog, rev'
31 text = revlog.revision(rev)
33 text = revlog.revision(rev)
32 sha256 = hashlib.sha256(text).digest()
34 sha256 = hashlib.sha256(text).digest()
33 sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256)
35 sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256)
34 return sidedata
36 return sidedata, NO_FLAGS
35
37
36
38
37 def reposetup(ui, repo):
39 def reposetup(ui, repo):
@@ -42,10 +44,12 b' def reposetup(ui, repo):'
42 sidedatamod.SD_TEST1,
44 sidedatamod.SD_TEST1,
43 (sidedatamod.SD_TEST1,),
45 (sidedatamod.SD_TEST1,),
44 compute_sidedata_1,
46 compute_sidedata_1,
47 0,
45 )
48 )
46 repo.register_sidedata_computer(
49 repo.register_sidedata_computer(
47 kind,
50 kind,
48 sidedatamod.SD_TEST2,
51 sidedatamod.SD_TEST2,
49 (sidedatamod.SD_TEST2,),
52 (sidedatamod.SD_TEST2,),
50 compute_sidedata_2,
53 compute_sidedata_2,
54 0,
51 )
55 )
@@ -22,13 +22,15 b' from mercurial import ('
22 from mercurial.revlogutils import sidedata as sidedatamod
22 from mercurial.revlogutils import sidedata as sidedatamod
23 from mercurial.revlogutils import constants
23 from mercurial.revlogutils import constants
24
24
25 NO_FLAGS = (0, 0)
26
25
27
26 def compute_sidedata_1(repo, revlog, rev, sidedata, text=None):
28 def compute_sidedata_1(repo, revlog, rev, sidedata, text=None):
27 sidedata = sidedata.copy()
29 sidedata = sidedata.copy()
28 if text is None:
30 if text is None:
29 text = revlog.revision(rev)
31 text = revlog.revision(rev)
30 sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text))
32 sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text))
31 return sidedata
33 return sidedata, NO_FLAGS
32
34
33
35
34 def compute_sidedata_2(repo, revlog, rev, sidedata, text=None):
36 def compute_sidedata_2(repo, revlog, rev, sidedata, text=None):
@@ -37,7 +39,7 b' def compute_sidedata_2(repo, revlog, rev'
37 text = revlog.revision(rev)
39 text = revlog.revision(rev)
38 sha256 = hashlib.sha256(text).digest()
40 sha256 = hashlib.sha256(text).digest()
39 sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256)
41 sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256)
40 return sidedata
42 return sidedata, NO_FLAGS
41
43
42
44
43 def compute_sidedata_3(repo, revlog, rev, sidedata, text=None):
45 def compute_sidedata_3(repo, revlog, rev, sidedata, text=None):
@@ -46,7 +48,7 b' def compute_sidedata_3(repo, revlog, rev'
46 text = revlog.revision(rev)
48 text = revlog.revision(rev)
47 sha384 = hashlib.sha384(text).digest()
49 sha384 = hashlib.sha384(text).digest()
48 sidedata[sidedatamod.SD_TEST3] = struct.pack('>48s', sha384)
50 sidedata[sidedatamod.SD_TEST3] = struct.pack('>48s', sha384)
49 return sidedata
51 return sidedata, NO_FLAGS
50
52
51
53
52 def wrapaddrevision(
54 def wrapaddrevision(
@@ -55,8 +57,8 b' def wrapaddrevision('
55 if kwargs.get('sidedata') is None:
57 if kwargs.get('sidedata') is None:
56 kwargs['sidedata'] = {}
58 kwargs['sidedata'] = {}
57 sd = kwargs['sidedata']
59 sd = kwargs['sidedata']
58 sd = compute_sidedata_1(None, self, None, sd, text=text)
60 sd, flags = compute_sidedata_1(None, self, None, sd, text=text)
59 kwargs['sidedata'] = compute_sidedata_2(None, self, None, sd, text=text)
61 kwargs['sidedata'] = compute_sidedata_2(None, self, None, sd, text=text)[0]
60 return orig(self, text, transaction, link, p1, p2, *args, **kwargs)
62 return orig(self, text, transaction, link, p1, p2, *args, **kwargs)
61
63
62
64
@@ -72,18 +74,21 b' def reposetup(ui, repo):'
72 sidedatamod.SD_TEST1,
74 sidedatamod.SD_TEST1,
73 (sidedatamod.SD_TEST1,),
75 (sidedatamod.SD_TEST1,),
74 compute_sidedata_1,
76 compute_sidedata_1,
77 0,
75 )
78 )
76 repo.register_sidedata_computer(
79 repo.register_sidedata_computer(
77 kind,
80 kind,
78 sidedatamod.SD_TEST2,
81 sidedatamod.SD_TEST2,
79 (sidedatamod.SD_TEST2,),
82 (sidedatamod.SD_TEST2,),
80 compute_sidedata_2,
83 compute_sidedata_2,
84 0,
81 )
85 )
82 repo.register_sidedata_computer(
86 repo.register_sidedata_computer(
83 kind,
87 kind,
84 sidedatamod.SD_TEST3,
88 sidedatamod.SD_TEST3,
85 (sidedatamod.SD_TEST3,),
89 (sidedatamod.SD_TEST3,),
86 compute_sidedata_3,
90 compute_sidedata_3,
91 0,
87 )
92 )
88 repo.register_wanted_sidedata(sidedatamod.SD_TEST1)
93 repo.register_wanted_sidedata(sidedatamod.SD_TEST1)
89 repo.register_wanted_sidedata(sidedatamod.SD_TEST2)
94 repo.register_wanted_sidedata(sidedatamod.SD_TEST2)
@@ -23,13 +23,15 b' from mercurial import ('
23 from mercurial.revlogutils import sidedata as sidedatamod
23 from mercurial.revlogutils import sidedata as sidedatamod
24 from mercurial.revlogutils import constants
24 from mercurial.revlogutils import constants
25
25
26 NO_FLAGS = (0, 0)
27
26
28
27 def compute_sidedata_1(repo, revlog, rev, sidedata, text=None):
29 def compute_sidedata_1(repo, revlog, rev, sidedata, text=None):
28 sidedata = sidedata.copy()
30 sidedata = sidedata.copy()
29 if text is None:
31 if text is None:
30 text = revlog.revision(rev)
32 text = revlog.revision(rev)
31 sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text))
33 sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text))
32 return sidedata
34 return sidedata, NO_FLAGS
33
35
34
36
35 def compute_sidedata_2(repo, revlog, rev, sidedata, text=None):
37 def compute_sidedata_2(repo, revlog, rev, sidedata, text=None):
@@ -38,7 +40,7 b' def compute_sidedata_2(repo, revlog, rev'
38 text = revlog.revision(rev)
40 text = revlog.revision(rev)
39 sha256 = hashlib.sha256(text).digest()
41 sha256 = hashlib.sha256(text).digest()
40 sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256)
42 sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256)
41 return sidedata
43 return sidedata, NO_FLAGS
42
44
43
45
44 def reposetup(ui, repo):
46 def reposetup(ui, repo):
@@ -49,12 +51,14 b' def reposetup(ui, repo):'
49 sidedatamod.SD_TEST1,
51 sidedatamod.SD_TEST1,
50 (sidedatamod.SD_TEST1,),
52 (sidedatamod.SD_TEST1,),
51 compute_sidedata_1,
53 compute_sidedata_1,
54 0,
52 )
55 )
53 repo.register_sidedata_computer(
56 repo.register_sidedata_computer(
54 kind,
57 kind,
55 sidedatamod.SD_TEST2,
58 sidedatamod.SD_TEST2,
56 (sidedatamod.SD_TEST2,),
59 (sidedatamod.SD_TEST2,),
57 compute_sidedata_2,
60 compute_sidedata_2,
61 0,
58 )
62 )
59
63
60 # We don't register sidedata computers because we don't care within these
64 # We don't register sidedata computers because we don't care within these
General Comments 0
You need to be logged in to leave comments. Login now