Commit Graph

371 Commits

Author SHA1 Message Date
Jun Wu
d22993888a alias: make alias command lazily resolved
With many aliases, resolving them could have some visible overhead. Below is
part of traceprof [1] output of `hg bookmark --hidden`:

  (time unit: ms)
  37  \ addaliases                             dispatch.py:526
  37   | __init__ (60 times)                   dispatch.py:402
  33   | findcmd (108 times)                   cmdutil.py:721
  16   | findpossible (49 times)               cmdutil.py:683

It may get better by optimizing `findcmd` to do a bisect, but we don't
really need to resolve an alias if it's not used, so let's make those
command entries lazy.

After this patch, `addalias` takes less than 1ms.

.. perf:: improved performance when many aliases are defined

[1]: 9aca0dbdbd/hgext3rd/traceprof.pyx

Differential Revision: https://phab.mercurial-scm.org/D805
2017-09-23 13:46:12 -07:00
Jun Wu
95208a99f4 alias: test duplicated definition earlier
This patch moves the old definition checking logic introduced by
df4ba5915933 earlier. So that the test itself does not depend on `aliasdef`.

The check is to avoid wrapping a same alias multiple times. It can be done
by checking the config name and value (`definition` in code), without
constructing a `cmdalias` instance.

This makes the next patch easier to review.

Differential Revision: https://phab.mercurial-scm.org/D804
2017-09-23 13:31:09 -07:00
Yuya Nishihara
a71f259bd2 doctest: bulk-replace string literals with b'' for Python 3
Our code transformer can't rewrite string literals in docstrings, and I
don't want to make the transformer more complex.
2017-09-03 14:32:11 +09:00
Jun Wu
f89434c718 wrapfunction: use functools.partial if possible
Every `extensions.bind` call inserts a frame in traceback:

   ... in closure
     return func(*(args + a), **kw)

which makes traceback noisy.

The Python stdlib has a `functools.partial` which is backed by C code and
does not pollute traceback. However it does not support instancemethod and
sets `args` attribute which could be problematic for alias handling.

This patch makes `wrapfunction` use `functools.partial` if we are wrapping a
function directly exported by a module (so it's impossible to be a class or
instance method), and special handles `wrapfunction` results so alias
handling code could handle `args` just fine.

As an example, `hg rebase -s . -d . --traceback` got 6 lines removed in my
setup:

   File "hg/mercurial/dispatch.py", line 898, in _dispatch
     cmdpats, cmdoptions)
  -File "hg/mercurial/extensions.py", line 333, in closure
  -  return func(*(args + a), **kw)
   File "hg/hgext/journal.py", line 84, in runcommand
     return orig(lui, repo, cmd, fullargs, *args)
  -File "hg/mercurial/extensions.py", line 333, in closure
  -  return func(*(args + a), **kw)
   File "fb-hgext/hgext3rd/fbamend/hiddenoverride.py", line 119, in runcommand
     result = orig(lui, repo, cmd, fullargs, *args)
   File "hg/mercurial/dispatch.py", line 660, in runcommand
     ret = _runcommand(ui, options, cmd, d)
  -File "hg/mercurial/extensions.py", line 333, in closure
  -  return func(*(args + a), **kw)
   File "hg/hgext/pager.py", line 69, in pagecmd
     return orig(ui, options, cmd, cmdfunc)
   ....

Differential Revision: https://phab.mercurial-scm.org/D632
2017-09-05 13:37:36 -07:00
Augie Fackler
e2774d9258 python3: wrap all uses of <exception>.strerror with strtolocal
Our string literals are bytes, and we mostly want to %-format a
strerror into a one of those literals, so this fixes a ton of issues.
2017-08-22 20:03:07 -04:00
FUJIWARA Katsunori
af39ee1c25 ui: enable pager always for explicit --pager=on (issue5580)
Before this patch, explicit --pager=on is unintentionally ignored by
any disabling factor, even if priority of it is less than --pager=on
(e.g. "[ui] paginate = off").
2017-08-01 18:52:52 +09:00
Jun Wu
e47f7dc2fa codemod: register core configitems using a script
This is done by a script [2] using RedBaron [1], a tool designed for doing
code refactoring. All "default" values are decided by the script and are
strongly consistent with the existing code.

