annotate mercurial/transaction.py @ 147:b6d8ed7aeba0

A new ancestor algorithm The old ancestor algorithm could get fooled into returning ancestors closer to root than it ought to. Hopefully this one, which strictly orders its search by distance from room, will be foolproof.
author mpm@selenic.com
date Tue, 24 May 2005 23:11:44 -0800
parents 8d55c2d72c7c
children 5dcbe4d9a30c
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
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
15
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
16 class transaction:
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
17 def __init__(self, opener, journal, after = None):
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
18 self.opener = opener
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
19 self.after = after
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
20 self.entries = []
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
21 self.map = {}
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
22 self.journal = journal
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
23
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
24 # abort here if the journal already exists
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
25 if os.path.exists(self.journal):
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
26 raise "journal already exists!"
43
42177b56b949 Attempt to recover journal automatically
mpm@selenic.com
parents: 42
diff changeset
27
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
28 self.file = open(self.journal, "w")
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
29
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
30 def __del__(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
31 if self.entries: self.abort()
13
eb87b7dc4236 Fix empty transaction destruction
mpm@selenic.com
parents: 12
diff changeset
32 try: os.unlink(self.journal)
eb87b7dc4236 Fix empty transaction destruction
mpm@selenic.com
parents: 12
diff changeset
33 except: pass
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
34
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
35 def add(self, file, offset):
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
36 if file in self.map: return
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
37 self.entries.append((file, offset))
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
38 self.map[file] = 1
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
39 # 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
40 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
41 self.file.flush()
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
42
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
43 def close(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
44 self.file.close()
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
45 self.entries = []
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
46 if self.after:
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
47 os.rename(self.journal, self.after)
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
48 else:
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
49 os.unlink(self.journal)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
50
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
51 def abort(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
52 if not self.entries: return
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 print "transaction abort!"
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
55
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
56 for f, o in self.entries:
108
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
57 try:
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
58 self.opener(f, "a").truncate(o)
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
59 except:
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
60 print "failed to truncate", f
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
61
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
62 self.entries = []
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
63
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
64 print "rollback completed"
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
65
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
66 def recover(self):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
67 for l in open(self.journal).readlines():
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
68 f, o = l.split('\0')
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
69 self.opener(f, "a").truncate(int(o))
43
42177b56b949 Attempt to recover journal automatically
mpm@selenic.com
parents: 42
diff changeset
70 os.unlink(self.journal)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
71