Mercurial > hg-stable
diff mercurial/dirstateguard.py @ 30497:751639bf6fc4
dirstateguard: move to new module so I can break some layering violations
Recently in a review I noticed that localrepo almost has no reason to
import cmdutil anymore. Also, cmdutil is a little on the enormous
side, so breaking this class out strikes me as a win.
author | Augie Fackler <augie@google.com> |
---|---|
date | Mon, 21 Nov 2016 21:29:32 -0500 |
parents | mercurial/cmdutil.py@39d13b8c101d |
children | ec306bc6915b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/dirstateguard.py Mon Nov 21 21:29:32 2016 -0500 @@ -0,0 +1,69 @@ +# dirstateguard.py - class to allow restoring dirstate after failure +# +# Copyright 2005-2007 Matt Mackall <mpm@selenic.com> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from __future__ import absolute_import + +from .i18n import _ + +from . import ( + error, +) + +class dirstateguard(object): + '''Restore dirstate at unexpected failure. + + At the construction, this class does: + + - write current ``repo.dirstate`` out, and + - save ``.hg/dirstate`` into the backup file + + This restores ``.hg/dirstate`` from backup file, if ``release()`` + is invoked before ``close()``. + + This just removes the backup file at ``close()`` before ``release()``. + ''' + + def __init__(self, repo, name): + self._repo = repo + self._active = False + self._closed = False + self._suffix = '.backup.%s.%d' % (name, id(self)) + repo.dirstate.savebackup(repo.currenttransaction(), self._suffix) + self._active = True + + def __del__(self): + if self._active: # still active + # this may occur, even if this class is used correctly: + # for example, releasing other resources like transaction + # may raise exception before ``dirstateguard.release`` in + # ``release(tr, ....)``. + self._abort() + + def close(self): + if not self._active: # already inactivated + msg = (_("can't close already inactivated backup: dirstate%s") + % self._suffix) + raise error.Abort(msg) + + self._repo.dirstate.clearbackup(self._repo.currenttransaction(), + self._suffix) + self._active = False + self._closed = True + + def _abort(self): + self._repo.dirstate.restorebackup(self._repo.currenttransaction(), + self._suffix) + self._active = False + + def release(self): + if not self._closed: + if not self._active: # already inactivated + msg = (_("can't release already inactivated backup:" + " dirstate%s") + % self._suffix) + raise error.Abort(msg) + self._abort()