##// END OF EJS Templates
strip: make repair.strip transactional to avoid repository corruption...
strip: make repair.strip transactional to avoid repository corruption Uses a transaction instance from the local repository to journal the truncation of revlog files, such that if a strip only partially completes, hg recover will be able to finish the truncate of all the files. The potential unbundling of changes that have been backed up to be restored later will, in case of an error, have to be unbundled manually. The difference is that it will be possible to recover the repository state so the unbundle can actually succeed.

File last commit:

r8071:9f14b668 default
r8073:e8a28556 default
Show More
transaction.py
118 lines | 3.3 KiB | text/x-python | PythonLexer
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 # 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.
#
Vadim Gelfer
update copyrights.
r2859 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 #
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Benoit Boissinot
add missing import from 618140c75d8d
r7335 import os, errno
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class transaction(object):
Alexis S. L. Carvalho
make the journal/undo files from transactions inherit the mode from .hg/store
r6065 def __init__(self, report, opener, journal, after=None, createmode=None):
mpm@selenic.com
Implement recover and undo commands...
r162 self.journal = None
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 self.count = 1
mpm@selenic.com
Remove all remaining print statements...
r582 self.report = report
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.opener = opener
mpm@selenic.com
Beginnings of transaction undo support
r95 self.after = after
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.entries = []
mpm@selenic.com
Fix multiple changes to file per transaction
r42 self.map = {}
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.journal = journal
self.file = open(self.journal, "w")
Alexis S. L. Carvalho
make the journal/undo files from transactions inherit the mode from .hg/store
r6065 if createmode is not None:
os.chmod(self.journal, createmode & 0666)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def __del__(self):
mpm@selenic.com
transaction: __del__ should do nothing if the journal already exists...
r558 if self.journal:
if self.entries: self.abort()
self.file.close()
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Chris Mason
...
r2084 def add(self, file, offset, data=None):
mpm@selenic.com
Fix multiple changes to file per transaction
r42 if file in self.map: return
Chris Mason
...
r2084 self.entries.append((file, offset, data))
self.map[file] = len(self.entries) - 1
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 # add enough data to the journal to do the truncate
self.file.write("%s\0%d\n" % (file, offset))
self.file.flush()
Chris Mason
...
r2084 def find(self, file):
if file in self.map:
return self.entries[self.map[file]]
return None
def replace(self, file, offset, data=None):
if file not in self.map:
raise KeyError(file)
index = self.map[file]
self.entries[index] = (file, offset, data)
self.file.write("%s\0%d\n" % (file, offset))
self.file.flush()
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 def nest(self):
self.count += 1
return self
def running(self):
return self.count > 0
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 def close(self):
mason@suse.com
Automatic nesting into running transactions in the same repository....
r1806 self.count -= 1
if self.count != 0:
return
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0 self.file.close()
self.entries = []
mpm@selenic.com
Beginnings of transaction undo support
r95 if self.after:
mpm@selenic.com
Fix undo after aborted commit bug...
r785 self.after()
mpm@selenic.com
Beginnings of transaction undo support
r95 else:
os.unlink(self.journal)
mpm@selenic.com
transaction: nullify journal after close()...
r573 self.journal = None
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
def abort(self):
if not self.entries: return
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.report(_("transaction abort!\n"))
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
Henrik Stuart
transaction: only delete journal on successful abort/commit...
r8071 failed = False
Chris Mason
...
r2084 for f, o, ignore in self.entries:
mpm@selenic.com
Warn if we fail to truncate something
r108 try:
self.opener(f, "a").truncate(o)
except:
Henrik Stuart
transaction: only delete journal on successful abort/commit...
r8071 failed = True
Benoit Boissinot
i18n part2: use '_' for all strings who are part of the user interface
r1402 self.report(_("failed to truncate %s\n") % f)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0
self.entries = []
Henrik Stuart
transaction: only delete journal on successful abort/commit...
r8071 if not failed:
self.file.close()
os.unlink(self.journal)
self.journal = None
self.report(_("rollback completed\n"))
else:
self.report(_("rollback failed - please run hg recover\n"))
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
Implement recover and undo commands...
r162 def rollback(opener, file):
Chris Mason
...
r2084 files = {}
mpm@selenic.com
Implement recover and undo commands...
r162 for l in open(file).readlines():
f, o = l.split('\0')
Brendan Cully
rollback: unlink files truncated to length 0
r6441 files[f] = int(o)
Chris Mason
...
r2084 for f in files:
o = files[f]
Brendan Cully
rollback: unlink files truncated to length 0
r6441 if o:
opener(f, "a").truncate(int(o))
else:
Benoit Boissinot
fix restart of interrupted recover...
r7334 try:
fn = opener(f).name
os.unlink(fn)
except OSError, inst:
if inst.errno != errno.ENOENT:
raise
mpm@selenic.com
Implement recover and undo commands...
r162 os.unlink(file)
mpm@selenic.com
Add back links from file revisions to changeset revisions...
r0