# HG changeset patch # User mpm@selenic.com # Date 1117127094 28800 # Node ID 5dcbe4d9a30c4e5561d34f9d9738df3322384d6d # Parent 0b4c5cb953d9a3c636a52a5109ecf192f2b3ee9f Implement recover and undo commands This adds an interface to transaction to rollback with a given journal file and commands to rollback an existing .hg/journal or .hg/undo. diff --git a/hg b/hg --- a/hg +++ b/hg @@ -423,6 +423,14 @@ elif cmd == "tags": r = "?" print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n)) +elif cmd == "recover": + ui.status("rolling back any existing journal") + repo.recover() + +elif cmd == "undo": + ui.status("rolling back previous transaction") + repo.recover("undo") + elif cmd == "verify": filelinkrevs = {} filenodes = {} diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -297,6 +297,11 @@ class localrepository: return transaction(self.opener, self.join("journal"), self.join("undo")) + def recover(self, f = "journal"): + self.lock() + if os.path.exists(self.join(f)): + return rollback(self.opener, self.join(f)) + def lock(self, wait = 1): try: return lock.lock(self.join("lock"), 0) diff --git a/mercurial/transaction.py b/mercurial/transaction.py --- a/mercurial/transaction.py +++ b/mercurial/transaction.py @@ -15,16 +15,18 @@ import os class transaction: def __init__(self, opener, journal, after = None): + self.journal = None + + # abort here if the journal already exists + if os.path.exists(journal): + raise "journal already exists - run hg recover" + self.opener = opener self.after = after self.entries = [] self.map = {} 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): @@ -63,9 +65,9 @@ class transaction: 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)) - os.unlink(self.journal) +def rollback(opener, file): + for l in open(file).readlines(): + f, o = l.split('\0') + opener(f, "a").truncate(int(o)) + os.unlink(file)