mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 22:37:37 +03:00
localrepo: silently recover from abandoned transaction
Summary: As we changed how Ctrl+C is handled, there would be more "abandoned transaction"s, just silently cleaned them up. Practically, we should never hit the "abandoned transaction found" case, because the `journal` file only contains how to truncate files to recover. Only legacy revlog uses file truncation and we don't use them in production. There might be a `journal.backupfiles` that tracks what files to rename to restore backup. Most of the key files like `bookmarks` are in metalog therefore no need to use backupfiles to restore. The remaining ones also seem fine to not restore in the old way: - dirstate: we use atomic replace on transaction close so it seems unnecessary to backup - fncache: not used by remotefilelog - phaseroots: not used when narrow-heads is on - commitcloudstate.<name>.<hash>: source of truth moved to metalog by D35232804 (3807e9662b
). - commitcloud/backedupheads.remote: used for "backed up" rendering in smartlog, not fatal if not restored. We might clean them up later. For now, let's just silently recover without printing the legacy messages. Note D33482320 (e75c4ca2d8
) is incorrect about `journal` being empty = no-op recover, since `journal.backupfiles` could be non-empty and trigger side effects on `recover`. Reviewed By: muirdm Differential Revision: D42912639 fbshipit-source-id: 8a576d2b73b2ffc053e4fc699f323a1f72498feb
This commit is contained in:
parent
58a05bb590
commit
ee4cd1bb2b
@ -1698,15 +1698,7 @@ class localrepository(object):
|
|||||||
# No existing transaction - this is the normal case.
|
# No existing transaction - this is the normal case.
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if stat.st_size > 0:
|
self.recover()
|
||||||
# Non-empty transaction already exists - bail.
|
|
||||||
raise errormod.AbandonedTransactionFoundError(
|
|
||||||
_("abandoned transaction found"),
|
|
||||||
hint=_("run '@prog@ 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())
|
idbase = b"%.40f#%f" % (random.random(), time.time())
|
||||||
ha = hex(hashlib.sha1(idbase).digest())
|
ha = hex(hashlib.sha1(idbase).digest())
|
||||||
@ -1959,7 +1951,7 @@ class localrepository(object):
|
|||||||
def recover(self):
|
def recover(self):
|
||||||
with self.lock():
|
with self.lock():
|
||||||
if self.svfs.exists("journal"):
|
if self.svfs.exists("journal"):
|
||||||
self.ui.status(_("rolling back interrupted transaction\n"))
|
self.ui.debug("rolling back interrupted transaction\n")
|
||||||
vfsmap = {
|
vfsmap = {
|
||||||
"": self.svfs,
|
"": self.svfs,
|
||||||
"shared": self.sharedvfs,
|
"shared": self.sharedvfs,
|
||||||
|
@ -10,20 +10,19 @@
|
|||||||
$ newclientrepo foo test:repo_server book
|
$ newclientrepo foo test:repo_server book
|
||||||
$ cd ../repo
|
$ cd ../repo
|
||||||
|
|
||||||
|
Journal is cleaned up automatically.
|
||||||
$ echo something > .hg/store/journal
|
$ echo something > .hg/store/journal
|
||||||
|
|
||||||
$ echo foo > a
|
$ echo foo > a
|
||||||
$ hg ci -Am0
|
$ hg ci -Am0
|
||||||
abort: abandoned transaction found!
|
couldn't read journal entry 'something\n'!
|
||||||
(run 'hg recover' to clean up transaction)
|
|
||||||
[255]
|
|
||||||
|
|
||||||
$ hg recover
|
$ hg recover
|
||||||
rolling back interrupted transaction
|
no interrupted transaction available
|
||||||
couldn't read journal entry 'something\n'!
|
[1]
|
||||||
|
|
||||||
Empty journal is cleaned up automatically.
|
Empty journal is cleaned up automatically.
|
||||||
$ touch .hg/store/journal
|
$ touch .hg/store/journal
|
||||||
$ hg ci -Am0
|
$ hg ci -Am0
|
||||||
cleaning up empty abandoned transaction
|
nothing changed
|
||||||
rolling back interrupted transaction
|
[1]
|
||||||
|
Loading…
Reference in New Issue
Block a user