##// END OF EJS Templates
upgrade: update only requirements if we can...
Pulkit Goyal -
r47097:f2c4224e default
parent child Browse files
Show More
@@ -1,538 +1,539
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 ..pycompat import getattr
14 14 from .. import (
15 15 changelog,
16 16 error,
17 17 filelog,
18 18 manifest,
19 19 metadata,
20 20 pycompat,
21 21 requirements,
22 22 revlog,
23 23 scmutil,
24 24 util,
25 25 vfs as vfsmod,
26 26 )
27 27
28 28
29 29 def _revlogfrompath(repo, path):
30 30 """Obtain a revlog from a repo path.
31 31
32 32 An instance of the appropriate class is returned.
33 33 """
34 34 if path == b'00changelog.i':
35 35 return changelog.changelog(repo.svfs)
36 36 elif path.endswith(b'00manifest.i'):
37 37 mandir = path[: -len(b'00manifest.i')]
38 38 return manifest.manifestrevlog(repo.svfs, tree=mandir)
39 39 else:
40 40 # reverse of "/".join(("data", path + ".i"))
41 41 return filelog.filelog(repo.svfs, path[5:-2])
42 42
43 43
44 44 def _copyrevlog(tr, destrepo, oldrl, unencodedname):
45 45 """copy all relevant files for `oldrl` into `destrepo` store
46 46
47 47 Files are copied "as is" without any transformation. The copy is performed
48 48 without extra checks. Callers are responsible for making sure the copied
49 49 content is compatible with format of the destination repository.
50 50 """
51 51 oldrl = getattr(oldrl, '_revlog', oldrl)
52 52 newrl = _revlogfrompath(destrepo, unencodedname)
53 53 newrl = getattr(newrl, '_revlog', newrl)
54 54
55 55 oldvfs = oldrl.opener
56 56 newvfs = newrl.opener
57 57 oldindex = oldvfs.join(oldrl.indexfile)
58 58 newindex = newvfs.join(newrl.indexfile)
59 59 olddata = oldvfs.join(oldrl.datafile)
60 60 newdata = newvfs.join(newrl.datafile)
61 61
62 62 with newvfs(newrl.indexfile, b'w'):
63 63 pass # create all the directories
64 64
65 65 util.copyfile(oldindex, newindex)
66 66 copydata = oldrl.opener.exists(oldrl.datafile)
67 67 if copydata:
68 68 util.copyfile(olddata, newdata)
69 69
70 70 if not (
71 71 unencodedname.endswith(b'00changelog.i')
72 72 or unencodedname.endswith(b'00manifest.i')
73 73 ):
74 74 destrepo.svfs.fncache.add(unencodedname)
75 75 if copydata:
76 76 destrepo.svfs.fncache.add(unencodedname[:-2] + b'.d')
77 77
78 78
79 79 UPGRADE_CHANGELOG = b"changelog"
80 80 UPGRADE_MANIFEST = b"manifest"
81 81 UPGRADE_FILELOGS = b"all-filelogs"
82 82
83 83 UPGRADE_ALL_REVLOGS = frozenset(
84 84 [UPGRADE_CHANGELOG, UPGRADE_MANIFEST, UPGRADE_FILELOGS]
85 85 )
86 86
87 87
88 88 def getsidedatacompanion(srcrepo, dstrepo):
89 89 sidedatacompanion = None
90 90 removedreqs = srcrepo.requirements - dstrepo.requirements
91 91 addedreqs = dstrepo.requirements - srcrepo.requirements
92 92 if requirements.SIDEDATA_REQUIREMENT in removedreqs:
93 93
94 94 def sidedatacompanion(rl, rev):
95 95 rl = getattr(rl, '_revlog', rl)
96 96 if rl.flags(rev) & revlog.REVIDX_SIDEDATA:
97 97 return True, (), {}, 0, 0
98 98 return False, (), {}, 0, 0
99 99
100 100 elif requirements.COPIESSDC_REQUIREMENT in addedreqs:
101 101 sidedatacompanion = metadata.getsidedataadder(srcrepo, dstrepo)
102 102 elif requirements.COPIESSDC_REQUIREMENT in removedreqs:
103 103 sidedatacompanion = metadata.getsidedataremover(srcrepo, dstrepo)
104 104 return sidedatacompanion
105 105
106 106
107 107 def matchrevlog(revlogfilter, entry):
108 108 """check if a revlog is selected for cloning.
109 109
110 110 In other words, are there any updates which need to be done on revlog
111 111 or it can be blindly copied.
112 112
113 113 The store entry is checked against the passed filter"""
114 114 if entry.endswith(b'00changelog.i'):
115 115 return UPGRADE_CHANGELOG in revlogfilter
116 116 elif entry.endswith(b'00manifest.i'):
117 117 return UPGRADE_MANIFEST in revlogfilter
118 118 return UPGRADE_FILELOGS in revlogfilter
119 119
120 120
121 121 def _perform_clone(
122 122 ui,
123 123 dstrepo,
124 124 tr,
125 125 old_revlog,
126 126 unencoded,
127 127 upgrade_op,
128 128 sidedatacompanion,
129 129 oncopiedrevision,
130 130 ):
131 131 """ returns the new revlog object created"""
132 132 newrl = None
133 133 if matchrevlog(upgrade_op.revlogs_to_process, unencoded):
134 134 ui.note(
135 135 _(b'cloning %d revisions from %s\n') % (len(old_revlog), unencoded)
136 136 )
137 137 newrl = _revlogfrompath(dstrepo, unencoded)
138 138 old_revlog.clone(
139 139 tr,
140 140 newrl,
141 141 addrevisioncb=oncopiedrevision,
142 142 deltareuse=upgrade_op.delta_reuse_mode,
143 143 forcedeltabothparents=upgrade_op.force_re_delta_both_parents,
144 144 sidedatacompanion=sidedatacompanion,
145 145 )
146 146 else:
147 147 msg = _(b'blindly copying %s containing %i revisions\n')
148 148 ui.note(msg % (unencoded, len(old_revlog)))
149 149 _copyrevlog(tr, dstrepo, old_revlog, unencoded)
150 150
151 151 newrl = _revlogfrompath(dstrepo, unencoded)
152 152 return newrl
153 153
154 154
155 155 def _clonerevlogs(
156 156 ui,
157 157 srcrepo,
158 158 dstrepo,
159 159 tr,
160 160 upgrade_op,
161 161 ):
162 162 """Copy revlogs between 2 repos."""
163 163 revcount = 0
164 164 srcsize = 0
165 165 srcrawsize = 0
166 166 dstsize = 0
167 167 fcount = 0
168 168 frevcount = 0
169 169 fsrcsize = 0
170 170 frawsize = 0
171 171 fdstsize = 0
172 172 mcount = 0
173 173 mrevcount = 0
174 174 msrcsize = 0
175 175 mrawsize = 0
176 176 mdstsize = 0
177 177 crevcount = 0
178 178 csrcsize = 0
179 179 crawsize = 0
180 180 cdstsize = 0
181 181
182 182 alldatafiles = list(srcrepo.store.walk())
183 183 # mapping of data files which needs to be cloned
184 184 # key is unencoded filename
185 185 # value is revlog_object_from_srcrepo
186 186 manifests = {}
187 187 changelogs = {}
188 188 filelogs = {}
189 189
190 190 # Perform a pass to collect metadata. This validates we can open all
191 191 # source files and allows a unified progress bar to be displayed.
192 192 for unencoded, encoded, size in alldatafiles:
193 193 if not unencoded.endswith(b'.i'):
194 194 continue
195 195
196 196 rl = _revlogfrompath(srcrepo, unencoded)
197 197
198 198 info = rl.storageinfo(
199 199 exclusivefiles=True,
200 200 revisionscount=True,
201 201 trackedsize=True,
202 202 storedsize=True,
203 203 )
204 204
205 205 revcount += info[b'revisionscount'] or 0
206 206 datasize = info[b'storedsize'] or 0
207 207 rawsize = info[b'trackedsize'] or 0
208 208
209 209 srcsize += datasize
210 210 srcrawsize += rawsize
211 211
212 212 # This is for the separate progress bars.
213 213 if isinstance(rl, changelog.changelog):
214 214 changelogs[unencoded] = rl
215 215 crevcount += len(rl)
216 216 csrcsize += datasize
217 217 crawsize += rawsize
218 218 elif isinstance(rl, manifest.manifestrevlog):
219 219 manifests[unencoded] = rl
220 220 mcount += 1
221 221 mrevcount += len(rl)
222 222 msrcsize += datasize
223 223 mrawsize += rawsize
224 224 elif isinstance(rl, filelog.filelog):
225 225 filelogs[unencoded] = rl
226 226 fcount += 1
227 227 frevcount += len(rl)
228 228 fsrcsize += datasize
229 229 frawsize += rawsize
230 230 else:
231 231 error.ProgrammingError(b'unknown revlog type')
232 232
233 233 if not revcount:
234 234 return
235 235
236 236 ui.status(
237 237 _(
238 238 b'migrating %d total revisions (%d in filelogs, %d in manifests, '
239 239 b'%d in changelog)\n'
240 240 )
241 241 % (revcount, frevcount, mrevcount, crevcount)
242 242 )
243 243 ui.status(
244 244 _(b'migrating %s in store; %s tracked data\n')
245 245 % ((util.bytecount(srcsize), util.bytecount(srcrawsize)))
246 246 )
247 247
248 248 # Used to keep track of progress.
249 249 progress = None
250 250
251 251 def oncopiedrevision(rl, rev, node):
252 252 progress.increment()
253 253
254 254 sidedatacompanion = getsidedatacompanion(srcrepo, dstrepo)
255 255
256 256 # Migrating filelogs
257 257 ui.status(
258 258 _(
259 259 b'migrating %d filelogs containing %d revisions '
260 260 b'(%s in store; %s tracked data)\n'
261 261 )
262 262 % (
263 263 fcount,
264 264 frevcount,
265 265 util.bytecount(fsrcsize),
266 266 util.bytecount(frawsize),
267 267 )
268 268 )
269 269 progress = srcrepo.ui.makeprogress(_(b'file revisions'), total=frevcount)
270 270 for unencoded, oldrl in sorted(filelogs.items()):
271 271 newrl = _perform_clone(
272 272 ui,
273 273 dstrepo,
274 274 tr,
275 275 oldrl,
276 276 unencoded,
277 277 upgrade_op,
278 278 sidedatacompanion,
279 279 oncopiedrevision,
280 280 )
281 281 info = newrl.storageinfo(storedsize=True)
282 282 fdstsize += info[b'storedsize'] or 0
283 283 ui.status(
284 284 _(
285 285 b'finished migrating %d filelog revisions across %d '
286 286 b'filelogs; change in size: %s\n'
287 287 )
288 288 % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize))
289 289 )
290 290
291 291 # Migrating manifests
292 292 ui.status(
293 293 _(
294 294 b'migrating %d manifests containing %d revisions '
295 295 b'(%s in store; %s tracked data)\n'
296 296 )
297 297 % (
298 298 mcount,
299 299 mrevcount,
300 300 util.bytecount(msrcsize),
301 301 util.bytecount(mrawsize),
302 302 )
303 303 )
304 304 if progress:
305 305 progress.complete()
306 306 progress = srcrepo.ui.makeprogress(
307 307 _(b'manifest revisions'), total=mrevcount
308 308 )
309 309 for unencoded, oldrl in sorted(manifests.items()):
310 310 newrl = _perform_clone(
311 311 ui,
312 312 dstrepo,
313 313 tr,
314 314 oldrl,
315 315 unencoded,
316 316 upgrade_op,
317 317 sidedatacompanion,
318 318 oncopiedrevision,
319 319 )
320 320 info = newrl.storageinfo(storedsize=True)
321 321 mdstsize += info[b'storedsize'] or 0
322 322 ui.status(
323 323 _(
324 324 b'finished migrating %d manifest revisions across %d '
325 325 b'manifests; change in size: %s\n'
326 326 )
327 327 % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize))
328 328 )
329 329
330 330 # Migrating changelog
331 331 ui.status(
332 332 _(
333 333 b'migrating changelog containing %d revisions '
334 334 b'(%s in store; %s tracked data)\n'
335 335 )
336 336 % (
337 337 crevcount,
338 338 util.bytecount(csrcsize),
339 339 util.bytecount(crawsize),
340 340 )
341 341 )
342 342 if progress:
343 343 progress.complete()
344 344 progress = srcrepo.ui.makeprogress(
345 345 _(b'changelog revisions'), total=crevcount
346 346 )
347 347 for unencoded, oldrl in sorted(changelogs.items()):
348 348 newrl = _perform_clone(
349 349 ui,
350 350 dstrepo,
351 351 tr,
352 352 oldrl,
353 353 unencoded,
354 354 upgrade_op,
355 355 sidedatacompanion,
356 356 oncopiedrevision,
357 357 )
358 358 info = newrl.storageinfo(storedsize=True)
359 359 cdstsize += info[b'storedsize'] or 0
360 360 progress.complete()
361 361 ui.status(
362 362 _(
363 363 b'finished migrating %d changelog revisions; change in size: '
364 364 b'%s\n'
365 365 )
366 366 % (crevcount, util.bytecount(cdstsize - csrcsize))
367 367 )
368 368
369 369 dstsize = fdstsize + mdstsize + cdstsize
370 370 ui.status(
371 371 _(
372 372 b'finished migrating %d total revisions; total change in store '
373 373 b'size: %s\n'
374 374 )
375 375 % (revcount, util.bytecount(dstsize - srcsize))
376 376 )
377 377
378 378
379 379 def _files_to_copy_post_revlog_clone(srcrepo):
380 380 """yields files which should be copied to destination after revlogs
381 381 are cloned"""
382 382 for path, kind, st in sorted(srcrepo.store.vfs.readdir(b'', stat=True)):
383 383 # don't copy revlogs as they are already cloned
384 384 if path.endswith((b'.i', b'.d', b'.n', b'.nd')):
385 385 continue
386 386 # Skip transaction related files.
387 387 if path.startswith(b'undo'):
388 388 continue
389 389 # Only copy regular files.
390 390 if kind != stat.S_IFREG:
391 391 continue
392 392 # Skip other skipped files.
393 393 if path in (b'lock', b'fncache'):
394 394 continue
395 395 # TODO: should we skip cache too?
396 396
397 397 yield path
398 398
399 399
400 400 def _replacestores(currentrepo, upgradedrepo, backupvfs, upgrade_op):
401 401 """Replace the stores after current repository is upgraded
402 402
403 403 Creates a backup of current repository store at backup path
404 404 Replaces upgraded store files in current repo from upgraded one
405 405
406 406 Arguments:
407 407 currentrepo: repo object of current repository
408 408 upgradedrepo: repo object of the upgraded data
409 409 backupvfs: vfs object for the backup path
410 410 upgrade_op: upgrade operation object
411 411 to be used to decide what all is upgraded
412 412 """
413 413 # TODO: don't blindly rename everything in store
414 414 # There can be upgrades where store is not touched at all
415 415 if upgrade_op.backup_store:
416 416 util.rename(currentrepo.spath, backupvfs.join(b'store'))
417 417 else:
418 418 currentrepo.vfs.rmtree(b'store', forcibly=True)
419 419 util.rename(upgradedrepo.spath, currentrepo.spath)
420 420
421 421
422 422 def finishdatamigration(ui, srcrepo, dstrepo, requirements):
423 423 """Hook point for extensions to perform additional actions during upgrade.
424 424
425 425 This function is called after revlogs and store files have been copied but
426 426 before the new store is swapped into the original location.
427 427 """
428 428
429 429
430 430 def upgrade(ui, srcrepo, dstrepo, upgrade_op):
431 431 """Do the low-level work of upgrading a repository.
432 432
433 433 The upgrade is effectively performed as a copy between a source
434 434 repository and a temporary destination repository.
435 435
436 436 The source repository is unmodified for as long as possible so the
437 437 upgrade can abort at any time without causing loss of service for
438 438 readers and without corrupting the source repository.
439 439 """
440 440 assert srcrepo.currentwlock()
441 441 assert dstrepo.currentwlock()
442 442 backuppath = None
443 443 backupvfs = None
444 444
445 445 ui.status(
446 446 _(
447 447 b'(it is safe to interrupt this process any time before '
448 448 b'data migration completes)\n'
449 449 )
450 450 )
451 451
452 if True:
452 if not upgrade_op.requirements_only:
453 453 with dstrepo.transaction(b'upgrade') as tr:
454 454 _clonerevlogs(
455 455 ui,
456 456 srcrepo,
457 457 dstrepo,
458 458 tr,
459 459 upgrade_op,
460 460 )
461 461
462 462 # Now copy other files in the store directory.
463 463 for p in _files_to_copy_post_revlog_clone(srcrepo):
464 464 srcrepo.ui.status(_(b'copying %s\n') % p)
465 465 src = srcrepo.store.rawvfs.join(p)
466 466 dst = dstrepo.store.rawvfs.join(p)
467 467 util.copyfile(src, dst, copystat=True)
468 468
469 469 finishdatamigration(ui, srcrepo, dstrepo, requirements)
470 470
471 471 ui.status(_(b'data fully upgraded in a temporary repository\n'))
472 472
473 473 if upgrade_op.backup_store:
474 474 backuppath = pycompat.mkdtemp(
475 475 prefix=b'upgradebackup.', dir=srcrepo.path
476 476 )
477 477 backupvfs = vfsmod.vfs(backuppath)
478 478
479 479 # Make a backup of requires file first, as it is the first to be modified.
480 480 util.copyfile(
481 481 srcrepo.vfs.join(b'requires'), backupvfs.join(b'requires')
482 482 )
483 483
484 484 # We install an arbitrary requirement that clients must not support
485 485 # as a mechanism to lock out new clients during the data swap. This is
486 486 # better than allowing a client to continue while the repository is in
487 487 # an inconsistent state.
488 488 ui.status(
489 489 _(
490 490 b'marking source repository as being upgraded; clients will be '
491 491 b'unable to read from repository\n'
492 492 )
493 493 )
494 494 scmutil.writereporequirements(
495 495 srcrepo, srcrepo.requirements | {b'upgradeinprogress'}
496 496 )
497 497
498 498 ui.status(_(b'starting in-place swap of repository data\n'))
499 499 if upgrade_op.backup_store:
500 500 ui.status(
501 501 _(b'replaced files will be backed up at %s\n') % backuppath
502 502 )
503 503
504 504 # Now swap in the new store directory. Doing it as a rename should make
505 505 # the operation nearly instantaneous and atomic (at least in well-behaved
506 506 # environments).
507 507 ui.status(_(b'replacing store...\n'))
508 508 tstart = util.timer()
509 509 _replacestores(srcrepo, dstrepo, backupvfs, upgrade_op)
510 510 elapsed = util.timer() - tstart
511 511 ui.status(
512 512 _(
513 513 b'store replacement complete; repository was inconsistent for '
514 514 b'%0.1fs\n'
515 515 )
516 516 % elapsed
517 517 )
518 518
519 519 # We first write the requirements file. Any new requirements will lock
520 520 # out legacy clients.
521 521 ui.status(
522 522 _(
523 523 b'finalizing requirements file and making repository readable '
524 524 b'again\n'
525 525 )
526 526 )
527 527 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
528 528
529 529 if upgrade_op.backup_store:
530 530 # The lock file from the old store won't be removed because nothing has a
531 531 # reference to its new location. So clean it up manually. Alternatively, we
532 532 # could update srcrepo.svfs and other variables to point to the new
533 533 # location. This is simpler.
534 534 backupvfs.unlink(b'store/lock')
535 535 else:
536 pass
536 ui.status(_(b'upgrading repository requirements\n'))
537 scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
537 538
538 539 return backuppath
@@ -1,626 +1,589
1 1 setup
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > share =
6 6 > [format]
7 7 > use-share-safe = True
8 8 > [storage]
9 9 > revlog.persistent-nodemap.slow-path=allow
10 10 > EOF
11 11
12 12 prepare source repo
13 13
14 14 $ hg init source
15 15 $ cd source
16 16 $ cat .hg/requires
17 17 share-safe
18 18 $ cat .hg/store/requires
19 19 dotencode
20 20 fncache
21 21 generaldelta
22 22 revlogv1
23 23 sparserevlog
24 24 store
25 25 $ hg debugrequirements
26 26 dotencode
27 27 fncache
28 28 generaldelta
29 29 revlogv1
30 30 share-safe
31 31 sparserevlog
32 32 store
33 33
34 34 $ echo a > a
35 35 $ hg ci -Aqm "added a"
36 36 $ echo b > b
37 37 $ hg ci -Aqm "added b"
38 38
39 39 $ HGEDITOR=cat hg config --shared
40 40 abort: repository is not shared; can't use --shared
41 41 [10]
42 42 $ cd ..
43 43
44 44 Create a shared repo and check the requirements are shared and read correctly
45 45 $ hg share source shared1
46 46 updating working directory
47 47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ cd shared1
49 49 $ cat .hg/requires
50 50 share-safe
51 51 shared
52 52
53 53 $ hg debugrequirements -R ../source
54 54 dotencode
55 55 fncache
56 56 generaldelta
57 57 revlogv1
58 58 share-safe
59 59 sparserevlog
60 60 store
61 61
62 62 $ hg debugrequirements
63 63 dotencode
64 64 fncache
65 65 generaldelta
66 66 revlogv1
67 67 share-safe
68 68 shared
69 69 sparserevlog
70 70 store
71 71
72 72 $ echo c > c
73 73 $ hg ci -Aqm "added c"
74 74
75 75 Check that config of the source repository is also loaded
76 76
77 77 $ hg showconfig ui.curses
78 78 [1]
79 79
80 80 $ echo "[ui]" >> ../source/.hg/hgrc
81 81 $ echo "curses=true" >> ../source/.hg/hgrc
82 82
83 83 $ hg showconfig ui.curses
84 84 true
85 85
86 86 Test that extensions of source repository are also loaded
87 87
88 88 $ hg debugextensions
89 89 share
90 90 $ hg extdiff -p echo
91 91 hg: unknown command 'extdiff'
92 92 'extdiff' is provided by the following extension:
93 93
94 94 extdiff command to allow external programs to compare revisions
95 95
96 96 (use 'hg help extensions' for information on enabling extensions)
97 97 [10]
98 98
99 99 $ echo "[extensions]" >> ../source/.hg/hgrc
100 100 $ echo "extdiff=" >> ../source/.hg/hgrc
101 101
102 102 $ hg debugextensions -R ../source
103 103 extdiff
104 104 share
105 105 $ hg extdiff -R ../source -p echo
106 106
107 107 BROKEN: the command below will not work if config of shared source is not loaded
108 108 on dispatch but debugextensions says that extension
109 109 is loaded
110 110 $ hg debugextensions
111 111 extdiff
112 112 share
113 113
114 114 $ hg extdiff -p echo
115 115
116 116 However, local .hg/hgrc should override the config set by share source
117 117
118 118 $ echo "[ui]" >> .hg/hgrc
119 119 $ echo "curses=false" >> .hg/hgrc
120 120
121 121 $ hg showconfig ui.curses
122 122 false
123 123
124 124 $ HGEDITOR=cat hg config --shared
125 125 [ui]
126 126 curses=true
127 127 [extensions]
128 128 extdiff=
129 129
130 130 $ HGEDITOR=cat hg config --local
131 131 [ui]
132 132 curses=false
133 133
134 134 Testing that hooks set in source repository also runs in shared repo
135 135
136 136 $ cd ../source
137 137 $ cat <<EOF >> .hg/hgrc
138 138 > [extensions]
139 139 > hooklib=
140 140 > [hooks]
141 141 > pretxnchangegroup.reject_merge_commits = \
142 142 > python:hgext.hooklib.reject_merge_commits.hook
143 143 > EOF
144 144
145 145 $ cd ..
146 146 $ hg clone source cloned
147 147 updating to branch default
148 148 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 149 $ cd cloned
150 150 $ hg up 0
151 151 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
152 152 $ echo bar > bar
153 153 $ hg ci -Aqm "added bar"
154 154 $ hg merge
155 155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 156 (branch merge, don't forget to commit)
157 157 $ hg ci -m "merge commit"
158 158
159 159 $ hg push ../source
160 160 pushing to ../source
161 161 searching for changes
162 162 adding changesets
163 163 adding manifests
164 164 adding file changes
165 165 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
166 166 transaction abort!
167 167 rollback completed
168 168 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
169 169 [255]
170 170
171 171 $ hg push ../shared1
172 172 pushing to ../shared1
173 173 searching for changes
174 174 adding changesets
175 175 adding manifests
176 176 adding file changes
177 177 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
178 178 transaction abort!
179 179 rollback completed
180 180 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
181 181 [255]
182 182
183 183 Test that if share source config is untrusted, we dont read it
184 184
185 185 $ cd ../shared1
186 186
187 187 $ cat << EOF > $TESTTMP/untrusted.py
188 188 > from mercurial import scmutil, util
189 189 > def uisetup(ui):
190 190 > class untrustedui(ui.__class__):
191 191 > def _trusted(self, fp, f):
192 192 > if util.normpath(fp.name).endswith(b'source/.hg/hgrc'):
193 193 > return False
194 194 > return super(untrustedui, self)._trusted(fp, f)
195 195 > ui.__class__ = untrustedui
196 196 > EOF
197 197
198 198 $ hg showconfig hooks
199 199 hooks.pretxnchangegroup.reject_merge_commits=python:hgext.hooklib.reject_merge_commits.hook
200 200
201 201 $ hg showconfig hooks --config extensions.untrusted=$TESTTMP/untrusted.py
202 202 [1]
203 203
204 204 Update the source repository format and check that shared repo works
205 205
206 206 $ cd ../source
207 207
208 208 Disable zstd related tests because its not present on pure version
209 209 #if zstd
210 210 $ echo "[format]" >> .hg/hgrc
211 211 $ echo "revlog-compression=zstd" >> .hg/hgrc
212 212
213 213 $ hg debugupgraderepo --run -q
214 214 upgrade will perform the following actions:
215 215
216 216 requirements
217 217 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store
218 218 added: revlog-compression-zstd
219 219
220 220 processed revlogs:
221 221 - all-filelogs
222 222 - changelog
223 223 - manifest
224 224
225 225 $ hg log -r .
226 226 changeset: 1:5f6d8a4bf34a
227 227 user: test
228 228 date: Thu Jan 01 00:00:00 1970 +0000
229 229 summary: added b
230 230
231 231 #endif
232 232 $ echo "[format]" >> .hg/hgrc
233 233 $ echo "use-persistent-nodemap=True" >> .hg/hgrc
234 234
235 235 $ hg debugupgraderepo --run -q -R ../shared1
236 236 abort: cannot upgrade repository; unsupported source requirement: shared
237 237 [255]
238 238
239 239 $ hg debugupgraderepo --run -q
240 240 upgrade will perform the following actions:
241 241
242 242 requirements
243 243 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd !)
244 244 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd !)
245 245 added: persistent-nodemap
246 246
247 247 processed revlogs:
248 248 - all-filelogs
249 249 - changelog
250 250 - manifest
251 251
252 252 $ hg log -r .
253 253 changeset: 1:5f6d8a4bf34a
254 254 user: test
255 255 date: Thu Jan 01 00:00:00 1970 +0000
256 256 summary: added b
257 257
258 258
259 259 Shared one should work
260 260 $ cd ../shared1
261 261 $ hg log -r .
262 262 changeset: 2:155349b645be
263 263 tag: tip
264 264 user: test
265 265 date: Thu Jan 01 00:00:00 1970 +0000
266 266 summary: added c
267 267
268 268
269 269 Testing that nonsharedrc is loaded for source and not shared
270 270
271 271 $ cd ../source
272 272 $ touch .hg/hgrc-not-shared
273 273 $ echo "[ui]" >> .hg/hgrc-not-shared
274 274 $ echo "traceback=true" >> .hg/hgrc-not-shared
275 275
276 276 $ hg showconfig ui.traceback
277 277 true
278 278
279 279 $ HGEDITOR=cat hg config --non-shared
280 280 [ui]
281 281 traceback=true
282 282
283 283 $ cd ../shared1
284 284 $ hg showconfig ui.traceback
285 285 [1]
286 286
287 287 Unsharing works
288 288
289 289 $ hg unshare
290 290
291 291 Test that source config is added to the shared one after unshare, and the config
292 292 of current repo is still respected over the config which came from source config
293 293 $ cd ../cloned
294 294 $ hg push ../shared1
295 295 pushing to ../shared1
296 296 searching for changes
297 297 adding changesets
298 298 adding manifests
299 299 adding file changes
300 300 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
301 301 transaction abort!
302 302 rollback completed
303 303 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
304 304 [255]
305 305 $ hg showconfig ui.curses -R ../shared1
306 306 false
307 307
308 308 $ cd ../
309 309
310 310 Test that upgrading using debugupgraderepo works
311 311 =================================================
312 312
313 313 $ hg init non-share-safe --config format.use-share-safe=false
314 314 $ cd non-share-safe
315 315 $ hg debugrequirements
316 316 dotencode
317 317 fncache
318 318 generaldelta
319 319 revlogv1
320 320 sparserevlog
321 321 store
322 322 $ echo foo > foo
323 323 $ hg ci -Aqm 'added foo'
324 324 $ echo bar > bar
325 325 $ hg ci -Aqm 'added bar'
326 326
327 327 Create a share before upgrading
328 328
329 329 $ cd ..
330 330 $ hg share non-share-safe nss-share
331 331 updating working directory
332 332 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 333 $ hg debugrequirements -R nss-share
334 334 dotencode
335 335 fncache
336 336 generaldelta
337 337 revlogv1
338 338 shared
339 339 sparserevlog
340 340 store
341 341 $ cd non-share-safe
342 342
343 343 Upgrade
344 344
345 345 $ hg debugupgraderepo -q
346 346 requirements
347 347 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
348 348 added: share-safe
349 349
350 350 processed revlogs:
351 351 - all-filelogs
352 352 - changelog
353 353 - manifest
354 354
355 355 $ hg debugupgraderepo --run
356 356 upgrade will perform the following actions:
357 357
358 358 requirements
359 359 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
360 360 added: share-safe
361 361
362 362 share-safe
363 363 Upgrades a repository to share-safe format so that future shares of this repository share its requirements and configs.
364 364
365 365 processed revlogs:
366 366 - all-filelogs
367 367 - changelog
368 368 - manifest
369 369
370 370 beginning upgrade...
371 371 repository locked and read-only
372 372 creating temporary repository to stage upgraded data: $TESTTMP/non-share-safe/.hg/upgrade.* (glob)
373 373 (it is safe to interrupt this process any time before data migration completes)
374 migrating 6 total revisions (2 in filelogs, 2 in manifests, 2 in changelog)
375 migrating 626 bytes in store; 271 bytes tracked data
376 migrating 2 filelogs containing 2 revisions (138 bytes in store; 8 bytes tracked data)
377 finished migrating 2 filelog revisions across 2 filelogs; change in size: 0 bytes
378 migrating 1 manifests containing 2 revisions (230 bytes in store; 135 bytes tracked data)
379 finished migrating 2 manifest revisions across 1 manifests; change in size: 0 bytes
380 migrating changelog containing 2 revisions (258 bytes in store; 128 bytes tracked data)
381 finished migrating 2 changelog revisions; change in size: 0 bytes
382 finished migrating 6 total revisions; total change in store size: 0 bytes
383 copying phaseroots
384 data fully upgraded in a temporary repository
385 marking source repository as being upgraded; clients will be unable to read from repository
386 starting in-place swap of repository data
387 replaced files will be backed up at $TESTTMP/non-share-safe/.hg/upgradebackup.* (glob)
388 replacing store...
389 store replacement complete; repository was inconsistent for *s (glob)
390 finalizing requirements file and making repository readable again
374 upgrading repository requirements
391 375 removing temporary repository $TESTTMP/non-share-safe/.hg/upgrade.* (glob)
392 copy of old repository backed up at $TESTTMP/non-share-safe/.hg/upgradebackup.* (glob)
393 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
394 376 repository upgraded to share safe mode, existing shares will still work in old non-safe mode. Re-share existing shares to use them in safe mode New shares will be created in safe mode.
395 377
396 378 $ hg debugrequirements
397 379 dotencode
398 380 fncache
399 381 generaldelta
400 382 revlogv1
401 383 share-safe
402 384 sparserevlog
403 385 store
404 386
405 387 $ cat .hg/requires
406 388 share-safe
407 389
408 390 $ cat .hg/store/requires
409 391 dotencode
410 392 fncache
411 393 generaldelta
412 394 revlogv1
413 395 sparserevlog
414 396 store
415 397
416 398 $ hg log -GT "{node}: {desc}\n"
417 399 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
418 400 |
419 401 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
420 402
421 403
422 404 Make sure existing shares dont work with default config
423 405
424 406 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
425 407 abort: version mismatch: source uses share-safe functionality while the current share does not
426 408 [255]
427 409
428 410
429 411 Create a safe share from upgrade one
430 412
431 413 $ cd ..
432 414 $ hg share non-share-safe ss-share
433 415 updating working directory
434 416 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
435 417 $ cd ss-share
436 418 $ hg log -GT "{node}: {desc}\n"
437 419 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
438 420 |
439 421 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
440 422
441 423 $ cd ../non-share-safe
442 424
443 425 Test that downgrading works too
444 426
445 427 $ cat >> $HGRCPATH <<EOF
446 428 > [extensions]
447 429 > share =
448 430 > [format]
449 431 > use-share-safe = False
450 432 > EOF
451 433
452 434 $ hg debugupgraderepo -q
453 435 requirements
454 436 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
455 437 removed: share-safe
456 438
457 439 processed revlogs:
458 440 - all-filelogs
459 441 - changelog
460 442 - manifest
461 443
462 444 $ hg debugupgraderepo --run
463 445 upgrade will perform the following actions:
464 446
465 447 requirements
466 448 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
467 449 removed: share-safe
468 450
469 451 processed revlogs:
470 452 - all-filelogs
471 453 - changelog
472 454 - manifest
473 455
474 456 beginning upgrade...
475 457 repository locked and read-only
476 458 creating temporary repository to stage upgraded data: $TESTTMP/non-share-safe/.hg/upgrade.* (glob)
477 459 (it is safe to interrupt this process any time before data migration completes)
478 migrating 6 total revisions (2 in filelogs, 2 in manifests, 2 in changelog)
479 migrating 626 bytes in store; 271 bytes tracked data
480 migrating 2 filelogs containing 2 revisions (138 bytes in store; 8 bytes tracked data)
481 finished migrating 2 filelog revisions across 2 filelogs; change in size: 0 bytes
482 migrating 1 manifests containing 2 revisions (230 bytes in store; 135 bytes tracked data)
483 finished migrating 2 manifest revisions across 1 manifests; change in size: 0 bytes
484 migrating changelog containing 2 revisions (258 bytes in store; 128 bytes tracked data)
485 finished migrating 2 changelog revisions; change in size: 0 bytes
486 finished migrating 6 total revisions; total change in store size: 0 bytes
487 copying phaseroots
488 copying requires
489 data fully upgraded in a temporary repository
490 marking source repository as being upgraded; clients will be unable to read from repository
491 starting in-place swap of repository data
492 replaced files will be backed up at $TESTTMP/non-share-safe/.hg/upgradebackup.* (glob)
493 replacing store...
494 store replacement complete; repository was inconsistent for *s (glob)
495 finalizing requirements file and making repository readable again
460 upgrading repository requirements
496 461 removing temporary repository $TESTTMP/non-share-safe/.hg/upgrade.* (glob)
497 copy of old repository backed up at $TESTTMP/non-share-safe/.hg/upgradebackup.* (glob)
498 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
499 462 repository downgraded to not use share safe mode, existing shares will not work and needs to be reshared.
500 463
501 464 $ hg debugrequirements
502 465 dotencode
503 466 fncache
504 467 generaldelta
505 468 revlogv1
506 469 sparserevlog
507 470 store
508 471
509 472 $ cat .hg/requires
510 473 dotencode
511 474 fncache
512 475 generaldelta
513 476 revlogv1
514 477 sparserevlog
515 478 store
516 479
517 480 $ test -f .hg/store/requires
518 481 [1]
519 482
520 483 $ hg log -GT "{node}: {desc}\n"
521 484 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
522 485 |
523 486 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
524 487
525 488
526 489 Make sure existing shares still works
527 490
528 491 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
529 492 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
530 493 |
531 494 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
532 495
533 496
534 497 $ hg log -GT "{node}: {desc}\n" -R ../ss-share
535 498 abort: share source does not support exp-sharesafe requirement
536 499 [255]
537 500
538 501 Testing automatic downgrade of shares when config is set
539 502
540 503 $ touch ../ss-share/.hg/wlock
541 504 $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config share.safe-mismatch.source-not-safe=downgrade-abort
542 505 abort: failed to downgrade share, got error: Lock held
543 506 [255]
544 507 $ rm ../ss-share/.hg/wlock
545 508
546 509 $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config share.safe-mismatch.source-not-safe=downgrade-abort
547 510 repository downgraded to not use share-safe mode
548 511 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
549 512 |
550 513 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
551 514
552 515
553 516 $ hg log -GT "{node}: {desc}\n" -R ../ss-share
554 517 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
555 518 |
556 519 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
557 520
558 521
559 522
560 523 Testing automatic upgrade of shares when config is set
561 524
562 525 $ hg debugupgraderepo -q --run --config format.use-share-safe=True
563 526 upgrade will perform the following actions:
564 527
565 528 requirements
566 529 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
567 530 added: share-safe
568 531
569 532 processed revlogs:
570 533 - all-filelogs
571 534 - changelog
572 535 - manifest
573 536
574 537 repository upgraded to share safe mode, existing shares will still work in old non-safe mode. Re-share existing shares to use them in safe mode New shares will be created in safe mode.
575 538 $ hg debugrequirements
576 539 dotencode
577 540 fncache
578 541 generaldelta
579 542 revlogv1
580 543 share-safe
581 544 sparserevlog
582 545 store
583 546 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
584 547 abort: version mismatch: source uses share-safe functionality while the current share does not
585 548 [255]
586 549
587 550 Check that if lock is taken, upgrade fails but read operation are successful
588 551 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgra
589 552 abort: share-safe mismatch with source.
590 553 Unrecognized value 'upgra' of `share.safe-mismatch.source-safe` set.
591 554 (run `hg help config.share.safe-mismatch.source-safe`)
592 555 [255]
593 556 $ touch ../nss-share/.hg/wlock
594 557 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-allow
595 558 failed to upgrade share, got error: Lock held
596 559 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
597 560 |
598 561 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
599 562
600 563
601 564 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-allow --config share.safe-mismatch.source-safe.warn=False
602 565 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
603 566 |
604 567 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
605 568
606 569
607 570 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-abort
608 571 abort: failed to upgrade share, got error: Lock held
609 572 [255]
610 573
611 574 $ rm ../nss-share/.hg/wlock
612 575 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-abort
613 576 repository upgraded to use share-safe mode
614 577 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
615 578 |
616 579 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
617 580
618 581
619 582 Test that unshare works
620 583
621 584 $ hg unshare -R ../nss-share
622 585 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
623 586 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
624 587 |
625 588 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
626 589
General Comments 0
You need to be logged in to leave comments. Login now