Show More
@@ -3259,3 +3259,59 b' def clearunfinished(repo):' | |||||
3259 | for f, clearable, allowcommit, msg, hint in unfinishedstates: |
|
3259 | for f, clearable, allowcommit, msg, hint in unfinishedstates: | |
3260 | if clearable and repo.vfs.exists(f): |
|
3260 | if clearable and repo.vfs.exists(f): | |
3261 | util.unlink(repo.join(f)) |
|
3261 | util.unlink(repo.join(f)) | |
|
3262 | ||||
|
3263 | class dirstateguard(object): | |||
|
3264 | '''Restore dirstate at unexpected failure. | |||
|
3265 | ||||
|
3266 | At the construction, this class does: | |||
|
3267 | ||||
|
3268 | - write current ``repo.dirstate`` out, and | |||
|
3269 | - save ``.hg/dirstate`` into the backup file | |||
|
3270 | ||||
|
3271 | This restores ``.hg/dirstate`` from backup file, if ``release()`` | |||
|
3272 | is invoked before ``close()``. | |||
|
3273 | ||||
|
3274 | This just removes the backup file at ``close()`` before ``release()``. | |||
|
3275 | ''' | |||
|
3276 | ||||
|
3277 | def __init__(self, repo, name): | |||
|
3278 | repo.dirstate.write() | |||
|
3279 | self._repo = repo | |||
|
3280 | self._filename = 'dirstate.backup.%s.%d' % (name, id(self)) | |||
|
3281 | repo.vfs.write(self._filename, repo.vfs.tryread('dirstate')) | |||
|
3282 | self._active = True | |||
|
3283 | self._closed = False | |||
|
3284 | ||||
|
3285 | def __del__(self): | |||
|
3286 | if self._active: # still active | |||
|
3287 | # this may occur, even if this class is used correctly: | |||
|
3288 | # for example, releasing other resources like transaction | |||
|
3289 | # may raise exception before ``dirstateguard.release`` in | |||
|
3290 | # ``release(tr, ....)``. | |||
|
3291 | self._abort() | |||
|
3292 | ||||
|
3293 | def close(self): | |||
|
3294 | if not self._active: # already inactivated | |||
|
3295 | msg = (_("can't close already inactivated backup: %s") | |||
|
3296 | % self._filename) | |||
|
3297 | raise util.Abort(msg) | |||
|
3298 | ||||
|
3299 | self._repo.vfs.unlink(self._filename) | |||
|
3300 | self._active = False | |||
|
3301 | self._closed = True | |||
|
3302 | ||||
|
3303 | def _abort(self): | |||
|
3304 | # this "invalidate()" prevents "wlock.release()" from writing | |||
|
3305 | # changes of dirstate out after restoring to original status | |||
|
3306 | self._repo.dirstate.invalidate() | |||
|
3307 | ||||
|
3308 | self._repo.vfs.rename(self._filename, 'dirstate') | |||
|
3309 | self._active = False | |||
|
3310 | ||||
|
3311 | def release(self): | |||
|
3312 | if not self._closed: | |||
|
3313 | if not self._active: # already inactivated | |||
|
3314 | msg = (_("can't release already inactivated backup: %s") | |||
|
3315 | % self._filename) | |||
|
3316 | raise util.Abort(msg) | |||
|
3317 | self._abort() |
General Comments 0
You need to be logged in to leave comments.
Login now