transaction: add atomic groups to transaction logic
When performing a strip operation on a repository, it is vital that all the
truncations are performed, or that none of them are. This is done by adding
support for writing a number of entries in a single operation.
Co-contributor: Sune Foldager <cryo@cyanite.org>
--- a/mercurial/repair.py Tue May 12 11:15:54 2009 +0200
+++ b/mercurial/repair.py Mon May 11 21:12:40 2009 +0200
@@ -125,10 +125,12 @@
tr = repo.transaction()
offset = len(tr.entries)
+ tr.startgroup()
cl.strip(striprev, tr)
mfst.strip(striprev, tr)
for f in fs:
f.strip(striprev, tr)
+ tr.endgroup()
try:
for i in xrange(offset, len(tr.entries)):
--- a/mercurial/transaction.py Tue May 12 11:15:54 2009 +0200
+++ b/mercurial/transaction.py Mon May 11 21:12:40 2009 +0200
@@ -51,6 +51,7 @@
self.entries = []
self.map = {}
self.journal = journal
+ self._queue = []
self.file = open(self.journal, "w")
if createmode is not None:
@@ -62,8 +63,25 @@
self.file.close()
@active
+ def startgroup(self):
+ self._queue.append([])
+
+ @active
+ def endgroup(self):
+ q = self._queue.pop()
+ d = ''.join(['%s\0%d\n' % (x[0], x[1]) for x in q])
+ self.entries.extend(q)
+ self.file.write(d)
+ self.file.flush()
+
+ @active
def add(self, file, offset, data=None):
if file in self.map: return
+
+ if self._queue:
+ self._queue[-1].append((file, offset, data))
+ return
+
self.entries.append((file, offset, data))
self.map[file] = len(self.entries) - 1
# add enough data to the journal to do the truncate
@@ -78,6 +96,11 @@
@active
def replace(self, file, offset, data=None):
+ '''
+ replace can only replace already committed entries
+ that are not pending in the queue
+ '''
+
if file not in self.map:
raise KeyError(file)
index = self.map[file]