There are 2 changes done manually to fix tests:

  [warn] mercurial/exchange.py: experimental.bundle2-output-capture: default needs manual removal
  [warn] mercurial/localrepo.py: experimental.hook-track-tags: default needs manual removal

Since RedBaron is not confident about how to indent things [2].

[1]: https://github.com/PyCQA/redbaron
[2]: https://github.com/PyCQA/redbaron/issues/100
[3]:

#!/usr/bin/env python
# codemod_configitems.py - codemod tool to fill configitems
#
# Copyright 2017 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.
from __future__ import absolute_import, print_function

import os
import sys

import redbaron

def readpath(path):
    with open(path) as f:
        return f.read()

def writepath(path, content):
    with open(path, 'w') as f:
        f.write(content)

_configmethods = {'config', 'configbool', 'configint', 'configbytes',
                  'configlist', 'configdate'}

def extractstring(rnode):
    """get the string from a RedBaron string or call_argument node"""
    while rnode.type != 'string':
        rnode = rnode.value
    return rnode.value[1:-1]  # unquote, "'str'" -> "str"

def uiconfigitems(red):
    """match *.ui.config* pattern, yield (node, method, args, section, name)"""
    for node in red.find_all('atomtrailers'):
        entry = None
        try:
            obj = node[-3].value
            method = node[-2].value
            args = node[-1]
            section = args[0].value
            name = args[1].value
            if (obj in ('ui', 'self') and method in _configmethods
                and section.type == 'string' and name.type == 'string'):
                entry = (node, method, args, extractstring(section),
                         extractstring(name))
        except Exception:
            pass
        else:
            if entry:
                yield entry

def coreconfigitems(red):
    """match coreconfigitem(...) pattern, yield (node, args, section, name)"""
    for node in red.find_all('atomtrailers'):
        entry = None
        try:
            args = node[1]
            section = args[0].value
            name = args[1].value
            if (node[0].value == 'coreconfigitem' and section.type == 'string'
                and name.type == 'string'):
                entry = (node, args, extractstring(section),
                         extractstring(name))
        except Exception:
            pass
        else:
            if entry:
                yield entry

def registercoreconfig(cfgred, section, name, defaultrepr):
    """insert coreconfigitem to cfgred AST

    section and name are plain string, defaultrepr is a string
    """
    # find a place to insert the "coreconfigitem" item
    entries = list(coreconfigitems(cfgred))
    for node, args, nodesection, nodename in reversed(entries):
        if (nodesection, nodename) < (section, name):
            # insert after this entry
            node.insert_after(
                'coreconfigitem(%r, %r,\n'
                '    default=%s,\n'
                ')' % (section, name, defaultrepr))
            return

