comparison mercurial/upgrade.py @ 32031:11a2461fc9b1

upgrade: move descriptions and selection logic in individual classes Our goal here is to get top level definition for all the format variants. Having them defined outside of the function enabled other users of that logic. They are two keys components of a format variant: 1) the name and various descriptions of its effect, 2) the code that checks if the repo is using this variant and if the config enables it. That second items make us pick a class-based approach, since different variants requires different code (even if in practice, many can reuse the same logic). Each variants define its own class that is then used like a singleton. The class-based approach also clarify the definitions part a bit since each are simple assignment in an indented block. The 'fromdefault' and 'fromconfig' are respectively replaced by a class attribute and a method to be called at the one place where "fromconfig" matters. Overall, they are many viable approach for this, but this is the one I picked.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Wed, 12 Apr 2017 16:34:05 +0200
parents e47223576b8d
children 189778a06743
comparison
equal deleted inserted replaced
32030:e47223576b8d 32031:11a2461fc9b1
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"""
678 if not run: 738 if not run:
679 fromconfig = [] 739 fromconfig = []
680 onlydefault = [] 740 onlydefault = []
681 741
682 for d in deficiencies: 742 for d in deficiencies:
683 if d.fromconfig: 743 if d.fromconfig(repo):
684 fromconfig.append(d) 744 fromconfig.append(d)
685 elif d.fromdefault: 745 elif d.default:
686 onlydefault.append(d) 746 onlydefault.append(d)
687 747
688 if fromconfig or onlydefault: 748 if fromconfig or onlydefault:
689 749
690 if fromconfig: 750 if fromconfig: