diff mercurial/transaction.py @ 0:9117c6561b0b

Add back links from file revisions to changeset revisions Add simple transaction support Add hg verify Improve caching in revlog Fix a bunch of bugs Self-hosting now that the metadata is close to finalized
author mpm@selenic.com
date Tue, 03 May 2005 13:16:10 -0800
parents
children 8b64243ee17b
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/mercurial/transaction.py
@@ -0,0 +1,62 @@
+# transaction.py - simple journalling scheme for mercurial
+#
+# This transaction scheme is intended to gracefully handle program
+# errors and interruptions. More serious failures like system crashes
+# can be recovered with an fsck-like tool. As the whole repository is
+# effectively log-structured, this should amount to simply truncating
+# anything that isn't referenced in the changelog.
+#
+# Copyright 2005 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+import os
+
+class transaction:
+    def __init__(self, opener, journal):
+        self.opener = opener
+        self.entries = []
+        self.journal = journal
+
+        # abort here if the journal already exists
+        if os.path.exists(self.journal):
+            raise "Journal already exists!"
+        self.file = open(self.journal, "w")
+
+    def __del__(self):
+        if self.entries: self.abort()
+
+    def add(self, file, offset):
+        self.entries.append((file, offset))
+        # add enough data to the journal to do the truncate
+        self.file.write("%s\0%d\n" % (file, offset))
+        self.file.flush()
+
+    def close(self):
+        self.file.close()
+        self.entries = []
+        os.unlink(self.journal)
+
+    def abort(self):
+        if not self.entries: return
+
+        print "transaction abort!"
+
+        for f, o in self.entries:
+            self.opener(f, "a").truncate(o)
+
+        self.entries = []
+
+        try:
+            os.unlink(self.journal)
+            self.file.close()
+        except: pass
+
+        print "rollback completed"
+        
+    def recover(self):
+        for l in open(self.journal).readlines():
+            f, o = l.split('\0')
+            self.opener(f, "a").truncate(int(o))
+