def main(argv):
    if not argv:
        print('Usage: codemod_configitems.py FILES\n'
              'For example, FILES could be "{hgext,mercurial}/*/**.py"')
    dirname = os.path.dirname
    reporoot = dirname(dirname(dirname(os.path.abspath(__file__))))

    # register configitems to this destination
    cfgpath = os.path.join(reporoot, 'mercurial', 'configitems.py')
    cfgred = redbaron.RedBaron(readpath(cfgpath))

    # state about what to do
    registered = set((s, n) for n, a, s, n in coreconfigitems(cfgred))
    toregister = {} # {(section, name): defaultrepr}
    coreconfigs = set() # {(section, name)}, whether it's used in core

    # first loop: scan all files before taking any action
    for i, path in enumerate(argv):
        print('(%d/%d) scanning %s' % (i + 1, len(argv), path))
        iscore = ('mercurial' in path) and ('hgext' not in path)
        red = redbaron.RedBaron(readpath(path))
        # find all repo.ui.config* and ui.config* calls, and collect their
        # section, name and default value information.
        for node, method, args, section, name in uiconfigitems(red):
            if section == 'web':
                # [web] section has some weirdness, ignore them for now
                continue
            defaultrepr = None
            key = (section, name)
            if len(args) == 2:
                if key in registered:
                    continue
                if method == 'configlist':
                    defaultrepr = 'list'
                elif method == 'configbool':
                    defaultrepr = 'False'
                else:
                    defaultrepr = 'None'
            elif len(args) >= 3 and (args[2].target is None or
                                     args[2].target.value == 'default'):
                # try to understand the "default" value
                dnode = args[2].value
                if dnode.type == 'name':
                    if dnode.value in {'None', 'True', 'False'}:
                        defaultrepr = dnode.value
                elif dnode.type == 'string':
                    defaultrepr = repr(dnode.value[1:-1])
                elif dnode.type in ('int', 'float'):
                    defaultrepr = dnode.value
            # inconsistent default
            if key in toregister and toregister[key] != defaultrepr:
                defaultrepr = None
            # interesting to rewrite
            if key not in registered:
                if defaultrepr is None:
                    print('[note] %s: %s.%s: unsupported default'
                          % (path, section, name))
                    registered.add(key) # skip checking it again
                else:
                    toregister[key] = defaultrepr
                    if iscore:
                        coreconfigs.add(key)

    # second loop: rewrite files given "toregister" result
    for path in argv:
        # reconstruct redbaron - trade CPU for memory
        red = redbaron.RedBaron(readpath(path))
        changed = False
        for node, method, args, section, name in uiconfigitems(red):
            key = (section, name)
            defaultrepr = toregister.get(key)
            if defaultrepr is None or key not in coreconfigs:
                continue
            if len(args) >= 3 and (args[2].target is None or
                                   args[2].target.value == 'default'):
                try:
                    del args[2]
                    changed = True
                except Exception:
                    # redbaron fails to do the rewrite due to indentation
                    # see https://github.com/PyCQA/redbaron/issues/100
                    print('[warn] %s: %s.%s: default needs manual removal'
                          % (path, section, name))
            if key not in registered:
                print('registering %s.%s' % (section, name))
                registercoreconfig(cfgred, section, name, defaultrepr)
                registered.add(key)
        if changed:
            print('updating %s' % path)
            writepath(path, red.dumps())

    if toregister:
        print('updating configitems.py')
        writepath(cfgpath, cfgred.dumps())

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
2017-07-14 14:22:40 -07:00
FUJIWARA Katsunori
b05e620ac0 dispatch: remove unused _loaded
Now, there is no user for dispatch._loaded.
2017-06-24 02:39:21 +09:00
FUJIWARA Katsunori
fdb6557cf4 extensions: register functions always at loading extension (issue5601)
Before this patch, functions defined in extensions are registered via
extra loaders only in _dispatch(). Therefore, loading extensions in
other code paths like below omits registration of functions.

  - WSGI service
  - operation across repositories (e.g. subrepo)
  - test-duplicateoptions.py, using extensions.loadall() directly

To register functions always at loading new extension, this patch
moves implementation for extra loading from dispatch._dispatch() to
extensions.loadall().

AFAIK, only commands module causes cyclic dependency between
extensions module, but this patch imports all related modules just
before extra loading in loadall(), in order to centralize them.

This patch makes extensions.py depend on many other modules, even
though extensions.py itself doesn't. It should be avoided if possible,
but I don't have any better idea. Some other places like below aren't
reasonable for extra loading, IMHO.

  - specific function in newly added module:
    existing callers of extensions.loadall() should invoke it, too

  - hg.repository() or so:
    no-repo commands aren't covered by this.

