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))