# HG changeset patch # User liscju # Date 1441896787 -7200 # Node ID 8c7d8d5e1e0fcb8fc662450409f9667499252307 # Parent ccab61d84ea715e8cf40744f8ab63404efb34ab2 mercurial: add debugextensions command (issue4676) Add debugextensions command to help users debug their extension problems. If there are no extensions command prints nothing, otherwise it prints names of extension modules. If quiet or verbose option is not specified it prints(after extensions name) last version of mercurial in which given module was tested for non internal modules or not tested with user mercurial version. If verbose is specified it prints following information for every extension: extension name, import source, testedwith and buglink information. Extensions are printed sorted by extension name. diff -r ccab61d84ea7 -r 8c7d8d5e1e0f mercurial/commands.py --- a/mercurial/commands.py Thu Sep 24 10:15:37 2015 +0300 +++ b/mercurial/commands.py Thu Sep 10 16:53:07 2015 +0200 @@ -19,7 +19,7 @@ import merge as mergemod import minirst, revset, fileset import dagparser, context, simplemerge, graphmod, copies -import random +import random, operator import setdiscovery, treediscovery, dagutil, pvec, localrepo import phases, obsolete, exchange, bundle2, repair, lock as lockmod import ui as uimod @@ -2171,6 +2171,45 @@ localrevs = opts.get('local_head') doit(localrevs, remoterevs) +@command('debugextensions', formatteropts, [], norepo=True) +def debugextensions(ui, **opts): + '''show information about active extensions''' + exts = extensions.extensions(ui) + fm = ui.formatter('debugextensions', opts) + for extname, extmod in sorted(exts, key=operator.itemgetter(0)): + extsource = extmod.__file__ + exttestedwith = getattr(extmod, 'testedwith', None) + if exttestedwith is not None: + exttestedwith = exttestedwith.split() + extbuglink = getattr(extmod, 'buglink', None) + + fm.startitem() + + if ui.quiet or ui.verbose: + fm.write('name', '%s\n', extname) + else: + fm.write('name', '%s', extname) + if not exttestedwith: + fm.plain(_(' (untested!)\n')) + else: + if exttestedwith == ['internal'] or \ + util.version() in exttestedwith: + fm.plain('\n') + else: + lasttestedversion = exttestedwith[-1] + fm.plain(' (%s!)\n' % lasttestedversion) + + fm.condwrite(ui.verbose and extsource, 'source', + _(' location: %s\n'), extsource or "") + + fm.condwrite(ui.verbose and exttestedwith, 'testedwith', + _(' tested with: %s\n'), ' '.join(exttestedwith or [])) + + fm.condwrite(ui.verbose and extbuglink, 'buglink', + _(' bug reporting: %s\n'), extbuglink or "") + + fm.end() + @command('debugfileset', [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))], _('[-r REV] FILESPEC')) diff -r ccab61d84ea7 -r 8c7d8d5e1e0f tests/test-completion.t --- a/tests/test-completion.t Thu Sep 24 10:15:37 2015 +0300 +++ b/tests/test-completion.t Thu Sep 10 16:53:07 2015 +0200 @@ -80,6 +80,7 @@ debugdate debugdirstate debugdiscovery + debugextensions debugfileset debugfsinfo debuggetbundle @@ -239,6 +240,7 @@ debugdate: extended debugdirstate: nodates, datesort debugdiscovery: old, nonheads, ssh, remotecmd, insecure + debugextensions: template debugfileset: rev debugfsinfo: debuggetbundle: head, common, type diff -r ccab61d84ea7 -r 8c7d8d5e1e0f tests/test-debugextensions.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-debugextensions.t Thu Sep 10 16:53:07 2015 +0200 @@ -0,0 +1,83 @@ + $ hg debugextensions + + $ debugpath=`pwd`/extwithoutinfos.py + + $ cat > extwithoutinfos.py < EOF + + $ cat >> $HGRCPATH < [extensions] + > color= + > histedit= + > patchbomb= + > rebase= + > mq= + > ext1 = $debugpath + > EOF + + $ hg debugextensions + color + ext1 (untested!) + histedit + mq + patchbomb + rebase + + $ hg debugextensions -v + color + location: */hgext/color.pyc (glob) + tested with: internal + ext1 + location: */extwithoutinfos.pyc (glob) + histedit + location: */hgext/histedit.pyc (glob) + tested with: internal + mq + location: */hgext/mq.pyc (glob) + tested with: internal + patchbomb + location: */hgext/patchbomb.pyc (glob) + tested with: internal + rebase + location: */hgext/rebase.pyc (glob) + tested with: internal + + $ hg debugextensions -Tjson + [ + { + "buglink": "", + "name": "color", + "source": "*/hgext/color.pyc", (glob) + "testedwith": "internal" + }, + { + "buglink": "", + "name": "ext1", + "source": "*/extwithoutinfos.pyc", (glob) + "testedwith": "" + }, + { + "buglink": "", + "name": "histedit", + "source": "*/hgext/histedit.pyc", (glob) + "testedwith": "internal" + }, + { + "buglink": "", + "name": "mq", + "source": "*/hgext/mq.pyc", (glob) + "testedwith": "internal" + }, + { + "buglink": "", + "name": "patchbomb", + "source": "*/hgext/patchbomb.pyc", (glob) + "testedwith": "internal" + }, + { + "buglink": "", + "name": "rebase", + "source": "*/hgext/rebase.pyc", (glob) + "testedwith": "internal" + } + ] diff -r ccab61d84ea7 -r 8c7d8d5e1e0f tests/test-extension.t --- a/tests/test-extension.t Thu Sep 24 10:15:37 2015 +0300 +++ b/tests/test-extension.t Thu Sep 10 16:53:07 2015 +0200 @@ -287,17 +287,23 @@ $ echo "debugextension = $debugpath" >> $HGRCPATH $ hg help debugextension - debugextension extension - only debugcommands + hg debugextensions + + show information about active extensions - no commands defined + options: + + (some details hidden, use --verbose to show complete help) $ hg --verbose help debugextension - debugextension extension - only debugcommands + hg debugextensions + + show information about active extensions - list of commands: + options: - foo yet another foo command + -T --template TEMPLATE display with template (EXPERIMENTAL) global options ([+] can be repeated): @@ -326,12 +332,13 @@ $ hg --debug help debugextension - debugextension extension - only debugcommands + hg debugextensions + + show information about active extensions - list of commands: + options: - debugfoobar yet another debug command - foo yet another foo command + -T --template TEMPLATE display with template (EXPERIMENTAL) global options ([+] can be repeated): @@ -545,20 +552,7 @@ Issue811: Problem loading extensions twice (by site and by user) - $ debugpath=`pwd`/debugissue811.py - $ cat > debugissue811.py < '''show all loaded extensions - > ''' - > from mercurial import cmdutil, commands, extensions - > cmdtable = {} - > command = cmdutil.command(cmdtable) - > @command('debugextensions', [], 'hg debugextensions', norepo=True) - > def debugextensions(ui): - > "yet another debug command" - > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()])) - > EOF $ cat <> $HGRCPATH - > debugissue811 = $debugpath > mq = > strip = > hgext.mq = @@ -569,9 +563,8 @@ (note that mq force load strip, also checking it's not loaded twice) $ hg debugextensions - debugissue811 + mq strip - mq For extensions, which name matches one of its commands, help message should ask '-v -e' to get list of built-in aliases diff -r ccab61d84ea7 -r 8c7d8d5e1e0f tests/test-help.t --- a/tests/test-help.t Thu Sep 24 10:15:37 2015 +0300 +++ b/tests/test-help.t Thu Sep 10 16:53:07 2015 +0200 @@ -775,6 +775,8 @@ show the contents of the current dirstate debugdiscovery runs the changeset discovery protocol in isolation + debugextensions + show information about active extensions debugfileset parse and apply a fileset specification debugfsinfo show information detected about current filesystem debuggetbundle