dirstateguard.py
84 lines
| 2.6 KiB
| text/x-python
|
PythonLexer
/ mercurial / dirstateguard.py
Augie Fackler
|
r30488 | # dirstateguard.py - class to allow restoring dirstate after failure | ||
# | ||||
Raphaël Gomès
|
r47575 | # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com> | ||
Augie Fackler
|
r30488 | # | ||
# 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, | ||||
Martin von Zweigbergk
|
r38905 | narrowspec, | ||
Martin von Zweigbergk
|
r33790 | util, | ||
Augie Fackler
|
r30488 | ) | ||
Augie Fackler
|
r43345 | |||
Martin von Zweigbergk
|
r33790 | class dirstateguard(util.transactional): | ||
Augie Fackler
|
r46554 | """Restore dirstate at unexpected failure. | ||
Augie Fackler
|
r30488 | |||
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()``. | ||||
Augie Fackler
|
r46554 | """ | ||
Augie Fackler
|
r30488 | |||
def __init__(self, repo, name): | ||||
self._repo = repo | ||||
self._active = False | ||||
self._closed = False | ||||
Augie Fackler
|
r43347 | self._backupname = b'dirstate.backup.%s.%d' % (name, id(self)) | ||
self._narrowspecbackupname = b'narrowspec.backup.%s.%d' % ( | ||||
Augie Fackler
|
r43345 | name, | ||
id(self), | ||||
) | ||||
Adam Simpkins
|
r33440 | repo.dirstate.savebackup(repo.currenttransaction(), self._backupname) | ||
Martin von Zweigbergk
|
r41263 | narrowspec.savewcbackup(repo, self._narrowspecbackupname) | ||
Augie Fackler
|
r30488 | self._active = True | ||
def __del__(self): | ||||
Augie Fackler
|
r43345 | if self._active: # still active | ||
Augie Fackler
|
r30488 | # 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): | ||||
Augie Fackler
|
r43345 | if not self._active: # already inactivated | ||
msg = ( | ||||
Augie Fackler
|
r43347 | _(b"can't close already inactivated backup: %s") | ||
Augie Fackler
|
r43345 | % self._backupname | ||
) | ||||
Augie Fackler
|
r30488 | raise error.Abort(msg) | ||
Augie Fackler
|
r43345 | self._repo.dirstate.clearbackup( | ||
self._repo.currenttransaction(), self._backupname | ||||
) | ||||
Martin von Zweigbergk
|
r41263 | narrowspec.clearwcbackup(self._repo, self._narrowspecbackupname) | ||
Augie Fackler
|
r30488 | self._active = False | ||
self._closed = True | ||||
def _abort(self): | ||||
Martin von Zweigbergk
|
r41263 | narrowspec.restorewcbackup(self._repo, self._narrowspecbackupname) | ||
Augie Fackler
|
r43345 | self._repo.dirstate.restorebackup( | ||
self._repo.currenttransaction(), self._backupname | ||||
) | ||||
Augie Fackler
|
r30488 | self._active = False | ||
def release(self): | ||||
if not self._closed: | ||||
Augie Fackler
|
r43345 | if not self._active: # already inactivated | ||
msg = ( | ||||
Augie Fackler
|
r43347 | _(b"can't release already inactivated backup: %s") | ||
Augie Fackler
|
r43345 | % self._backupname | ||
) | ||||
Augie Fackler
|
r30488 | raise error.Abort(msg) | ||
self._abort() | ||||