##// END OF EJS Templates
upgrade: support upgrade to/from zstd storage (issue6088)...
marmoute -
r42306:d086ba38 default
parent child Browse files
Show More
@@ -1,955 +1,980
1 # upgrade.py - functions for in place upgrade of Mercurial repository
1 # upgrade.py - functions for in place upgrade of Mercurial repository
2 #
2 #
3 # Copyright (c) 2016-present, Gregory Szorc
3 # Copyright (c) 2016-present, Gregory Szorc
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import stat
10 import stat
11
11
12 from .i18n import _
12 from .i18n import _
13 from . import (
13 from . import (
14 changelog,
14 changelog,
15 error,
15 error,
16 filelog,
16 filelog,
17 hg,
17 hg,
18 localrepo,
18 localrepo,
19 manifest,
19 manifest,
20 pycompat,
20 pycompat,
21 revlog,
21 revlog,
22 scmutil,
22 scmutil,
23 util,
23 util,
24 vfs as vfsmod,
24 vfs as vfsmod,
25 )
25 )
26
26
27 from .utils import (
28 compression,
29 )
30
27 def requiredsourcerequirements(repo):
31 def requiredsourcerequirements(repo):
28 """Obtain requirements required to be present to upgrade a repo.
32 """Obtain requirements required to be present to upgrade a repo.
29
33
30 An upgrade will not be allowed if the repository doesn't have the
34 An upgrade will not be allowed if the repository doesn't have the
31 requirements returned by this function.
35 requirements returned by this function.
32 """
36 """
33 return {
37 return {
34 # Introduced in Mercurial 0.9.2.
38 # Introduced in Mercurial 0.9.2.
35 'revlogv1',
39 'revlogv1',
36 # Introduced in Mercurial 0.9.2.
40 # Introduced in Mercurial 0.9.2.
37 'store',
41 'store',
38 }
42 }
39
43
40 def blocksourcerequirements(repo):
44 def blocksourcerequirements(repo):
41 """Obtain requirements that will prevent an upgrade from occurring.
45 """Obtain requirements that will prevent an upgrade from occurring.
42
46
43 An upgrade cannot be performed if the source repository contains a
47 An upgrade cannot be performed if the source repository contains a
44 requirements in the returned set.
48 requirements in the returned set.
45 """
49 """
46 return {
50 return {
47 # The upgrade code does not yet support these experimental features.
51 # The upgrade code does not yet support these experimental features.
48 # This is an artificial limitation.
52 # This is an artificial limitation.
49 'treemanifest',
53 'treemanifest',
50 # This was a precursor to generaldelta and was never enabled by default.
54 # This was a precursor to generaldelta and was never enabled by default.
51 # It should (hopefully) not exist in the wild.
55 # It should (hopefully) not exist in the wild.
52 'parentdelta',
56 'parentdelta',
53 # Upgrade should operate on the actual store, not the shared link.
57 # Upgrade should operate on the actual store, not the shared link.
54 'shared',
58 'shared',
55 }
59 }
56
60
57 def supportremovedrequirements(repo):
61 def supportremovedrequirements(repo):
58 """Obtain requirements that can be removed during an upgrade.
62 """Obtain requirements that can be removed during an upgrade.
59
63
60 If an upgrade were to create a repository that dropped a requirement,
64 If an upgrade were to create a repository that dropped a requirement,
61 the dropped requirement must appear in the returned set for the upgrade
65 the dropped requirement must appear in the returned set for the upgrade
62 to be allowed.
66 to be allowed.
63 """
67 """
64 return {
68 supported = {
65 localrepo.SPARSEREVLOG_REQUIREMENT,
69 localrepo.SPARSEREVLOG_REQUIREMENT,
66 }
70 }
71 for name in compression.compengines:
72 engine = compression.compengines[name]
73 if engine.available() and engine.revlogheader():
74 supported.add(b'exp-compression-%s' % name)
75 if engine.name() == 'zstd':
76 supported.add(b'revlog-compression-zstd')
77 return supported
67
78
68 def supporteddestrequirements(repo):
79 def supporteddestrequirements(repo):
69 """Obtain requirements that upgrade supports in the destination.
80 """Obtain requirements that upgrade supports in the destination.
70
81
71 If the result of the upgrade would create requirements not in this set,
82 If the result of the upgrade would create requirements not in this set,
72 the upgrade is disallowed.
83 the upgrade is disallowed.
73
84
74 Extensions should monkeypatch this to add their custom requirements.
85 Extensions should monkeypatch this to add their custom requirements.
75 """
86 """
76 return {
87 supported = {
77 'dotencode',
88 'dotencode',
78 'fncache',
89 'fncache',
79 'generaldelta',
90 'generaldelta',
80 'revlogv1',
91 'revlogv1',
81 'store',
92 'store',
82 localrepo.SPARSEREVLOG_REQUIREMENT,
93 localrepo.SPARSEREVLOG_REQUIREMENT,
83 }
94 }
95 for name in compression.compengines:
96 engine = compression.compengines[name]
97 if engine.available() and engine.revlogheader():
98 supported.add(b'exp-compression-%s' % name)
99 if engine.name() == 'zstd':
100 supported.add(b'revlog-compression-zstd')
101 return supported
84
102
85 def allowednewrequirements(repo):
103 def allowednewrequirements(repo):
86 """Obtain requirements that can be added to a repository during upgrade.
104 """Obtain requirements that can be added to a repository during upgrade.
87
105
88 This is used to disallow proposed requirements from being added when
106 This is used to disallow proposed requirements from being added when
89 they weren't present before.
107 they weren't present before.
90
108
91 We use a list of allowed requirement additions instead of a list of known
109 We use a list of allowed requirement additions instead of a list of known
92 bad additions because the whitelist approach is safer and will prevent
110 bad additions because the whitelist approach is safer and will prevent
93 future, unknown requirements from accidentally being added.
111 future, unknown requirements from accidentally being added.
94 """
112 """
95 return {
113 supported = {
96 'dotencode',
114 'dotencode',
97 'fncache',
115 'fncache',
98 'generaldelta',
116 'generaldelta',
99 localrepo.SPARSEREVLOG_REQUIREMENT,
117 localrepo.SPARSEREVLOG_REQUIREMENT,
100 }
118 }
119 for name in compression.compengines:
120 engine = compression.compengines[name]
121 if engine.available() and engine.revlogheader():
122 supported.add(b'exp-compression-%s' % name)
123 if engine.name() == 'zstd':
124 supported.add(b'revlog-compression-zstd')
125 return supported
101
126
102 def preservedrequirements(repo):
127 def preservedrequirements(repo):
103 return set()
128 return set()
104
129
105 deficiency = 'deficiency'
130 deficiency = 'deficiency'
106 optimisation = 'optimization'
131 optimisation = 'optimization'
107
132
108 class improvement(object):
133 class improvement(object):
109 """Represents an improvement that can be made as part of an upgrade.
134 """Represents an improvement that can be made as part of an upgrade.
110
135
111 The following attributes are defined on each instance:
136 The following attributes are defined on each instance:
112
137
113 name
138 name
114 Machine-readable string uniquely identifying this improvement. It
139 Machine-readable string uniquely identifying this improvement. It
115 will be mapped to an action later in the upgrade process.
140 will be mapped to an action later in the upgrade process.
116
141
117 type
142 type
118 Either ``deficiency`` or ``optimisation``. A deficiency is an obvious
143 Either ``deficiency`` or ``optimisation``. A deficiency is an obvious
119 problem. An optimization is an action (sometimes optional) that
144 problem. An optimization is an action (sometimes optional) that
120 can be taken to further improve the state of the repository.
145 can be taken to further improve the state of the repository.
121
146
122 description
147 description
123 Message intended for humans explaining the improvement in more detail,
148 Message intended for humans explaining the improvement in more detail,
124 including the implications of it. For ``deficiency`` types, should be
149 including the implications of it. For ``deficiency`` types, should be
125 worded in the present tense. For ``optimisation`` types, should be
150 worded in the present tense. For ``optimisation`` types, should be
126 worded in the future tense.
151 worded in the future tense.
127
152
128 upgrademessage
153 upgrademessage
129 Message intended for humans explaining what an upgrade addressing this
154 Message intended for humans explaining what an upgrade addressing this
130 issue will do. Should be worded in the future tense.
155 issue will do. Should be worded in the future tense.
131 """
156 """
132 def __init__(self, name, type, description, upgrademessage):
157 def __init__(self, name, type, description, upgrademessage):
133 self.name = name
158 self.name = name
134 self.type = type
159 self.type = type
135 self.description = description
160 self.description = description
136 self.upgrademessage = upgrademessage
161 self.upgrademessage = upgrademessage
137
162
138 def __eq__(self, other):
163 def __eq__(self, other):
139 if not isinstance(other, improvement):
164 if not isinstance(other, improvement):
140 # This is what python tell use to do
165 # This is what python tell use to do
141 return NotImplemented
166 return NotImplemented
142 return self.name == other.name
167 return self.name == other.name
143
168
144 def __ne__(self, other):
169 def __ne__(self, other):
145 return not (self == other)
170 return not (self == other)
146
171
147 def __hash__(self):
172 def __hash__(self):
148 return hash(self.name)
173 return hash(self.name)
149
174
150 allformatvariant = []
175 allformatvariant = []
151
176
152 def registerformatvariant(cls):
177 def registerformatvariant(cls):
153 allformatvariant.append(cls)
178 allformatvariant.append(cls)
154 return cls
179 return cls
155
180
156 class formatvariant(improvement):
181 class formatvariant(improvement):
157 """an improvement subclass dedicated to repository format"""
182 """an improvement subclass dedicated to repository format"""
158 type = deficiency
183 type = deficiency
159 ### The following attributes should be defined for each class:
184 ### The following attributes should be defined for each class:
160
185
161 # machine-readable string uniquely identifying this improvement. it will be
186 # machine-readable string uniquely identifying this improvement. it will be
162 # mapped to an action later in the upgrade process.
187 # mapped to an action later in the upgrade process.
163 name = None
188 name = None
164
189
165 # message intended for humans explaining the improvement in more detail,
190 # message intended for humans explaining the improvement in more detail,
166 # including the implications of it ``deficiency`` types, should be worded
191 # including the implications of it ``deficiency`` types, should be worded
167 # in the present tense.
192 # in the present tense.
168 description = None
193 description = None
169
194
170 # message intended for humans explaining what an upgrade addressing this
195 # message intended for humans explaining what an upgrade addressing this
171 # issue will do. should be worded in the future tense.
196 # issue will do. should be worded in the future tense.
172 upgrademessage = None
197 upgrademessage = None
173
198
174 # value of current Mercurial default for new repository
199 # value of current Mercurial default for new repository
175 default = None
200 default = None
176
201
177 def __init__(self):
202 def __init__(self):
178 raise NotImplementedError()
203 raise NotImplementedError()
179
204
180 @staticmethod
205 @staticmethod
181 def fromrepo(repo):
206 def fromrepo(repo):
182 """current value of the variant in the repository"""
207 """current value of the variant in the repository"""
183 raise NotImplementedError()
208 raise NotImplementedError()
184
209
185 @staticmethod
210 @staticmethod
186 def fromconfig(repo):
211 def fromconfig(repo):
187 """current value of the variant in the configuration"""
212 """current value of the variant in the configuration"""
188 raise NotImplementedError()
213 raise NotImplementedError()
189
214
190 class requirementformatvariant(formatvariant):
215 class requirementformatvariant(formatvariant):
191 """formatvariant based on a 'requirement' name.
216 """formatvariant based on a 'requirement' name.
192
217
193 Many format variant are controlled by a 'requirement'. We define a small
218 Many format variant are controlled by a 'requirement'. We define a small
194 subclass to factor the code.
219 subclass to factor the code.
195 """
220 """
196
221
197 # the requirement that control this format variant
222 # the requirement that control this format variant
198 _requirement = None
223 _requirement = None
199
224
200 @staticmethod
225 @staticmethod
201 def _newreporequirements(ui):
226 def _newreporequirements(ui):
202 return localrepo.newreporequirements(
227 return localrepo.newreporequirements(
203 ui, localrepo.defaultcreateopts(ui))
228 ui, localrepo.defaultcreateopts(ui))
204
229
205 @classmethod
230 @classmethod
206 def fromrepo(cls, repo):
231 def fromrepo(cls, repo):
207 assert cls._requirement is not None
232 assert cls._requirement is not None
208 return cls._requirement in repo.requirements
233 return cls._requirement in repo.requirements
209
234
210 @classmethod
235 @classmethod
211 def fromconfig(cls, repo):
236 def fromconfig(cls, repo):
212 assert cls._requirement is not None
237 assert cls._requirement is not None
213 return cls._requirement in cls._newreporequirements(repo.ui)
238 return cls._requirement in cls._newreporequirements(repo.ui)
214
239
215 @registerformatvariant
240 @registerformatvariant
216 class fncache(requirementformatvariant):
241 class fncache(requirementformatvariant):
217 name = 'fncache'
242 name = 'fncache'
218
243
219 _requirement = 'fncache'
244 _requirement = 'fncache'
220
245
221 default = True
246 default = True
222
247
223 description = _('long and reserved filenames may not work correctly; '
248 description = _('long and reserved filenames may not work correctly; '
224 'repository performance is sub-optimal')
249 'repository performance is sub-optimal')
225
250
226 upgrademessage = _('repository will be more resilient to storing '
251 upgrademessage = _('repository will be more resilient to storing '
227 'certain paths and performance of certain '
252 'certain paths and performance of certain '
228 'operations should be improved')
253 'operations should be improved')
229
254
230 @registerformatvariant
255 @registerformatvariant
231 class dotencode(requirementformatvariant):
256 class dotencode(requirementformatvariant):
232 name = 'dotencode'
257 name = 'dotencode'
233
258
234 _requirement = 'dotencode'
259 _requirement = 'dotencode'
235
260
236 default = True
261 default = True
237
262
238 description = _('storage of filenames beginning with a period or '
263 description = _('storage of filenames beginning with a period or '
239 'space may not work correctly')
264 'space may not work correctly')
240
265
241 upgrademessage = _('repository will be better able to store files '
266 upgrademessage = _('repository will be better able to store files '
242 'beginning with a space or period')
267 'beginning with a space or period')
243
268
244 @registerformatvariant
269 @registerformatvariant
245 class generaldelta(requirementformatvariant):
270 class generaldelta(requirementformatvariant):
246 name = 'generaldelta'
271 name = 'generaldelta'
247
272
248 _requirement = 'generaldelta'
273 _requirement = 'generaldelta'
249
274
250 default = True
275 default = True
251
276
252 description = _('deltas within internal storage are unable to '
277 description = _('deltas within internal storage are unable to '
253 'choose optimal revisions; repository is larger and '
278 'choose optimal revisions; repository is larger and '
254 'slower than it could be; interaction with other '
279 'slower than it could be; interaction with other '
255 'repositories may require extra network and CPU '
280 'repositories may require extra network and CPU '
256 'resources, making "hg push" and "hg pull" slower')
281 'resources, making "hg push" and "hg pull" slower')
257
282
258 upgrademessage = _('repository storage will be able to create '
283 upgrademessage = _('repository storage will be able to create '
259 'optimal deltas; new repository data will be '
284 'optimal deltas; new repository data will be '
260 'smaller and read times should decrease; '
285 'smaller and read times should decrease; '
261 'interacting with other repositories using this '
286 'interacting with other repositories using this '
262 'storage model should require less network and '
287 'storage model should require less network and '
263 'CPU resources, making "hg push" and "hg pull" '
288 'CPU resources, making "hg push" and "hg pull" '
264 'faster')
289 'faster')
265
290
266 @registerformatvariant
291 @registerformatvariant
267 class sparserevlog(requirementformatvariant):
292 class sparserevlog(requirementformatvariant):
268 name = 'sparserevlog'
293 name = 'sparserevlog'
269
294
270 _requirement = localrepo.SPARSEREVLOG_REQUIREMENT
295 _requirement = localrepo.SPARSEREVLOG_REQUIREMENT
271
296
272 default = True
297 default = True
273
298
274 description = _('in order to limit disk reading and memory usage on older '
299 description = _('in order to limit disk reading and memory usage on older '
275 'version, the span of a delta chain from its root to its '
300 'version, the span of a delta chain from its root to its '
276 'end is limited, whatever the relevant data in this span. '
301 'end is limited, whatever the relevant data in this span. '
277 'This can severly limit Mercurial ability to build good '
302 'This can severly limit Mercurial ability to build good '
278 'chain of delta resulting is much more storage space being '
303 'chain of delta resulting is much more storage space being '
279 'taken and limit reusability of on disk delta during '
304 'taken and limit reusability of on disk delta during '
280 'exchange.'
305 'exchange.'
281 )
306 )
282
307
283 upgrademessage = _('Revlog supports delta chain with more unused data '
308 upgrademessage = _('Revlog supports delta chain with more unused data '
284 'between payload. These gaps will be skipped at read '
309 'between payload. These gaps will be skipped at read '
285 'time. This allows for better delta chains, making a '
310 'time. This allows for better delta chains, making a '
286 'better compression and faster exchange with server.')
311 'better compression and faster exchange with server.')
287
312
288 @registerformatvariant
313 @registerformatvariant
289 class removecldeltachain(formatvariant):
314 class removecldeltachain(formatvariant):
290 name = 'plain-cl-delta'
315 name = 'plain-cl-delta'
291
316
292 default = True
317 default = True
293
318
294 description = _('changelog storage is using deltas instead of '
319 description = _('changelog storage is using deltas instead of '
295 'raw entries; changelog reading and any '
320 'raw entries; changelog reading and any '
296 'operation relying on changelog data are slower '
321 'operation relying on changelog data are slower '
297 'than they could be')
322 'than they could be')
298
323
299 upgrademessage = _('changelog storage will be reformated to '
324 upgrademessage = _('changelog storage will be reformated to '
300 'store raw entries; changelog reading will be '
325 'store raw entries; changelog reading will be '
301 'faster; changelog size may be reduced')
326 'faster; changelog size may be reduced')
302
327
303 @staticmethod
328 @staticmethod
304 def fromrepo(repo):
329 def fromrepo(repo):
305 # Mercurial 4.0 changed changelogs to not use delta chains. Search for
330 # Mercurial 4.0 changed changelogs to not use delta chains. Search for
306 # changelogs with deltas.
331 # changelogs with deltas.
307 cl = repo.changelog
332 cl = repo.changelog
308 chainbase = cl.chainbase
333 chainbase = cl.chainbase
309 return all(rev == chainbase(rev) for rev in cl)
334 return all(rev == chainbase(rev) for rev in cl)
310
335
311 @staticmethod
336 @staticmethod
312 def fromconfig(repo):
337 def fromconfig(repo):
313 return True
338 return True
314
339
315 @registerformatvariant
340 @registerformatvariant
316 class compressionengine(formatvariant):
341 class compressionengine(formatvariant):
317 name = 'compression'
342 name = 'compression'
318 default = 'zlib'
343 default = 'zlib'
319
344
320 description = _('Compresion algorithm used to compress data. '
345 description = _('Compresion algorithm used to compress data. '
321 'Some engine are faster than other')
346 'Some engine are faster than other')
322
347
323 upgrademessage = _('revlog content will be recompressed with the new '
348 upgrademessage = _('revlog content will be recompressed with the new '
324 'algorithm.')
349 'algorithm.')
325
350
326 @classmethod
351 @classmethod
327 def fromrepo(cls, repo):
352 def fromrepo(cls, repo):
328 # we allow multiple compression engine requirement to co-exist because
353 # we allow multiple compression engine requirement to co-exist because
329 # strickly speaking, revlog seems to support mixed compression style.
354 # strickly speaking, revlog seems to support mixed compression style.
330 #
355 #
331 # The compression used for new entries will be "the last one"
356 # The compression used for new entries will be "the last one"
332 compression = 'zlib'
357 compression = 'zlib'
333 for req in repo.requirements:
358 for req in repo.requirements:
334 prefix = req.startswith
359 prefix = req.startswith
335 if prefix('revlog-compression-') or prefix('exp-compression-'):
360 if prefix('revlog-compression-') or prefix('exp-compression-'):
336 compression = req.split('-', 2)[2]
361 compression = req.split('-', 2)[2]
337 return compression
362 return compression
338
363
339 @classmethod
364 @classmethod
340 def fromconfig(cls, repo):
365 def fromconfig(cls, repo):
341 return repo.ui.config('format', 'revlog-compression')
366 return repo.ui.config('format', 'revlog-compression')
342
367
343 @registerformatvariant
368 @registerformatvariant
344 class compressionlevel(formatvariant):
369 class compressionlevel(formatvariant):
345 name = 'compression-level'
370 name = 'compression-level'
346 default = 'default'
371 default = 'default'
347
372
348 description = _('compression level')
373 description = _('compression level')
349
374
350 upgrademessage = _('revlog content will be recompressed')
375 upgrademessage = _('revlog content will be recompressed')
351
376
352 @classmethod
377 @classmethod
353 def fromrepo(cls, repo):
378 def fromrepo(cls, repo):
354 comp = compressionengine.fromrepo(repo)
379 comp = compressionengine.fromrepo(repo)
355 level = None
380 level = None
356 if comp == 'zlib':
381 if comp == 'zlib':
357 level = repo.ui.configint('storage', 'revlog.zlib.level')
382 level = repo.ui.configint('storage', 'revlog.zlib.level')
358 elif comp == 'zstd':
383 elif comp == 'zstd':
359 level = repo.ui.configint('storage', 'revlog.zstd.level')
384 level = repo.ui.configint('storage', 'revlog.zstd.level')
360 if level is None:
385 if level is None:
361 return 'default'
386 return 'default'
362 return bytes(level)
387 return bytes(level)
363
388
364 @classmethod
389 @classmethod
365 def fromconfig(cls, repo):
390 def fromconfig(cls, repo):
366 comp = compressionengine.fromconfig(repo)
391 comp = compressionengine.fromconfig(repo)
367 level = None
392 level = None
368 if comp == 'zlib':
393 if comp == 'zlib':
369 level = repo.ui.configint('storage', 'revlog.zlib.level')
394 level = repo.ui.configint('storage', 'revlog.zlib.level')
370 elif comp == 'zstd':
395 elif comp == 'zstd':
371 level = repo.ui.configint('storage', 'revlog.zstd.level')
396 level = repo.ui.configint('storage', 'revlog.zstd.level')
372 if level is None:
397 if level is None:
373 return 'default'
398 return 'default'
374 return bytes(level)
399 return bytes(level)
375
400
376 def finddeficiencies(repo):
401 def finddeficiencies(repo):
377 """returns a list of deficiencies that the repo suffer from"""
402 """returns a list of deficiencies that the repo suffer from"""
378 deficiencies = []
403 deficiencies = []
379
404
380 # We could detect lack of revlogv1 and store here, but they were added
405 # We could detect lack of revlogv1 and store here, but they were added
381 # in 0.9.2 and we don't support upgrading repos without these
406 # in 0.9.2 and we don't support upgrading repos without these
382 # requirements, so let's not bother.
407 # requirements, so let's not bother.
383
408
384 for fv in allformatvariant:
409 for fv in allformatvariant:
385 if not fv.fromrepo(repo):
410 if not fv.fromrepo(repo):
386 deficiencies.append(fv)
411 deficiencies.append(fv)
387
412
388 return deficiencies
413 return deficiencies
389
414
390 # search without '-' to support older form on newer client.
415 # search without '-' to support older form on newer client.
391 #
416 #
392 # We don't enforce backward compatibility for debug command so this
417 # We don't enforce backward compatibility for debug command so this
393 # might eventually be dropped. However, having to use two different
418 # might eventually be dropped. However, having to use two different
394 # forms in script when comparing result is anoying enough to add
419 # forms in script when comparing result is anoying enough to add
395 # backward compatibility for a while.
420 # backward compatibility for a while.
396 legacy_opts_map = {
421 legacy_opts_map = {
397 'redeltaparent': 're-delta-parent',
422 'redeltaparent': 're-delta-parent',
398 'redeltamultibase': 're-delta-multibase',
423 'redeltamultibase': 're-delta-multibase',
399 'redeltaall': 're-delta-all',
424 'redeltaall': 're-delta-all',
400 'redeltafulladd': 're-delta-fulladd',
425 'redeltafulladd': 're-delta-fulladd',
401 }
426 }
402
427
403 def findoptimizations(repo):
428 def findoptimizations(repo):
404 """Determine optimisation that could be used during upgrade"""
429 """Determine optimisation that could be used during upgrade"""
405 # These are unconditionally added. There is logic later that figures out
430 # These are unconditionally added. There is logic later that figures out
406 # which ones to apply.
431 # which ones to apply.
407 optimizations = []
432 optimizations = []
408
433
409 optimizations.append(improvement(
434 optimizations.append(improvement(
410 name='re-delta-parent',
435 name='re-delta-parent',
411 type=optimisation,
436 type=optimisation,
412 description=_('deltas within internal storage will be recalculated to '
437 description=_('deltas within internal storage will be recalculated to '
413 'choose an optimal base revision where this was not '
438 'choose an optimal base revision where this was not '
414 'already done; the size of the repository may shrink and '
439 'already done; the size of the repository may shrink and '
415 'various operations may become faster; the first time '
440 'various operations may become faster; the first time '
416 'this optimization is performed could slow down upgrade '
441 'this optimization is performed could slow down upgrade '
417 'execution considerably; subsequent invocations should '
442 'execution considerably; subsequent invocations should '
418 'not run noticeably slower'),
443 'not run noticeably slower'),
419 upgrademessage=_('deltas within internal storage will choose a new '
444 upgrademessage=_('deltas within internal storage will choose a new '
420 'base revision if needed')))
445 'base revision if needed')))
421
446
422 optimizations.append(improvement(
447 optimizations.append(improvement(
423 name='re-delta-multibase',
448 name='re-delta-multibase',
424 type=optimisation,
449 type=optimisation,
425 description=_('deltas within internal storage will be recalculated '
450 description=_('deltas within internal storage will be recalculated '
426 'against multiple base revision and the smallest '
451 'against multiple base revision and the smallest '
427 'difference will be used; the size of the repository may '
452 'difference will be used; the size of the repository may '
428 'shrink significantly when there are many merges; this '
453 'shrink significantly when there are many merges; this '
429 'optimization will slow down execution in proportion to '
454 'optimization will slow down execution in proportion to '
430 'the number of merges in the repository and the amount '
455 'the number of merges in the repository and the amount '
431 'of files in the repository; this slow down should not '
456 'of files in the repository; this slow down should not '
432 'be significant unless there are tens of thousands of '
457 'be significant unless there are tens of thousands of '
433 'files and thousands of merges'),
458 'files and thousands of merges'),
434 upgrademessage=_('deltas within internal storage will choose an '
459 upgrademessage=_('deltas within internal storage will choose an '
435 'optimal delta by computing deltas against multiple '
460 'optimal delta by computing deltas against multiple '
436 'parents; may slow down execution time '
461 'parents; may slow down execution time '
437 'significantly')))
462 'significantly')))
438
463
439 optimizations.append(improvement(
464 optimizations.append(improvement(
440 name='re-delta-all',
465 name='re-delta-all',
441 type=optimisation,
466 type=optimisation,
442 description=_('deltas within internal storage will always be '
467 description=_('deltas within internal storage will always be '
443 'recalculated without reusing prior deltas; this will '
468 'recalculated without reusing prior deltas; this will '
444 'likely make execution run several times slower; this '
469 'likely make execution run several times slower; this '
445 'optimization is typically not needed'),
470 'optimization is typically not needed'),
446 upgrademessage=_('deltas within internal storage will be fully '
471 upgrademessage=_('deltas within internal storage will be fully '
447 'recomputed; this will likely drastically slow down '
472 'recomputed; this will likely drastically slow down '
448 'execution time')))
473 'execution time')))
449
474
450 optimizations.append(improvement(
475 optimizations.append(improvement(
451 name='re-delta-fulladd',
476 name='re-delta-fulladd',
452 type=optimisation,
477 type=optimisation,
453 description=_('every revision will be re-added as if it was new '
478 description=_('every revision will be re-added as if it was new '
454 'content. It will go through the full storage '
479 'content. It will go through the full storage '
455 'mechanism giving extensions a chance to process it '
480 'mechanism giving extensions a chance to process it '
456 '(eg. lfs). This is similar to "re-delta-all" but even '
481 '(eg. lfs). This is similar to "re-delta-all" but even '
457 'slower since more logic is involved.'),
482 'slower since more logic is involved.'),
458 upgrademessage=_('each revision will be added as new content to the '
483 upgrademessage=_('each revision will be added as new content to the '
459 'internal storage; this will likely drastically slow '
484 'internal storage; this will likely drastically slow '
460 'down execution time, but some extensions might need '
485 'down execution time, but some extensions might need '
461 'it')))
486 'it')))
462
487
463 return optimizations
488 return optimizations
464
489
465 def determineactions(repo, deficiencies, sourcereqs, destreqs):
490 def determineactions(repo, deficiencies, sourcereqs, destreqs):
466 """Determine upgrade actions that will be performed.
491 """Determine upgrade actions that will be performed.
467
492
468 Given a list of improvements as returned by ``finddeficiencies`` and
493 Given a list of improvements as returned by ``finddeficiencies`` and
469 ``findoptimizations``, determine the list of upgrade actions that
494 ``findoptimizations``, determine the list of upgrade actions that
470 will be performed.
495 will be performed.
471
496
472 The role of this function is to filter improvements if needed, apply
497 The role of this function is to filter improvements if needed, apply
473 recommended optimizations from the improvements list that make sense,
498 recommended optimizations from the improvements list that make sense,
474 etc.
499 etc.
475
500
476 Returns a list of action names.
501 Returns a list of action names.
477 """
502 """
478 newactions = []
503 newactions = []
479
504
480 knownreqs = supporteddestrequirements(repo)
505 knownreqs = supporteddestrequirements(repo)
481
506
482 for d in deficiencies:
507 for d in deficiencies:
483 name = d.name
508 name = d.name
484
509
485 # If the action is a requirement that doesn't show up in the
510 # If the action is a requirement that doesn't show up in the
486 # destination requirements, prune the action.
511 # destination requirements, prune the action.
487 if name in knownreqs and name not in destreqs:
512 if name in knownreqs and name not in destreqs:
488 continue
513 continue
489
514
490 newactions.append(d)
515 newactions.append(d)
491
516
492 # FUTURE consider adding some optimizations here for certain transitions.
517 # FUTURE consider adding some optimizations here for certain transitions.
493 # e.g. adding generaldelta could schedule parent redeltas.
518 # e.g. adding generaldelta could schedule parent redeltas.
494
519
495 return newactions
520 return newactions
496
521
497 def _revlogfrompath(repo, path):
522 def _revlogfrompath(repo, path):
498 """Obtain a revlog from a repo path.
523 """Obtain a revlog from a repo path.
499
524
500 An instance of the appropriate class is returned.
525 An instance of the appropriate class is returned.
501 """
526 """
502 if path == '00changelog.i':
527 if path == '00changelog.i':
503 return changelog.changelog(repo.svfs)
528 return changelog.changelog(repo.svfs)
504 elif path.endswith('00manifest.i'):
529 elif path.endswith('00manifest.i'):
505 mandir = path[:-len('00manifest.i')]
530 mandir = path[:-len('00manifest.i')]
506 return manifest.manifestrevlog(repo.svfs, tree=mandir)
531 return manifest.manifestrevlog(repo.svfs, tree=mandir)
507 else:
532 else:
508 #reverse of "/".join(("data", path + ".i"))
533 #reverse of "/".join(("data", path + ".i"))
509 return filelog.filelog(repo.svfs, path[5:-2])
534 return filelog.filelog(repo.svfs, path[5:-2])
510
535
511 def _copyrevlogs(ui, srcrepo, dstrepo, tr, deltareuse, forcedeltabothparents):
536 def _copyrevlogs(ui, srcrepo, dstrepo, tr, deltareuse, forcedeltabothparents):
512 """Copy revlogs between 2 repos."""
537 """Copy revlogs between 2 repos."""
513 revcount = 0
538 revcount = 0
514 srcsize = 0
539 srcsize = 0
515 srcrawsize = 0
540 srcrawsize = 0
516 dstsize = 0
541 dstsize = 0
517 fcount = 0
542 fcount = 0
518 frevcount = 0
543 frevcount = 0
519 fsrcsize = 0
544 fsrcsize = 0
520 frawsize = 0
545 frawsize = 0
521 fdstsize = 0
546 fdstsize = 0
522 mcount = 0
547 mcount = 0
523 mrevcount = 0
548 mrevcount = 0
524 msrcsize = 0
549 msrcsize = 0
525 mrawsize = 0
550 mrawsize = 0
526 mdstsize = 0
551 mdstsize = 0
527 crevcount = 0
552 crevcount = 0
528 csrcsize = 0
553 csrcsize = 0
529 crawsize = 0
554 crawsize = 0
530 cdstsize = 0
555 cdstsize = 0
531
556
532 # Perform a pass to collect metadata. This validates we can open all
557 # Perform a pass to collect metadata. This validates we can open all
533 # source files and allows a unified progress bar to be displayed.
558 # source files and allows a unified progress bar to be displayed.
534 for unencoded, encoded, size in srcrepo.store.walk():
559 for unencoded, encoded, size in srcrepo.store.walk():
535 if unencoded.endswith('.d'):
560 if unencoded.endswith('.d'):
536 continue
561 continue
537
562
538 rl = _revlogfrompath(srcrepo, unencoded)
563 rl = _revlogfrompath(srcrepo, unencoded)
539
564
540 info = rl.storageinfo(exclusivefiles=True, revisionscount=True,
565 info = rl.storageinfo(exclusivefiles=True, revisionscount=True,
541 trackedsize=True, storedsize=True)
566 trackedsize=True, storedsize=True)
542
567
543 revcount += info['revisionscount'] or 0
568 revcount += info['revisionscount'] or 0
544 datasize = info['storedsize'] or 0
569 datasize = info['storedsize'] or 0
545 rawsize = info['trackedsize'] or 0
570 rawsize = info['trackedsize'] or 0
546
571
547 srcsize += datasize
572 srcsize += datasize
548 srcrawsize += rawsize
573 srcrawsize += rawsize
549
574
550 # This is for the separate progress bars.
575 # This is for the separate progress bars.
551 if isinstance(rl, changelog.changelog):
576 if isinstance(rl, changelog.changelog):
552 crevcount += len(rl)
577 crevcount += len(rl)
553 csrcsize += datasize
578 csrcsize += datasize
554 crawsize += rawsize
579 crawsize += rawsize
555 elif isinstance(rl, manifest.manifestrevlog):
580 elif isinstance(rl, manifest.manifestrevlog):
556 mcount += 1
581 mcount += 1
557 mrevcount += len(rl)
582 mrevcount += len(rl)
558 msrcsize += datasize
583 msrcsize += datasize
559 mrawsize += rawsize
584 mrawsize += rawsize
560 elif isinstance(rl, filelog.filelog):
585 elif isinstance(rl, filelog.filelog):
561 fcount += 1
586 fcount += 1
562 frevcount += len(rl)
587 frevcount += len(rl)
563 fsrcsize += datasize
588 fsrcsize += datasize
564 frawsize += rawsize
589 frawsize += rawsize
565 else:
590 else:
566 error.ProgrammingError('unknown revlog type')
591 error.ProgrammingError('unknown revlog type')
567
592
568 if not revcount:
593 if not revcount:
569 return
594 return
570
595
571 ui.write(_('migrating %d total revisions (%d in filelogs, %d in manifests, '
596 ui.write(_('migrating %d total revisions (%d in filelogs, %d in manifests, '
572 '%d in changelog)\n') %
597 '%d in changelog)\n') %
573 (revcount, frevcount, mrevcount, crevcount))
598 (revcount, frevcount, mrevcount, crevcount))
574 ui.write(_('migrating %s in store; %s tracked data\n') % (
599 ui.write(_('migrating %s in store; %s tracked data\n') % (
575 (util.bytecount(srcsize), util.bytecount(srcrawsize))))
600 (util.bytecount(srcsize), util.bytecount(srcrawsize))))
576
601
577 # Used to keep track of progress.
602 # Used to keep track of progress.
578 progress = None
603 progress = None
579 def oncopiedrevision(rl, rev, node):
604 def oncopiedrevision(rl, rev, node):
580 progress.increment()
605 progress.increment()
581
606
582 # Do the actual copying.
607 # Do the actual copying.
583 # FUTURE this operation can be farmed off to worker processes.
608 # FUTURE this operation can be farmed off to worker processes.
584 seen = set()
609 seen = set()
585 for unencoded, encoded, size in srcrepo.store.walk():
610 for unencoded, encoded, size in srcrepo.store.walk():
586 if unencoded.endswith('.d'):
611 if unencoded.endswith('.d'):
587 continue
612 continue
588
613
589 oldrl = _revlogfrompath(srcrepo, unencoded)
614 oldrl = _revlogfrompath(srcrepo, unencoded)
590 newrl = _revlogfrompath(dstrepo, unencoded)
615 newrl = _revlogfrompath(dstrepo, unencoded)
591
616
592 if isinstance(oldrl, changelog.changelog) and 'c' not in seen:
617 if isinstance(oldrl, changelog.changelog) and 'c' not in seen:
593 ui.write(_('finished migrating %d manifest revisions across %d '
618 ui.write(_('finished migrating %d manifest revisions across %d '
594 'manifests; change in size: %s\n') %
619 'manifests; change in size: %s\n') %
595 (mrevcount, mcount, util.bytecount(mdstsize - msrcsize)))
620 (mrevcount, mcount, util.bytecount(mdstsize - msrcsize)))
596
621
597 ui.write(_('migrating changelog containing %d revisions '
622 ui.write(_('migrating changelog containing %d revisions '
598 '(%s in store; %s tracked data)\n') %
623 '(%s in store; %s tracked data)\n') %
599 (crevcount, util.bytecount(csrcsize),
624 (crevcount, util.bytecount(csrcsize),
600 util.bytecount(crawsize)))
625 util.bytecount(crawsize)))
601 seen.add('c')
626 seen.add('c')
602 progress = srcrepo.ui.makeprogress(_('changelog revisions'),
627 progress = srcrepo.ui.makeprogress(_('changelog revisions'),
603 total=crevcount)
628 total=crevcount)
604 elif isinstance(oldrl, manifest.manifestrevlog) and 'm' not in seen:
629 elif isinstance(oldrl, manifest.manifestrevlog) and 'm' not in seen:
605 ui.write(_('finished migrating %d filelog revisions across %d '
630 ui.write(_('finished migrating %d filelog revisions across %d '
606 'filelogs; change in size: %s\n') %
631 'filelogs; change in size: %s\n') %
607 (frevcount, fcount, util.bytecount(fdstsize - fsrcsize)))
632 (frevcount, fcount, util.bytecount(fdstsize - fsrcsize)))
608
633
609 ui.write(_('migrating %d manifests containing %d revisions '
634 ui.write(_('migrating %d manifests containing %d revisions '
610 '(%s in store; %s tracked data)\n') %
635 '(%s in store; %s tracked data)\n') %
611 (mcount, mrevcount, util.bytecount(msrcsize),
636 (mcount, mrevcount, util.bytecount(msrcsize),
612 util.bytecount(mrawsize)))
637 util.bytecount(mrawsize)))
613 seen.add('m')
638 seen.add('m')
614 if progress:
639 if progress:
615 progress.complete()
640 progress.complete()
616 progress = srcrepo.ui.makeprogress(_('manifest revisions'),
641 progress = srcrepo.ui.makeprogress(_('manifest revisions'),
617 total=mrevcount)
642 total=mrevcount)
618 elif 'f' not in seen:
643 elif 'f' not in seen:
619 ui.write(_('migrating %d filelogs containing %d revisions '
644 ui.write(_('migrating %d filelogs containing %d revisions '
620 '(%s in store; %s tracked data)\n') %
645 '(%s in store; %s tracked data)\n') %
621 (fcount, frevcount, util.bytecount(fsrcsize),
646 (fcount, frevcount, util.bytecount(fsrcsize),
622 util.bytecount(frawsize)))
647 util.bytecount(frawsize)))
623 seen.add('f')
648 seen.add('f')
624 if progress:
649 if progress:
625 progress.complete()
650 progress.complete()
626 progress = srcrepo.ui.makeprogress(_('file revisions'),
651 progress = srcrepo.ui.makeprogress(_('file revisions'),
627 total=frevcount)
652 total=frevcount)
628
653
629
654
630 ui.note(_('cloning %d revisions from %s\n') % (len(oldrl), unencoded))
655 ui.note(_('cloning %d revisions from %s\n') % (len(oldrl), unencoded))
631 oldrl.clone(tr, newrl, addrevisioncb=oncopiedrevision,
656 oldrl.clone(tr, newrl, addrevisioncb=oncopiedrevision,
632 deltareuse=deltareuse,
657 deltareuse=deltareuse,
633 forcedeltabothparents=forcedeltabothparents)
658 forcedeltabothparents=forcedeltabothparents)
634
659
635 info = newrl.storageinfo(storedsize=True)
660 info = newrl.storageinfo(storedsize=True)
636 datasize = info['storedsize'] or 0
661 datasize = info['storedsize'] or 0
637
662
638 dstsize += datasize
663 dstsize += datasize
639
664
640 if isinstance(newrl, changelog.changelog):
665 if isinstance(newrl, changelog.changelog):
641 cdstsize += datasize
666 cdstsize += datasize
642 elif isinstance(newrl, manifest.manifestrevlog):
667 elif isinstance(newrl, manifest.manifestrevlog):
643 mdstsize += datasize
668 mdstsize += datasize
644 else:
669 else:
645 fdstsize += datasize
670 fdstsize += datasize
646
671
647 progress.complete()
672 progress.complete()
648
673
649 ui.write(_('finished migrating %d changelog revisions; change in size: '
674 ui.write(_('finished migrating %d changelog revisions; change in size: '
650 '%s\n') % (crevcount, util.bytecount(cdstsize - csrcsize)))
675 '%s\n') % (crevcount, util.bytecount(cdstsize - csrcsize)))
651
676
652 ui.write(_('finished migrating %d total revisions; total change in store '
677 ui.write(_('finished migrating %d total revisions; total change in store '
653 'size: %s\n') % (revcount, util.bytecount(dstsize - srcsize)))
678 'size: %s\n') % (revcount, util.bytecount(dstsize - srcsize)))
654
679
655 def _filterstorefile(srcrepo, dstrepo, requirements, path, mode, st):
680 def _filterstorefile(srcrepo, dstrepo, requirements, path, mode, st):
656 """Determine whether to copy a store file during upgrade.
681 """Determine whether to copy a store file during upgrade.
657
682
658 This function is called when migrating store files from ``srcrepo`` to
683 This function is called when migrating store files from ``srcrepo`` to
659 ``dstrepo`` as part of upgrading a repository.
684 ``dstrepo`` as part of upgrading a repository.
660
685
661 Args:
686 Args:
662 srcrepo: repo we are copying from
687 srcrepo: repo we are copying from
663 dstrepo: repo we are copying to
688 dstrepo: repo we are copying to
664 requirements: set of requirements for ``dstrepo``
689 requirements: set of requirements for ``dstrepo``
665 path: store file being examined
690 path: store file being examined
666 mode: the ``ST_MODE`` file type of ``path``
691 mode: the ``ST_MODE`` file type of ``path``
667 st: ``stat`` data structure for ``path``
692 st: ``stat`` data structure for ``path``
668
693
669 Function should return ``True`` if the file is to be copied.
694 Function should return ``True`` if the file is to be copied.
670 """
695 """
671 # Skip revlogs.
696 # Skip revlogs.
672 if path.endswith(('.i', '.d')):
697 if path.endswith(('.i', '.d')):
673 return False
698 return False
674 # Skip transaction related files.
699 # Skip transaction related files.
675 if path.startswith('undo'):
700 if path.startswith('undo'):
676 return False
701 return False
677 # Only copy regular files.
702 # Only copy regular files.
678 if mode != stat.S_IFREG:
703 if mode != stat.S_IFREG:
679 return False
704 return False
680 # Skip other skipped files.
705 # Skip other skipped files.
681 if path in ('lock', 'fncache'):
706 if path in ('lock', 'fncache'):
682 return False
707 return False
683
708
684 return True
709 return True
685
710
686 def _finishdatamigration(ui, srcrepo, dstrepo, requirements):
711 def _finishdatamigration(ui, srcrepo, dstrepo, requirements):
687 """Hook point for extensions to perform additional actions during upgrade.
712 """Hook point for extensions to perform additional actions during upgrade.
688
713
689 This function is called after revlogs and store files have been copied but
714 This function is called after revlogs and store files have been copied but
690 before the new store is swapped into the original location.
715 before the new store is swapped into the original location.
691 """
716 """
692
717
693 def _upgraderepo(ui, srcrepo, dstrepo, requirements, actions):
718 def _upgraderepo(ui, srcrepo, dstrepo, requirements, actions):
694 """Do the low-level work of upgrading a repository.
719 """Do the low-level work of upgrading a repository.
695
720
696 The upgrade is effectively performed as a copy between a source
721 The upgrade is effectively performed as a copy between a source
697 repository and a temporary destination repository.
722 repository and a temporary destination repository.
698
723
699 The source repository is unmodified for as long as possible so the
724 The source repository is unmodified for as long as possible so the
700 upgrade can abort at any time without causing loss of service for
725 upgrade can abort at any time without causing loss of service for
701 readers and without corrupting the source repository.
726 readers and without corrupting the source repository.
702 """
727 """
703 assert srcrepo.currentwlock()
728 assert srcrepo.currentwlock()
704 assert dstrepo.currentwlock()
729 assert dstrepo.currentwlock()
705
730
706 ui.write(_('(it is safe to interrupt this process any time before '
731 ui.write(_('(it is safe to interrupt this process any time before '
707 'data migration completes)\n'))
732 'data migration completes)\n'))
708
733
709 if 're-delta-all' in actions:
734 if 're-delta-all' in actions:
710 deltareuse = revlog.revlog.DELTAREUSENEVER
735 deltareuse = revlog.revlog.DELTAREUSENEVER
711 elif 're-delta-parent' in actions:
736 elif 're-delta-parent' in actions:
712 deltareuse = revlog.revlog.DELTAREUSESAMEREVS
737 deltareuse = revlog.revlog.DELTAREUSESAMEREVS
713 elif 're-delta-multibase' in actions:
738 elif 're-delta-multibase' in actions:
714 deltareuse = revlog.revlog.DELTAREUSESAMEREVS
739 deltareuse = revlog.revlog.DELTAREUSESAMEREVS
715 elif 're-delta-fulladd' in actions:
740 elif 're-delta-fulladd' in actions:
716 deltareuse = revlog.revlog.DELTAREUSEFULLADD
741 deltareuse = revlog.revlog.DELTAREUSEFULLADD
717 else:
742 else:
718 deltareuse = revlog.revlog.DELTAREUSEALWAYS
743 deltareuse = revlog.revlog.DELTAREUSEALWAYS
719
744
720 with dstrepo.transaction('upgrade') as tr:
745 with dstrepo.transaction('upgrade') as tr:
721 _copyrevlogs(ui, srcrepo, dstrepo, tr, deltareuse,
746 _copyrevlogs(ui, srcrepo, dstrepo, tr, deltareuse,
722 're-delta-multibase' in actions)
747 're-delta-multibase' in actions)
723
748
724 # Now copy other files in the store directory.
749 # Now copy other files in the store directory.
725 # The sorted() makes execution deterministic.
750 # The sorted() makes execution deterministic.
726 for p, kind, st in sorted(srcrepo.store.vfs.readdir('', stat=True)):
751 for p, kind, st in sorted(srcrepo.store.vfs.readdir('', stat=True)):
727 if not _filterstorefile(srcrepo, dstrepo, requirements,
752 if not _filterstorefile(srcrepo, dstrepo, requirements,
728 p, kind, st):
753 p, kind, st):
729 continue
754 continue
730
755
731 srcrepo.ui.write(_('copying %s\n') % p)
756 srcrepo.ui.write(_('copying %s\n') % p)
732 src = srcrepo.store.rawvfs.join(p)
757 src = srcrepo.store.rawvfs.join(p)
733 dst = dstrepo.store.rawvfs.join(p)
758 dst = dstrepo.store.rawvfs.join(p)
734 util.copyfile(src, dst, copystat=True)
759 util.copyfile(src, dst, copystat=True)
735
760
736 _finishdatamigration(ui, srcrepo, dstrepo, requirements)
761 _finishdatamigration(ui, srcrepo, dstrepo, requirements)
737
762
738 ui.write(_('data fully migrated to temporary repository\n'))
763 ui.write(_('data fully migrated to temporary repository\n'))
739
764
740 backuppath = pycompat.mkdtemp(prefix='upgradebackup.', dir=srcrepo.path)
765 backuppath = pycompat.mkdtemp(prefix='upgradebackup.', dir=srcrepo.path)
741 backupvfs = vfsmod.vfs(backuppath)
766 backupvfs = vfsmod.vfs(backuppath)
742
767
743 # Make a backup of requires file first, as it is the first to be modified.
768 # Make a backup of requires file first, as it is the first to be modified.
744 util.copyfile(srcrepo.vfs.join('requires'), backupvfs.join('requires'))
769 util.copyfile(srcrepo.vfs.join('requires'), backupvfs.join('requires'))
745
770
746 # We install an arbitrary requirement that clients must not support
771 # We install an arbitrary requirement that clients must not support
747 # as a mechanism to lock out new clients during the data swap. This is
772 # as a mechanism to lock out new clients during the data swap. This is
748 # better than allowing a client to continue while the repository is in
773 # better than allowing a client to continue while the repository is in
749 # an inconsistent state.
774 # an inconsistent state.
750 ui.write(_('marking source repository as being upgraded; clients will be '
775 ui.write(_('marking source repository as being upgraded; clients will be '
751 'unable to read from repository\n'))
776 'unable to read from repository\n'))
752 scmutil.writerequires(srcrepo.vfs,
777 scmutil.writerequires(srcrepo.vfs,
753 srcrepo.requirements | {'upgradeinprogress'})
778 srcrepo.requirements | {'upgradeinprogress'})
754
779
755 ui.write(_('starting in-place swap of repository data\n'))
780 ui.write(_('starting in-place swap of repository data\n'))
756 ui.write(_('replaced files will be backed up at %s\n') %
781 ui.write(_('replaced files will be backed up at %s\n') %
757 backuppath)
782 backuppath)
758
783
759 # Now swap in the new store directory. Doing it as a rename should make
784 # Now swap in the new store directory. Doing it as a rename should make
760 # the operation nearly instantaneous and atomic (at least in well-behaved
785 # the operation nearly instantaneous and atomic (at least in well-behaved
761 # environments).
786 # environments).
762 ui.write(_('replacing store...\n'))
787 ui.write(_('replacing store...\n'))
763 tstart = util.timer()
788 tstart = util.timer()
764 util.rename(srcrepo.spath, backupvfs.join('store'))
789 util.rename(srcrepo.spath, backupvfs.join('store'))
765 util.rename(dstrepo.spath, srcrepo.spath)
790 util.rename(dstrepo.spath, srcrepo.spath)
766 elapsed = util.timer() - tstart
791 elapsed = util.timer() - tstart
767 ui.write(_('store replacement complete; repository was inconsistent for '
792 ui.write(_('store replacement complete; repository was inconsistent for '
768 '%0.1fs\n') % elapsed)
793 '%0.1fs\n') % elapsed)
769
794
770 # We first write the requirements file. Any new requirements will lock
795 # We first write the requirements file. Any new requirements will lock
771 # out legacy clients.
796 # out legacy clients.
772 ui.write(_('finalizing requirements file and making repository readable '
797 ui.write(_('finalizing requirements file and making repository readable '
773 'again\n'))
798 'again\n'))
774 scmutil.writerequires(srcrepo.vfs, requirements)
799 scmutil.writerequires(srcrepo.vfs, requirements)
775
800
776 # The lock file from the old store won't be removed because nothing has a
801 # The lock file from the old store won't be removed because nothing has a
777 # reference to its new location. So clean it up manually. Alternatively, we
802 # reference to its new location. So clean it up manually. Alternatively, we
778 # could update srcrepo.svfs and other variables to point to the new
803 # could update srcrepo.svfs and other variables to point to the new
779 # location. This is simpler.
804 # location. This is simpler.
780 backupvfs.unlink('store/lock')
805 backupvfs.unlink('store/lock')
781
806
782 return backuppath
807 return backuppath
783
808
784 def upgraderepo(ui, repo, run=False, optimize=None, backup=True):
809 def upgraderepo(ui, repo, run=False, optimize=None, backup=True):
785 """Upgrade a repository in place."""
810 """Upgrade a repository in place."""
786 if optimize is None:
811 if optimize is None:
787 optimize = []
812 optimize = []
788 optimize = set(legacy_opts_map.get(o, o) for o in optimize)
813 optimize = set(legacy_opts_map.get(o, o) for o in optimize)
789 repo = repo.unfiltered()
814 repo = repo.unfiltered()
790
815
791 # Ensure the repository can be upgraded.
816 # Ensure the repository can be upgraded.
792 missingreqs = requiredsourcerequirements(repo) - repo.requirements
817 missingreqs = requiredsourcerequirements(repo) - repo.requirements
793 if missingreqs:
818 if missingreqs:
794 raise error.Abort(_('cannot upgrade repository; requirement '
819 raise error.Abort(_('cannot upgrade repository; requirement '
795 'missing: %s') % _(', ').join(sorted(missingreqs)))
820 'missing: %s') % _(', ').join(sorted(missingreqs)))
796
821
797 blockedreqs = blocksourcerequirements(repo) & repo.requirements
822 blockedreqs = blocksourcerequirements(repo) & repo.requirements
798 if blockedreqs:
823 if blockedreqs:
799 raise error.Abort(_('cannot upgrade repository; unsupported source '
824 raise error.Abort(_('cannot upgrade repository; unsupported source '
800 'requirement: %s') %
825 'requirement: %s') %
801 _(', ').join(sorted(blockedreqs)))
826 _(', ').join(sorted(blockedreqs)))
802
827
803 # FUTURE there is potentially a need to control the wanted requirements via
828 # FUTURE there is potentially a need to control the wanted requirements via
804 # command arguments or via an extension hook point.
829 # command arguments or via an extension hook point.
805 newreqs = localrepo.newreporequirements(
830 newreqs = localrepo.newreporequirements(
806 repo.ui, localrepo.defaultcreateopts(repo.ui))
831 repo.ui, localrepo.defaultcreateopts(repo.ui))
807 newreqs.update(preservedrequirements(repo))
832 newreqs.update(preservedrequirements(repo))
808
833
809 noremovereqs = (repo.requirements - newreqs -
834 noremovereqs = (repo.requirements - newreqs -
810 supportremovedrequirements(repo))
835 supportremovedrequirements(repo))
811 if noremovereqs:
836 if noremovereqs:
812 raise error.Abort(_('cannot upgrade repository; requirement would be '
837 raise error.Abort(_('cannot upgrade repository; requirement would be '
813 'removed: %s') % _(', ').join(sorted(noremovereqs)))
838 'removed: %s') % _(', ').join(sorted(noremovereqs)))
814
839
815 noaddreqs = (newreqs - repo.requirements -
840 noaddreqs = (newreqs - repo.requirements -
816 allowednewrequirements(repo))
841 allowednewrequirements(repo))
817 if noaddreqs:
842 if noaddreqs:
818 raise error.Abort(_('cannot upgrade repository; do not support adding '
843 raise error.Abort(_('cannot upgrade repository; do not support adding '
819 'requirement: %s') %
844 'requirement: %s') %
820 _(', ').join(sorted(noaddreqs)))
845 _(', ').join(sorted(noaddreqs)))
821
846
822 unsupportedreqs = newreqs - supporteddestrequirements(repo)
847 unsupportedreqs = newreqs - supporteddestrequirements(repo)
823 if unsupportedreqs:
848 if unsupportedreqs:
824 raise error.Abort(_('cannot upgrade repository; do not support '
849 raise error.Abort(_('cannot upgrade repository; do not support '
825 'destination requirement: %s') %
850 'destination requirement: %s') %
826 _(', ').join(sorted(unsupportedreqs)))
851 _(', ').join(sorted(unsupportedreqs)))
827
852
828 # Find and validate all improvements that can be made.
853 # Find and validate all improvements that can be made.
829 alloptimizations = findoptimizations(repo)
854 alloptimizations = findoptimizations(repo)
830
855
831 # Apply and Validate arguments.
856 # Apply and Validate arguments.
832 optimizations = []
857 optimizations = []
833 for o in alloptimizations:
858 for o in alloptimizations:
834 if o.name in optimize:
859 if o.name in optimize:
835 optimizations.append(o)
860 optimizations.append(o)
836 optimize.discard(o.name)
861 optimize.discard(o.name)
837
862
838 if optimize: # anything left is unknown
863 if optimize: # anything left is unknown
839 raise error.Abort(_('unknown optimization action requested: %s') %
864 raise error.Abort(_('unknown optimization action requested: %s') %
840 ', '.join(sorted(optimize)),
865 ', '.join(sorted(optimize)),
841 hint=_('run without arguments to see valid '
866 hint=_('run without arguments to see valid '
842 'optimizations'))
867 'optimizations'))
843
868
844 deficiencies = finddeficiencies(repo)
869 deficiencies = finddeficiencies(repo)
845 actions = determineactions(repo, deficiencies, repo.requirements, newreqs)
870 actions = determineactions(repo, deficiencies, repo.requirements, newreqs)
846 actions.extend(o for o in sorted(optimizations)
871 actions.extend(o for o in sorted(optimizations)
847 # determineactions could have added optimisation
872 # determineactions could have added optimisation
848 if o not in actions)
873 if o not in actions)
849
874
850 def printrequirements():
875 def printrequirements():
851 ui.write(_('requirements\n'))
876 ui.write(_('requirements\n'))
852 ui.write(_(' preserved: %s\n') %
877 ui.write(_(' preserved: %s\n') %
853 _(', ').join(sorted(newreqs & repo.requirements)))
878 _(', ').join(sorted(newreqs & repo.requirements)))
854
879
855 if repo.requirements - newreqs:
880 if repo.requirements - newreqs:
856 ui.write(_(' removed: %s\n') %
881 ui.write(_(' removed: %s\n') %
857 _(', ').join(sorted(repo.requirements - newreqs)))
882 _(', ').join(sorted(repo.requirements - newreqs)))
858
883
859 if newreqs - repo.requirements:
884 if newreqs - repo.requirements:
860 ui.write(_(' added: %s\n') %
885 ui.write(_(' added: %s\n') %
861 _(', ').join(sorted(newreqs - repo.requirements)))
886 _(', ').join(sorted(newreqs - repo.requirements)))
862
887
863 ui.write('\n')
888 ui.write('\n')
864
889
865 def printupgradeactions():
890 def printupgradeactions():
866 for a in actions:
891 for a in actions:
867 ui.write('%s\n %s\n\n' % (a.name, a.upgrademessage))
892 ui.write('%s\n %s\n\n' % (a.name, a.upgrademessage))
868
893
869 if not run:
894 if not run:
870 fromconfig = []
895 fromconfig = []
871 onlydefault = []
896 onlydefault = []
872
897
873 for d in deficiencies:
898 for d in deficiencies:
874 if d.fromconfig(repo):
899 if d.fromconfig(repo):
875 fromconfig.append(d)
900 fromconfig.append(d)
876 elif d.default:
901 elif d.default:
877 onlydefault.append(d)
902 onlydefault.append(d)
878
903
879 if fromconfig or onlydefault:
904 if fromconfig or onlydefault:
880
905
881 if fromconfig:
906 if fromconfig:
882 ui.write(_('repository lacks features recommended by '
907 ui.write(_('repository lacks features recommended by '
883 'current config options:\n\n'))
908 'current config options:\n\n'))
884 for i in fromconfig:
909 for i in fromconfig:
885 ui.write('%s\n %s\n\n' % (i.name, i.description))
910 ui.write('%s\n %s\n\n' % (i.name, i.description))
886
911
887 if onlydefault:
912 if onlydefault:
888 ui.write(_('repository lacks features used by the default '
913 ui.write(_('repository lacks features used by the default '
889 'config options:\n\n'))
914 'config options:\n\n'))
890 for i in onlydefault:
915 for i in onlydefault:
891 ui.write('%s\n %s\n\n' % (i.name, i.description))
916 ui.write('%s\n %s\n\n' % (i.name, i.description))
892
917
893 ui.write('\n')
918 ui.write('\n')
894 else:
919 else:
895 ui.write(_('(no feature deficiencies found in existing '
920 ui.write(_('(no feature deficiencies found in existing '
896 'repository)\n'))
921 'repository)\n'))
897
922
898 ui.write(_('performing an upgrade with "--run" will make the following '
923 ui.write(_('performing an upgrade with "--run" will make the following '
899 'changes:\n\n'))
924 'changes:\n\n'))
900
925
901 printrequirements()
926 printrequirements()
902 printupgradeactions()
927 printupgradeactions()
903
928
904 unusedoptimize = [i for i in alloptimizations if i not in actions]
929 unusedoptimize = [i for i in alloptimizations if i not in actions]
905
930
906 if unusedoptimize:
931 if unusedoptimize:
907 ui.write(_('additional optimizations are available by specifying '
932 ui.write(_('additional optimizations are available by specifying '
908 '"--optimize <name>":\n\n'))
933 '"--optimize <name>":\n\n'))
909 for i in unusedoptimize:
934 for i in unusedoptimize:
910 ui.write(_('%s\n %s\n\n') % (i.name, i.description))
935 ui.write(_('%s\n %s\n\n') % (i.name, i.description))
911 return
936 return
912
937
913 # Else we're in the run=true case.
938 # Else we're in the run=true case.
914 ui.write(_('upgrade will perform the following actions:\n\n'))
939 ui.write(_('upgrade will perform the following actions:\n\n'))
915 printrequirements()
940 printrequirements()
916 printupgradeactions()
941 printupgradeactions()
917
942
918 upgradeactions = [a.name for a in actions]
943 upgradeactions = [a.name for a in actions]
919
944
920 ui.write(_('beginning upgrade...\n'))
945 ui.write(_('beginning upgrade...\n'))
921 with repo.wlock(), repo.lock():
946 with repo.wlock(), repo.lock():
922 ui.write(_('repository locked and read-only\n'))
947 ui.write(_('repository locked and read-only\n'))
923 # Our strategy for upgrading the repository is to create a new,
948 # Our strategy for upgrading the repository is to create a new,
924 # temporary repository, write data to it, then do a swap of the
949 # temporary repository, write data to it, then do a swap of the
925 # data. There are less heavyweight ways to do this, but it is easier
950 # data. There are less heavyweight ways to do this, but it is easier
926 # to create a new repo object than to instantiate all the components
951 # to create a new repo object than to instantiate all the components
927 # (like the store) separately.
952 # (like the store) separately.
928 tmppath = pycompat.mkdtemp(prefix='upgrade.', dir=repo.path)
953 tmppath = pycompat.mkdtemp(prefix='upgrade.', dir=repo.path)
929 backuppath = None
954 backuppath = None
930 try:
955 try:
931 ui.write(_('creating temporary repository to stage migrated '
956 ui.write(_('creating temporary repository to stage migrated '
932 'data: %s\n') % tmppath)
957 'data: %s\n') % tmppath)
933
958
934 # clone ui without using ui.copy because repo.ui is protected
959 # clone ui without using ui.copy because repo.ui is protected
935 repoui = repo.ui.__class__(repo.ui)
960 repoui = repo.ui.__class__(repo.ui)
936 dstrepo = hg.repository(repoui, path=tmppath, create=True)
961 dstrepo = hg.repository(repoui, path=tmppath, create=True)
937
962
938 with dstrepo.wlock(), dstrepo.lock():
963 with dstrepo.wlock(), dstrepo.lock():
939 backuppath = _upgraderepo(ui, repo, dstrepo, newreqs,
964 backuppath = _upgraderepo(ui, repo, dstrepo, newreqs,
940 upgradeactions)
965 upgradeactions)
941 if not (backup or backuppath is None):
966 if not (backup or backuppath is None):
942 ui.write(_('removing old repository content%s\n') % backuppath)
967 ui.write(_('removing old repository content%s\n') % backuppath)
943 repo.vfs.rmtree(backuppath, forcibly=True)
968 repo.vfs.rmtree(backuppath, forcibly=True)
944 backuppath = None
969 backuppath = None
945
970
946 finally:
971 finally:
947 ui.write(_('removing temporary repository %s\n') % tmppath)
972 ui.write(_('removing temporary repository %s\n') % tmppath)
948 repo.vfs.rmtree(tmppath, forcibly=True)
973 repo.vfs.rmtree(tmppath, forcibly=True)
949
974
950 if backuppath:
975 if backuppath:
951 ui.warn(_('copy of old repository backed up at %s\n') %
976 ui.warn(_('copy of old repository backed up at %s\n') %
952 backuppath)
977 backuppath)
953 ui.warn(_('the old repository will not be deleted; remove '
978 ui.warn(_('the old repository will not be deleted; remove '
954 'it to free up disk space once the upgraded '
979 'it to free up disk space once the upgraded '
955 'repository is verified\n'))
980 'repository is verified\n'))
@@ -1,857 +1,931
1 #require no-reposimplestore
1 #require no-reposimplestore
2
2
3 $ cat >> $HGRCPATH << EOF
3 $ cat >> $HGRCPATH << EOF
4 > [extensions]
4 > [extensions]
5 > share =
5 > share =
6 > EOF
6 > EOF
7
7
8 store and revlogv1 are required in source
8 store and revlogv1 are required in source
9
9
10 $ hg --config format.usestore=false init no-store
10 $ hg --config format.usestore=false init no-store
11 $ hg -R no-store debugupgraderepo
11 $ hg -R no-store debugupgraderepo
12 abort: cannot upgrade repository; requirement missing: store
12 abort: cannot upgrade repository; requirement missing: store
13 [255]
13 [255]
14
14
15 $ hg init no-revlogv1
15 $ hg init no-revlogv1
16 $ cat > no-revlogv1/.hg/requires << EOF
16 $ cat > no-revlogv1/.hg/requires << EOF
17 > dotencode
17 > dotencode
18 > fncache
18 > fncache
19 > generaldelta
19 > generaldelta
20 > store
20 > store
21 > EOF
21 > EOF
22
22
23 $ hg -R no-revlogv1 debugupgraderepo
23 $ hg -R no-revlogv1 debugupgraderepo
24 abort: cannot upgrade repository; requirement missing: revlogv1
24 abort: cannot upgrade repository; requirement missing: revlogv1
25 [255]
25 [255]
26
26
27 Cannot upgrade shared repositories
27 Cannot upgrade shared repositories
28
28
29 $ hg init share-parent
29 $ hg init share-parent
30 $ hg -q share share-parent share-child
30 $ hg -q share share-parent share-child
31
31
32 $ hg -R share-child debugupgraderepo
32 $ hg -R share-child debugupgraderepo
33 abort: cannot upgrade repository; unsupported source requirement: shared
33 abort: cannot upgrade repository; unsupported source requirement: shared
34 [255]
34 [255]
35
35
36 Do not yet support upgrading treemanifest repos
36 Do not yet support upgrading treemanifest repos
37
37
38 $ hg --config experimental.treemanifest=true init treemanifest
38 $ hg --config experimental.treemanifest=true init treemanifest
39 $ hg -R treemanifest debugupgraderepo
39 $ hg -R treemanifest debugupgraderepo
40 abort: cannot upgrade repository; unsupported source requirement: treemanifest
40 abort: cannot upgrade repository; unsupported source requirement: treemanifest
41 [255]
41 [255]
42
42
43 Cannot add treemanifest requirement during upgrade
43 Cannot add treemanifest requirement during upgrade
44
44
45 $ hg init disallowaddedreq
45 $ hg init disallowaddedreq
46 $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo
46 $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo
47 abort: cannot upgrade repository; do not support adding requirement: treemanifest
47 abort: cannot upgrade repository; do not support adding requirement: treemanifest
48 [255]
48 [255]
49
49
50 An upgrade of a repository created with recommended settings only suggests optimizations
50 An upgrade of a repository created with recommended settings only suggests optimizations
51
51
52 $ hg init empty
52 $ hg init empty
53 $ cd empty
53 $ cd empty
54 $ hg debugformat
54 $ hg debugformat
55 format-variant repo
55 format-variant repo
56 fncache: yes
56 fncache: yes
57 dotencode: yes
57 dotencode: yes
58 generaldelta: yes
58 generaldelta: yes
59 sparserevlog: yes
59 sparserevlog: yes
60 plain-cl-delta: yes
60 plain-cl-delta: yes
61 compression: zlib
61 compression: zlib
62 compression-level: default
62 compression-level: default
63 $ hg debugformat --verbose
63 $ hg debugformat --verbose
64 format-variant repo config default
64 format-variant repo config default
65 fncache: yes yes yes
65 fncache: yes yes yes
66 dotencode: yes yes yes
66 dotencode: yes yes yes
67 generaldelta: yes yes yes
67 generaldelta: yes yes yes
68 sparserevlog: yes yes yes
68 sparserevlog: yes yes yes
69 plain-cl-delta: yes yes yes
69 plain-cl-delta: yes yes yes
70 compression: zlib zlib zlib
70 compression: zlib zlib zlib
71 compression-level: default default default
71 compression-level: default default default
72 $ hg debugformat --verbose --config format.usefncache=no
72 $ hg debugformat --verbose --config format.usefncache=no
73 format-variant repo config default
73 format-variant repo config default
74 fncache: yes no yes
74 fncache: yes no yes
75 dotencode: yes no yes
75 dotencode: yes no yes
76 generaldelta: yes yes yes
76 generaldelta: yes yes yes
77 sparserevlog: yes yes yes
77 sparserevlog: yes yes yes
78 plain-cl-delta: yes yes yes
78 plain-cl-delta: yes yes yes
79 compression: zlib zlib zlib
79 compression: zlib zlib zlib
80 compression-level: default default default
80 compression-level: default default default
81 $ hg debugformat --verbose --config format.usefncache=no --color=debug
81 $ hg debugformat --verbose --config format.usefncache=no --color=debug
82 format-variant repo config default
82 format-variant repo config default
83 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
83 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
84 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
84 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
85 [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
85 [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
86 [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
86 [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
87 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
87 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
88 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
88 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
89 [formatvariant.name.uptodate|compression-level:][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
89 [formatvariant.name.uptodate|compression-level:][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
90 $ hg debugformat -Tjson
90 $ hg debugformat -Tjson
91 [
91 [
92 {
92 {
93 "config": true,
93 "config": true,
94 "default": true,
94 "default": true,
95 "name": "fncache",
95 "name": "fncache",
96 "repo": true
96 "repo": true
97 },
97 },
98 {
98 {
99 "config": true,
99 "config": true,
100 "default": true,
100 "default": true,
101 "name": "dotencode",
101 "name": "dotencode",
102 "repo": true
102 "repo": true
103 },
103 },
104 {
104 {
105 "config": true,
105 "config": true,
106 "default": true,
106 "default": true,
107 "name": "generaldelta",
107 "name": "generaldelta",
108 "repo": true
108 "repo": true
109 },
109 },
110 {
110 {
111 "config": true,
111 "config": true,
112 "default": true,
112 "default": true,
113 "name": "sparserevlog",
113 "name": "sparserevlog",
114 "repo": true
114 "repo": true
115 },
115 },
116 {
116 {
117 "config": true,
117 "config": true,
118 "default": true,
118 "default": true,
119 "name": "plain-cl-delta",
119 "name": "plain-cl-delta",
120 "repo": true
120 "repo": true
121 },
121 },
122 {
122 {
123 "config": "zlib",
123 "config": "zlib",
124 "default": "zlib",
124 "default": "zlib",
125 "name": "compression",
125 "name": "compression",
126 "repo": "zlib"
126 "repo": "zlib"
127 },
127 },
128 {
128 {
129 "config": "default",
129 "config": "default",
130 "default": "default",
130 "default": "default",
131 "name": "compression-level",
131 "name": "compression-level",
132 "repo": "default"
132 "repo": "default"
133 }
133 }
134 ]
134 ]
135 $ hg debugupgraderepo
135 $ hg debugupgraderepo
136 (no feature deficiencies found in existing repository)
136 (no feature deficiencies found in existing repository)
137 performing an upgrade with "--run" will make the following changes:
137 performing an upgrade with "--run" will make the following changes:
138
138
139 requirements
139 requirements
140 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
140 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
141
141
142 additional optimizations are available by specifying "--optimize <name>":
142 additional optimizations are available by specifying "--optimize <name>":
143
143
144 re-delta-parent
144 re-delta-parent
145 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
145 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
146
146
147 re-delta-multibase
147 re-delta-multibase
148 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
148 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
149
149
150 re-delta-all
150 re-delta-all
151 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
151 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
152
152
153 re-delta-fulladd
153 re-delta-fulladd
154 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
154 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
155
155
156
156
157 --optimize can be used to add optimizations
157 --optimize can be used to add optimizations
158
158
159 $ hg debugupgrade --optimize redeltaparent
159 $ hg debugupgrade --optimize redeltaparent
160 (no feature deficiencies found in existing repository)
160 (no feature deficiencies found in existing repository)
161 performing an upgrade with "--run" will make the following changes:
161 performing an upgrade with "--run" will make the following changes:
162
162
163 requirements
163 requirements
164 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
164 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
165
165
166 re-delta-parent
166 re-delta-parent
167 deltas within internal storage will choose a new base revision if needed
167 deltas within internal storage will choose a new base revision if needed
168
168
169 additional optimizations are available by specifying "--optimize <name>":
169 additional optimizations are available by specifying "--optimize <name>":
170
170
171 re-delta-multibase
171 re-delta-multibase
172 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
172 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
173
173
174 re-delta-all
174 re-delta-all
175 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
175 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
176
176
177 re-delta-fulladd
177 re-delta-fulladd
178 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
178 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
179
179
180
180
181 modern form of the option
181 modern form of the option
182
182
183 $ hg debugupgrade --optimize re-delta-parent
183 $ hg debugupgrade --optimize re-delta-parent
184 (no feature deficiencies found in existing repository)
184 (no feature deficiencies found in existing repository)
185 performing an upgrade with "--run" will make the following changes:
185 performing an upgrade with "--run" will make the following changes:
186
186
187 requirements
187 requirements
188 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
188 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
189
189
190 re-delta-parent
190 re-delta-parent
191 deltas within internal storage will choose a new base revision if needed
191 deltas within internal storage will choose a new base revision if needed
192
192
193 additional optimizations are available by specifying "--optimize <name>":
193 additional optimizations are available by specifying "--optimize <name>":
194
194
195 re-delta-multibase
195 re-delta-multibase
196 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
196 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
197
197
198 re-delta-all
198 re-delta-all
199 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
199 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
200
200
201 re-delta-fulladd
201 re-delta-fulladd
202 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
202 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
203
203
204
204
205 unknown optimization:
205 unknown optimization:
206
206
207 $ hg debugupgrade --optimize foobar
207 $ hg debugupgrade --optimize foobar
208 abort: unknown optimization action requested: foobar
208 abort: unknown optimization action requested: foobar
209 (run without arguments to see valid optimizations)
209 (run without arguments to see valid optimizations)
210 [255]
210 [255]
211
211
212 Various sub-optimal detections work
212 Various sub-optimal detections work
213
213
214 $ cat > .hg/requires << EOF
214 $ cat > .hg/requires << EOF
215 > revlogv1
215 > revlogv1
216 > store
216 > store
217 > EOF
217 > EOF
218
218
219 $ hg debugformat
219 $ hg debugformat
220 format-variant repo
220 format-variant repo
221 fncache: no
221 fncache: no
222 dotencode: no
222 dotencode: no
223 generaldelta: no
223 generaldelta: no
224 sparserevlog: no
224 sparserevlog: no
225 plain-cl-delta: yes
225 plain-cl-delta: yes
226 compression: zlib
226 compression: zlib
227 compression-level: default
227 compression-level: default
228 $ hg debugformat --verbose
228 $ hg debugformat --verbose
229 format-variant repo config default
229 format-variant repo config default
230 fncache: no yes yes
230 fncache: no yes yes
231 dotencode: no yes yes
231 dotencode: no yes yes
232 generaldelta: no yes yes
232 generaldelta: no yes yes
233 sparserevlog: no yes yes
233 sparserevlog: no yes yes
234 plain-cl-delta: yes yes yes
234 plain-cl-delta: yes yes yes
235 compression: zlib zlib zlib
235 compression: zlib zlib zlib
236 compression-level: default default default
236 compression-level: default default default
237 $ hg debugformat --verbose --config format.usegeneraldelta=no
237 $ hg debugformat --verbose --config format.usegeneraldelta=no
238 format-variant repo config default
238 format-variant repo config default
239 fncache: no yes yes
239 fncache: no yes yes
240 dotencode: no yes yes
240 dotencode: no yes yes
241 generaldelta: no no yes
241 generaldelta: no no yes
242 sparserevlog: no no yes
242 sparserevlog: no no yes
243 plain-cl-delta: yes yes yes
243 plain-cl-delta: yes yes yes
244 compression: zlib zlib zlib
244 compression: zlib zlib zlib
245 compression-level: default default default
245 compression-level: default default default
246 $ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug
246 $ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug
247 format-variant repo config default
247 format-variant repo config default
248 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
248 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
249 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
249 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
250 [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
250 [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
251 [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
251 [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
252 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
252 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
253 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
253 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
254 [formatvariant.name.uptodate|compression-level:][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
254 [formatvariant.name.uptodate|compression-level:][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
255 $ hg debugupgraderepo
255 $ hg debugupgraderepo
256 repository lacks features recommended by current config options:
256 repository lacks features recommended by current config options:
257
257
258 fncache
258 fncache
259 long and reserved filenames may not work correctly; repository performance is sub-optimal
259 long and reserved filenames may not work correctly; repository performance is sub-optimal
260
260
261 dotencode
261 dotencode
262 storage of filenames beginning with a period or space may not work correctly
262 storage of filenames beginning with a period or space may not work correctly
263
263
264 generaldelta
264 generaldelta
265 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
265 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
266
266
267 sparserevlog
267 sparserevlog
268 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
268 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
269
269
270
270
271 performing an upgrade with "--run" will make the following changes:
271 performing an upgrade with "--run" will make the following changes:
272
272
273 requirements
273 requirements
274 preserved: revlogv1, store
274 preserved: revlogv1, store
275 added: dotencode, fncache, generaldelta, sparserevlog
275 added: dotencode, fncache, generaldelta, sparserevlog
276
276
277 fncache
277 fncache
278 repository will be more resilient to storing certain paths and performance of certain operations should be improved
278 repository will be more resilient to storing certain paths and performance of certain operations should be improved
279
279
280 dotencode
280 dotencode
281 repository will be better able to store files beginning with a space or period
281 repository will be better able to store files beginning with a space or period
282
282
283 generaldelta
283 generaldelta
284 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
284 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
285
285
286 sparserevlog
286 sparserevlog
287 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
287 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
288
288
289 additional optimizations are available by specifying "--optimize <name>":
289 additional optimizations are available by specifying "--optimize <name>":
290
290
291 re-delta-parent
291 re-delta-parent
292 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
292 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
293
293
294 re-delta-multibase
294 re-delta-multibase
295 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
295 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
296
296
297 re-delta-all
297 re-delta-all
298 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
298 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
299
299
300 re-delta-fulladd
300 re-delta-fulladd
301 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
301 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
302
302
303
303
304 $ hg --config format.dotencode=false debugupgraderepo
304 $ hg --config format.dotencode=false debugupgraderepo
305 repository lacks features recommended by current config options:
305 repository lacks features recommended by current config options:
306
306
307 fncache
307 fncache
308 long and reserved filenames may not work correctly; repository performance is sub-optimal
308 long and reserved filenames may not work correctly; repository performance is sub-optimal
309
309
310 generaldelta
310 generaldelta
311 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
311 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
312
312
313 sparserevlog
313 sparserevlog
314 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
314 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
315
315
316 repository lacks features used by the default config options:
316 repository lacks features used by the default config options:
317
317
318 dotencode
318 dotencode
319 storage of filenames beginning with a period or space may not work correctly
319 storage of filenames beginning with a period or space may not work correctly
320
320
321
321
322 performing an upgrade with "--run" will make the following changes:
322 performing an upgrade with "--run" will make the following changes:
323
323
324 requirements
324 requirements
325 preserved: revlogv1, store
325 preserved: revlogv1, store
326 added: fncache, generaldelta, sparserevlog
326 added: fncache, generaldelta, sparserevlog
327
327
328 fncache
328 fncache
329 repository will be more resilient to storing certain paths and performance of certain operations should be improved
329 repository will be more resilient to storing certain paths and performance of certain operations should be improved
330
330
331 generaldelta
331 generaldelta
332 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
332 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
333
333
334 sparserevlog
334 sparserevlog
335 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
335 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
336
336
337 additional optimizations are available by specifying "--optimize <name>":
337 additional optimizations are available by specifying "--optimize <name>":
338
338
339 re-delta-parent
339 re-delta-parent
340 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
340 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
341
341
342 re-delta-multibase
342 re-delta-multibase
343 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
343 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
344
344
345 re-delta-all
345 re-delta-all
346 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
346 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
347
347
348 re-delta-fulladd
348 re-delta-fulladd
349 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
349 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
350
350
351
351
352 $ cd ..
352 $ cd ..
353
353
354 Upgrading a repository that is already modern essentially no-ops
354 Upgrading a repository that is already modern essentially no-ops
355
355
356 $ hg init modern
356 $ hg init modern
357 $ hg -R modern debugupgraderepo --run
357 $ hg -R modern debugupgraderepo --run
358 upgrade will perform the following actions:
358 upgrade will perform the following actions:
359
359
360 requirements
360 requirements
361 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
361 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
362
362
363 beginning upgrade...
363 beginning upgrade...
364 repository locked and read-only
364 repository locked and read-only
365 creating temporary repository to stage migrated data: $TESTTMP/modern/.hg/upgrade.* (glob)
365 creating temporary repository to stage migrated data: $TESTTMP/modern/.hg/upgrade.* (glob)
366 (it is safe to interrupt this process any time before data migration completes)
366 (it is safe to interrupt this process any time before data migration completes)
367 data fully migrated to temporary repository
367 data fully migrated to temporary repository
368 marking source repository as being upgraded; clients will be unable to read from repository
368 marking source repository as being upgraded; clients will be unable to read from repository
369 starting in-place swap of repository data
369 starting in-place swap of repository data
370 replaced files will be backed up at $TESTTMP/modern/.hg/upgradebackup.* (glob)
370 replaced files will be backed up at $TESTTMP/modern/.hg/upgradebackup.* (glob)
371 replacing store...
371 replacing store...
372 store replacement complete; repository was inconsistent for *s (glob)
372 store replacement complete; repository was inconsistent for *s (glob)
373 finalizing requirements file and making repository readable again
373 finalizing requirements file and making repository readable again
374 removing temporary repository $TESTTMP/modern/.hg/upgrade.* (glob)
374 removing temporary repository $TESTTMP/modern/.hg/upgrade.* (glob)
375 copy of old repository backed up at $TESTTMP/modern/.hg/upgradebackup.* (glob)
375 copy of old repository backed up at $TESTTMP/modern/.hg/upgradebackup.* (glob)
376 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
376 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
377
377
378 Upgrading a repository to generaldelta works
378 Upgrading a repository to generaldelta works
379
379
380 $ hg --config format.usegeneraldelta=false init upgradegd
380 $ hg --config format.usegeneraldelta=false init upgradegd
381 $ cd upgradegd
381 $ cd upgradegd
382 $ touch f0
382 $ touch f0
383 $ hg -q commit -A -m initial
383 $ hg -q commit -A -m initial
384 $ touch f1
384 $ touch f1
385 $ hg -q commit -A -m 'add f1'
385 $ hg -q commit -A -m 'add f1'
386 $ hg -q up -r 0
386 $ hg -q up -r 0
387 $ touch f2
387 $ touch f2
388 $ hg -q commit -A -m 'add f2'
388 $ hg -q commit -A -m 'add f2'
389
389
390 $ hg debugupgraderepo --run --config format.sparse-revlog=false
390 $ hg debugupgraderepo --run --config format.sparse-revlog=false
391 upgrade will perform the following actions:
391 upgrade will perform the following actions:
392
392
393 requirements
393 requirements
394 preserved: dotencode, fncache, revlogv1, store
394 preserved: dotencode, fncache, revlogv1, store
395 added: generaldelta
395 added: generaldelta
396
396
397 generaldelta
397 generaldelta
398 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
398 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
399
399
400 beginning upgrade...
400 beginning upgrade...
401 repository locked and read-only
401 repository locked and read-only
402 creating temporary repository to stage migrated data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
402 creating temporary repository to stage migrated data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
403 (it is safe to interrupt this process any time before data migration completes)
403 (it is safe to interrupt this process any time before data migration completes)
404 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
404 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
405 migrating 917 bytes in store; 401 bytes tracked data
405 migrating 917 bytes in store; 401 bytes tracked data
406 migrating 3 filelogs containing 3 revisions (192 bytes in store; 0 bytes tracked data)
406 migrating 3 filelogs containing 3 revisions (192 bytes in store; 0 bytes tracked data)
407 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
407 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
408 migrating 1 manifests containing 3 revisions (349 bytes in store; 220 bytes tracked data)
408 migrating 1 manifests containing 3 revisions (349 bytes in store; 220 bytes tracked data)
409 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
409 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
410 migrating changelog containing 3 revisions (376 bytes in store; 181 bytes tracked data)
410 migrating changelog containing 3 revisions (376 bytes in store; 181 bytes tracked data)
411 finished migrating 3 changelog revisions; change in size: 0 bytes
411 finished migrating 3 changelog revisions; change in size: 0 bytes
412 finished migrating 9 total revisions; total change in store size: 0 bytes
412 finished migrating 9 total revisions; total change in store size: 0 bytes
413 copying phaseroots
413 copying phaseroots
414 data fully migrated to temporary repository
414 data fully migrated to temporary repository
415 marking source repository as being upgraded; clients will be unable to read from repository
415 marking source repository as being upgraded; clients will be unable to read from repository
416 starting in-place swap of repository data
416 starting in-place swap of repository data
417 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
417 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
418 replacing store...
418 replacing store...
419 store replacement complete; repository was inconsistent for *s (glob)
419 store replacement complete; repository was inconsistent for *s (glob)
420 finalizing requirements file and making repository readable again
420 finalizing requirements file and making repository readable again
421 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
421 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
422 copy of old repository backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
422 copy of old repository backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
423 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
423 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
424
424
425 Original requirements backed up
425 Original requirements backed up
426
426
427 $ cat .hg/upgradebackup.*/requires
427 $ cat .hg/upgradebackup.*/requires
428 dotencode
428 dotencode
429 fncache
429 fncache
430 revlogv1
430 revlogv1
431 store
431 store
432
432
433 generaldelta added to original requirements files
433 generaldelta added to original requirements files
434
434
435 $ cat .hg/requires
435 $ cat .hg/requires
436 dotencode
436 dotencode
437 fncache
437 fncache
438 generaldelta
438 generaldelta
439 revlogv1
439 revlogv1
440 store
440 store
441
441
442 store directory has files we expect
442 store directory has files we expect
443
443
444 $ ls .hg/store
444 $ ls .hg/store
445 00changelog.i
445 00changelog.i
446 00manifest.i
446 00manifest.i
447 data
447 data
448 fncache
448 fncache
449 phaseroots
449 phaseroots
450 undo
450 undo
451 undo.backupfiles
451 undo.backupfiles
452 undo.phaseroots
452 undo.phaseroots
453
453
454 manifest should be generaldelta
454 manifest should be generaldelta
455
455
456 $ hg debugrevlog -m | grep flags
456 $ hg debugrevlog -m | grep flags
457 flags : inline, generaldelta
457 flags : inline, generaldelta
458
458
459 verify should be happy
459 verify should be happy
460
460
461 $ hg verify
461 $ hg verify
462 checking changesets
462 checking changesets
463 checking manifests
463 checking manifests
464 crosschecking files in changesets and manifests
464 crosschecking files in changesets and manifests
465 checking files
465 checking files
466 checked 3 changesets with 3 changes to 3 files
466 checked 3 changesets with 3 changes to 3 files
467
467
468 old store should be backed up
468 old store should be backed up
469
469
470 $ ls -d .hg/upgradebackup.*/
470 $ ls -d .hg/upgradebackup.*/
471 .hg/upgradebackup.*/ (glob)
471 .hg/upgradebackup.*/ (glob)
472 $ ls .hg/upgradebackup.*/store
472 $ ls .hg/upgradebackup.*/store
473 00changelog.i
473 00changelog.i
474 00manifest.i
474 00manifest.i
475 data
475 data
476 fncache
476 fncache
477 phaseroots
477 phaseroots
478 undo
478 undo
479 undo.backup.fncache
479 undo.backup.fncache
480 undo.backupfiles
480 undo.backupfiles
481 undo.phaseroots
481 undo.phaseroots
482
482
483 unless --no-backup is passed
483 unless --no-backup is passed
484
484
485 $ rm -rf .hg/upgradebackup.*/
485 $ rm -rf .hg/upgradebackup.*/
486 $ hg debugupgraderepo --run --no-backup
486 $ hg debugupgraderepo --run --no-backup
487 upgrade will perform the following actions:
487 upgrade will perform the following actions:
488
488
489 requirements
489 requirements
490 preserved: dotencode, fncache, generaldelta, revlogv1, store
490 preserved: dotencode, fncache, generaldelta, revlogv1, store
491 added: sparserevlog
491 added: sparserevlog
492
492
493 sparserevlog
493 sparserevlog
494 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
494 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
495
495
496 beginning upgrade...
496 beginning upgrade...
497 repository locked and read-only
497 repository locked and read-only
498 creating temporary repository to stage migrated data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
498 creating temporary repository to stage migrated data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
499 (it is safe to interrupt this process any time before data migration completes)
499 (it is safe to interrupt this process any time before data migration completes)
500 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
500 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
501 migrating 917 bytes in store; 401 bytes tracked data
501 migrating 917 bytes in store; 401 bytes tracked data
502 migrating 3 filelogs containing 3 revisions (192 bytes in store; 0 bytes tracked data)
502 migrating 3 filelogs containing 3 revisions (192 bytes in store; 0 bytes tracked data)
503 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
503 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
504 migrating 1 manifests containing 3 revisions (349 bytes in store; 220 bytes tracked data)
504 migrating 1 manifests containing 3 revisions (349 bytes in store; 220 bytes tracked data)
505 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
505 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
506 migrating changelog containing 3 revisions (376 bytes in store; 181 bytes tracked data)
506 migrating changelog containing 3 revisions (376 bytes in store; 181 bytes tracked data)
507 finished migrating 3 changelog revisions; change in size: 0 bytes
507 finished migrating 3 changelog revisions; change in size: 0 bytes
508 finished migrating 9 total revisions; total change in store size: 0 bytes
508 finished migrating 9 total revisions; total change in store size: 0 bytes
509 copying phaseroots
509 copying phaseroots
510 data fully migrated to temporary repository
510 data fully migrated to temporary repository
511 marking source repository as being upgraded; clients will be unable to read from repository
511 marking source repository as being upgraded; clients will be unable to read from repository
512 starting in-place swap of repository data
512 starting in-place swap of repository data
513 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
513 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
514 replacing store...
514 replacing store...
515 store replacement complete; repository was inconsistent for * (glob)
515 store replacement complete; repository was inconsistent for * (glob)
516 finalizing requirements file and making repository readable again
516 finalizing requirements file and making repository readable again
517 removing old repository content$TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
517 removing old repository content$TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
518 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
518 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
519 $ ls -1 .hg/ | grep upgradebackup
519 $ ls -1 .hg/ | grep upgradebackup
520 [1]
520 [1]
521 $ cd ..
521 $ cd ..
522
522
523
523
524 store files with special filenames aren't encoded during copy
524 store files with special filenames aren't encoded during copy
525
525
526 $ hg init store-filenames
526 $ hg init store-filenames
527 $ cd store-filenames
527 $ cd store-filenames
528 $ touch foo
528 $ touch foo
529 $ hg -q commit -A -m initial
529 $ hg -q commit -A -m initial
530 $ touch .hg/store/.XX_special_filename
530 $ touch .hg/store/.XX_special_filename
531
531
532 $ hg debugupgraderepo --run
532 $ hg debugupgraderepo --run
533 upgrade will perform the following actions:
533 upgrade will perform the following actions:
534
534
535 requirements
535 requirements
536 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
536 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
537
537
538 beginning upgrade...
538 beginning upgrade...
539 repository locked and read-only
539 repository locked and read-only
540 creating temporary repository to stage migrated data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
540 creating temporary repository to stage migrated data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
541 (it is safe to interrupt this process any time before data migration completes)
541 (it is safe to interrupt this process any time before data migration completes)
542 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
542 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
543 migrating 301 bytes in store; 107 bytes tracked data
543 migrating 301 bytes in store; 107 bytes tracked data
544 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
544 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
545 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
545 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
546 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
546 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
547 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
547 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
548 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
548 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
549 finished migrating 1 changelog revisions; change in size: 0 bytes
549 finished migrating 1 changelog revisions; change in size: 0 bytes
550 finished migrating 3 total revisions; total change in store size: 0 bytes
550 finished migrating 3 total revisions; total change in store size: 0 bytes
551 copying .XX_special_filename
551 copying .XX_special_filename
552 copying phaseroots
552 copying phaseroots
553 data fully migrated to temporary repository
553 data fully migrated to temporary repository
554 marking source repository as being upgraded; clients will be unable to read from repository
554 marking source repository as being upgraded; clients will be unable to read from repository
555 starting in-place swap of repository data
555 starting in-place swap of repository data
556 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
556 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
557 replacing store...
557 replacing store...
558 store replacement complete; repository was inconsistent for *s (glob)
558 store replacement complete; repository was inconsistent for *s (glob)
559 finalizing requirements file and making repository readable again
559 finalizing requirements file and making repository readable again
560 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
560 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
561 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
561 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
562 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
562 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
563 $ hg debugupgraderepo --run --optimize redeltafulladd
563 $ hg debugupgraderepo --run --optimize redeltafulladd
564 upgrade will perform the following actions:
564 upgrade will perform the following actions:
565
565
566 requirements
566 requirements
567 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
567 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
568
568
569 re-delta-fulladd
569 re-delta-fulladd
570 each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it
570 each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it
571
571
572 beginning upgrade...
572 beginning upgrade...
573 repository locked and read-only
573 repository locked and read-only
574 creating temporary repository to stage migrated data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
574 creating temporary repository to stage migrated data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
575 (it is safe to interrupt this process any time before data migration completes)
575 (it is safe to interrupt this process any time before data migration completes)
576 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
576 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
577 migrating 301 bytes in store; 107 bytes tracked data
577 migrating 301 bytes in store; 107 bytes tracked data
578 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
578 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
579 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
579 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
580 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
580 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
581 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
581 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
582 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
582 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
583 finished migrating 1 changelog revisions; change in size: 0 bytes
583 finished migrating 1 changelog revisions; change in size: 0 bytes
584 finished migrating 3 total revisions; total change in store size: 0 bytes
584 finished migrating 3 total revisions; total change in store size: 0 bytes
585 copying .XX_special_filename
585 copying .XX_special_filename
586 copying phaseroots
586 copying phaseroots
587 data fully migrated to temporary repository
587 data fully migrated to temporary repository
588 marking source repository as being upgraded; clients will be unable to read from repository
588 marking source repository as being upgraded; clients will be unable to read from repository
589 starting in-place swap of repository data
589 starting in-place swap of repository data
590 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
590 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
591 replacing store...
591 replacing store...
592 store replacement complete; repository was inconsistent for *s (glob)
592 store replacement complete; repository was inconsistent for *s (glob)
593 finalizing requirements file and making repository readable again
593 finalizing requirements file and making repository readable again
594 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
594 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
595 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
595 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
596 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
596 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
597
597
598 fncache is valid after upgrade
598 fncache is valid after upgrade
599
599
600 $ hg debugrebuildfncache
600 $ hg debugrebuildfncache
601 fncache already up to date
601 fncache already up to date
602
602
603 $ cd ..
603 $ cd ..
604
604
605 Check upgrading a large file repository
605 Check upgrading a large file repository
606 ---------------------------------------
606 ---------------------------------------
607
607
608 $ hg init largefilesrepo
608 $ hg init largefilesrepo
609 $ cat << EOF >> largefilesrepo/.hg/hgrc
609 $ cat << EOF >> largefilesrepo/.hg/hgrc
610 > [extensions]
610 > [extensions]
611 > largefiles =
611 > largefiles =
612 > EOF
612 > EOF
613
613
614 $ cd largefilesrepo
614 $ cd largefilesrepo
615 $ touch foo
615 $ touch foo
616 $ hg add --large foo
616 $ hg add --large foo
617 $ hg -q commit -m initial
617 $ hg -q commit -m initial
618 $ cat .hg/requires
618 $ cat .hg/requires
619 dotencode
619 dotencode
620 fncache
620 fncache
621 generaldelta
621 generaldelta
622 largefiles
622 largefiles
623 revlogv1
623 revlogv1
624 sparserevlog
624 sparserevlog
625 store
625 store
626
626
627 $ hg debugupgraderepo --run
627 $ hg debugupgraderepo --run
628 upgrade will perform the following actions:
628 upgrade will perform the following actions:
629
629
630 requirements
630 requirements
631 preserved: dotencode, fncache, generaldelta, largefiles, revlogv1, sparserevlog, store
631 preserved: dotencode, fncache, generaldelta, largefiles, revlogv1, sparserevlog, store
632
632
633 beginning upgrade...
633 beginning upgrade...
634 repository locked and read-only
634 repository locked and read-only
635 creating temporary repository to stage migrated data: $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
635 creating temporary repository to stage migrated data: $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
636 (it is safe to interrupt this process any time before data migration completes)
636 (it is safe to interrupt this process any time before data migration completes)
637 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
637 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
638 migrating 355 bytes in store; 160 bytes tracked data
638 migrating 355 bytes in store; 160 bytes tracked data
639 migrating 1 filelogs containing 1 revisions (106 bytes in store; 41 bytes tracked data)
639 migrating 1 filelogs containing 1 revisions (106 bytes in store; 41 bytes tracked data)
640 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
640 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
641 migrating 1 manifests containing 1 revisions (116 bytes in store; 51 bytes tracked data)
641 migrating 1 manifests containing 1 revisions (116 bytes in store; 51 bytes tracked data)
642 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
642 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
643 migrating changelog containing 1 revisions (133 bytes in store; 68 bytes tracked data)
643 migrating changelog containing 1 revisions (133 bytes in store; 68 bytes tracked data)
644 finished migrating 1 changelog revisions; change in size: 0 bytes
644 finished migrating 1 changelog revisions; change in size: 0 bytes
645 finished migrating 3 total revisions; total change in store size: 0 bytes
645 finished migrating 3 total revisions; total change in store size: 0 bytes
646 copying phaseroots
646 copying phaseroots
647 data fully migrated to temporary repository
647 data fully migrated to temporary repository
648 marking source repository as being upgraded; clients will be unable to read from repository
648 marking source repository as being upgraded; clients will be unable to read from repository
649 starting in-place swap of repository data
649 starting in-place swap of repository data
650 replaced files will be backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
650 replaced files will be backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
651 replacing store...
651 replacing store...
652 store replacement complete; repository was inconsistent for *s (glob)
652 store replacement complete; repository was inconsistent for *s (glob)
653 finalizing requirements file and making repository readable again
653 finalizing requirements file and making repository readable again
654 removing temporary repository $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
654 removing temporary repository $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
655 copy of old repository backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
655 copy of old repository backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
656 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
656 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
657 $ cat .hg/requires
657 $ cat .hg/requires
658 dotencode
658 dotencode
659 fncache
659 fncache
660 generaldelta
660 generaldelta
661 largefiles
661 largefiles
662 revlogv1
662 revlogv1
663 sparserevlog
663 sparserevlog
664 store
664 store
665
665
666 $ cat << EOF >> .hg/hgrc
666 $ cat << EOF >> .hg/hgrc
667 > [extensions]
667 > [extensions]
668 > lfs =
668 > lfs =
669 > [lfs]
669 > [lfs]
670 > threshold = 10
670 > threshold = 10
671 > EOF
671 > EOF
672 $ echo '123456789012345' > lfs.bin
672 $ echo '123456789012345' > lfs.bin
673 $ hg ci -Am 'lfs.bin'
673 $ hg ci -Am 'lfs.bin'
674 adding lfs.bin
674 adding lfs.bin
675 $ grep lfs .hg/requires
675 $ grep lfs .hg/requires
676 lfs
676 lfs
677 $ find .hg/store/lfs -type f
677 $ find .hg/store/lfs -type f
678 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
678 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
679
679
680 $ hg debugupgraderepo --run
680 $ hg debugupgraderepo --run
681 upgrade will perform the following actions:
681 upgrade will perform the following actions:
682
682
683 requirements
683 requirements
684 preserved: dotencode, fncache, generaldelta, largefiles, lfs, revlogv1, sparserevlog, store
684 preserved: dotencode, fncache, generaldelta, largefiles, lfs, revlogv1, sparserevlog, store
685
685
686 beginning upgrade...
686 beginning upgrade...
687 repository locked and read-only
687 repository locked and read-only
688 creating temporary repository to stage migrated data: $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
688 creating temporary repository to stage migrated data: $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
689 (it is safe to interrupt this process any time before data migration completes)
689 (it is safe to interrupt this process any time before data migration completes)
690 migrating 6 total revisions (2 in filelogs, 2 in manifests, 2 in changelog)
690 migrating 6 total revisions (2 in filelogs, 2 in manifests, 2 in changelog)
691 migrating 801 bytes in store; 467 bytes tracked data
691 migrating 801 bytes in store; 467 bytes tracked data
692 migrating 2 filelogs containing 2 revisions (296 bytes in store; 182 bytes tracked data)
692 migrating 2 filelogs containing 2 revisions (296 bytes in store; 182 bytes tracked data)
693 finished migrating 2 filelog revisions across 2 filelogs; change in size: 0 bytes
693 finished migrating 2 filelog revisions across 2 filelogs; change in size: 0 bytes
694 migrating 1 manifests containing 2 revisions (241 bytes in store; 151 bytes tracked data)
694 migrating 1 manifests containing 2 revisions (241 bytes in store; 151 bytes tracked data)
695 finished migrating 2 manifest revisions across 1 manifests; change in size: 0 bytes
695 finished migrating 2 manifest revisions across 1 manifests; change in size: 0 bytes
696 migrating changelog containing 2 revisions (264 bytes in store; 134 bytes tracked data)
696 migrating changelog containing 2 revisions (264 bytes in store; 134 bytes tracked data)
697 finished migrating 2 changelog revisions; change in size: 0 bytes
697 finished migrating 2 changelog revisions; change in size: 0 bytes
698 finished migrating 6 total revisions; total change in store size: 0 bytes
698 finished migrating 6 total revisions; total change in store size: 0 bytes
699 copying phaseroots
699 copying phaseroots
700 copying lfs blob d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
700 copying lfs blob d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
701 data fully migrated to temporary repository
701 data fully migrated to temporary repository
702 marking source repository as being upgraded; clients will be unable to read from repository
702 marking source repository as being upgraded; clients will be unable to read from repository
703 starting in-place swap of repository data
703 starting in-place swap of repository data
704 replaced files will be backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
704 replaced files will be backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
705 replacing store...
705 replacing store...
706 store replacement complete; repository was inconsistent for *s (glob)
706 store replacement complete; repository was inconsistent for *s (glob)
707 finalizing requirements file and making repository readable again
707 finalizing requirements file and making repository readable again
708 removing temporary repository $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
708 removing temporary repository $TESTTMP/largefilesrepo/.hg/upgrade.* (glob)
709 copy of old repository backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
709 copy of old repository backed up at $TESTTMP/largefilesrepo/.hg/upgradebackup.* (glob)
710 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
710 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
711
711
712 $ grep lfs .hg/requires
712 $ grep lfs .hg/requires
713 lfs
713 lfs
714 $ find .hg/store/lfs -type f
714 $ find .hg/store/lfs -type f
715 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
715 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
716 $ hg verify
716 $ hg verify
717 checking changesets
717 checking changesets
718 checking manifests
718 checking manifests
719 crosschecking files in changesets and manifests
719 crosschecking files in changesets and manifests
720 checking files
720 checking files
721 checked 2 changesets with 2 changes to 2 files
721 checked 2 changesets with 2 changes to 2 files
722 $ hg debugdata lfs.bin 0
722 $ hg debugdata lfs.bin 0
723 version https://git-lfs.github.com/spec/v1
723 version https://git-lfs.github.com/spec/v1
724 oid sha256:d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
724 oid sha256:d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
725 size 16
725 size 16
726 x-is-binary 0
726 x-is-binary 0
727
727
728 $ cd ..
728 $ cd ..
729
729
730 repository config is taken in account
730 repository config is taken in account
731 -------------------------------------
731 -------------------------------------
732
732
733 $ cat << EOF >> $HGRCPATH
733 $ cat << EOF >> $HGRCPATH
734 > [format]
734 > [format]
735 > maxchainlen = 1
735 > maxchainlen = 1
736 > EOF
736 > EOF
737
737
738 $ hg init localconfig
738 $ hg init localconfig
739 $ cd localconfig
739 $ cd localconfig
740 $ cat << EOF > file
740 $ cat << EOF > file
741 > some content
741 > some content
742 > with some length
742 > with some length
743 > to make sure we get a delta
743 > to make sure we get a delta
744 > after changes
744 > after changes
745 > very long
745 > very long
746 > very long
746 > very long
747 > very long
747 > very long
748 > very long
748 > very long
749 > very long
749 > very long
750 > very long
750 > very long
751 > very long
751 > very long
752 > very long
752 > very long
753 > very long
753 > very long
754 > very long
754 > very long
755 > very long
755 > very long
756 > EOF
756 > EOF
757 $ hg -q commit -A -m A
757 $ hg -q commit -A -m A
758 $ echo "new line" >> file
758 $ echo "new line" >> file
759 $ hg -q commit -m B
759 $ hg -q commit -m B
760 $ echo "new line" >> file
760 $ echo "new line" >> file
761 $ hg -q commit -m C
761 $ hg -q commit -m C
762
762
763 $ cat << EOF >> .hg/hgrc
763 $ cat << EOF >> .hg/hgrc
764 > [format]
764 > [format]
765 > maxchainlen = 9001
765 > maxchainlen = 9001
766 > EOF
766 > EOF
767 $ hg config format
767 $ hg config format
768 format.maxchainlen=9001
768 format.maxchainlen=9001
769 $ hg debugdeltachain file
769 $ hg debugdeltachain file
770 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
770 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
771 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
771 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
772 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
772 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
773 2 1 2 0 other 30 200 107 0.53500 128 21 0.19626 128 128 0.83594 1
773 2 1 2 0 other 30 200 107 0.53500 128 21 0.19626 128 128 0.83594 1
774
774
775 $ hg debugupgraderepo --run --optimize redeltaall
775 $ hg debugupgraderepo --run --optimize redeltaall
776 upgrade will perform the following actions:
776 upgrade will perform the following actions:
777
777
778 requirements
778 requirements
779 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
779 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
780
780
781 re-delta-all
781 re-delta-all
782 deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time
782 deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time
783
783
784 beginning upgrade...
784 beginning upgrade...
785 repository locked and read-only
785 repository locked and read-only
786 creating temporary repository to stage migrated data: $TESTTMP/localconfig/.hg/upgrade.* (glob)
786 creating temporary repository to stage migrated data: $TESTTMP/localconfig/.hg/upgrade.* (glob)
787 (it is safe to interrupt this process any time before data migration completes)
787 (it is safe to interrupt this process any time before data migration completes)
788 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
788 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
789 migrating 1019 bytes in store; 882 bytes tracked data
789 migrating 1019 bytes in store; 882 bytes tracked data
790 migrating 1 filelogs containing 3 revisions (320 bytes in store; 573 bytes tracked data)
790 migrating 1 filelogs containing 3 revisions (320 bytes in store; 573 bytes tracked data)
791 finished migrating 3 filelog revisions across 1 filelogs; change in size: -9 bytes
791 finished migrating 3 filelog revisions across 1 filelogs; change in size: -9 bytes
792 migrating 1 manifests containing 3 revisions (333 bytes in store; 138 bytes tracked data)
792 migrating 1 manifests containing 3 revisions (333 bytes in store; 138 bytes tracked data)
793 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
793 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
794 migrating changelog containing 3 revisions (366 bytes in store; 171 bytes tracked data)
794 migrating changelog containing 3 revisions (366 bytes in store; 171 bytes tracked data)
795 finished migrating 3 changelog revisions; change in size: 0 bytes
795 finished migrating 3 changelog revisions; change in size: 0 bytes
796 finished migrating 9 total revisions; total change in store size: -9 bytes
796 finished migrating 9 total revisions; total change in store size: -9 bytes
797 copying phaseroots
797 copying phaseroots
798 data fully migrated to temporary repository
798 data fully migrated to temporary repository
799 marking source repository as being upgraded; clients will be unable to read from repository
799 marking source repository as being upgraded; clients will be unable to read from repository
800 starting in-place swap of repository data
800 starting in-place swap of repository data
801 replaced files will be backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
801 replaced files will be backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
802 replacing store...
802 replacing store...
803 store replacement complete; repository was inconsistent for *s (glob)
803 store replacement complete; repository was inconsistent for *s (glob)
804 finalizing requirements file and making repository readable again
804 finalizing requirements file and making repository readable again
805 removing temporary repository $TESTTMP/localconfig/.hg/upgrade.* (glob)
805 removing temporary repository $TESTTMP/localconfig/.hg/upgrade.* (glob)
806 copy of old repository backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
806 copy of old repository backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
807 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
807 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
808 $ hg debugdeltachain file
808 $ hg debugdeltachain file
809 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
809 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
810 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
810 0 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
811 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
811 1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
812 2 1 3 1 p1 21 200 119 0.59500 119 0 0.00000 119 119 1.00000 1
812 2 1 3 1 p1 21 200 119 0.59500 119 0 0.00000 119 119 1.00000 1
813 $ cd ..
813 $ cd ..
814
814
815 $ cat << EOF >> $HGRCPATH
815 $ cat << EOF >> $HGRCPATH
816 > [format]
816 > [format]
817 > maxchainlen = 9001
817 > maxchainlen = 9001
818 > EOF
818 > EOF
819
819
820 Check upgrading a sparse-revlog repository
820 Check upgrading a sparse-revlog repository
821 ---------------------------------------
821 ---------------------------------------
822
822
823 $ hg init sparserevlogrepo --config format.sparse-revlog=no
823 $ hg init sparserevlogrepo --config format.sparse-revlog=no
824 $ cd sparserevlogrepo
824 $ cd sparserevlogrepo
825 $ touch foo
825 $ touch foo
826 $ hg add foo
826 $ hg add foo
827 $ hg -q commit -m "foo"
827 $ hg -q commit -m "foo"
828 $ cat .hg/requires
828 $ cat .hg/requires
829 dotencode
829 dotencode
830 fncache
830 fncache
831 generaldelta
831 generaldelta
832 revlogv1
832 revlogv1
833 store
833 store
834
834
835 Check that we can add the sparse-revlog format requirement
835 Check that we can add the sparse-revlog format requirement
836 $ hg --config format.sparse-revlog=yes debugupgraderepo --run >/dev/null
836 $ hg --config format.sparse-revlog=yes debugupgraderepo --run >/dev/null
837 copy of old repository backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
837 copy of old repository backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
838 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
838 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
839 $ cat .hg/requires
839 $ cat .hg/requires
840 dotencode
840 dotencode
841 fncache
841 fncache
842 generaldelta
842 generaldelta
843 revlogv1
843 revlogv1
844 sparserevlog
844 sparserevlog
845 store
845 store
846
846
847 Check that we can remove the sparse-revlog format requirement
847 Check that we can remove the sparse-revlog format requirement
848 $ hg --config format.sparse-revlog=no debugupgraderepo --run >/dev/null
848 $ hg --config format.sparse-revlog=no debugupgraderepo --run >/dev/null
849 copy of old repository backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
849 copy of old repository backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
850 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
850 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
851 $ cat .hg/requires
851 $ cat .hg/requires
852 dotencode
852 dotencode
853 fncache
853 fncache
854 generaldelta
854 generaldelta
855 revlogv1
855 revlogv1
856 store
856 store
857
858 #if zstd
859
860 Check upgrading to a zstd revlog
861 --------------------------------
862
863 upgrade
864
865 $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup >/dev/null
866 $ hg debugformat -v
867 format-variant repo config default
868 fncache: yes yes yes
869 dotencode: yes yes yes
870 generaldelta: yes yes yes
871 sparserevlog: yes yes yes
872 plain-cl-delta: yes yes yes
873 compression: zstd zlib zlib
874 compression-level: default default default
875 $ cat .hg/requires
876 dotencode
877 fncache
878 generaldelta
879 revlog-compression-zstd
880 revlogv1
881 sparserevlog
882 store
883
884 downgrade
885
886 $ hg debugupgraderepo --run --no-backup > /dev/null
887 $ hg debugformat -v
888 format-variant repo config default
889 fncache: yes yes yes
890 dotencode: yes yes yes
891 generaldelta: yes yes yes
892 sparserevlog: yes yes yes
893 plain-cl-delta: yes yes yes
894 compression: zlib zlib zlib
895 compression-level: default default default
896 $ cat .hg/requires
897 dotencode
898 fncache
899 generaldelta
900 revlogv1
901 sparserevlog
902 store
903
904 upgrade from hgrc
905
906 $ cat >> .hg/hgrc << EOF
907 > [format]
908 > revlog-compression=zstd
909 > EOF
910 $ hg debugupgraderepo --run --no-backup > /dev/null
911 $ hg debugformat -v
912 format-variant repo config default
913 fncache: yes yes yes
914 dotencode: yes yes yes
915 generaldelta: yes yes yes
916 sparserevlog: yes yes yes
917 plain-cl-delta: yes yes yes
918 compression: zstd zstd zlib
919 compression-level: default default default
920 $ cat .hg/requires
921 dotencode
922 fncache
923 generaldelta
924 revlog-compression-zstd
925 revlogv1
926 sparserevlog
927 store
928
857 $ cd ..
929 $ cd ..
930
931 #endif
General Comments 0
You need to be logged in to leave comments. Login now