##// END OF EJS Templates
store: use boolean property for upgrade's matchrevlog
marmoute -
r51396:aede5746 default
parent child Browse files
Show More
@@ -1,668 +1,668 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
9 9 import stat
10 10
11 11 from ..i18n import _
12 12 from ..pycompat import getattr
13 13 from .. import (
14 14 changelog,
15 15 error,
16 16 filelog,
17 17 manifest,
18 18 metadata,
19 19 pycompat,
20 20 requirements,
21 21 scmutil,
22 22 store,
23 23 util,
24 24 vfs as vfsmod,
25 25 )
26 26 from ..revlogutils import (
27 27 constants as revlogconst,
28 28 flagutil,
29 29 nodemap,
30 30 sidedata as sidedatamod,
31 31 )
32 32 from . import actions as upgrade_actions
33 33
34 34
35 35 def get_sidedata_helpers(srcrepo, dstrepo):
36 36 use_w = srcrepo.ui.configbool(b'experimental', b'worker.repository-upgrade')
37 37 sequential = pycompat.iswindows or not use_w
38 38 if not sequential:
39 39 srcrepo.register_sidedata_computer(
40 40 revlogconst.KIND_CHANGELOG,
41 41 sidedatamod.SD_FILES,
42 42 (sidedatamod.SD_FILES,),
43 43 metadata._get_worker_sidedata_adder(srcrepo, dstrepo),
44 44 flagutil.REVIDX_HASCOPIESINFO,
45 45 replace=True,
46 46 )
47 47 return sidedatamod.get_sidedata_helpers(srcrepo, dstrepo._wanted_sidedata)
48 48
49 49
50 50 def _revlog_from_store_entry(repo, entry):
51 51 """Obtain a revlog from a repo store entry.
52 52
53 53 An instance of the appropriate class is returned.
54 54 """
55 55 if entry.is_changelog:
56 56 return changelog.changelog(repo.svfs)
57 57 elif entry.is_manifestlog:
58 58 mandir = entry.target_id.rstrip(b'/')
59 59 return manifest.manifestrevlog(
60 60 repo.nodeconstants, repo.svfs, tree=mandir
61 61 )
62 62 else:
63 63 return filelog.filelog(repo.svfs, entry.target_id)
64 64
65 65
66 66 def _copyrevlog(tr, destrepo, oldrl, entry):
67 67 """copy all relevant files for `oldrl` into `destrepo` store
68 68
69 69 Files are copied "as is" without any transformation. The copy is performed
70 70 without extra checks. Callers are responsible for making sure the copied
71 71 content is compatible with format of the destination repository.
72 72 """
73 73 oldrl = getattr(oldrl, '_revlog', oldrl)
74 74 newrl = _revlog_from_store_entry(destrepo, entry)
75 75 newrl = getattr(newrl, '_revlog', newrl)
76 76
77 77 oldvfs = oldrl.opener
78 78 newvfs = newrl.opener
79 79 oldindex = oldvfs.join(oldrl._indexfile)
80 80 newindex = newvfs.join(newrl._indexfile)
81 81 olddata = oldvfs.join(oldrl._datafile)
82 82 newdata = newvfs.join(newrl._datafile)
83 83
84 84 with newvfs(newrl._indexfile, b'w'):
85 85 pass # create all the directories
86 86
87 87 util.copyfile(oldindex, newindex)
88 88 copydata = oldrl.opener.exists(oldrl._datafile)
89 89 if copydata:
90 90 util.copyfile(olddata, newdata)
91 91
92 92 if entry.is_filelog:
93 93 unencodedname = entry.main_file_path()
94 94 destrepo.svfs.fncache.add(unencodedname)
95 95 if copydata:
96 96 destrepo.svfs.fncache.add(unencodedname[:-2] + b'.d')
97 97
98 98
99 99 UPGRADE_CHANGELOG = b"changelog"
100 100 UPGRADE_MANIFEST = b"manifest"
101 101 UPGRADE_FILELOGS = b"all-filelogs"
102 102
103 103 UPGRADE_ALL_REVLOGS = frozenset(
104 104 [UPGRADE_CHANGELOG, UPGRADE_MANIFEST, UPGRADE_FILELOGS]
105 105 )
106 106
107 107
108 def matchrevlog(revlogfilter, rl_type):
108 def matchrevlog(revlogfilter, entry):
109 109 """check if a revlog is selected for cloning.
110 110
111 111 In other words, are there any updates which need to be done on revlog
112 112 or it can be blindly copied.
113 113
114 114 The store entry is checked against the passed filter"""
115 if rl_type & store.FILEFLAGS_CHANGELOG:
115 if entry.is_changelog:
116 116 return UPGRADE_CHANGELOG in revlogfilter
117 elif rl_type & store.FILEFLAGS_MANIFESTLOG:
117 elif entry.is_manifestlog:
118 118 return UPGRADE_MANIFEST in revlogfilter
119 assert rl_type & store.FILEFLAGS_FILELOG
119 assert entry.is_filelog
120 120 return UPGRADE_FILELOGS in revlogfilter
121 121
122 122
123 123 def _perform_clone(
124 124 ui,
125 125 dstrepo,
126 126 tr,
127 127 old_revlog,
128 128 entry,
129 129 upgrade_op,
130 130 sidedata_helpers,
131 131 oncopiedrevision,
132 132 ):
133 133 """returns the new revlog object created"""
134 134 newrl = None
135 135 revlog_path = entry.main_file_path()
136 if matchrevlog(upgrade_op.revlogs_to_process, entry.revlog_type):
136 if matchrevlog(upgrade_op.revlogs_to_process, entry):
137 137 ui.note(
138 138 _(b'cloning %d revisions from %s\n')
139 139 % (len(old_revlog), revlog_path)
140 140 )
141 141 newrl = _revlog_from_store_entry(dstrepo, entry)
142 142 old_revlog.clone(
143 143 tr,
144 144 newrl,
145 145 addrevisioncb=oncopiedrevision,
146 146 deltareuse=upgrade_op.delta_reuse_mode,
147 147 forcedeltabothparents=upgrade_op.force_re_delta_both_parents,
148 148 sidedata_helpers=sidedata_helpers,
149 149 )
150 150 else:
151 151 msg = _(b'blindly copying %s containing %i revisions\n')
152 152 ui.note(msg % (revlog_path, len(old_revlog)))
153 153 _copyrevlog(tr, dstrepo, old_revlog, entry)
154 154
155 155 newrl = _revlog_from_store_entry(dstrepo, entry)
156 156 return newrl
157 157
158 158
159 159 def _clonerevlogs(
160 160 ui,
161 161 srcrepo,
162 162 dstrepo,
163 163 tr,
164 164 upgrade_op,
165 165 ):
166 166 """Copy revlogs between 2 repos."""
167 167 revcount = 0
168 168 srcsize = 0
169 169 srcrawsize = 0
170 170 dstsize = 0
171 171 fcount = 0
172 172 frevcount = 0
173 173 fsrcsize = 0
174 174 frawsize = 0
175 175 fdstsize = 0
176 176 mcount = 0
177 177 mrevcount = 0
178 178 msrcsize = 0
179 179 mrawsize = 0
180 180 mdstsize = 0
181 181 crevcount = 0
182 182 csrcsize = 0
183 183 crawsize = 0
184 184 cdstsize = 0
185 185
186 186 alldatafiles = list(srcrepo.store.walk())
187 187 # mapping of data files which needs to be cloned
188 188 # key is unencoded filename
189 189 # value is revlog_object_from_srcrepo
190 190 manifests = {}
191 191 changelogs = {}
192 192 filelogs = {}
193 193
194 194 # Perform a pass to collect metadata. This validates we can open all
195 195 # source files and allows a unified progress bar to be displayed.
196 196 for entry in alldatafiles:
197 197 if not entry.is_revlog:
198 198 continue
199 199
200 200 rl = _revlog_from_store_entry(srcrepo, entry)
201 201
202 202 info = rl.storageinfo(
203 203 exclusivefiles=True,
204 204 revisionscount=True,
205 205 trackedsize=True,
206 206 storedsize=True,
207 207 )
208 208
209 209 revcount += info[b'revisionscount'] or 0
210 210 datasize = info[b'storedsize'] or 0
211 211 rawsize = info[b'trackedsize'] or 0
212 212
213 213 srcsize += datasize
214 214 srcrawsize += rawsize
215 215
216 216 # This is for the separate progress bars.
217 217 if entry.is_changelog:
218 218 changelogs[entry.target_id] = entry
219 219 crevcount += len(rl)
220 220 csrcsize += datasize
221 221 crawsize += rawsize
222 222 elif entry.is_manifestlog:
223 223 manifests[entry.target_id] = entry
224 224 mcount += 1
225 225 mrevcount += len(rl)
226 226 msrcsize += datasize
227 227 mrawsize += rawsize
228 228 elif entry.is_filelog:
229 229 filelogs[entry.target_id] = entry
230 230 fcount += 1
231 231 frevcount += len(rl)
232 232 fsrcsize += datasize
233 233 frawsize += rawsize
234 234 else:
235 235 error.ProgrammingError(b'unknown revlog type')
236 236
237 237 if not revcount:
238 238 return
239 239
240 240 ui.status(
241 241 _(
242 242 b'migrating %d total revisions (%d in filelogs, %d in manifests, '
243 243 b'%d in changelog)\n'
244 244 )
245 245 % (revcount, frevcount, mrevcount, crevcount)
246 246 )
247 247 ui.status(
248 248 _(b'migrating %s in store; %s tracked data\n')
249 249 % ((util.bytecount(srcsize), util.bytecount(srcrawsize)))
250 250 )
251 251
252 252 # Used to keep track of progress.
253 253 progress = None
254 254
255 255 def oncopiedrevision(rl, rev, node):
256 256 progress.increment()
257 257
258 258 sidedata_helpers = get_sidedata_helpers(srcrepo, dstrepo)
259 259
260 260 # Migrating filelogs
261 261 ui.status(
262 262 _(
263 263 b'migrating %d filelogs containing %d revisions '
264 264 b'(%s in store; %s tracked data)\n'
265 265 )
266 266 % (
267 267 fcount,
268 268 frevcount,
269 269 util.bytecount(fsrcsize),
270 270 util.bytecount(frawsize),
271 271 )
272 272 )
273 273 progress = srcrepo.ui.makeprogress(_(b'file revisions'), total=frevcount)
274 274 for target_id, entry in sorted(filelogs.items()):
275 275 oldrl = _revlog_from_store_entry(srcrepo, entry)
276 276
277 277 newrl = _perform_clone(
278 278 ui,
279 279 dstrepo,
280 280 tr,
281 281 oldrl,
282 282 entry,
283 283 upgrade_op,
284 284 sidedata_helpers,
285 285 oncopiedrevision,
286 286 )
287 287 info = newrl.storageinfo(storedsize=True)
288 288 fdstsize += info[b'storedsize'] or 0
289 289 ui.status(
290 290 _(
291 291 b'finished migrating %d filelog revisions across %d '
292 292 b'filelogs; change in size: %s\n'
293 293 )
294 294 % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize))
295 295 )
296 296
297 297 # Migrating manifests
298 298 ui.status(
299 299 _(
300 300 b'migrating %d manifests containing %d revisions '
301 301 b'(%s in store; %s tracked data)\n'
302 302 )
303 303 % (
304 304 mcount,
305 305 mrevcount,
306 306 util.bytecount(msrcsize),
307 307 util.bytecount(mrawsize),
308 308 )
309 309 )
310 310 if progress:
311 311 progress.complete()
312 312 progress = srcrepo.ui.makeprogress(
313 313 _(b'manifest revisions'), total=mrevcount
314 314 )
315 315 for target_id, entry in sorted(manifests.items()):
316 316 oldrl = _revlog_from_store_entry(srcrepo, entry)
317 317 newrl = _perform_clone(
318 318 ui,
319 319 dstrepo,
320 320 tr,
321 321 oldrl,
322 322 entry,
323 323 upgrade_op,
324 324 sidedata_helpers,
325 325 oncopiedrevision,
326 326 )
327 327 info = newrl.storageinfo(storedsize=True)
328 328 mdstsize += info[b'storedsize'] or 0
329 329 ui.status(
330 330 _(
331 331 b'finished migrating %d manifest revisions across %d '
332 332 b'manifests; change in size: %s\n'
333 333 )
334 334 % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize))
335 335 )
336 336
337 337 # Migrating changelog
338 338 ui.status(
339 339 _(
340 340 b'migrating changelog containing %d revisions '
341 341 b'(%s in store; %s tracked data)\n'
342 342 )
343 343 % (
344 344 crevcount,
345 345 util.bytecount(csrcsize),
346 346 util.bytecount(crawsize),
347 347 )
348 348 )
349 349 if progress:
350 350 progress.complete()
351 351 progress = srcrepo.ui.makeprogress(
352 352 _(b'changelog revisions'), total=crevcount
353 353 )
354 354 for target_id, entry in sorted(changelogs.items()):
355 355 oldrl = _revlog_from_store_entry(srcrepo, entry)
356 356 newrl = _perform_clone(
357 357 ui,
358 358 dstrepo,
359 359 tr,
360 360 oldrl,
361 361 entry,
362 362 upgrade_op,
363 363 sidedata_helpers,
364 364 oncopiedrevision,
365 365 )
366 366 info = newrl.storageinfo(storedsize=True)
367 367 cdstsize += info[b'storedsize'] or 0
368 368 progress.complete()
369 369 ui.status(
370 370 _(
371 371 b'finished migrating %d changelog revisions; change in size: '
372 372 b'%s\n'
373 373 )
374 374 % (crevcount, util.bytecount(cdstsize - csrcsize))
375 375 )
376 376
377 377 dstsize = fdstsize + mdstsize + cdstsize
378 378 ui.status(
379 379 _(
380 380 b'finished migrating %d total revisions; total change in store '
381 381 b'size: %s\n'
382 382 )
383 383 % (revcount, util.bytecount(dstsize - srcsize))
384 384 )
385 385
386 386
387 387 def _files_to_copy_post_revlog_clone(srcrepo):
388 388 """yields files which should be copied to destination after revlogs
389 389 are cloned"""
390 390 for path, kind, st in sorted(srcrepo.store.vfs.readdir(b'', stat=True)):
391 391 # don't copy revlogs as they are already cloned
392 392 if store.revlog_type(path) is not None:
393 393 continue
394 394 # Skip transaction related files.
395 395 if path.startswith(b'undo'):
396 396 continue
397 397 # Only copy regular files.
398 398 if kind != stat.S_IFREG:
399 399 continue
400 400 # Skip other skipped files.
401 401 if path in (b'lock', b'fncache'):
402 402 continue
403 403 # TODO: should we skip cache too?
404 404
405 405 yield path
406 406
407 407
408 408 def _replacestores(currentrepo, upgradedrepo, backupvfs, upgrade_op):
409 409 """Replace the stores after current repository is upgraded
410 410
411 411 Creates a backup of current repository store at backup path
412 412 Replaces upgraded store files in current repo from upgraded one
413 413
414 414 Arguments:
415 415 currentrepo: repo object of current repository
416 416 upgradedrepo: repo object of the upgraded data
417 417 backupvfs: vfs object for the backup path
418 418 upgrade_op: upgrade operation object
419 419 to be used to decide what all is upgraded
420 420 """
421 421 # TODO: don't blindly rename everything in store
422 422 # There can be upgrades where store is not touched at all
423 423 if upgrade_op.backup_store:
424 424 util.rename(currentrepo.spath, backupvfs.join(b'store'))
425 425 else:
426 426 currentrepo.vfs.rmtree(b'store', forcibly=True)
427 427 util.rename(upgradedrepo.spath, currentrepo.spath)
428 428
429 429
430 430 def finishdatamigration(ui, srcrepo, dstrepo, requirements):
431 431 """Hook point for extensions to perform additional actions during upgrade.
432 432
433 433 This function is called after revlogs and store files have been copied but
434 434 before the new store is swapped into the original location.
435 435 """
436 436
437 437
438 438 def upgrade(ui, srcrepo, dstrepo, upgrade_op):
439 439 """Do the low-level work of upgrading a repository.
440 440
441 441 The upgrade is effectively performed as a copy between a source
442 442 repository and a temporary destination repository.
443 443
444 444 The source repository is unmodified for as long as possible so the
445 445 upgrade can abort at any time without causing loss of service for
446 446 readers and without corrupting the source repository.
447 447 """
448 448 assert srcrepo.currentwlock()
449 449 assert dstrepo.currentwlock()
450 450 backuppath = None
451 451 backupvfs = None
452 452
453 453 ui.status(
454 454 _(
455 455 b'(it is safe to interrupt this process any time before '
456 456 b'data migration completes)\n'
457 457 )
458 458 )
459 459
460 460 if upgrade_actions.dirstatev2 in upgrade_op.upgrade_actions:
461 461 ui.status(_(b'upgrading to dirstate-v2 from v1\n'))
462 462 upgrade_dirstate(ui, srcrepo, upgrade_op, b'v1', b'v2')
463 463 upgrade_op.upgrade_actions.remove(upgrade_actions.dirstatev2)
464 464
465 465 if upgrade_actions.dirstatev2 in upgrade_op.removed_actions:
466 466 ui.status(_(b'downgrading from dirstate-v2 to v1\n'))
467 467 upgrade_dirstate(ui, srcrepo, upgrade_op, b'v2', b'v1')
468 468 upgrade_op.removed_actions.remove(upgrade_actions.dirstatev2)
469 469
470 470 if upgrade_actions.dirstatetrackedkey in upgrade_op.upgrade_actions:
471 471 ui.status(_(b'create dirstate-tracked-hint file\n'))
472 472 upgrade_tracked_hint(ui, srcrepo, upgrade_op, add=True)
473 473 upgrade_op.upgrade_actions.remove(upgrade_actions.dirstatetrackedkey)
474 474 elif upgrade_actions.dirstatetrackedkey in upgrade_op.removed_actions:
475 475 ui.status(_(b'remove dirstate-tracked-hint file\n'))
476 476 upgrade_tracked_hint(ui, srcrepo, upgrade_op, add=False)
477 477 upgrade_op.removed_actions.remove(upgrade_actions.dirstatetrackedkey)
478 478
479 479 if not (upgrade_op.upgrade_actions or upgrade_op.removed_actions):
480 480 return
481 481
482 482 if upgrade_op.requirements_only:
483 483 ui.status(_(b'upgrading repository requirements\n'))
484 484 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
485 485 # if there is only one action and that is persistent nodemap upgrade
486 486 # directly write the nodemap file and update requirements instead of going
487 487 # through the whole cloning process
488 488 elif (
489 489 len(upgrade_op.upgrade_actions) == 1
490 490 and b'persistent-nodemap' in upgrade_op.upgrade_actions_names
491 491 and not upgrade_op.removed_actions
492 492 ):
493 493 ui.status(
494 494 _(b'upgrading repository to use persistent nodemap feature\n')
495 495 )
496 496 with srcrepo.transaction(b'upgrade') as tr:
497 497 unfi = srcrepo.unfiltered()
498 498 cl = unfi.changelog
499 499 nodemap.persist_nodemap(tr, cl, force=True)
500 500 # we want to directly operate on the underlying revlog to force
501 501 # create a nodemap file. This is fine since this is upgrade code
502 502 # and it heavily relies on repository being revlog based
503 503 # hence accessing private attributes can be justified
504 504 nodemap.persist_nodemap(
505 505 tr, unfi.manifestlog._rootstore._revlog, force=True
506 506 )
507 507 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
508 508 elif (
509 509 len(upgrade_op.removed_actions) == 1
510 510 and [
511 511 x
512 512 for x in upgrade_op.removed_actions
513 513 if x.name == b'persistent-nodemap'
514 514 ]
515 515 and not upgrade_op.upgrade_actions
516 516 ):
517 517 ui.status(
518 518 _(b'downgrading repository to not use persistent nodemap feature\n')
519 519 )
520 520 with srcrepo.transaction(b'upgrade') as tr:
521 521 unfi = srcrepo.unfiltered()
522 522 cl = unfi.changelog
523 523 nodemap.delete_nodemap(tr, srcrepo, cl)
524 524 # check comment 20 lines above for accessing private attributes
525 525 nodemap.delete_nodemap(
526 526 tr, srcrepo, unfi.manifestlog._rootstore._revlog
527 527 )
528 528 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
529 529 else:
530 530 with dstrepo.transaction(b'upgrade') as tr:
531 531 _clonerevlogs(
532 532 ui,
533 533 srcrepo,
534 534 dstrepo,
535 535 tr,
536 536 upgrade_op,
537 537 )
538 538
539 539 # Now copy other files in the store directory.
540 540 for p in _files_to_copy_post_revlog_clone(srcrepo):
541 541 srcrepo.ui.status(_(b'copying %s\n') % p)
542 542 src = srcrepo.store.rawvfs.join(p)
543 543 dst = dstrepo.store.rawvfs.join(p)
544 544 util.copyfile(src, dst, copystat=True)
545 545
546 546 finishdatamigration(ui, srcrepo, dstrepo, requirements)
547 547
548 548 ui.status(_(b'data fully upgraded in a temporary repository\n'))
549 549
550 550 if upgrade_op.backup_store:
551 551 backuppath = pycompat.mkdtemp(
552 552 prefix=b'upgradebackup.', dir=srcrepo.path
553 553 )
554 554 backupvfs = vfsmod.vfs(backuppath)
555 555
556 556 # Make a backup of requires file first, as it is the first to be modified.
557 557 util.copyfile(
558 558 srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires')
559 559 )
560 560
561 561 # We install an arbitrary requirement that clients must not support
562 562 # as a mechanism to lock out new clients during the data swap. This is
563 563 # better than allowing a client to continue while the repository is in
564 564 # an inconsistent state.
565 565 ui.status(
566 566 _(
567 567 b'marking source repository as being upgraded; clients will be '
568 568 b'unable to read from repository\n'
569 569 )
570 570 )
571 571 scmutil.writereporequirements(
572 572 srcrepo, srcrepo.requirements | {b'upgradeinprogress'}
573 573 )
574 574
575 575 ui.status(_(b'starting in-place swap of repository data\n'))
576 576 if upgrade_op.backup_store:
577 577 ui.status(
578 578 _(b'replaced files will be backed up at %s\n') % backuppath
579 579 )
580 580
581 581 # Now swap in the new store directory. Doing it as a rename should make
582 582 # the operation nearly instantaneous and atomic (at least in well-behaved
583 583 # environments).
584 584 ui.status(_(b'replacing store...\n'))
585 585 tstart = util.timer()
586 586 _replacestores(srcrepo, dstrepo, backupvfs, upgrade_op)
587 587 elapsed = util.timer() - tstart
588 588 ui.status(
589 589 _(
590 590 b'store replacement complete; repository was inconsistent for '
591 591 b'%0.1fs\n'
592 592 )
593 593 % elapsed
594 594 )
595 595
596 596 # We first write the requirements file. Any new requirements will lock
597 597 # out legacy clients.
598 598 ui.status(
599 599 _(
600 600 b'finalizing requirements file and making repository readable '
601 601 b'again\n'
602 602 )
603 603 )
604 604 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
605 605
606 606 if upgrade_op.backup_store:
607 607 # The lock file from the old store won't be removed because nothing has a
608 608 # reference to its new location. So clean it up manually. Alternatively, we
609 609 # could update srcrepo.svfs and other variables to point to the new
610 610 # location. This is simpler.
611 611 assert backupvfs is not None # help pytype
612 612 backupvfs.unlink(b'store/lock')
613 613
614 614 return backuppath
615 615
616 616
617 617 def upgrade_dirstate(ui, srcrepo, upgrade_op, old, new):
618 618 if upgrade_op.backup_store:
619 619 backuppath = pycompat.mkdtemp(
620 620 prefix=b'upgradebackup.', dir=srcrepo.path
621 621 )
622 622 ui.status(_(b'replaced files will be backed up at %s\n') % backuppath)
623 623 backupvfs = vfsmod.vfs(backuppath)
624 624 util.copyfile(
625 625 srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires')
626 626 )
627 627 try:
628 628 util.copyfile(
629 629 srcrepo.vfs.join(b'dirstate'), backupvfs.join(b'dirstate')
630 630 )
631 631 except FileNotFoundError:
632 632 # The dirstate does not exist on an empty repo or a repo with no
633 633 # revision checked out
634 634 pass
635 635
636 636 assert srcrepo.dirstate._use_dirstate_v2 == (old == b'v2')
637 637 use_v2 = new == b'v2'
638 638 if use_v2:
639 639 # Write the requirements *before* upgrading
640 640 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
641 641
642 642 srcrepo.dirstate._map.preload()
643 643 srcrepo.dirstate._use_dirstate_v2 = use_v2
644 644 srcrepo.dirstate._map._use_dirstate_v2 = use_v2
645 645 srcrepo.dirstate._dirty = True
646 646 try:
647 647 srcrepo.vfs.unlink(b'dirstate')
648 648 except FileNotFoundError:
649 649 # The dirstate does not exist on an empty repo or a repo with no
650 650 # revision checked out
651 651 pass
652 652
653 653 srcrepo.dirstate.write(None)
654 654 if not use_v2:
655 655 # Remove the v2 requirement *after* downgrading
656 656 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
657 657
658 658
659 659 def upgrade_tracked_hint(ui, srcrepo, upgrade_op, add):
660 660 if add:
661 661 srcrepo.dirstate._use_tracked_hint = True
662 662 srcrepo.dirstate._dirty = True
663 663 srcrepo.dirstate._dirty_tracked_set = True
664 664 srcrepo.dirstate.write(None)
665 665 if not add:
666 666 srcrepo.dirstate.delete_tracked_hint()
667 667
668 668 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
General Comments 0
You need to be logged in to leave comments. Login now