annotate mercurial/transaction.py @ 535:fba26990604a

Deal with failed clone/transaction interaction -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Deal with failed clone/transaction interaction > What is happening is that something in the transaction machinery is > causing the directory to be completely recreated. The transaction gets rolled back by its destructor. This is critical so it happens whenever an exception occurs that unwinds the stack. Unfortunately, what's happening with clone is we're trying to delete the directory during exception propagation. And a reference to the transaction is held in the exception backtrace stack frames so it still exists until the exception is completely resolved. So there's no way to do the directory delete inside the exception handling cleanly. But we can handle it similarly to the transaction itself: use an object with a destructor. manifest hash: fc38550a20d64d08333f256bbedc312493c1390b -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCxDT2ywK+sNU5EO8RAjikAJ0Tej56rAutxQDfYzVbFGtT1sEC5ACgmVds /fwdQyHn+FwshugqXLemUaM= =3f78 -----END PGP SIGNATURE-----
author mpm@selenic.com
date Thu, 30 Jun 2005 10:07:50 -0800
parents 03f27b1381f9
children 0ceea19182a9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
1 # transaction.py - simple journalling scheme for mercurial
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
2 #
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
3 # This transaction scheme is intended to gracefully handle program
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
4 # errors and interruptions. More serious failures like system crashes
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
5 # can be recovered with an fsck-like tool. As the whole repository is
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
6 # effectively log-structured, this should amount to simply truncating
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
7 # anything that isn't referenced in the changelog.
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
8 #
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
9 # Copyright 2005 Matt Mackall <mpm@selenic.com>
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
10 #
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
11 # This software may be used and distributed according to the terms
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
12 # of the GNU General Public License, incorporated herein by reference.
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
13
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
14 import os
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 162
diff changeset
15 import util
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
16
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
17 class transaction:
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
18 def __init__(self, opener, journal, after = None):
162
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
19 self.journal = None
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
20
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
21 # abort here if the journal already exists
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
22 if os.path.exists(journal):
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
23 raise "journal already exists - run hg recover"
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
24
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
25 self.opener = opener
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
26 self.after = after
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
27 self.entries = []
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
28 self.map = {}
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
29 self.journal = journal
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
30
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
31 self.file = open(self.journal, "w")
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
32
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
33 def __del__(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
34 if self.entries: self.abort()
13
eb87b7dc4236 Fix empty transaction destruction
mpm@selenic.com
parents: 12
diff changeset
35 try: os.unlink(self.journal)
eb87b7dc4236 Fix empty transaction destruction
mpm@selenic.com
parents: 12
diff changeset
36 except: pass
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
37
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
38 def add(self, file, offset):
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
39 if file in self.map: return
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
40 self.entries.append((file, offset))
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
41 self.map[file] = 1
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
42 # add enough data to the journal to do the truncate
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
43 self.file.write("%s\0%d\n" % (file, offset))
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
44 self.file.flush()
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
45
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
46 def close(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
47 self.file.close()
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
48 self.entries = []
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
49 if self.after:
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 162
diff changeset
50 util.rename(self.journal, self.after)
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
51 else:
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
52 os.unlink(self.journal)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
53
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
54 def abort(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
55 if not self.entries: return
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
56
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
57 print "transaction abort!"
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
58
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
59 for f, o in self.entries:
108
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
60 try:
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
61 self.opener(f, "a").truncate(o)
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
62 except:
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
63 print "failed to truncate", f
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
64
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
65 self.entries = []
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
66
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
67 print "rollback completed"
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 429
diff changeset
68
162
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
69 def rollback(opener, file):
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
70 for l in open(file).readlines():
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
71 f, o = l.split('\0')
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
72 opener(f, "a").truncate(int(o))
5dcbe4d9a30c Implement recover and undo commands
mpm@selenic.com
parents: 108
diff changeset
73 os.unlink(file)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
74