BTW, this patch removes _loaded.add(name) on relocation, because
dispatch._loaded is used only for extraloaders (for similar reason,
"exts" variable is removed, too).
2017-06-24 02:39:20 +09:00
Pierre-Yves David
2fdfd87513 profile: drop maybeprofile
It seems sufficiently simple to use "profile(enabled=X)" to not justify having
a dedicated context manager just to read the config.

(I do not have a too strong opinion about this).
2017-06-09 12:29:29 +01:00
Pierre-Yves David
81c8d3b7b6 profile: support --profile in alias and abbreviated version (--prof)
We now process the "--profile" a second time after alias has been processed and
the command argument fully parsed. If appropriate we enable profiling at that
time.

In these situation, the --profile will cover less than if the full --profile
flag was passed on the command line. This is better than the previous behavior
(flag ignored) and still fullfil multiple valid usecases.
2017-06-09 12:36:07 +01:00
Yuya Nishihara
02355fbadc dispatch: do not close stdout and stderr, just flush() instead
Since 348863ccec7e "util: always force line buffered stdout when stdout is
a tty", we have two file objects attached to the same STDOUT_FILENO. If one
is closed, the underlying file descriptor is also closed, and writing to
the other file object would crash the Python interpreter in a hard way, at
least on Windows.

So, it seems safer to not close the standard streams. This also matches
the behavior of the default sys.stdout/stderr.close(), which never close
the FILE* streams in C layer.

https://hg.python.org/cpython/file/v2.7.13/Python/sysmodule.c#l1401
2017-04-23 00:31:29 +09:00
Augie Fackler
9a722d4382 merge with stable 2017-06-03 16:33:28 -04:00
FUJIWARA Katsunori
6e23c59850 dispatch: setup color before pager for correct console information on windows
Before this patch, "hg CMD --pager on" on Windows shows output
unintentionally decorated with ANSI color escape sequences, if color
mode is "auto". This issue occurs in steps below.

  1. dispatch() invokes ui.pager() at detection of "--pager on"
  2. stdout of hg process is redirected into stdin of pager process
  3. "ui.formatted" = True, because isatty(stdout) is so before (2)
  4. color module is loaded for colorization
  5. color.w32effects = None, because GetConsoleScreenBufferInfo()
     fails on stdout redirected at (2)
  6. "ansi" color mode is chosen, because of "not w32effects"
  7. output is colorized in "ansi" mode because of "ui.formatted" = True

Even if "ansi" color mode is chosen, ordinarily redirected stdout
makes ui.formatted() return False, and colorization is avoided. But in
this issue case, "ui.formatted" = True at (3) forces output to be
colorized.

For correct console information on win32, it is needed to ensure that
color module is loaded before redirection of stdout for pagination.

BTW, if any of enabled extensions has "colortable" attribute, this
issue is avoided even before this patch, because color module is
imported as a part of loading such extension, and extension loading
occurs before setting up pager. For example, mq and keyword have
"colortable".
2017-05-23 03:29:23 +09:00
Augie Fackler
3d0bf6c892 freeze: merge default into stable for 4.2 code freeze 2017-04-18 12:24:34 -04:00
Augie Fackler
b2bd435955 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Some shared-ssh installations assume that 'hg serve --stdio' is a safe
command to run for minimally trusted users. Unfortunately, the messy
implementation of argument parsing here meant that trying to access a
repo named '--debugger' would give the user a pdb prompt, thereby
sidestepping any hoped-for sandboxing. Serving repositories over HTTP(S)
is unaffected.

We're not currently hardening any subcommands other than 'serve'. If
your service exposes other commands to users with arbitrary repository
names, it is imperative that you defend against repository names of
'--debugger' and anything starting with '--config'.

The read-only mode of hg-ssh stopped working because it provided its hook
configuration to "hg serve --stdio" via --config parameter. This is banned for
security reasons now. This patch switches it to directly call ui.setconfig().
If your custom hosting infrastructure relies on passing --config to
"hg serve --stdio", you'll need to find a different way to get that configuration
into Mercurial, either by using ui.setconfig() as hg-ssh does in this patch,
or by placing an hgrc file someplace where Mercurial will read it.

