sapling/gitlikebookmarks.py
Laurent Charignon 2de054be8d gitlikebookmark: add a -x option for git like bookmarks for rebase and histedit
Summary:
This diff adds a -x flag to the rebase and histedits commands to only move the
current bookmark. It shows an issue with inhibit that we have to address and
can be extended to other commands.

Test Plan:
Adds a test, shows an issue with the way inhibit handles the
rebase set

Reviewers: pyd, mitrandir, durham

Differential Revision: https://phabricator.fb.com/D2680168
2015-11-25 10:09:45 -08:00

75 lines
2.7 KiB
Python

# gitlikebookmarks.py - add git like behavior for bookmarks
#
# Copyright 2015 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.
"""add git like behavior for bookmarks: only move the active bookmark
Add a -x specified to several commands. When the -x flag is specied, the
commands only allow the active bookmark to move.
"""
from mercurial import extensions
from mercurial import bookmarks
from mercurial import util
from mercurial.i18n import _
gitlikebookmarkscommands = (
# module name, command name
('rebase', 'rebase'),
('histedit', 'histedit'),
)
def _bookmarkwrite(orig, bkmstoreinst, *args, **kwargs):
repo = bkmstoreinst._repo
activebook = None
bookmarksbefore = None
if util.safehasattr(bkmstoreinst, "oldactivebookmark"):
activebook = bkmstoreinst.oldactivebookmark
bookmarksbefore = bkmstoreinst.oldbookmarks
if activebook != None:
override = []
for book in bkmstoreinst:
if book == activebook:
continue
override.append(book)
for k in override:
if k in bookmarksbefore:
bkmstoreinst[k] = bookmarksbefore[k]
if repo._activebookmark != activebook:
bookmarks.activate(repo, activebook)
# XXX will be an issue with chg, -x will persist accross commands
# Possible fixes:
# 1) setting activebook to None here would only work
# for commands with a single transaction (we have no guarantee of that)
# 2) put all this code in _wrapfn and wrap the call to orig(...) in a
# transaction but it will rollback if rebase/histedit has conflicts (not
# intended behavior as we want to leave the conflicts in the workdir)
return orig(bkmstoreinst, *args, **kwargs)
def _wrapfn(orig, ui, repo, *args, **kwargs):
# Normal behavior unless -x is specified
if not kwargs.get('stickybookmark'):
return orig(ui, repo, *args, **kwargs)
repo._bookmarks.oldactivebookmark = bookmarks.readactive(repo)
repo._bookmarks.oldbookmarks = repo._bookmarks.copy()
return orig(ui, repo, *args, **kwargs)
def extsetup(ui):
extensions.wrapfunction(bookmarks.bmstore, '_write', _bookmarkwrite)
for module, fn in gitlikebookmarkscommands:
try:
ext = extensions.find(module)
if ext:
entry = extensions.wrapcommand(ext.cmdtable, fn, _wrapfn)
entry[1].append(('x','stickybookmark', None,
_('only allow the active bookmark to move'
' during the operation')))
except KeyError:
# Extension not present
pass