sapling/morestatus.py
Christian Delahousse 93ef580a25 morestatus: include clean merge state, refactor state detection
Summary:
I was mostly taking into consideration conflicted states when I wrote this
extension. That means that a repo could be in a clean merge state, that is,
where the working copy has two parents and no conflicted files, and morestatus
wouldn't display it's extra status output.

Test Plan: See new test

Reviewers: #sourcecontrol, durham

Reviewed By: durham

Subscribers: akushner

Differential Revision: https://phabricator.fb.com/D2567597

Tasks: 8802101

Signature: t1:2567597:1445468752:429a63dda5a7269841aee16631049b937c13360e
2015-10-21 15:20:24 -07:00

129 lines
4.2 KiB
Python

# morestatus.py
#
# 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.
"""Make status give a bit more context
This extension will wrap the status command to make it show more context about
the state of the repo
"""
from mercurial import commands
from mercurial.extensions import wrapcommand
from mercurial.i18n import _
from mercurial import merge as mergemod
from mercurial import scmutil
def prefixlines(raw):
'''Surround lineswith a comment char and a new line'''
lines = raw.splitlines()
commentedlines = ['# %s' % line for line in lines]
return '\n'.join(commentedlines) + '\n'
def conflictsmsg(repo, ui):
mergestate = mergemod.mergestate(repo)
if not mergestate.active():
return
m = scmutil.match(repo[None])
unresolvedlist = [f for f in mergestate if m(f) and mergestate[f] == 'u']
if unresolvedlist:
mergeliststr = '\n'.join([' %s' % path for path in unresolvedlist])
msg = _('''Unresolved merge conflicts:
%s
To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
else:
msg = _('No unresolved merge conflicts.')
ui.warn(prefixlines(msg))
def helpmessage(ui, continuecmd, abortcmd):
msg = _('To continue: %s\n'
'To abort: %s') % (continuecmd, abortcmd)
ui.warn(prefixlines(msg))
def rebasemsg(ui):
helpmessage(ui, 'hg rebase --continue', 'hg rebase --abort')
def histeditmsg(ui):
helpmessage(ui, 'hg histedit --continue', 'hg histedit --abort')
def unshelvemsg(ui):
helpmessage(ui, 'hg unshelve --continue', 'hg unshelve --abort')
def graftmsg(ui):
# tweakdefaults requires `update` to have a rev hence the `.`
helpmessage(ui, 'hg graft --continue', 'hg update .')
def mergemsg(ui):
# tweakdefaults requires `update` to have a rev hence the `.`
helpmessage(ui, 'hg commit', 'hg update --clean . (warning: this will '
'erase all uncommitted changed)')
def bisectmsg(ui):
msg = _('To mark the commit good: hg bisect --good\n'
'To mark the commit bad: hg bisect --bad\n'
'To abort: hg bisect --reset\n')
ui.warn(prefixlines(msg))
def fileexistspredicate(filename):
return lambda repo: repo.vfs.exists(filename)
def cleanmergepredicate(repo):
return len(repo.parents()) > 1
STATES = (
# (state, predicate to detect states, helpful message function)
('histedit', fileexistspredicate('histedit-state'), histeditmsg),
('bisect', fileexistspredicate('bisect.state'), bisectmsg),
('graft', fileexistspredicate('graftstate'), graftmsg),
('unshelve', fileexistspredicate('unshelverebasestate'), unshelvemsg),
('rebase', fileexistspredicate('rebasestate'), rebasemsg),
# The merge state is part of a list that will be iterated over. It needs to
# be second to last because some of the other unfinished states may also be
# in a conflicted or clean merge state (eg. histedit, graft, etc). We want
# those to have priority.
('merge', fileexistspredicate('merge'), mergemsg),
('merge', cleanmergepredicate, mergemsg),
)
def extsetup(ui):
if ui.configbool('morestatus', 'show', False) and not ui.plain():
wrapcommand(commands.table, 'status', statuscmd)
def statuscmd(orig, ui, repo, *pats, **opts):
"""
Wrap the status command to barf out the state of the repository. States
being mid histediting, mid bisecting, grafting, merging, etc.
Output is to stderr to avoid breaking scripts.
"""
ret = orig(ui, repo, *pats, **opts)
statetuple = getrepostate(repo)
if statetuple:
state, statedetectionpredicate, helpfulmsg = statetuple
statemsg = _('The repository is in an unfinished *%s* state.') % state
ui.warn('\n' + prefixlines(statemsg))
conflictsmsg(repo, ui)
if helpfulmsg:
helpfulmsg(ui)
# TODO(cdelahousse): check to see if current bookmark needs updating. See
# scmprompt.
return ret
def getrepostate(repo):
for state, statedetectionpredicate, msgfn in STATES:
if statedetectionpredicate(repo):
return (state, statedetectionpredicate, msgfn)