comparison mercurial/upgrade.py @ 44798:e295ba238bd8

upgrade: support the --quiet flag The command is currently very verbose with a various bit of output being time sensitive or randomized. The make invocation bulky and hard to match in the test. We move various message from `ui.write` to `ui.status` in order for the `--quiet` flag to have effect and helps the situation. As a side benefit, we can replace the various redirection to > /dev/null with the --quiet flag. Differential Revision: https://phab.mercurial-scm.org/D8429
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 15 Apr 2020 18:58:35 +0200
parents 5ee4b2119af9
children ea9563e9e65a
comparison
equal deleted inserted replaced
44797:5ee4b2119af9 44798:e295ba238bd8
805 error.ProgrammingError(b'unknown revlog type') 805 error.ProgrammingError(b'unknown revlog type')
806 806
807 if not revcount: 807 if not revcount:
808 return 808 return
809 809
810 ui.write( 810 ui.status(
811 _( 811 _(
812 b'migrating %d total revisions (%d in filelogs, %d in manifests, ' 812 b'migrating %d total revisions (%d in filelogs, %d in manifests, '
813 b'%d in changelog)\n' 813 b'%d in changelog)\n'
814 ) 814 )
815 % (revcount, frevcount, mrevcount, crevcount) 815 % (revcount, frevcount, mrevcount, crevcount)
816 ) 816 )
817 ui.write( 817 ui.status(
818 _(b'migrating %s in store; %s tracked data\n') 818 _(b'migrating %s in store; %s tracked data\n')
819 % ((util.bytecount(srcsize), util.bytecount(srcrawsize))) 819 % ((util.bytecount(srcsize), util.bytecount(srcrawsize)))
820 ) 820 )
821 821
822 # Used to keep track of progress. 822 # Used to keep track of progress.
835 continue 835 continue
836 836
837 oldrl = _revlogfrompath(srcrepo, unencoded) 837 oldrl = _revlogfrompath(srcrepo, unencoded)
838 838
839 if isinstance(oldrl, changelog.changelog) and b'c' not in seen: 839 if isinstance(oldrl, changelog.changelog) and b'c' not in seen:
840 ui.write( 840 ui.status(
841 _( 841 _(
842 b'finished migrating %d manifest revisions across %d ' 842 b'finished migrating %d manifest revisions across %d '
843 b'manifests; change in size: %s\n' 843 b'manifests; change in size: %s\n'
844 ) 844 )
845 % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize)) 845 % (mrevcount, mcount, util.bytecount(mdstsize - msrcsize))
846 ) 846 )
847 847
848 ui.write( 848 ui.status(
849 _( 849 _(
850 b'migrating changelog containing %d revisions ' 850 b'migrating changelog containing %d revisions '
851 b'(%s in store; %s tracked data)\n' 851 b'(%s in store; %s tracked data)\n'
852 ) 852 )
853 % ( 853 % (
859 seen.add(b'c') 859 seen.add(b'c')
860 progress = srcrepo.ui.makeprogress( 860 progress = srcrepo.ui.makeprogress(
861 _(b'changelog revisions'), total=crevcount 861 _(b'changelog revisions'), total=crevcount
862 ) 862 )
863 elif isinstance(oldrl, manifest.manifestrevlog) and b'm' not in seen: 863 elif isinstance(oldrl, manifest.manifestrevlog) and b'm' not in seen:
864 ui.write( 864 ui.status(
865 _( 865 _(
866 b'finished migrating %d filelog revisions across %d ' 866 b'finished migrating %d filelog revisions across %d '
867 b'filelogs; change in size: %s\n' 867 b'filelogs; change in size: %s\n'
868 ) 868 )
869 % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize)) 869 % (frevcount, fcount, util.bytecount(fdstsize - fsrcsize))
870 ) 870 )
871 871
872 ui.write( 872 ui.status(
873 _( 873 _(
874 b'migrating %d manifests containing %d revisions ' 874 b'migrating %d manifests containing %d revisions '
875 b'(%s in store; %s tracked data)\n' 875 b'(%s in store; %s tracked data)\n'
876 ) 876 )
877 % ( 877 % (
886 progress.complete() 886 progress.complete()
887 progress = srcrepo.ui.makeprogress( 887 progress = srcrepo.ui.makeprogress(
888 _(b'manifest revisions'), total=mrevcount 888 _(b'manifest revisions'), total=mrevcount
889 ) 889 )
890 elif b'f' not in seen: 890 elif b'f' not in seen:
891 ui.write( 891 ui.status(
892 _( 892 _(
893 b'migrating %d filelogs containing %d revisions ' 893 b'migrating %d filelogs containing %d revisions '
894 b'(%s in store; %s tracked data)\n' 894 b'(%s in store; %s tracked data)\n'
895 ) 895 )
896 % ( 896 % (
939 else: 939 else:
940 fdstsize += datasize 940 fdstsize += datasize
941 941
942 progress.complete() 942 progress.complete()
943 943
944 ui.write( 944 ui.status(
945 _( 945 _(
946 b'finished migrating %d changelog revisions; change in size: ' 946 b'finished migrating %d changelog revisions; change in size: '
947 b'%s\n' 947 b'%s\n'
948 ) 948 )
949 % (crevcount, util.bytecount(cdstsize - csrcsize)) 949 % (crevcount, util.bytecount(cdstsize - csrcsize))
950 ) 950 )
951 951
952 ui.write( 952 ui.status(
953 _( 953 _(
954 b'finished migrating %d total revisions; total change in store ' 954 b'finished migrating %d total revisions; total change in store '
955 b'size: %s\n' 955 b'size: %s\n'
956 ) 956 )
957 % (revcount, util.bytecount(dstsize - srcsize)) 957 % (revcount, util.bytecount(dstsize - srcsize))
1011 readers and without corrupting the source repository. 1011 readers and without corrupting the source repository.
1012 """ 1012 """
1013 assert srcrepo.currentwlock() 1013 assert srcrepo.currentwlock()
1014 assert dstrepo.currentwlock() 1014 assert dstrepo.currentwlock()
1015 1015
1016 ui.write( 1016 ui.status(
1017 _( 1017 _(
1018 b'(it is safe to interrupt this process any time before ' 1018 b'(it is safe to interrupt this process any time before '
1019 b'data migration completes)\n' 1019 b'data migration completes)\n'
1020 ) 1020 )
1021 ) 1021 )
1046 # The sorted() makes execution deterministic. 1046 # The sorted() makes execution deterministic.
1047 for p, kind, st in sorted(srcrepo.store.vfs.readdir(b'', stat=True)): 1047 for p, kind, st in sorted(srcrepo.store.vfs.readdir(b'', stat=True)):
1048 if not _filterstorefile(srcrepo, dstrepo, requirements, p, kind, st): 1048 if not _filterstorefile(srcrepo, dstrepo, requirements, p, kind, st):
1049 continue 1049 continue
1050 1050
1051 srcrepo.ui.write(_(b'copying %s\n') % p) 1051 srcrepo.ui.status(_(b'copying %s\n') % p)
1052 src = srcrepo.store.rawvfs.join(p) 1052 src = srcrepo.store.rawvfs.join(p)
1053 dst = dstrepo.store.rawvfs.join(p) 1053 dst = dstrepo.store.rawvfs.join(p)
1054 util.copyfile(src, dst, copystat=True) 1054 util.copyfile(src, dst, copystat=True)
1055 1055
1056 _finishdatamigration(ui, srcrepo, dstrepo, requirements) 1056 _finishdatamigration(ui, srcrepo, dstrepo, requirements)
1057 1057
1058 ui.write(_(b'data fully migrated to temporary repository\n')) 1058 ui.status(_(b'data fully migrated to temporary repository\n'))
1059 1059
1060 backuppath = pycompat.mkdtemp(prefix=b'upgradebackup.', dir=srcrepo.path) 1060 backuppath = pycompat.mkdtemp(prefix=b'upgradebackup.', dir=srcrepo.path)
1061 backupvfs = vfsmod.vfs(backuppath) 1061 backupvfs = vfsmod.vfs(backuppath)
1062 1062
1063 # Make a backup of requires file first, as it is the first to be modified. 1063 # Make a backup of requires file first, as it is the first to be modified.
1065 1065
1066 # We install an arbitrary requirement that clients must not support 1066 # We install an arbitrary requirement that clients must not support
1067 # as a mechanism to lock out new clients during the data swap. This is 1067 # as a mechanism to lock out new clients during the data swap. This is
1068 # better than allowing a client to continue while the repository is in 1068 # better than allowing a client to continue while the repository is in
1069 # an inconsistent state. 1069 # an inconsistent state.
1070 ui.write( 1070 ui.status(
1071 _( 1071 _(
1072 b'marking source repository as being upgraded; clients will be ' 1072 b'marking source repository as being upgraded; clients will be '
1073 b'unable to read from repository\n' 1073 b'unable to read from repository\n'
1074 ) 1074 )
1075 ) 1075 )
1076 scmutil.writerequires( 1076 scmutil.writerequires(
1077 srcrepo.vfs, srcrepo.requirements | {b'upgradeinprogress'} 1077 srcrepo.vfs, srcrepo.requirements | {b'upgradeinprogress'}
1078 ) 1078 )
1079 1079
1080 ui.write(_(b'starting in-place swap of repository data\n')) 1080 ui.status(_(b'starting in-place swap of repository data\n'))
1081 ui.write(_(b'replaced files will be backed up at %s\n') % backuppath) 1081 ui.status(_(b'replaced files will be backed up at %s\n') % backuppath)
1082 1082
1083 # Now swap in the new store directory. Doing it as a rename should make 1083 # Now swap in the new store directory. Doing it as a rename should make
1084 # the operation nearly instantaneous and atomic (at least in well-behaved 1084 # the operation nearly instantaneous and atomic (at least in well-behaved
1085 # environments). 1085 # environments).
1086 ui.write(_(b'replacing store...\n')) 1086 ui.status(_(b'replacing store...\n'))
1087 tstart = util.timer() 1087 tstart = util.timer()
1088 util.rename(srcrepo.spath, backupvfs.join(b'store')) 1088 util.rename(srcrepo.spath, backupvfs.join(b'store'))
1089 util.rename(dstrepo.spath, srcrepo.spath) 1089 util.rename(dstrepo.spath, srcrepo.spath)
1090 elapsed = util.timer() - tstart 1090 elapsed = util.timer() - tstart
1091 ui.write( 1091 ui.status(
1092 _( 1092 _(
1093 b'store replacement complete; repository was inconsistent for ' 1093 b'store replacement complete; repository was inconsistent for '
1094 b'%0.1fs\n' 1094 b'%0.1fs\n'
1095 ) 1095 )
1096 % elapsed 1096 % elapsed
1097 ) 1097 )
1098 1098
1099 # We first write the requirements file. Any new requirements will lock 1099 # We first write the requirements file. Any new requirements will lock
1100 # out legacy clients. 1100 # out legacy clients.
1101 ui.write( 1101 ui.status(
1102 _( 1102 _(
1103 b'finalizing requirements file and making repository readable ' 1103 b'finalizing requirements file and making repository readable '
1104 b'again\n' 1104 b'again\n'
1105 ) 1105 )
1106 ) 1106 )
1285 ) 1285 )
1286 ui.write(b'\n\n') 1286 ui.write(b'\n\n')
1287 1287
1288 def printupgradeactions(): 1288 def printupgradeactions():
1289 for a in actions: 1289 for a in actions:
1290 ui.write(b'%s\n %s\n\n' % (a.name, a.upgrademessage)) 1290 ui.status(b'%s\n %s\n\n' % (a.name, a.upgrademessage))
1291 1291
1292 if not run: 1292 if not run:
1293 fromconfig = [] 1293 fromconfig = []
1294 onlydefault = [] 1294 onlydefault = []
1295 1295
1300 onlydefault.append(d) 1300 onlydefault.append(d)
1301 1301
1302 if fromconfig or onlydefault: 1302 if fromconfig or onlydefault:
1303 1303
1304 if fromconfig: 1304 if fromconfig:
1305 ui.write( 1305 ui.status(
1306 _( 1306 _(
1307 b'repository lacks features recommended by ' 1307 b'repository lacks features recommended by '
1308 b'current config options:\n\n' 1308 b'current config options:\n\n'
1309 ) 1309 )
1310 ) 1310 )
1311 for i in fromconfig: 1311 for i in fromconfig:
1312 ui.write(b'%s\n %s\n\n' % (i.name, i.description)) 1312 ui.status(b'%s\n %s\n\n' % (i.name, i.description))
1313 1313
1314 if onlydefault: 1314 if onlydefault:
1315 ui.write( 1315 ui.status(
1316 _( 1316 _(
1317 b'repository lacks features used by the default ' 1317 b'repository lacks features used by the default '
1318 b'config options:\n\n' 1318 b'config options:\n\n'
1319 ) 1319 )
1320 ) 1320 )
1321 for i in onlydefault: 1321 for i in onlydefault:
1322 ui.write(b'%s\n %s\n\n' % (i.name, i.description)) 1322 ui.status(b'%s\n %s\n\n' % (i.name, i.description))
1323 1323
1324 ui.write(b'\n') 1324 ui.status(b'\n')
1325 else: 1325 else:
1326 ui.write( 1326 ui.status(
1327 _( 1327 _(
1328 b'(no feature deficiencies found in existing ' 1328 b'(no feature deficiencies found in existing '
1329 b'repository)\n' 1329 b'repository)\n'
1330 ) 1330 )
1331 ) 1331 )
1332 1332
1333 ui.write( 1333 ui.status(
1334 _( 1334 _(
1335 b'performing an upgrade with "--run" will make the following ' 1335 b'performing an upgrade with "--run" will make the following '
1336 b'changes:\n\n' 1336 b'changes:\n\n'
1337 ) 1337 )
1338 ) 1338 )
1342 printupgradeactions() 1342 printupgradeactions()
1343 1343
1344 unusedoptimize = [i for i in alloptimizations if i not in actions] 1344 unusedoptimize = [i for i in alloptimizations if i not in actions]
1345 1345
1346 if unusedoptimize: 1346 if unusedoptimize:
1347 ui.write( 1347 ui.status(
1348 _( 1348 _(
1349 b'additional optimizations are available by specifying ' 1349 b'additional optimizations are available by specifying '
1350 b'"--optimize <name>":\n\n' 1350 b'"--optimize <name>":\n\n'
1351 ) 1351 )
1352 ) 1352 )
1353 for i in unusedoptimize: 1353 for i in unusedoptimize:
1354 ui.write(_(b'%s\n %s\n\n') % (i.name, i.description)) 1354 ui.status(_(b'%s\n %s\n\n') % (i.name, i.description))
1355 return 1355 return
1356 1356
1357 # Else we're in the run=true case. 1357 # Else we're in the run=true case.
1358 ui.write(_(b'upgrade will perform the following actions:\n\n')) 1358 ui.write(_(b'upgrade will perform the following actions:\n\n'))
1359 printrequirements() 1359 printrequirements()
1360 printoptimisations() 1360 printoptimisations()
1361 printupgradeactions() 1361 printupgradeactions()
1362 1362
1363 upgradeactions = [a.name for a in actions] 1363 upgradeactions = [a.name for a in actions]
1364 1364
1365 ui.write(_(b'beginning upgrade...\n')) 1365 ui.status(_(b'beginning upgrade...\n'))
1366 with repo.wlock(), repo.lock(): 1366 with repo.wlock(), repo.lock():
1367 ui.write(_(b'repository locked and read-only\n')) 1367 ui.status(_(b'repository locked and read-only\n'))
1368 # Our strategy for upgrading the repository is to create a new, 1368 # Our strategy for upgrading the repository is to create a new,
1369 # temporary repository, write data to it, then do a swap of the 1369 # temporary repository, write data to it, then do a swap of the
1370 # data. There are less heavyweight ways to do this, but it is easier 1370 # data. There are less heavyweight ways to do this, but it is easier
1371 # to create a new repo object than to instantiate all the components 1371 # to create a new repo object than to instantiate all the components
1372 # (like the store) separately. 1372 # (like the store) separately.
1373 tmppath = pycompat.mkdtemp(prefix=b'upgrade.', dir=repo.path) 1373 tmppath = pycompat.mkdtemp(prefix=b'upgrade.', dir=repo.path)
1374 backuppath = None 1374 backuppath = None
1375 try: 1375 try:
1376 ui.write( 1376 ui.status(
1377 _( 1377 _(
1378 b'creating temporary repository to stage migrated ' 1378 b'creating temporary repository to stage migrated '
1379 b'data: %s\n' 1379 b'data: %s\n'
1380 ) 1380 )
1381 % tmppath 1381 % tmppath
1388 with dstrepo.wlock(), dstrepo.lock(): 1388 with dstrepo.wlock(), dstrepo.lock():
1389 backuppath = _upgraderepo( 1389 backuppath = _upgraderepo(
1390 ui, repo, dstrepo, newreqs, upgradeactions, revlogs=revlogs 1390 ui, repo, dstrepo, newreqs, upgradeactions, revlogs=revlogs
1391 ) 1391 )
1392 if not (backup or backuppath is None): 1392 if not (backup or backuppath is None):
1393 ui.write(_(b'removing old repository content%s\n') % backuppath) 1393 ui.status(
1394 _(b'removing old repository content%s\n') % backuppath
1395 )
1394 repo.vfs.rmtree(backuppath, forcibly=True) 1396 repo.vfs.rmtree(backuppath, forcibly=True)
1395 backuppath = None 1397 backuppath = None
1396 1398
1397 finally: 1399 finally:
1398 ui.write(_(b'removing temporary repository %s\n') % tmppath) 1400 ui.status(_(b'removing temporary repository %s\n') % tmppath)
1399 repo.vfs.rmtree(tmppath, forcibly=True) 1401 repo.vfs.rmtree(tmppath, forcibly=True)
1400 1402
1401 if backuppath: 1403 if backuppath and not ui.quiet:
1402 ui.warn( 1404 ui.warn(
1403 _(b'copy of old repository backed up at %s\n') % backuppath 1405 _(b'copy of old repository backed up at %s\n') % backuppath
1404 ) 1406 )
1405 ui.warn( 1407 ui.warn(
1406 _( 1408 _(