2015-10-02 06:17:28 +03:00
|
|
|
# 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.
|
2017-03-25 01:22:31 +03:00
|
|
|
"""make status give a bit more context
|
2015-10-02 06:17:28 +03:00
|
|
|
|
|
|
|
This extension will wrap the status command to make it show more context about
|
|
|
|
the state of the repo
|
|
|
|
"""
|
|
|
|
|
2017-05-17 17:13:41 +03:00
|
|
|
import os
|
2015-11-27 16:16:53 +03:00
|
|
|
from mercurial import commands
|
2015-10-02 06:17:28 +03:00
|
|
|
from mercurial.extensions import wrapcommand
|
|
|
|
from mercurial.i18n import _
|
2015-10-02 07:24:43 +03:00
|
|
|
from mercurial import merge as mergemod
|
|
|
|
from mercurial import scmutil
|
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
UPDATEARGS = 'updateargs'
|
|
|
|
|
2015-10-02 07:24:43 +03:00
|
|
|
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):
|
2015-12-01 04:39:30 +03:00
|
|
|
mergestate = mergemod.mergestate.read(repo)
|
2015-10-02 07:24:43 +03:00
|
|
|
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:
|
2017-05-17 17:13:41 +03:00
|
|
|
mergeliststr = '\n'.join(
|
|
|
|
[' %s' % os.path.relpath(
|
|
|
|
os.path.join(repo.root, path),
|
|
|
|
os.getcwd()) for path in unresolvedlist])
|
2015-10-02 07:24:43 +03:00
|
|
|
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))
|
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
def rebasemsg(repo, ui):
|
2015-10-08 03:03:17 +03:00
|
|
|
helpmessage(ui, 'hg rebase --continue', 'hg rebase --abort')
|
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
def histeditmsg(repo, ui):
|
2015-10-08 03:03:17 +03:00
|
|
|
helpmessage(ui, 'hg histedit --continue', 'hg histedit --abort')
|
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
def unshelvemsg(repo, ui):
|
2015-10-08 03:03:17 +03:00
|
|
|
helpmessage(ui, 'hg unshelve --continue', 'hg unshelve --abort')
|
|
|
|
|
2017-01-03 19:25:52 +03:00
|
|
|
def updatecleanmsg(dest=None):
|
|
|
|
warning = _('warning: this will discard uncommitted changes')
|
|
|
|
return 'hg update --clean %s (%s)' % (dest or '.', warning)
|
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
def graftmsg(repo, ui):
|
2016-01-08 05:30:24 +03:00
|
|
|
# tweakdefaults requires `update` to have a rev hence the `.`
|
2017-01-03 19:25:52 +03:00
|
|
|
helpmessage(ui, 'hg graft --continue', updatecleanmsg())
|
2015-10-08 03:03:17 +03:00
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
def updatemsg(repo, ui):
|
|
|
|
previousargs = repo.vfs.tryread(UPDATEARGS)
|
|
|
|
if previousargs:
|
|
|
|
continuecmd = 'hg ' + previousargs
|
|
|
|
else:
|
|
|
|
continuecmd = 'hg update ' + repo.vfs.read('updatestate')[:12]
|
2017-01-03 19:25:52 +03:00
|
|
|
abortcmd = updatecleanmsg(repo._activebookmark)
|
2015-11-27 16:16:53 +03:00
|
|
|
helpmessage(ui, continuecmd, abortcmd)
|
|
|
|
|
|
|
|
def mergemsg(repo, ui):
|
2016-01-08 05:30:24 +03:00
|
|
|
# tweakdefaults requires `update` to have a rev hence the `.`
|
2017-01-03 19:25:52 +03:00
|
|
|
helpmessage(ui, 'hg commit', updatecleanmsg())
|
2015-10-02 07:24:43 +03:00
|
|
|
|
2015-11-27 16:16:53 +03:00
|
|
|
def bisectmsg(repo, ui):
|
2016-09-21 17:45:25 +03:00
|
|
|
msg = _('To mark the changeset good: hg bisect --good\n'
|
|
|
|
'To mark the changeset bad: hg bisect --bad\n'
|
2015-10-08 03:40:42 +03:00
|
|
|
'To abort: hg bisect --reset\n')
|
|
|
|
ui.warn(prefixlines(msg))
|
|
|
|
|
2015-10-22 01:20:24 +03:00
|
|
|
def fileexistspredicate(filename):
|
|
|
|
return lambda repo: repo.vfs.exists(filename)
|
|
|
|
|
2015-10-28 00:48:34 +03:00
|
|
|
def mergepredicate(repo):
|
2015-12-19 05:05:35 +03:00
|
|
|
return len(repo[None].parents()) > 1
|
2015-10-22 01:20:24 +03:00
|
|
|
|
2015-10-02 07:24:43 +03:00
|
|
|
STATES = (
|
2015-10-22 01:20:24 +03:00
|
|
|
# (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),
|
2016-08-11 00:19:30 +03:00
|
|
|
# The merge and update states are part of a list that will be iterated over.
|
|
|
|
# They need to be last because some of the other unfinished states may also
|
|
|
|
# be in a merge or update state (eg. rebase, histedit, graft, etc).
|
|
|
|
# We want those to have priority.
|
2015-10-28 00:48:34 +03:00
|
|
|
('merge', mergepredicate, mergemsg),
|
2016-08-11 00:19:30 +03:00
|
|
|
('update', fileexistspredicate('updatestate'), updatemsg),
|
2015-10-02 07:24:43 +03:00
|
|
|
)
|
2015-10-02 06:17:28 +03:00
|
|
|
|
2015-10-22 01:20:24 +03:00
|
|
|
|
2015-10-02 06:17:28 +03:00
|
|
|
def extsetup(ui):
|
|
|
|
if ui.configbool('morestatus', 'show', False) and not ui.plain():
|
|
|
|
wrapcommand(commands.table, 'status', statuscmd)
|
2015-11-27 16:16:53 +03:00
|
|
|
# Write down `hg update` args to show the continue command in
|
|
|
|
# interrupted update state.
|
|
|
|
ui.setconfig('hooks', 'pre-update.morestatus', saveupdateargs)
|
|
|
|
ui.setconfig('hooks', 'post-update.morestatus', cleanupdateargs)
|
|
|
|
|
|
|
|
def saveupdateargs(repo, args, **kwargs):
|
|
|
|
# args is a string containing all flags and arguments
|
|
|
|
repo.vfs.write(UPDATEARGS, args)
|
|
|
|
|
|
|
|
def cleanupdateargs(repo, **kwargs):
|
|
|
|
try:
|
|
|
|
repo.vfs.unlink(UPDATEARGS)
|
2016-01-08 05:30:24 +03:00
|
|
|
except Exception:
|
2015-11-27 16:16:53 +03:00
|
|
|
pass
|
2015-10-02 06:17:28 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2015-10-02 07:24:43 +03:00
|
|
|
statetuple = getrepostate(repo)
|
|
|
|
if statetuple:
|
2015-10-22 01:20:24 +03:00
|
|
|
state, statedetectionpredicate, helpfulmsg = statetuple
|
2015-10-02 07:24:43 +03:00
|
|
|
statemsg = _('The repository is in an unfinished *%s* state.') % state
|
|
|
|
ui.warn('\n' + prefixlines(statemsg))
|
|
|
|
conflictsmsg(repo, ui)
|
|
|
|
if helpfulmsg:
|
2015-11-27 16:16:53 +03:00
|
|
|
helpfulmsg(repo, ui)
|
2015-10-02 06:17:28 +03:00
|
|
|
|
|
|
|
# TODO(cdelahousse): check to see if current bookmark needs updating. See
|
|
|
|
# scmprompt.
|
|
|
|
|
|
|
|
return ret
|
2015-10-02 07:24:43 +03:00
|
|
|
|
|
|
|
def getrepostate(repo):
|
2017-05-03 20:34:36 +03:00
|
|
|
# experimental config: morestatus.skipstates
|
|
|
|
skip = set(repo.ui.configlist('morestatus', 'skipstates', []))
|
2015-10-22 01:20:24 +03:00
|
|
|
for state, statedetectionpredicate, msgfn in STATES:
|
2017-05-03 20:34:36 +03:00
|
|
|
if state in skip:
|
|
|
|
continue
|
2015-10-22 01:20:24 +03:00
|
|
|
if statedetectionpredicate(repo):
|
|
|
|
return (state, statedetectionpredicate, msgfn)
|