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