138 |
138 |
139 def __hash__(self): |
139 def __hash__(self): |
140 return hash(self.name) |
140 return hash(self.name) |
141 |
141 |
142 class formatvariant(improvement): |
142 class formatvariant(improvement): |
143 """an improvement subclass dedicated to repository format |
143 """an improvement subclass dedicated to repository format""" |
144 |
144 type = deficiency |
145 extra attributes: |
145 ### The following attributes should be defined for each class: |
146 |
146 |
147 fromdefault (``deficiency`` types only) |
147 # machine-readable string uniquely identifying this improvement. it will be |
148 Boolean indicating whether the current (deficient) state deviates |
148 # mapped to an action later in the upgrade process. |
149 from Mercurial's default configuration. |
149 name = None |
150 |
150 |
151 fromconfig (``deficiency`` types only) |
151 # message intended for humans explaining the improvement in more detail, |
152 Boolean indicating whether the current (deficient) state deviates |
152 # including the implications of it ``deficiency`` types, should be worded |
153 from the current Mercurial configuration. |
153 # in the present tense. |
154 """ |
154 description = None |
155 |
155 |
156 def __init__(self, name, description, upgrademessage, fromdefault, |
156 # message intended for humans explaining what an upgrade addressing this |
157 fromconfig): |
157 # issue will do. should be worded in the future tense. |
158 super(formatvariant, self).__init__(name, deficiency, description, |
158 upgrademessage = None |
159 upgrademessage) |
159 |
160 self.fromdefault = fromdefault |
160 # value of current Mercurial default for new repository |
161 self.fromconfig = fromconfig |
161 default = None |
|
162 |
|
163 def __init__(self): |
|
164 raise NotImplementedError() |
|
165 |
|
166 @staticmethod |
|
167 def fromrepo(repo): |
|
168 """current value of the variant in the repository""" |
|
169 raise NotImplementedError() |
|
170 |
|
171 @staticmethod |
|
172 def fromconfig(repo): |
|
173 """current value of the variant in the configuration""" |
|
174 raise NotImplementedError() |
|
175 |
|
176 class requirementformatvariant(formatvariant): |
|
177 """formatvariant based on a 'requirement' name. |
|
178 |
|
179 Many format variant are controlled by a 'requirement'. We define a small |
|
180 subclass to factor the code. |
|
181 """ |
|
182 |
|
183 # the requirement that control this format variant |
|
184 _requirement = None |
|
185 |
|
186 @staticmethod |
|
187 def _newreporequirements(repo): |
|
188 return localrepo.newreporequirements(repo) |
|
189 |
|
190 @classmethod |
|
191 def fromrepo(cls, repo): |
|
192 assert cls._requirement is not None |
|
193 return cls._requirement in repo.requirements |
|
194 |
|
195 @classmethod |
|
196 def fromconfig(cls, repo): |
|
197 assert cls._requirement is not None |
|
198 return cls._requirement in cls._newreporequirements(repo) |
|
199 |
|
200 class fncache(requirementformatvariant): |
|
201 name = 'fncache' |
|
202 |
|
203 _requirement = 'fncache' |
|
204 |
|
205 default = True |
|
206 |
|
207 description = _('long and reserved filenames may not work correctly; ' |
|
208 'repository performance is sub-optimal') |
|
209 |
|
210 upgrademessage = _('repository will be more resilient to storing ' |
|
211 'certain paths and performance of certain ' |
|
212 'operations should be improved') |
|
213 |
|
214 class dotencode(requirementformatvariant): |
|
215 name = 'dotencode' |
|
216 |
|
217 _requirement = 'dotencode' |
|
218 |
|
219 default = True |
|
220 |
|
221 description = _('storage of filenames beginning with a period or ' |
|
222 'space may not work correctly') |
|
223 |
|
224 upgrademessage = _('repository will be better able to store files ' |
|
225 'beginning with a space or period') |
|
226 |
|
227 class generaldelta(requirementformatvariant): |
|
228 name = 'generaldelta' |
|
229 |
|
230 _requirement = 'generaldelta' |
|
231 |
|
232 default = True |
|
233 |
|
234 description = _('deltas within internal storage are unable to ' |
|
235 'choose optimal revisions; repository is larger and ' |
|
236 'slower than it could be; interaction with other ' |
|
237 'repositories may require extra network and CPU ' |
|
238 'resources, making "hg push" and "hg pull" slower') |
|
239 |
|
240 upgrademessage = _('repository storage will be able to create ' |
|
241 'optimal deltas; new repository data will be ' |
|
242 'smaller and read times should decrease; ' |
|
243 'interacting with other repositories using this ' |
|
244 'storage model should require less network and ' |
|
245 'CPU resources, making "hg push" and "hg pull" ' |
|
246 'faster') |
|
247 |
|
248 class removecldeltachain(formatvariant): |
|
249 name = 'removecldeltachain' |
|
250 |
|
251 default = True |
|
252 |
|
253 description = _('changelog storage is using deltas instead of ' |
|
254 'raw entries; changelog reading and any ' |
|
255 'operation relying on changelog data are slower ' |
|
256 'than they could be') |
|
257 |
|
258 upgrademessage = _('changelog storage will be reformated to ' |
|
259 'store raw entries; changelog reading will be ' |
|
260 'faster; changelog size may be reduced') |
|
261 |
|
262 @staticmethod |
|
263 def fromrepo(repo): |
|
264 # Mercurial 4.0 changed changelogs to not use delta chains. Search for |
|
265 # changelogs with deltas. |
|
266 cl = repo.changelog |
|
267 chainbase = cl.chainbase |
|
268 return all(rev == chainbase(rev) for rev in cl) |
|
269 |
|
270 @staticmethod |
|
271 def fromconfig(repo): |
|
272 return True |
162 |
273 |
163 def finddeficiencies(repo): |
274 def finddeficiencies(repo): |
164 """returns a list of deficiencies that the repo suffer from""" |
275 """returns a list of deficiencies that the repo suffer from""" |
165 newreporeqs = localrepo.newreporequirements(repo) |
|
166 |
|
167 deficiencies = [] |
276 deficiencies = [] |
168 |
277 |
169 # We could detect lack of revlogv1 and store here, but they were added |
278 # We could detect lack of revlogv1 and store here, but they were added |
170 # in 0.9.2 and we don't support upgrading repos without these |
279 # in 0.9.2 and we don't support upgrading repos without these |
171 # requirements, so let's not bother. |
280 # requirements, so let's not bother. |
172 |
281 |
173 if 'fncache' not in repo.requirements: |
282 if not fncache.fromrepo(repo): |
174 deficiencies.append(formatvariant( |
283 deficiencies.append(fncache) |
175 name='fncache', |
284 if not dotencode.fromrepo(repo): |
176 description=_('long and reserved filenames may not work correctly; ' |
285 deficiencies.append(dotencode) |
177 'repository performance is sub-optimal'), |
286 if not generaldelta.fromrepo(repo): |
178 upgrademessage=_('repository will be more resilient to storing ' |
287 deficiencies.append(generaldelta) |
179 'certain paths and performance of certain ' |
288 if not removecldeltachain.fromrepo(repo): |
180 'operations should be improved'), |
289 deficiencies.append(removecldeltachain) |
181 fromdefault=True, |
|
182 fromconfig='fncache' in newreporeqs)) |
|
183 |
|
184 if 'dotencode' not in repo.requirements: |
|
185 deficiencies.append(formatvariant( |
|
186 name='dotencode', |
|
187 description=_('storage of filenames beginning with a period or ' |
|
188 'space may not work correctly'), |
|
189 upgrademessage=_('repository will be better able to store files ' |
|
190 'beginning with a space or period'), |
|
191 fromdefault=True, |
|
192 fromconfig='dotencode' in newreporeqs)) |
|
193 |
|
194 if 'generaldelta' not in repo.requirements: |
|
195 deficiencies.append(formatvariant( |
|
196 name='generaldelta', |
|
197 description=_('deltas within internal storage are unable to ' |
|
198 'choose optimal revisions; repository is larger and ' |
|
199 'slower than it could be; interaction with other ' |
|
200 'repositories may require extra network and CPU ' |
|
201 'resources, making "hg push" and "hg pull" slower'), |
|
202 upgrademessage=_('repository storage will be able to create ' |
|
203 'optimal deltas; new repository data will be ' |
|
204 'smaller and read times should decrease; ' |
|
205 'interacting with other repositories using this ' |
|
206 'storage model should require less network and ' |
|
207 'CPU resources, making "hg push" and "hg pull" ' |
|
208 'faster'), |
|
209 fromdefault=True, |
|
210 fromconfig='generaldelta' in newreporeqs)) |
|
211 |
|
212 # Mercurial 4.0 changed changelogs to not use delta chains. Search for |
|
213 # changelogs with deltas. |
|
214 cl = repo.changelog |
|
215 for rev in cl: |
|
216 chainbase = cl.chainbase(rev) |
|
217 if chainbase != rev: |
|
218 deficiencies.append(formatvariant( |
|
219 name='removecldeltachain', |
|
220 description=_('changelog storage is using deltas instead of ' |
|
221 'raw entries; changelog reading and any ' |
|
222 'operation relying on changelog data are slower ' |
|
223 'than they could be'), |
|
224 upgrademessage=_('changelog storage will be reformated to ' |
|
225 'store raw entries; changelog reading will be ' |
|
226 'faster; changelog size may be reduced'), |
|
227 fromdefault=True, |
|
228 fromconfig=True)) |
|
229 break |
|
230 |
290 |
231 return deficiencies |
291 return deficiencies |
232 |
292 |
233 def findoptimizations(repo): |
293 def findoptimizations(repo): |
234 """Determine optimisation that could be used during upgrade""" |
294 """Determine optimisation that could be used during upgrade""" |