mitrandir@fb.com provided some extra fixes for the dispatch code and
for hg-ssh in places that I overlooked.
2017-04-12 11:23:55 -07:00
Yuya Nishihara
649f9bf987 dispatch: ignore further SIGPIPE while handling KeyboardInterrupt
I got the following error by running "hg log" and quitting the pager
immediately. Any output here may trigger another SIGPIPE, so only thing
we can do is to swallow the exception and exit with an error status.

  Traceback (most recent call last):
    File "./hg", line 45, in <module>
      mercurial.dispatch.run()
    File "mercurial/dispatch.py", line 83, in run
      status = (dispatch(req) or 0) & 255
    File "mercurial/dispatch.py", line 167, in dispatch
      req.ui.warn(_("interrupted!\n"))
    File "mercurial/ui.py", line 1224, in warn
      self.write_err(*msg, **opts)
    File "mercurial/ui.py", line 790, in write_err
      self._write_err(*msgs, **opts)
    File "mercurial/ui.py", line 798, in _write_err
      self.ferr.write(a)
    File "mercurial/ui.py", line 129, in _catchterm
      raise error.SignalInterrupt
  mercurial.error.SignalInterrupt

Perhaps this wasn't visible before ee4f321cd621 because the original stderr
handle was restored very late.
2017-04-17 23:53:19 +09:00
Yuya Nishihara
aabbe05fb5 dispatch: print traceback in scmutil.callcatch() if --traceback specified
Otherwise, traceback wouldn't be printed for a known exception occurred in
worker processes.
2017-04-15 13:02:34 +09:00
Yuya Nishihara
1ea92e7f19 dispatch: mark callcatch() as a private function 2017-04-15 12:58:06 +09:00
Bryan O'Sullivan
ebffdb4558 stdio: catch StdioError in dispatch.run and clean up appropriately
We attempt to report what went wrong, and more importantly exit the
program with an error code.

(The exception we catch is not yet raised anywhere in the code.)
2017-04-11 14:54:12 -07:00
Bryan O'Sullivan
287bd28acf atexit: switch to home-grown implementation 2017-04-11 14:54:12 -07:00
Bryan O'Sullivan
0c663fe04d ui: add special-purpose atexit functionality
In spite of its longstanding use, Python's built-in atexit code is
not suitable for Mercurial's purposes, for several reasons:

* Handlers run after application code has finished.

