diff --git a/hgext3rd/morestatus.py b/hgext3rd/morestatus.py --- a/hgext3rd/morestatus.py +++ b/hgext3rd/morestatus.py @@ -10,16 +10,12 @@ the state of the repo """ -import os -from mercurial import commands -from mercurial.extensions import wrapcommand -from mercurial.i18n import _ -from mercurial import merge as mergemod -from mercurial import scmutil - from mercurial import ( + cmdutil, + extensions, registrar, ) +from mercurial.i18n import _ UPDATEARGS = 'updateargs' @@ -27,107 +23,56 @@ configitem = registrar.configitem(configtable) configitem('morestatus', 'show', default=False) - -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' - +configitem('morestatus', 'skipstates', default=[]) -def conflictsmsg(repo, ui): - mergestate = mergemod.mergestate.read(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' % os.path.relpath( - os.path.join(repo.root, path), - os.getcwd()) for path in unresolvedlist]) - msg = _('''Unresolved merge conflicts: +def _isonlyupdatestate(repo): + for state, fn, msgfn in cmdutil.STATES: + if fn(repo) and state != 'update': + return False + return True -%s - -To mark files as resolved: hg resolve --mark FILE''') % mergeliststr - else: - msg = _('No unresolved merge conflicts.') - - ui.warn(prefixlines(msg)) +def wrapconflictmsg(orig, repo): + msg = orig(repo) + if repo.vfs.exists('updatestate') and _isonlyupdatestate(repo): + previousargs = repo.vfs.tryread(UPDATEARGS) + if previousargs: + continuecmd = 'hg ' + previousargs + else: + continuecmd = 'hg update ' + repo.vfs.read('updatestate')[:12] + abortcmd = updatecleanmsg(repo._activebookmark) + hmessage = cmdutil._helpmessage(continuecmd, abortcmd) + if msg is None: + msg = hmessage + else: + msg += '\n' + hmessage -def helpmessage(ui, continuecmd, abortcmd): - msg = _('To continue: %s\n' - 'To abort: %s') % (continuecmd, abortcmd) - ui.warn(prefixlines(msg)) - -def rebasemsg(repo, ui): - helpmessage(ui, 'hg rebase --continue', 'hg rebase --abort') - -def histeditmsg(repo, ui): - helpmessage(ui, 'hg histedit --continue', 'hg histedit --abort') - -def unshelvemsg(repo, ui): - helpmessage(ui, 'hg unshelve --continue', 'hg unshelve --abort') + return msg def updatecleanmsg(dest=None): warning = _('warning: this will discard uncommitted changes') return 'hg update --clean %s (%s)' % (dest or '.', warning) -def graftmsg(repo, ui): - # tweakdefaults requires `update` to have a rev hence the `.` - helpmessage(ui, 'hg graft --continue', updatecleanmsg()) - -def updatemsg(repo, ui): - previousargs = repo.vfs.tryread(UPDATEARGS) - if previousargs: - continuecmd = 'hg ' + previousargs - else: - continuecmd = 'hg update ' + repo.vfs.read('updatestate')[:12] - abortcmd = updatecleanmsg(repo._activebookmark) - helpmessage(ui, continuecmd, abortcmd) - -def mergemsg(repo, ui): - # tweakdefaults requires `update` to have a rev hence the `.` - helpmessage(ui, 'hg commit', updatecleanmsg()) - -def bisectmsg(repo, ui): - msg = _('To mark the changeset good: hg bisect --good\n' - 'To mark the changeset 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 mergepredicate(repo): - return len(repo[None].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 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. - ('merge', mergepredicate, mergemsg), - ('update', fileexistspredicate('updatestate'), updatemsg), -) - - def extsetup(ui): if ui.configbool('morestatus', 'show') and not ui.plain(): - wrapcommand(commands.table, 'status', statuscmd) # 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) + updatetuple = (('update', cmdutil.fileexistspredicate('updatestate'), + None),) + cmdutil.STATES = cmdutil.STATES + updatetuple + # ugly hacking to make update part working + extensions.wrapfunction(cmdutil, '_conflictsmsg', wrapconflictmsg) + +def reposetup(ui, repo): + if repo.ui.configbool('morestatus', 'show'): + repo.ui.setconfig('commands', 'status.verbose', True, 'morestatus-ext') + skipstates = repo.ui.config('morestatus', 'skipstates') + if skipstates: + repo.ui.setconfig('commands', 'status.skipstates', skipstates, + 'morestatus-ext') + def saveupdateargs(repo, args, **kwargs): # args is a string containing all flags and arguments with repo.wlock(): @@ -136,35 +81,3 @@ def cleanupdateargs(repo, **kwargs): with repo.wlock(): repo.vfs.tryunlink(UPDATEARGS) - -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(repo, ui) - - # TODO(cdelahousse): check to see if current bookmark needs updating. See - # scmprompt. - - return ret - -def getrepostate(repo): - # experimental config: morestatus.skipstates - skip = set(repo.ui.configlist('morestatus', 'skipstates', [])) - for state, statedetectionpredicate, msgfn in STATES: - if state in skip: - continue - if statedetectionpredicate(repo): - return (state, statedetectionpredicate, msgfn) diff --git a/tests/test-check-config-hg.t b/tests/test-check-config-hg.t --- a/tests/test-check-config-hg.t +++ b/tests/test-check-config-hg.t @@ -38,6 +38,7 @@ undocumented: grep.command (str) undocumented: infinitepush.bundle-stream (bool) undocumented: morestatus.show (bool) + undocumented: morestatus.skipstates (str) undocumented: nointerrupt.interactiveonly (bool) [True] undocumented: perftweaks.cachenoderevs (bool) [True] undocumented: perftweaks.disablebranchcache (bool) diff --git a/tests/test-morestatus.t b/tests/test-morestatus.t --- a/tests/test-morestatus.t +++ b/tests/test-morestatus.t @@ -40,10 +40,11 @@ > EOF [1] $ hg status + # The repository is in an unfinished *histedit* state. - # The repository is in an unfinished *histedit* state. # To continue: hg histedit --continue # To abort: hg histedit --abort + Test disabling output. Nothing should be shown $ hg status --config morestatus.show=False @@ -56,11 +57,12 @@ Test bisect state $ hg bisect --good $ hg status + # The repository is in an unfinished *bisect* state. - # The repository is in an unfinished *bisect* state. # To mark the changeset good: hg bisect --good # To mark the changeset bad: hg bisect --bad # To abort: hg bisect --reset + Verify that suppressing a morestatus state warning works with the config knob: $ hg status --config morestatus.skipstates=bisect @@ -85,15 +87,17 @@ $ hg status M a ? a.orig + # The repository is in an unfinished *graft* state. - # The repository is in an unfinished *graft* state. # Unresolved merge conflicts: # # a # # To mark files as resolved: hg resolve --mark FILE + # To continue: hg graft --continue # To abort: hg update --clean . (warning: this will discard uncommitted changes) + Test hg status is normal after graft abort $ hg up --clean -q @@ -115,15 +119,17 @@ $ hg status M a ? a.orig + # The repository is in an unfinished *unshelve* state. - # The repository is in an unfinished *unshelve* state. # Unresolved merge conflicts: # # a # # To mark files as resolved: hg resolve --mark FILE + # To continue: hg unshelve --continue # To abort: hg unshelve --abort + Test hg status is normal after unshelve abort $ hg unshelve --abort @@ -145,15 +151,17 @@ $ hg status M a ? a.orig + # The repository is in an unfinished *rebase* state. - # The repository is in an unfinished *rebase* state. # Unresolved merge conflicts: # # a # # To mark files as resolved: hg resolve --mark FILE + # To continue: hg rebase --continue # To abort: hg rebase --abort + Test status in rebase state with resolved files $ hg resolve --mark a @@ -162,11 +170,13 @@ $ hg status M a ? a.orig + # The repository is in an unfinished *rebase* state. - # The repository is in an unfinished *rebase* state. # No unresolved merge conflicts. + # To continue: hg rebase --continue # To abort: hg rebase --abort + Test hg status is normal after rebase abort $ hg rebase --abort -q @@ -180,10 +190,11 @@ $ hg rebase -s 2977a57ce863 -d 79361b8cdbb5 -q $ unbreakupdate $ hg status + # The repository is in an unfinished *rebase* state. - # The repository is in an unfinished *rebase* state. # To continue: hg rebase --continue # To abort: hg rebase --abort + $ hg rebase --abort -q rebase aborted @@ -194,15 +205,17 @@ $ hg status M a ? a.orig + # The repository is in an unfinished *merge* state. - # The repository is in an unfinished *merge* state. # Unresolved merge conflicts: # # a # # To mark files as resolved: hg resolve --mark FILE + # To continue: hg commit # To abort: hg update --clean . (warning: this will discard uncommitted changes) + Test if listed files have a relative path to current location $ mkdir -p b/c @@ -210,15 +223,17 @@ $ hg status M a ? a.orig + # The repository is in an unfinished *merge* state. - # The repository is in an unfinished *merge* state. # Unresolved merge conflicts: # # ../../a # # To mark files as resolved: hg resolve --mark FILE + # To continue: hg commit # To abort: hg update --clean . (warning: this will discard uncommitted changes) + $ cd ../.. Test hg status is normal after merge abort @@ -235,10 +250,11 @@ $ hg merge -r 79361b8cdbb -q $ hg status M a + # The repository is in an unfinished *merge* state. - # The repository is in an unfinished *merge* state. # To continue: hg commit # To abort: hg update --clean . (warning: this will discard uncommitted changes) + Test hg status is normal after merge commit (no output) $ hg commit -m 'merge commit' -q @@ -248,20 +264,22 @@ $ breakupdate $ hg update -C 2977a57ce863 $ hg status + # The repository is in an unfinished *update* state. - # The repository is in an unfinished *update* state. # To continue: hg update -C 2977a57ce863 # To abort: hg update --clean . (warning: this will discard uncommitted changes) + Test interrupted update state, with active bookmark and REV is a bookmark $ hg bookmark b1 $ hg bookmark -r 79361b8cdbb5 b2 $ hg update b2 $ hg status + # The repository is in an unfinished *update* state. - # The repository is in an unfinished *update* state. # To continue: hg update b2 # To abort: hg update --clean b1 (warning: this will discard uncommitted changes) + Test update state can be reset using bookmark $ hg update b1 -q @@ -273,10 +291,11 @@ $ hg commit --date "1234567890 0" -m m -q $ hg update --date 1970-1-1 -q $ hg status + # The repository is in an unfinished *update* state. - # The repository is in an unfinished *update* state. # To continue: hg update --date 1970-1-1 -q # To abort: hg update --clean . (warning: this will discard uncommitted changes) + $ unbreakupdate