From e75c4ca2d8d5ab2812968f4fe505d3854237fd12 Mon Sep 17 00:00:00 2001 From: Muir Manders Date: Mon, 10 Jan 2022 18:35:03 -0800 Subject: [PATCH] transaction: automatically clean up empty abandoned txs Summary: When creating a transaction we now automatically clean up an existing (abandoned) transaction if it is empty. This seems safe since recover() should be a no-op (other than cleaning up the tx files). I've seen multiple cases of empty transaction files due to commands crashing/being killed in a transaction (but before anything has been written). Reviewed By: quark-zju Differential Revision: D33482320 fbshipit-source-id: a6ef74a30de96c600385a701ab2ab61bb149afb9 --- eden/scm/edenscm/mercurial/localrepo.py | 21 +++++++++++++++------ eden/scm/tests/test-journal-exists.t | 9 ++++++++- eden/scm/tests/test-visibility.t | 2 +- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/eden/scm/edenscm/mercurial/localrepo.py b/eden/scm/edenscm/mercurial/localrepo.py index 1ed93f9a56..e16ecfabb5 100644 --- a/eden/scm/edenscm/mercurial/localrepo.py +++ b/eden/scm/edenscm/mercurial/localrepo.py @@ -1665,12 +1665,21 @@ class localrepository(object): if tr is not None: return tr.nest() - # abort here if the journal already exists - if self.svfs.exists("journal"): - raise errormod.AbandonedTransactionFoundError( - _("abandoned transaction found"), - hint=_("run 'hg recover' to clean up transaction"), - ) + try: + stat = self.svfs.stat("journal") + except FileNotFoundError: + # No existing transaction - this is the normal case. + pass + else: + if stat.st_size > 0: + # Non-empty transaction already exists - bail. + raise errormod.AbandonedTransactionFoundError( + _("abandoned transaction found"), + hint=_("run 'hg recover' to clean up transaction"), + ) + else: + self.ui.status(_("cleaning up empty abandoned transaction\n")) + self.recover() idbase = b"%.40f#%f" % (random.random(), time.time()) ha = hex(hashlib.sha1(idbase).digest()) diff --git a/eden/scm/tests/test-journal-exists.t b/eden/scm/tests/test-journal-exists.t index b16fd51085..2a7aab0063 100644 --- a/eden/scm/tests/test-journal-exists.t +++ b/eden/scm/tests/test-journal-exists.t @@ -9,7 +9,7 @@ $ newclientrepo foo test:repo_server book $ cd ../repo - $ touch .hg/store/journal + $ echo something > .hg/store/journal $ echo foo > a $ hg ci -Am0 @@ -19,3 +19,10 @@ $ hg recover rolling back interrupted transaction + couldn't read journal entry 'something\n'! + +Empty journal is cleaned up automatically. + $ touch .hg/store/journal + $ hg ci -Am0 + cleaning up empty abandoned transaction + rolling back interrupted transaction diff --git a/eden/scm/tests/test-visibility.t b/eden/scm/tests/test-visibility.t index c37d5cfa4f..f574245b6c 100644 --- a/eden/scm/tests/test-visibility.t +++ b/eden/scm/tests/test-visibility.t @@ -567,7 +567,7 @@ Migration up $ setconfig visibility.enabled=true (Test if the repo contains an abandoned transaction, the auto migration does not crash) - $ touch .hg/store/journal + $ echo something > .hg/store/journal $ hg debugedenimporthelper --get-manifest-node df4f53cec30af1e4f669102135076fd4f9673fcc switching to explicit tracking of visible commits 4e7eb8574ed56675aa89d2b5abbced12d5688cef