Mercurial > hg
comparison mercurial/revlogutils/nodemap.py @ 44337:1d2b37def017
nodemap: double check the source docket when doing incremental update
In theory, the index will have the information we expect it to have. However by
security, it seems safer to double check that the incremental data are generated
from the data currently on disk.
Differential Revision: https://phab.mercurial-scm.org/D7890
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Wed, 15 Jan 2020 15:50:33 +0100 |
parents | 8374b69aef75 |
children | 2ea6a67ff502 |
comparison
equal
deleted
inserted
replaced
44336:8374b69aef75 | 44337:1d2b37def017 |
---|---|
75 raise error.ProgrammingError(msg) | 75 raise error.ProgrammingError(msg) |
76 | 76 |
77 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental") | 77 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental") |
78 ondisk_docket = revlog._nodemap_docket | 78 ondisk_docket = revlog._nodemap_docket |
79 | 79 |
80 data = None | |
80 # first attemp an incremental update of the data | 81 # first attemp an incremental update of the data |
81 if can_incremental and ondisk_docket is not None: | 82 if can_incremental and ondisk_docket is not None: |
82 target_docket = revlog._nodemap_docket.copy() | 83 target_docket = revlog._nodemap_docket.copy() |
83 data_changed_count, data = revlog.index.nodemap_data_incremental() | 84 ( |
84 datafile = _rawdata_filepath(revlog, target_docket) | 85 src_docket, |
85 # EXP-TODO: if this is a cache, this should use a cache vfs, not a | 86 data_changed_count, |
86 # store vfs | 87 data, |
87 with revlog.opener(datafile, b'a') as fd: | 88 ) = revlog.index.nodemap_data_incremental() |
88 fd.write(data) | 89 if src_docket != target_docket: |
89 target_docket.data_length += len(data) | 90 data = None |
90 target_docket.data_unused += data_changed_count | 91 else: |
91 else: | 92 datafile = _rawdata_filepath(revlog, target_docket) |
93 # EXP-TODO: if this is a cache, this should use a cache vfs, not a | |
94 # store vfs | |
95 with revlog.opener(datafile, b'a') as fd: | |
96 fd.write(data) | |
97 target_docket.data_length += len(data) | |
98 target_docket.data_unused += data_changed_count | |
99 | |
100 if data is None: | |
92 # otherwise fallback to a full new export | 101 # otherwise fallback to a full new export |
93 target_docket = NodeMapDocket() | 102 target_docket = NodeMapDocket() |
94 datafile = _rawdata_filepath(revlog, target_docket) | 103 datafile = _rawdata_filepath(revlog, target_docket) |
95 if util.safehasattr(revlog.index, "nodemap_data_all"): | 104 if util.safehasattr(revlog.index, "nodemap_data_all"): |
96 data = revlog.index.nodemap_data_all() | 105 data = revlog.index.nodemap_data_all() |
179 new = NodeMapDocket(uid=self.uid) | 188 new = NodeMapDocket(uid=self.uid) |
180 new.tip_rev = self.tip_rev | 189 new.tip_rev = self.tip_rev |
181 new.data_length = self.data_length | 190 new.data_length = self.data_length |
182 new.data_unused = self.data_unused | 191 new.data_unused = self.data_unused |
183 return new | 192 return new |
193 | |
194 def __cmp__(self, other): | |
195 if self.uid < other.uid: | |
196 return -1 | |
197 if self.uid > other.uid: | |
198 return 1 | |
199 elif self.data_length < other.data_length: | |
200 return -1 | |
201 elif self.data_length > other.data_length: | |
202 return 1 | |
203 return 0 | |
204 | |
205 def __eq__(self, other): | |
206 return self.uid == other.uid and self.data_length == other.data_length | |
184 | 207 |
185 def serialize(self): | 208 def serialize(self): |
186 """return serialized bytes for a docket using the passed uid""" | 209 """return serialized bytes for a docket using the passed uid""" |
187 data = [] | 210 data = [] |
188 data.append(S_VERSION.pack(ONDISK_VERSION)) | 211 data.append(S_VERSION.pack(ONDISK_VERSION)) |