Mercurial > hg
changeset 38527:6e0c66ef8cd0
repair: mark the critical section of strip() as unsafe
When our experimental nointerrupt feature is enabled, this will
help prevent users from corrupting their repo during a strip.
Differential Revision: https://phab.mercurial-scm.org/D3717
author | Augie Fackler <augie@google.com> |
---|---|
date | Mon, 11 Jun 2018 17:03:29 -0400 |
parents | 313a940d49a3 |
children | a1d5951efce7 |
files | mercurial/repair.py |
diffstat | 1 files changed, 64 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/repair.py Wed Jun 27 10:47:14 2018 -0400 +++ b/mercurial/repair.py Mon Jun 11 17:03:29 2018 -0400 @@ -186,76 +186,77 @@ tmpbundlefile = backupbundle(repo, savebases, saveheads, node, 'temp', compress=False, obsolescence=False) - try: - with repo.transaction("strip") as tr: - offset = len(tr.entries) + with ui.uninterruptable(): + try: + with repo.transaction("strip") as tr: + offset = len(tr.entries) - tr.startgroup() - cl.strip(striprev, tr) - stripmanifest(repo, striprev, tr, files) - - for fn in files: - repo.file(fn).strip(striprev, tr) - tr.endgroup() + tr.startgroup() + cl.strip(striprev, tr) + stripmanifest(repo, striprev, tr, files) - for i in xrange(offset, len(tr.entries)): - file, troffset, ignore = tr.entries[i] - with repo.svfs(file, 'a', checkambig=True) as fp: - fp.truncate(troffset) - if troffset == 0: - repo.store.markremoved(file) + for fn in files: + repo.file(fn).strip(striprev, tr) + tr.endgroup() - deleteobsmarkers(repo.obsstore, stripobsidx) - del repo.obsstore - repo.invalidatevolatilesets() - repo._phasecache.filterunknown(repo) + for i in xrange(offset, len(tr.entries)): + file, troffset, ignore = tr.entries[i] + with repo.svfs(file, 'a', checkambig=True) as fp: + fp.truncate(troffset) + if troffset == 0: + repo.store.markremoved(file) + + deleteobsmarkers(repo.obsstore, stripobsidx) + del repo.obsstore + repo.invalidatevolatilesets() + repo._phasecache.filterunknown(repo) - if tmpbundlefile: - ui.note(_("adding branch\n")) - f = vfs.open(tmpbundlefile, "rb") - gen = exchange.readbundle(ui, f, tmpbundlefile, vfs) - if not repo.ui.verbose: - # silence internal shuffling chatter - repo.ui.pushbuffer() - tmpbundleurl = 'bundle:' + vfs.join(tmpbundlefile) - txnname = 'strip' - if not isinstance(gen, bundle2.unbundle20): - txnname = "strip\n%s" % util.hidepassword(tmpbundleurl) - with repo.transaction(txnname) as tr: - bundle2.applybundle(repo, gen, tr, source='strip', - url=tmpbundleurl) - if not repo.ui.verbose: - repo.ui.popbuffer() - f.close() + if tmpbundlefile: + ui.note(_("adding branch\n")) + f = vfs.open(tmpbundlefile, "rb") + gen = exchange.readbundle(ui, f, tmpbundlefile, vfs) + if not repo.ui.verbose: + # silence internal shuffling chatter + repo.ui.pushbuffer() + tmpbundleurl = 'bundle:' + vfs.join(tmpbundlefile) + txnname = 'strip' + if not isinstance(gen, bundle2.unbundle20): + txnname = "strip\n%s" % util.hidepassword(tmpbundleurl) + with repo.transaction(txnname) as tr: + bundle2.applybundle(repo, gen, tr, source='strip', + url=tmpbundleurl) + if not repo.ui.verbose: + repo.ui.popbuffer() + f.close() - with repo.transaction('repair') as tr: - bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm] - bm.applychanges(repo, tr, bmchanges) + with repo.transaction('repair') as tr: + bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm] + bm.applychanges(repo, tr, bmchanges) - # remove undo files - for undovfs, undofile in repo.undofiles(): - try: - undovfs.unlink(undofile) - except OSError as e: - if e.errno != errno.ENOENT: - ui.warn(_('error removing %s: %s\n') % - (undovfs.join(undofile), - stringutil.forcebytestr(e))) + # remove undo files + for undovfs, undofile in repo.undofiles(): + try: + undovfs.unlink(undofile) + except OSError as e: + if e.errno != errno.ENOENT: + ui.warn(_('error removing %s: %s\n') % + (undovfs.join(undofile), + stringutil.forcebytestr(e))) - except: # re-raises - if backupfile: - ui.warn(_("strip failed, backup bundle stored in '%s'\n") - % vfs.join(backupfile)) - if tmpbundlefile: - ui.warn(_("strip failed, unrecovered changes stored in '%s'\n") - % vfs.join(tmpbundlefile)) - ui.warn(_("(fix the problem, then recover the changesets with " - "\"hg unbundle '%s'\")\n") % vfs.join(tmpbundlefile)) - raise - else: - if tmpbundlefile: - # Remove temporary bundle only if there were no exceptions - vfs.unlink(tmpbundlefile) + except: # re-raises + if backupfile: + ui.warn(_("strip failed, backup bundle stored in '%s'\n") + % vfs.join(backupfile)) + if tmpbundlefile: + ui.warn(_("strip failed, unrecovered changes stored in '%s'\n") + % vfs.join(tmpbundlefile)) + ui.warn(_("(fix the problem, then recover the changesets with " + "\"hg unbundle '%s'\")\n") % vfs.join(tmpbundlefile)) + raise + else: + if tmpbundlefile: + # Remove temporary bundle only if there were no exceptions + vfs.unlink(tmpbundlefile) repo.destroyed() # return the backup file path (or None if 'backup' was False) so