Show More
@@ -1,84 +1,97 b'' | |||||
1 | # dirstateguard.py - class to allow restoring dirstate after failure |
|
1 | # dirstateguard.py - class to allow restoring dirstate after failure | |
2 | # |
|
2 | # | |
3 | # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com> |
|
3 | # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com> | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
|
10 | import os | |||
10 | from .i18n import _ |
|
11 | from .i18n import _ | |
11 |
|
12 | |||
12 | from . import ( |
|
13 | from . import ( | |
13 | error, |
|
14 | error, | |
14 | narrowspec, |
|
15 | narrowspec, | |
|
16 | requirements, | |||
15 | util, |
|
17 | util, | |
16 | ) |
|
18 | ) | |
17 |
|
19 | |||
18 |
|
20 | |||
19 | class dirstateguard(util.transactional): |
|
21 | class dirstateguard(util.transactional): | |
20 | """Restore dirstate at unexpected failure. |
|
22 | """Restore dirstate at unexpected failure. | |
21 |
|
23 | |||
22 | At the construction, this class does: |
|
24 | At the construction, this class does: | |
23 |
|
25 | |||
24 | - write current ``repo.dirstate`` out, and |
|
26 | - write current ``repo.dirstate`` out, and | |
25 | - save ``.hg/dirstate`` into the backup file |
|
27 | - save ``.hg/dirstate`` into the backup file | |
26 |
|
28 | |||
27 | This restores ``.hg/dirstate`` from backup file, if ``release()`` |
|
29 | This restores ``.hg/dirstate`` from backup file, if ``release()`` | |
28 | is invoked before ``close()``. |
|
30 | is invoked before ``close()``. | |
29 |
|
31 | |||
30 | This just removes the backup file at ``close()`` before ``release()``. |
|
32 | This just removes the backup file at ``close()`` before ``release()``. | |
31 | """ |
|
33 | """ | |
32 |
|
34 | |||
33 | def __init__(self, repo, name): |
|
35 | def __init__(self, repo, name): | |
34 | self._repo = repo |
|
36 | self._repo = repo | |
35 | self._active = False |
|
37 | self._active = False | |
36 | self._closed = False |
|
38 | self._closed = False | |
37 | self._backupname = b'dirstate.backup.%s.%d' % (name, id(self)) |
|
39 | ||
38 | self._narrowspecbackupname = b'narrowspec.backup.%s.%d' % ( |
|
40 | def getname(prefix): | |
39 | name, |
|
41 | fd, fname = repo.vfs.mkstemp(prefix=prefix) | |
40 |
|
|
42 | os.close(fd) | |
|
43 | return fname | |||
|
44 | ||||
|
45 | self._backupname = getname(b'dirstate.backup.%s.' % name) | |||
|
46 | repo.dirstate.savebackup(repo.currenttransaction(), self._backupname) | |||
|
47 | # Don't make this the empty string, things may join it with stuff and | |||
|
48 | # blindly try to unlink it, which could be bad. | |||
|
49 | self._narrowspecbackupname = None | |||
|
50 | if requirements.NARROW_REQUIREMENT in repo.requirements: | |||
|
51 | self._narrowspecbackupname = getname( | |||
|
52 | b'narrowspec.backup.%s.' % name | |||
41 | ) |
|
53 | ) | |
42 | repo.dirstate.savebackup(repo.currenttransaction(), self._backupname) |
|
|||
43 | narrowspec.savewcbackup(repo, self._narrowspecbackupname) |
|
54 | narrowspec.savewcbackup(repo, self._narrowspecbackupname) | |
44 | self._active = True |
|
55 | self._active = True | |
45 |
|
56 | |||
46 | def __del__(self): |
|
57 | def __del__(self): | |
47 | if self._active: # still active |
|
58 | if self._active: # still active | |
48 | # this may occur, even if this class is used correctly: |
|
59 | # this may occur, even if this class is used correctly: | |
49 | # for example, releasing other resources like transaction |
|
60 | # for example, releasing other resources like transaction | |
50 | # may raise exception before ``dirstateguard.release`` in |
|
61 | # may raise exception before ``dirstateguard.release`` in | |
51 | # ``release(tr, ....)``. |
|
62 | # ``release(tr, ....)``. | |
52 | self._abort() |
|
63 | self._abort() | |
53 |
|
64 | |||
54 | def close(self): |
|
65 | def close(self): | |
55 | if not self._active: # already inactivated |
|
66 | if not self._active: # already inactivated | |
56 | msg = ( |
|
67 | msg = ( | |
57 | _(b"can't close already inactivated backup: %s") |
|
68 | _(b"can't close already inactivated backup: %s") | |
58 | % self._backupname |
|
69 | % self._backupname | |
59 | ) |
|
70 | ) | |
60 | raise error.Abort(msg) |
|
71 | raise error.Abort(msg) | |
61 |
|
72 | |||
62 | self._repo.dirstate.clearbackup( |
|
73 | self._repo.dirstate.clearbackup( | |
63 | self._repo.currenttransaction(), self._backupname |
|
74 | self._repo.currenttransaction(), self._backupname | |
64 | ) |
|
75 | ) | |
|
76 | if self._narrowspecbackupname: | |||
65 | narrowspec.clearwcbackup(self._repo, self._narrowspecbackupname) |
|
77 | narrowspec.clearwcbackup(self._repo, self._narrowspecbackupname) | |
66 | self._active = False |
|
78 | self._active = False | |
67 | self._closed = True |
|
79 | self._closed = True | |
68 |
|
80 | |||
69 | def _abort(self): |
|
81 | def _abort(self): | |
|
82 | if self._narrowspecbackupname: | |||
70 | narrowspec.restorewcbackup(self._repo, self._narrowspecbackupname) |
|
83 | narrowspec.restorewcbackup(self._repo, self._narrowspecbackupname) | |
71 | self._repo.dirstate.restorebackup( |
|
84 | self._repo.dirstate.restorebackup( | |
72 | self._repo.currenttransaction(), self._backupname |
|
85 | self._repo.currenttransaction(), self._backupname | |
73 | ) |
|
86 | ) | |
74 | self._active = False |
|
87 | self._active = False | |
75 |
|
88 | |||
76 | def release(self): |
|
89 | def release(self): | |
77 | if not self._closed: |
|
90 | if not self._closed: | |
78 | if not self._active: # already inactivated |
|
91 | if not self._active: # already inactivated | |
79 | msg = ( |
|
92 | msg = ( | |
80 | _(b"can't release already inactivated backup: %s") |
|
93 | _(b"can't release already inactivated backup: %s") | |
81 | % self._backupname |
|
94 | % self._backupname | |
82 | ) |
|
95 | ) | |
83 | raise error.Abort(msg) |
|
96 | raise error.Abort(msg) | |
84 | self._abort() |
|
97 | self._abort() |
General Comments 0
You need to be logged in to leave comments.
Login now