sapling/hgext3rd/undo.py
Felix Merk fbd87d6923 undo: store op history
Summary: Store basic operational history: bookmarks, commands, private heads, date and working copy parent

Test Plan: Unit tests

Reviewers: durham, #mercurial, mitrandir, quark

Reviewed By: quark

Subscribers: stash, mitrandir

Differential Revision: https://phabricator.intern.facebook.com/D5293596

Tasks: 19261492, 19563903, 19450726

Tags: Hg Undo

Signature: t1:5293596:1498245082:264e344054ee5061a439dec1c6071c2a60ffcf55
2017-06-23 12:19:09 -07:00

101 lines
2.7 KiB
Python

# undo.py: records data in revlog for future undo functionality
#
# Copyright 2017 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from mercurial import (
dispatch,
extensions,
revlog,
)
from mercurial.util import (
os,
makedate,
)
from mercurial.node import (
hex,
nullid,
)
staticcommand = []
# Wrappers
def _runcommandwrapper(orig, lui, repo, cmd, fullargs, *args):
# This wrapper executes whenever a command is run.
# Some commands (eg hg sl) don't actually modify anything
# ie can't be undone, but the command doesn't know this.
global staticcommand
staticcommand = fullargs
return orig(lui, repo, cmd, fullargs, *args)
# Hooks
def writeloghook(ui, repo, **kwargs):
nodes = {
'bookmarks': _logbookmarks(repo),
'draftheads': _logdraftheads(repo),
'workingparent': _logworkingparent(repo),
'date': _logdate(repo),
'command': _logcommand(repo),
}
_logindex(repo, nodes)
# Logs
def writelog(repo, name, revstring):
assert repo.currenttransaction() is not None
# The transaction code doesn't work with vfs
# specifically, repo.recover() assumes svfs?
repo.svfs.makedirs('undolog')
path = os.path.join('undolog', name)
rlog = revlog.revlog(repo.svfs, path)
tr = repo.currenttransaction()
node = rlog.addrevision(revstring, tr, 1, nullid, nullid)
return hex(node)
def _logdate(repo):
revstring = " ".join(str(x) for x in makedate())
return writelog(repo, "date.i", revstring)
def _logdraftheads(repo):
revs = repo.revs('heads(draft())')
tonode = repo.changelog.node
hexnodes = [hex(tonode(x)) for x in revs]
revstring = "\n".join(sorted(hexnodes))
return writelog(repo, "draftheads.i", revstring)
def _logcommand(repo):
global staticcommand
assert staticcommand
revstring = "\0".join(staticcommand)
staticcommand = []
return writelog(repo, "command.i", revstring)
def _logbookmarks(repo):
revstring = "\n".join(sorted('%s %s' % (name, hex(node))
for name, node in repo._bookmarks.iteritems()))
return writelog(repo, "bookmarks.i", revstring)
def _logworkingparent(repo):
revstring = repo['.'].hex()
return writelog(repo, "workingparent.i", revstring)
def _logindex(repo, nodes):
revstring = "\n".join(sorted('%s %s' % (k, v) for k, v in nodes.items()))
return writelog(repo, "index.i", revstring)
# Setup
def reposetup(ui, repo):
repo.ui.setconfig("hooks", "pretxnclose.undo", writeloghook)
def extsetup(ui):
extensions.wrapfunction(dispatch, 'runcommand', _runcommandwrapper)