* Because of this, the code that runs handlers swallows exceptions
  (since there's no possible stacktrace to associate errors with).
  If we're lucky, we'll get something spat out to stderr (if stderr
  still works), which of course isn't any use in a big deployment
  where it's important that exceptions get logged and aggregated.

* Mercurial's current atexit handlers make unfortunate assumptions
  about process state (specifically stdio) that, coupled with the
  above problems, make it impossible to deal with certain categories
  of error (try "hg status > /dev/full" on a Linux box).

* In Python 3, the atexit implementation is completely hidden, so
  we can't hijack the platform's atexit code to run handlers at a
  time of our choosing.

As a result, here's a perfectly cromulent atexit-like implementation
over which we have control.  This lets us decide exactly when the
handlers run (after each request has completed), and control what
the process state is when that occurs (and afterwards).
2017-04-11 14:54:12 -07:00
Augie Fackler
11355eb015 dispatch: convert exception payload to bytes more carefully
We were previously depending on str() doing something reasonable here,
and we can't depend on the objects in question supporting __bytes__,
so we work around the lack of direct bytes formatting.
2017-05-28 15:47:00 -04:00
Pulkit Goyal
dbc47c9005 dispatch: use pycompat.maplist() instead of map() to get a list 2017-03-26 20:49:18 +05:30
Pulkit Goyal
d310fba3dd py3: have a bytes version of shlex.split()
shlex.split() only accepts unicodes on Python 3. After this patch we will be
using pycompat.shlexsplit(). This patch also replaces existing occurences of
shlex.split with pycompat.shlexsplit.
2016-12-25 03:06:55 +05:30
Pierre-Yves David
9ff835aa99 color: load 'colortable' from extension using an 'extraloader'
Now that we have the '_style' dictionary in core, we can use the clean and
standard 'extraloader' mechanism to load extension's 'colortable'.
color.loadcolortable
2016-11-18 18:18:15 +01:00
Pulkit Goyal
9d833da676 py3: make keys of keyword arguments strings
keys of keyword arguments on Python 3 has to be string. We are dealing with
bytes in our codebase so the keys are also bytes. Done that using
pycompat.strkwargs().

Also after this patch, `hg version` now runs on Python 3.5. Hurray!
2016-12-13 20:53:40 +05:30
Pulkit Goyal
9523fa9b6b fancyopts: switch from fancyopts.getopt.* to getopt.*
In the next patch, we will be creating a bytes version of getopt.getopt() and
doing that will leave getopt as unused import in fancyopts. So before removing
that there are instances in codebase where instead of importing getopt, we
have used fancyopts.getopt. This patch will switch all those cases so that
the next patch can remove the import of getopt from fancyopts without breaking
things.
2016-12-06 06:27:58 +05:30
Yuya Nishihara
1d44bd2bbb ui: factor out ui.load() to create a ui without loading configs (API)
This allows us to write doctests depending on a ui object, but not on global
configs.

ui.load() is a class method so we can do wsgiui.load(). All ui() calls but
for doctests are replaced with ui.load(). Some of them could be changed to
not load configs later.
2016-10-22 14:35:10 +09:00
Jun Wu
115ee04855 dispatch: move part of callcatch to scmutil
Per discussion at 7d927e65eaf2 [1], we need "callcatch" in worker.py. Move
it to scmutil.py to avoid cycles.

Note that dispatch's callcatch handles some additional high-level exceptions
related to config parsing, and commands. Moving them to scmutil will make
scmutil depend on "commands" or require "_formatparse" and "_getsimilar"
(and "difflib") to be moved as well. In the worker use-case, it is forked
when config and commands are fully loaded. So it should not care about those
exceptions.

[1]: https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-August/087116.html
2016-11-24 00:48:40 +00:00
Pulkit Goyal
97f340e354 py3: use pycompat.getcwd() instead of os.getcwd()
We have pycompat.getcwd() which returns bytes path on Python 3. This patch
changes most of the occurences of the os.getcwd() with pycompat one.
2016-11-23 00:03:11 +05:30
Pulkit Goyal
57f271b08e py3: add os.getcwdb() to have bytes path
Following the behaviour of Python 3, os.getcwd() return unicodes. We need
bytes version as path variables are bytes in UNIX. Python 3 has os.getcwdb()
which returns current working directory in bytes.

Like rest of the things there in pycompat, like osname, ossep, we need to
rewrite every instance of os.getcwd to pycompat.getcwd to make them work
correctly on Python 3.
2016-11-22 18:46:50 +05:30
Augie Fackler
d3b8e6d277 dispatch: stop supporting non-use of @command
We said we'd delete this after 3.8. It's time.
2016-11-21 21:51:23 -05:00
Yuya Nishihara
47f9c8b52e py3: bulk replace sys.stdin/out/err by util's
Almost all sys.stdin/out/err in hgext/ and mercurial/ are replaced by util's.
There are a few exceptions:

 - lsprof.py and statprof.py are untouched since they are a kind of vendor
   code and they never import mercurial modules right now.
 - ui._readline() needs to replace sys.stdin and stdout to pass them to
   raw_input(). We'll need another workaround here.
2016-10-20 23:53:36 +09:00
Pulkit Goyal
bf942f7498 py3: use pycompat.sysargv in dispatch.run()
Another one to have a bytes result from sys.argv in Python 3.
This one is also a part of running `hg version` on Python 3.
2016-11-21 15:35:22 +05:30
Augie Fackler
7a3b5c3c7d dispatch: use pycompat.maplist to allow summing with args 2017-03-19 14:17:07 -04:00
Augie Fackler
f1710548b8 dispatch: replace mayberepr with shellquote
The quoting logic here was actually insufficient, and would have had
bogus b-prefixes on Python 3. shellquote seems more appropriate
anyway. Surprisingly, only two tests have output changes, and both of
them look reasonable to me (both are in blackbox logs).

Spotted by Yuya during review.
2017-03-19 14:23:30 -04:00
Augie Fackler
4eeee9b0e9 dispatch: ensure repr is bytes in _mayberepr
Fixes command line arguments containing spaces on Python 3.
2017-03-19 00:22:04 -04:00
Augie Fackler
ecf3381175 dispatch: extract maybe-use-repr formatting to helper function
I think this makes the code much clearer. I had to think for a bit to
unpack the old-school `condition and if-true or if-false` dance, and
formatting argument lists here shouldn't be performance critical.
2017-03-19 00:21:26 -04:00
Augie Fackler
956c1da8ce dispatch: consolidate formatting of arguments
This was getting done twice, and it's clever enough I'm about to split
it apart and then fix it for Python 3.
2017-03-19 00:18:53 -04:00
Pulkit Goyal
03903626e4 py3: make the regular expression bytes to prevent TypeError 2017-03-17 05:10:58 +05:30
Yuya Nishihara
877b7b1d1a help: pass commands module by argument
This removes import cycle.
2017-05-21 16:57:32 +09:00
Jun Wu
cf441f3e42 dispatch: make request accept additional reposetups
chg needs special logic around repo object creation (like, collecting and
reporting repo path to the master server). Adding "reposetup" to
dispatch.request seems to be an easy and reasonably clean way to allow that.
2017-04-29 21:39:47 -07:00
Yuya Nishihara
c283f56e61 debugcommands: use temporary dict for its command table
Instead, load the table by commands.py so the debug commands should always
be populated. The table in debugcommands.py is unnamed so extension authors
wouldn't be confused to wrap debugcommands.table in place of commands.table.
2017-05-04 17:13:12 +09:00
Yuya Nishihara
1e7ba75af3 error: add hint to ProgrammingError
As the hint isn't shown by the default exception handler, we need to print
it manually. I've copied the "** " style from _exceptionwarning().
2017-05-14 15:41:27 +09:00
Martin von Zweigbergk
c3406ac3db cleanup: use set literals
We no longer support Python 2.6, so we can now use set literals.
2017-02-10 16:56:29 -08:00
Pulkit Goyal
a52d872f30 py3: make adefaults keys str to be compatible with getattr
getattr passes a str value of the attribute to be looked and keys in adefaults
dict are bytes which resulted in AttributeError. This patch abuses r'' to
make the keys str.
2017-05-04 00:44:53 +05:30
Pulkit Goyal
fb9e5b4f21 py3: use %d instead of %s for integers
dispatch._runcatch() always returns an integer value.
2017-04-21 01:13:18 +05:30
Jun Wu
1894115dcb dispatch: take over SignalInterrupt handling from scmutil
dispatch handles KeyboardInterrupt already. This makes the code more
consistent, and makes worker not print "killed!" if it receives SIGTERM in
most cases (in rare cases there is still "killed!" printed, which will be
fixed by the next patch).
2017-04-22 15:00:17 -07:00
Gregory Szorc
f70b24b885 debugcommands: introduce standalone module for debug commands
commands.py is our largest .py file by nearly 2x. Debug commands live
in a world of their own. So let's extract them to their own module.

We start with "debugancestor."

We currently reuse the commands table with commands.py and have a hack
in dispatch.py for loading debugcommands.py. In the future, we could
potentially use a separate commands table and avoid the import of
debugcommands.py.
2016-08-17 21:07:38 -07:00