##// END OF EJS Templates
interfaces: make the `peer` mixin not a Protocol to fix Python 3.10 failures...
interfaces: make the `peer` mixin not a Protocol to fix Python 3.10 failures I can't find any documentation on this, but it appears that Protocol class attributes don't get inherited in subclasses that explicitly subclass a Protocol until Python 3.11, which caused a ton of failures in CI on macOS and Windows (which both test using Python 3.9). The problem started with 1df97507c6b8, and typically manifested as most tests failing to access `ui` on various `peer` classes. Here's a short proof of concept: from __future__ import annotations from typing import ( Protocol, ) class peer(Protocol): limitedarguments: bool = False def __init__(self, arg1, arg2, remotehidden: bool = False) -> None: self.arg1 = arg1 self.arg2 = arg2 class subclass(peer): def __init__(self, arg1, arg2): super(subclass, self).__init__(arg1, arg2, False) sub = subclass(1, 2) print("sub.arg1 is %r" % sub.arg1) When run with Python 3.8.10, 3.9.13, and 3.10.11, the result is: $ py -3.8 prot-test.py Traceback (most recent call last): File "prot-test.py", line 20, in <module> print("sub.arg1 is %r" % sub.arg1) AttributeError: 'subclass' object has no attribute 'arg1' On Python 3.11.9, 3.12.7, and 3.13.0, the result is: $ py -3.11 ../prot-test.py sub.arg1 is 1 Explicitly adding annotations to `peer` like `limitedarguments` didn't help.

File last commit:

r53339:b3214b7d stable
r53403:199b0e62 default
Show More
ui.py
2345 lines | 83.1 KiB | text/x-python | PythonLexer
mpm@selenic.com
Move ui class to its own module...
r207 # ui.py - user interface bits for mercurial
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
mpm@selenic.com
Move ui class to its own module...
r207 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Move ui class to its own module...
r207
Matt Harbison
typing: add `from __future__ import annotations` to most files...
r52756 from __future__ import annotations
Gregory Szorc
ui: use absolute_import...
r25989
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 import collections
Kostia Balytskyi
ui: add configoverride context manager...
r30480 import contextlib
Joerg Sonnenberger
ui: add option to timestamp status and diagnostic messages...
r45564 import datetime
Gregory Szorc
ui: use absolute_import...
r25989 import errno
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629 import inspect
Gregory Szorc
ui: use absolute_import...
r25989 import os
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392 import re
Augie Fackler
pager: move pager-initiating code into core...
r30992 import signal
Gregory Szorc
ui: use absolute_import...
r25989 import socket
Augie Fackler
pager: move pager-initiating code into core...
r30992 import subprocess
Gregory Szorc
ui: use absolute_import...
r25989 import sys
import traceback
pytype: import typing directly...
r52178 import typing
Gregory Szorc
ui: use absolute_import...
r25989
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 from typing import (
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 Any,
Callable,
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 Dict,
List,
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 NoReturn,
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 Optional,
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 Tuple,
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 Type,
TypeVar,
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 Union,
cast,
Matt Harbison
typing: add type hints to the prompt methods in mercurial/ui.py...
r50694 overload,
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 )
Gregory Szorc
ui: use absolute_import...
r25989 from .i18n import _
from .node import hex
from . import (
Pierre-Yves David
color: move the 'colorlabel' call to the core 'ui' class...
r31087 color,
Gregory Szorc
ui: use absolute_import...
r25989 config,
configitems: introduce a central registry for config option...
r32984 configitems,
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 encoding,
Gregory Szorc
ui: use absolute_import...
r25989 error,
Raphaël Gomès
configitems: move blackbox's config items to the new configitems.toml...
r51658 extensions,
Gregory Szorc
ui: use absolute_import...
r25989 formatter,
Yuya Nishihara
ui: install logger that sends debug.extensions messages to stderr...
r41030 loggingutil,
Gregory Szorc
ui: use absolute_import...
r25989 progress,
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 pycompat,
Gregory Szorc
ui: use absolute_import...
r25989 scmutil,
util,
)
config: move `rcutil` module under a new `mercurial.configuration` module...
r53313 from .configuration import rcutil
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
dateutil,
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil,
Matt Harbison
ui: refactor `readconfig()` into a form that can consume resources...
r44482 resourceutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
urlutil: extract `path` related code into a new module...
r47668 urlutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 )
mpm@selenic.com
Move ui class to its own module...
r207
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 _ConfigItems = Dict[Tuple[bytes, bytes], object] # {(section, name) : value}
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 # The **opts args of the various write() methods can be basically anything, but
# there's no way to express it as "anything but str". So type it to be the
# handful of known types that are used.
_MsgOpts = Union[bytes, bool, List["_PromptChoice"]]
_PromptChoice = Tuple[bytes, bytes]
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 _Tui = TypeVar('_Tui', bound="ui")
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690
liscju
url: remember http password database in ui object...
r29378 urlreq = util.urlreq
Simon Farnsworth
ui: time calls to ui.system...
r30979 # for use with str.translate(None, _keepalnum), to keep just alphanumerics
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 _keepalnum: bytes = b''.join(
Augie Fackler
formatting: blacken the codebase...
r43346 c for c in map(pycompat.bytechr, range(256)) if not c.isalnum()
)
Simon Farnsworth
ui: time calls to ui.system...
r30979
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 # The config knobs that will be altered (if unset) by ui.tweakdefaults.
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 tweakrc: bytes = b"""
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 [ui]
# The rollback command is dangerous. As a rule, don't use it.
rollback = False
Martin von Zweigbergk
tweakdefaults: turn on ui.statuscopies...
r35066 # Make `hg status` report copy information
statuscopies = yes
Augie Fackler
ui: add curses interface to tweakdefaults...
r35307 # Prefer curses UIs when available. Revert to plain-text with `text`.
interface = curses
Martin von Zweigbergk
tweakdefaults: set ui.relative-paths instead of command.status.relative...
r41634 # Make compatible commands emit cwd-relative paths by default.
relative-paths = yes
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872
[commands]
Yuya Nishihara
grep: restore pre-9ef10437bb88 behavior, enable wdir search by tweakdefaults...
r38674 # Grep working directory by default.
grep.all-files = True
Augie Fackler
tweakdefaults: make commands.update.check be `noconflict`...
r34708 # Refuse to perform an `hg update` that would cause a file content merge
update.check = noconflict
Pulkit Goyal
tweakdefaults: add commands.status.verbose to tweakefaults...
r36926 # Show conflicts information in `hg status`
status.verbose = True
Valentin Gatien-Baron
tweakdefaults: make hg resolve require --re-merge flag to re-merge...
r42764 # Make `hg resolve` with no action (like `-m`) fail instead of re-merging.
resolve.explicit-re-merge = True
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872
[diff]
git = 1
Augie Fackler
ui: add diff.showfunc to tweakdefaults...
r35308 showfunc = 1
Augie Fackler
tweakdefaults: enable word-diff by default...
r38642 word-diff = 1
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 """
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 samplehgrcs: Dict[bytes, bytes] = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'user': b"""# example user config (see 'hg help config' for more info)
Matt Mackall
ui: move samplehgrcs from config...
r22419 [ui]
# name and email, e.g.
# username = Jane Doe <jdoe@example.com>
username =
Augie Fackler
ui: recommend tweakdefaults in the default hgrc template...
r34569 # We recommend enabling tweakdefaults to get slight improvements to
# the UI over time. Make sure to set HGPLAIN in the environment when
# writing scripts!
# tweakdefaults = True
Pierre-Yves David
color: reflect the new default in the example hgrc...
r32094 # uncomment to disable color in command output
Pierre-Yves David
color: point to the global help in the example hgrc...
r32095 # (see 'hg help color' for details)
Pierre-Yves David
color: reflect the new default in the example hgrc...
r32094 # color = never
Pierre-Yves David
config: suggest the 'ui.color' instead of the 'color' extension...
r31124
Pierre-Yves David
pager: advertise the config option in the default hgrc...
r32101 # uncomment to disable command output pagination
# (see 'hg help pager' for details)
Pierre-Yves David
pager: rename 'pager.enable' to 'ui.paginate'...
r32105 # paginate = never
Pierre-Yves David
pager: advertise the config option in the default hgrc...
r32101
Matt Mackall
ui: move samplehgrcs from config...
r22419 [extensions]
Jordi Gutiérrez Hermoso
samplehgrcs: clarify which lines should be uncommented...
r42165 # uncomment the lines below to enable some popular extensions
timeless
samplehgrcs: use single quotes in use warning
r29978 # (see 'hg help extensions' for more info)
Matt Mackall
ui: move samplehgrcs from config...
r22419 #
Jordi Gutiérrez Hermoso
samplehgrcs: update the list of suggested extensions...
r42166 # histedit =
# rebase =
# uncommit =
Pierre-Yves David
config: drop pager from the recommended extension...
r32098 """,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'cloned': b"""# example repository config (see 'hg help config' for more info)
Jordi Gutiérrez Hermoso
config: use the same hgrc for a cloned repo as for an uninitted repo...
r22837 [paths]
default = %s
# path aliases to other clones of this repo in URLs or filesystem paths
timeless
samplehgrcs: use single quotes in use warning
r29978 # (see 'hg help config.paths' for more info)
Jordi Gutiérrez Hermoso
config: use the same hgrc for a cloned repo as for an uninitted repo...
r22837 #
Rishabh Madan
ui: replace obsolete default-push with default:pushurl (issue5485)...
r31064 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
# my-fork = ssh://jdoe@example.net/hg/jdoes-fork
# my-clone = /home/jdoe/jdoes-clone
Jordi Gutiérrez Hermoso
config: use the same hgrc for a cloned repo as for an uninitted repo...
r22837
[ui]
# name and email (local to this repository, optional), e.g.
# username = Jane Doe <jdoe@example.com>
""",
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'local': b"""# example repository config (see 'hg help config' for more info)
Jordi Gutiérrez Hermoso
config: give a more detailed sample repo config...
r22836 [paths]
# path aliases to other clones of this repo in URLs or filesystem paths
timeless
samplehgrcs: use single quotes in use warning
r29978 # (see 'hg help config.paths' for more info)
Jordi Gutiérrez Hermoso
config: give a more detailed sample repo config...
r22836 #
Rishabh Madan
ui: replace obsolete default-push with default:pushurl (issue5485)...
r31064 # default = http://example.com/hg/example-repo
# default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
# my-fork = ssh://jdoe@example.net/hg/jdoes-fork
# my-clone = /home/jdoe/jdoes-clone
Jordi Gutiérrez Hermoso
config: give a more detailed sample repo config...
r22836
[ui]
# name and email (local to this repository, optional), e.g.
# username = Jane Doe <jdoe@example.com>
Matt Mackall
ui: move samplehgrcs from config...
r22419 """,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'global': b"""# example system-wide hg config (see 'hg help config' for more info)
Matt Mackall
ui: move samplehgrcs from config...
r22419
Pierre-Yves David
config: suggest the 'ui.color' instead of the 'color' extension...
r31124 [ui]
Pierre-Yves David
color: reflect the new default in the example hgrc...
r32094 # uncomment to disable color in command output
Pierre-Yves David
color: point to the global help in the example hgrc...
r32095 # (see 'hg help color' for details)
Pierre-Yves David
color: reflect the new default in the example hgrc...
r32094 # color = never
Pierre-Yves David
config: suggest the 'ui.color' instead of the 'color' extension...
r31124
Pierre-Yves David
pager: advertise the config option in the default hgrc...
r32101 # uncomment to disable command output pagination
# (see 'hg help pager' for details)
Pierre-Yves David
pager: rename 'pager.enable' to 'ui.paginate'...
r32105 # paginate = never
Pierre-Yves David
pager: advertise the config option in the default hgrc...
r32101
Matt Mackall
ui: move samplehgrcs from config...
r22419 [extensions]
Jordi Gutiérrez Hermoso
samplehgrcs: clarify which lines should be uncommented...
r42165 # uncomment the lines below to enable some popular extensions
timeless
samplehgrcs: use single quotes in use warning
r29978 # (see 'hg help extensions' for more info)
Matt Mackall
ui: move samplehgrcs from config...
r22419 #
# blackbox =
Pierre-Yves David
config: use "churn" as an example extension...
r32097 # churn =
Pierre-Yves David
config: drop pager from the recommended extension...
r32098 """,
Matt Mackall
ui: move samplehgrcs from config...
r22419 }
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483 def _maybestrurl(maybebytes):
Yuya Nishihara
pycompat: move rapply() from util...
r38594 return pycompat.rapply(pycompat.strurl, maybebytes)
Augie Fackler
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483 def _maybebytesurl(maybestr):
Yuya Nishihara
pycompat: move rapply() from util...
r38594 return pycompat.rapply(pycompat.bytesurl, maybestr)
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class httppasswordmgrdbproxy:
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945 """Delays loading urllib2 until it's needed."""
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def __init__(self) -> None:
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945 self._mgr = None
def _get_mgr(self):
if self._mgr is None:
self._mgr = urlreq.httppasswordmgrwithdefaultrealm()
return self._mgr
Augie Fackler
httppasswordmgrdbproxy: specify exact arguments...
r34427 def add_password(self, realm, uris, user, passwd):
Augie Fackler
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483 return self._get_mgr().add_password(
Augie Fackler
formatting: blacken the codebase...
r43346 _maybestrurl(realm),
_maybestrurl(uris),
_maybestrurl(user),
_maybestrurl(passwd),
)
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945
Augie Fackler
httppasswordmgrdbproxy: specify exact arguments...
r34427 def find_user_password(self, realm, uri):
Yuya Nishihara
py3: factor out helpers to apply string conversion recursively
r35918 mgr = self._get_mgr()
Augie Fackler
formatting: blacken the codebase...
r43346 return _maybebytesurl(
mgr.find_user_password(_maybestrurl(realm), _maybestrurl(uri))
)
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _catchterm(*args) -> NoReturn:
Augie Fackler
pager: move pager-initiating code into core...
r30992 raise error.SignalInterrupt
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945
Augie Fackler
formatting: blacken the codebase...
r43346
config: explicitly track the use of the standard default value...
r32958 # unique object used to detect no default value has been provided when
# retrieving configuration value.
_unset = object()
Saurabh Singh
ui: move request exit handlers to global state...
r34883 # _reqexithandlers: callbacks run at the end of a request
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 _reqexithandlers: List = []
Saurabh Singh
ui: move request exit handlers to global state...
r34883
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class ui:
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def __init__(self, src: Optional["ui"] = None) -> None:
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 """Create a fresh new ui object if no src given
Use uimod.ui.load() to create a ui which knows global and user configs.
In most cases, you should use ui.copy() to create a copy of an existing
ui object.
"""
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 # _buffers: used for temporary capture of output
Matt Mackall
ui: buffers -> _buffers
r8202 self._buffers = []
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 # 3-tuple describing how each buffer in the stack behaves.
# Values are (capture stderr, capture subprocesses, apply labels).
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 self._bufferstates = []
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 # When a buffer is active, defines whether we are expanding labels.
# This exists to prevent an extra list lookup.
self._bufferapplylabels = None
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
Matt Mackall
ui: make interactive a method
r8208 self._reportuntrusted = True
configitems: introduce a central registry for config option...
r32984 self._knownconfig = configitems.coreitems
Augie Fackler
formatting: blacken the codebase...
r43346 self._ocfg = config.config() # overlay
self._tcfg = config.config() # trusted
self._ucfg = config.config() # untrusted
Martin Geisler
ui: use set instead of dict
r8478 self._trustusers = set()
self._trustgroups = set()
Idan Kamara
ui: add a variable to control whether hooks should be called...
r17048 self.callhooks = True
urlutil: move url "fixing" at the time of `ui.paths` initialization...
r48046 # hold the root to use for each [paths] entry
self._path_to_root = {}
Gregory Szorc
ui: add an instance flag to hold --insecure bit...
r29109 # Insecure server connections requested.
self.insecureconnections = False
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 # Blocked time
self.logblockedtimes = False
Pierre-Yves David
color: have the 'ui' object carry the '_colormode' directly...
r31106 # color mode: see mercurial/color.py for possible value
self._colormode = None
Pierre-Yves David
color: move the dict with terminfo parameters on the ui object...
r31113 self._terminfoparams = {}
Pierre-Yves David
color: move 'styles' definition on the 'ui' object...
r31115 self._styles = {}
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 self._uninterruptible = False
Joerg Sonnenberger
ui: add option to timestamp status and diagnostic messages...
r45564 self.showtimestamp = False
Matt Mackall
ui: refactor option setting...
r8136
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 if src:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 self._fout = src._fout
self._ferr = src._ferr
self._fin = src._fin
Yuya Nishihara
dispatch: pass around ui.fmsg channel...
r40623 self._fmsg = src._fmsg
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 self._fmsgout = src._fmsgout
self._fmsgerr = src._fmsgerr
Yuya Nishihara
chgserver: do not send system() back to client if stdio redirected (issue5992)...
r39875 self._finoutredirected = src._finoutredirected
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 self._loggers = src._loggers.copy()
Augie Fackler
pager: move pager-initiating code into core...
r30992 self.pageractive = src.pageractive
Augie Fackler
ui: rename neverpager to disablepager...
r31026 self._disablepager = src._disablepager
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 self._tweaked = src._tweaked
Idan Kamara
ui: add I/O descriptors
r14612
Matt Mackall
ui: privatize cdata vars
r8203 self._tcfg = src._tcfg.copy()
self._ucfg = src._ucfg.copy()
self._ocfg = src._ocfg.copy()
Matt Mackall
ui: trusted_users -> _trustusers, trusted_groups -> _trustgroups
r8201 self._trustusers = src._trustusers.copy()
self._trustgroups = src._trustgroups.copy()
Sune Foldager
ui: add environ property to access os.environ or wsgirequest.environ...
r9887 self.environ = src.environ
Idan Kamara
ui: add a variable to control whether hooks should be called...
r17048 self.callhooks = src.callhooks
urlutil: move url "fixing" at the time of `ui.paths` initialization...
r48046 self._path_to_root = src._path_to_root
Gregory Szorc
ui: add an instance flag to hold --insecure bit...
r29109 self.insecureconnections = src.insecureconnections
Pierre-Yves David
color: have the 'ui' object carry the '_colormode' directly...
r31106 self._colormode = src._colormode
Pierre-Yves David
color: move the dict with terminfo parameters on the ui object...
r31113 self._terminfoparams = src._terminfoparams.copy()
Pierre-Yves David
color: move 'styles' definition on the 'ui' object...
r31115 self._styles = src._styles.copy()
Pierre-Yves David
color: have the 'ui' object carry the '_colormode' directly...
r31106
Matt Mackall
ui: simplify init, kill dupconfig
r8143 self.fixconfig()
liscju
url: remember http password database in ui object...
r29378
self.httppasswordmgrdb = src.httppasswordmgrdb
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 self._blockedtimes = src._blockedtimes
Matt Mackall
ui: simplify init, kill dupconfig
r8143 else:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 self._fout = procutil.stdout
self._ferr = procutil.stderr
self._fin = procutil.stdin
Yuya Nishihara
dispatch: pass around ui.fmsg channel...
r40623 self._fmsg = None
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 self._fmsgout = self.fout # configurable
self._fmsgerr = self.ferr # configurable
Yuya Nishihara
chgserver: do not send system() back to client if stdio redirected (issue5992)...
r39875 self._finoutredirected = False
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 self._loggers = {}
Augie Fackler
pager: move pager-initiating code into core...
r30992 self.pageractive = False
Augie Fackler
ui: rename neverpager to disablepager...
r31026 self._disablepager = False
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 self._tweaked = False
Idan Kamara
ui: add I/O descriptors
r14612
Sune Foldager
ui: add environ property to access os.environ or wsgirequest.environ...
r9887 # shared read-only environment
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 4 of 5)
r30637 self.environ = encoding.environ
Dirkjan Ochtman
more whitespace cleanup and some other style nits
r8222
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945 self.httppasswordmgrdb = httppasswordmgrdbproxy()
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 self._blockedtimes = collections.defaultdict(int)
liscju
url: remember http password database in ui object...
r29378
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 allowed = self.configlist(b'experimental', b'exportableenviron')
if b'*' in allowed:
Matt Harbison
ui: introduce an experimental dict of exportable environment variables...
r30832 self._exportableenviron = self.environ
else:
self._exportableenviron = {}
for k in allowed:
if k in self.environ:
self._exportableenviron[k] = self.environ[k]
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _new_source(self) -> None:
config: track the "level" of a value...
r47367 self._ocfg.new_source()
self._tcfg.new_source()
self._ucfg.new_source()
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 @classmethod
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def load(cls: Type[_Tui]) -> _Tui:
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 """Create a ui and load global and user configs"""
u = cls()
Jun Wu
rcutil: let environ override system configs (BC)...
r31685 # we always trust global config files and environment variables
config: include the component level when returning them...
r53323 for _lvl, t, f in rcutil.rccomponents():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if t == b'path':
Jun Wu
rcutil: let rccomponents return different types of configs (API)...
r31683 u.readconfig(f, trust=True)
Matt Harbison
ui: add the ability to apply `defaultrc` configs from resources...
r44483 elif t == b'resource':
u.read_resource_config(f, trust=True)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif t == b'items':
config: track the "level" of a value...
r47367 u._new_source()
Jun Wu
rcutil: let environ override system configs (BC)...
r31685 sections = set()
for section, name, value, source in f:
# do not set u._ocfg
# XXX clean this up once immutable config object is a thing
u._tcfg.set(section, name, value, source)
u._ucfg.set(section, name, value, source)
sections.add(section)
for section in sections:
u.fixconfig(section=section)
Jun Wu
rcutil: let rccomponents return different types of configs (API)...
r31683 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.ProgrammingError(b'unknown rctype: %s' % t)
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 u._maybetweakdefaults()
config: track the "level" of a value...
r47367 u._new_source() # anything after that is a different level
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 return u
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _maybetweakdefaults(self) -> None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not self.configbool(b'ui', b'tweakdefaults'):
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._tweaked or self.plain(b'tweakdefaults'):
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 return
# Note: it is SUPER IMPORTANT that you set self._tweaked to
# True *before* any calls to setconfig(), otherwise you'll get
# infinite recursion between setconfig and this method.
#
# TODO: We should extract an inner method in setconfig() to
# avoid this weirdness.
self._tweaked = True
tmpcfg = config.config()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tmpcfg.parse(b'<tweakdefaults>', tweakrc)
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 for section in tmpcfg:
for name, value in tmpcfg.items(section):
if not self.hasconfig(section, name):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.setconfig(section, name, value, b"<tweakdefaults>")
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def copy(self: _Tui) -> _Tui:
Ronny Pfannschmidt
ui: ui.copy() now takes the ui class into account...
r8220 return self.__class__(self)
Thomas Arendsen Hein
Create local ui object per repository, so .hg/hgrc don't get mixed....
r1839
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def resetstate(self) -> None:
Yuya Nishihara
ui: provide official way to reset internal state per command...
r29366 """Clear internal state that shouldn't persist across commands"""
if self._progbar:
self._progbar.resetstate() # reset last-print time of progress bar
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945 self.httppasswordmgrdb = httppasswordmgrdbproxy()
Yuya Nishihara
ui: provide official way to reset internal state per command...
r29366
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 @contextlib.contextmanager
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def timeblockedsection(self, key: bytes):
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 # this is open-coded below - search for timeblockedsection to find them
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 starttime = util.timer()
try:
yield
finally:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._blockedtimes[key + b'_blocked'] += (
Augie Fackler
formatting: blacken the codebase...
r43346 util.timer() - starttime
) * 1000
Yuya Nishihara
ui: provide official way to reset internal state per command...
r29366
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 @contextlib.contextmanager
Kyle Lippincott
procutil: correct spelling of uninterruptable -> uninterruptible...
r41106 def uninterruptible(self):
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 """Mark an operation as unsafe.
Most operations on a repository are safe to interrupt, but a
few are risky (for example repair.strip). This context manager
lets you advise Mercurial that something risky is happening so
that control-C etc can be blocked if desired.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 enabled = self.configbool(b'experimental', b'nointerrupt')
Augie Fackler
formatting: blacken the codebase...
r43346 if enabled and self.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'experimental', b'nointerrupt-interactiveonly'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 enabled = self.interactive()
if self._uninterruptible or not enabled:
# if nointerrupt support is turned off, the process isn't
Kyle Lippincott
procutil: correct spelling of uninterruptable -> uninterruptible...
r41106 # interactive, or we're already in an uninterruptible
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 # block, do nothing.
yield
return
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 def warn():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.warn(_(b"shutting down cleanly\n"))
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"press ^C again to terminate immediately (dangerous)\n")
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 return True
Augie Fackler
formatting: blacken the codebase...
r43346
Kyle Lippincott
procutil: correct spelling of uninterruptable -> uninterruptible...
r41106 with procutil.uninterruptible(warn):
Augie Fackler
ui: add an uninterruptable context manager that can block SIGINT...
r38545 try:
self._uninterruptible = True
yield
finally:
self._uninterruptible = False
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def formatter(self, topic: bytes, opts):
Yuya Nishihara
formatter: add option to redirect output to file object...
r32573 return formatter.formatter(self, self, topic, opts)
Matt Mackall
ui: add formatter method
r16135
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _trusted(self, fp, f: bytes) -> bool:
Alexis S. L. Carvalho
Avoid looking up usernames if the current user owns the .hgrc file...
r3677 st = util.fstat(fp)
Martin Geisler
posix: do not use fstat in isowner...
r8657 if util.isowner(st):
Alexis S. L. Carvalho
Avoid looking up usernames if the current user owns the .hgrc file...
r3677 return True
Matt Mackall
ui: cleanup _is_trusted a bit
r8141
Matt Mackall
ui: trusted_users -> _trustusers, trusted_groups -> _trustgroups
r8201 tusers, tgroups = self._trustusers, self._trustgroups
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'*' in tusers or b'*' in tgroups:
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 return True
user = util.username(st.st_uid)
group = util.groupname(st.st_gid)
if user in tusers or group in tgroups or user == util.username():
return True
Matt Mackall
ui: report_untrusted fixes...
r8204 if self._reportuntrusted:
Augie Fackler
formatting: blacken the codebase...
r43346 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(
b'not trusting file %s from untrusted '
b'user %s, group %s\n'
)
Augie Fackler
formatting: blacken the codebase...
r43346 % (f, user, group)
)
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 return False
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551
Matt Harbison
ui: refactor `readconfig()` into a form that can consume resources...
r44482 def read_resource_config(
self, name, root=None, trust=False, sections=None, remap=None
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 ) -> None:
Matt Harbison
ui: refactor `readconfig()` into a form that can consume resources...
r44482 try:
fp = resourceutil.open_resource(name[0], name[1])
except IOError:
if not sections: # ignore unless we were looking for something
return
raise
self._readconfig(
b'resource:%s.%s' % name, fp, root, trust, sections, remap
)
Augie Fackler
formatting: blacken the codebase...
r43346 def readconfig(
self, filename, root=None, trust=False, sections=None, remap=None
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 ) -> None:
Matt Mackall
ui: fold readsections into readconfig...
r8142 try:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 fp = open(filename, 'rb')
Matt Mackall
ui: fold readsections into readconfig...
r8142 except IOError:
Augie Fackler
formatting: blacken the codebase...
r43346 if not sections: # ignore unless we were looking for something
Matt Mackall
ui: fold readsections into readconfig...
r8142 return
raise
Matt Mackall
ui: always have ucdata...
r8139
Matt Harbison
ui: refactor `readconfig()` into a form that can consume resources...
r44482 self._readconfig(filename, fp, root, trust, sections, remap)
def _readconfig(
self, filename, fp, root=None, trust=False, sections=None, remap=None
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 ) -> None:
Martin von Zweigbergk
config: close file even if we fail to read it...
r44362 with fp:
cfg = config.config()
trusted = sections or trust or self._trusted(fp, filename)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Martin von Zweigbergk
config: close file even if we fail to read it...
r44362 try:
cfg.read(filename, fp, sections=sections, remap=remap)
Martin von Zweigbergk
errors: raise ConfigError on failure to parse config file...
r46506 except error.ConfigError as inst:
Martin von Zweigbergk
config: close file even if we fail to read it...
r44362 if trusted:
raise
Martin von Zweigbergk
config: clean up message about ignored untrusted config...
r46501 self.warn(
_(b'ignored %s: %s\n') % (inst.location, inst.message)
)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Matt Harbison
config: add a function to insert non-file based, but overridable settings...
r44585 self._applyconfig(cfg, trusted, root)
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def applyconfig(
self, configitems: _ConfigItems, source=b"", root=None
) -> None:
Matt Harbison
config: add a function to insert non-file based, but overridable settings...
r44585 """Add configitems from a non-file source. Unlike with ``setconfig()``,
they can be overridden by subsequent config file reads. The items are
in the same format as ``configoverride()``, namely a dict of the
following structures: {(section, name) : value}
Typically this is used by extensions that inject themselves into the
config file load procedure by monkeypatching ``localrepo.loadhgrc()``.
"""
cfg = config.config()
for (section, name), value in configitems.items():
cfg.set(section, name, value, source)
self._applyconfig(cfg, True, root)
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _applyconfig(self, cfg, trusted, root) -> None:
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 if self.plain():
Augie Fackler
formatting: blacken the codebase...
r43346 for k in (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'debug',
b'fallbackencoding',
b'quiet',
b'slash',
b'logtemplate',
b'message-output',
b'statuscopies',
b'style',
b'traceback',
b'verbose',
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if k in cfg[b'ui']:
del cfg[b'ui'][k]
for k, v in cfg.items(b'defaults'):
del cfg[b'defaults'][k]
for k, v in cfg.items(b'commands'):
del cfg[b'commands'][k]
Martin von Zweigbergk
config: add a new [command-templates] section for templates defined by hg...
r46350 for k, v in cfg.items(b'command-templates'):
del cfg[b'command-templates'][k]
"Yann E. MORIN"
ui: enable alias exception when reading config in plain mode...
r14373 # Don't remove aliases from the configuration if in the exceptionlist
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.plain(b'alias'):
for k, v in cfg.items(b'alias'):
del cfg[b'alias'][k]
if self.plain(b'revsetalias'):
for k, v in cfg.items(b'revsetalias'):
del cfg[b'revsetalias'][k]
if self.plain(b'templatealias'):
for k, v in cfg.items(b'templatealias'):
del cfg[b'templatealias'][k]
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455
Matt Mackall
ui: fold readsections into readconfig...
r8142 if trusted:
Matt Mackall
ui: privatize cdata vars
r8203 self._tcfg.update(cfg)
self._tcfg.update(self._ocfg)
self._ucfg.update(cfg)
self._ucfg.update(self._ocfg)
Matt Mackall
ui: always have ucdata...
r8139
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347 if root is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 root = os.path.expanduser(b'~')
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347 self.fixconfig(root=root)
Alexis S. L. Carvalho
load extensions only after the ui object has been completely initialized...
r3014
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def fixconfig(self, root=None, section=None) -> None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if section in (None, b'paths'):
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 # expand vars and ~
# translate paths relative to root (or home) into absolute paths
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 root = root or encoding.getcwd()
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 for c in self._tcfg, self._ucfg, self._ocfg:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for n, p in c.items(b'paths'):
urlutil: move url "fixing" at the time of `ui.paths` initialization...
r48046 old_p = p
s = self.configsource(b'paths', n) or b'none'
root_key = (n, p, s)
if root_key not in self._path_to_root:
self._path_to_root[root_key] = root
Gregory Szorc
ui: don't fixup [paths] sub-options...
r29412 # Ignore sub-options.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b':' in n:
Gregory Szorc
ui: don't fixup [paths] sub-options...
r29412 continue
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if not p:
continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'%%' in p:
urlutil: move url "fixing" at the time of `ui.paths` initialization...
r48046 if s is None:
s = 'none'
Augie Fackler
formatting: blacken the codebase...
r43346 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"(deprecated '%%' in path %s=%s from %s)\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % (n, p, s)
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 p = p.replace(b'%%', b'%')
urlutil: move url "fixing" at the time of `ui.paths` initialization...
r48046 if p != old_p:
c.alter(b"paths", n, p)
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if section in (None, b'ui'):
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 # update ui options
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 self._fmsgout, self._fmsgerr = _selectmsgdests(self)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.debugflag = self.configbool(b'ui', b'debug')
self.verbose = self.debugflag or self.configbool(b'ui', b'verbose')
self.quiet = not self.debugflag and self.configbool(b'ui', b'quiet')
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if self.verbose and self.quiet:
self.quiet = self.verbose = False
Augie Fackler
formatting: blacken the codebase...
r43346 self._reportuntrusted = self.debugflag or self.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"ui", b"report_untrusted"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Joerg Sonnenberger
ui: add option to timestamp status and diagnostic messages...
r45564 self.showtimestamp = self.configbool(b'ui', b'timestamp-output')
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.tracebackflag = self.configbool(b'ui', b'traceback')
self.logblockedtimes = self.configbool(b'ui', b'logblockedtimes')
Alexis S. L. Carvalho
update ui.quiet/verbose/debug/interactive every time the config changes...
r3350
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if section in (None, b'trusted'):
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 # update trust information
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._trustusers.update(self.configlist(b'trusted', b'users'))
self._trustgroups.update(self.configlist(b'trusted', b'groups'))
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551
Yuya Nishihara
ui: install logger that sends debug.extensions messages to stderr...
r41030 if section in (None, b'devel', b'ui') and self.debugflag:
tracked = set()
if self.configbool(b'devel', b'debug.extensions'):
tracked.add(b'extension')
if tracked:
logger = loggingutil.fileobjectlogger(self._ferr, tracked)
self.setlogger(b'debug', logger)
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 def backupconfig(self, section, item):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
self._ocfg.backup(section, item),
self._tcfg.backup(section, item),
self._ucfg.backup(section, item),
)
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def restoreconfig(self, data) -> None:
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 self._ocfg.restore(data[0])
self._tcfg.restore(data[1])
self._ucfg.restore(data[2])
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def setconfig(self, section, name, value, source=b'') -> None:
Mads Kiilerich
config: backout 77f1f206e135 - 743daa601445 removed the only use of overlay
r20787 for cfg in (self._ocfg, self._tcfg, self._ucfg):
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 cfg.set(section, name, value, source)
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 self.fixconfig(section=section)
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 self._maybetweakdefaults()
mpm@selenic.com
Add ui.setconfig overlay...
r960
Matt Mackall
ui: _get_cdata -> _data
r8199 def _data(self, untrusted):
Matt Mackall
ui: privatize cdata vars
r8203 return untrusted and self._ucfg or self._tcfg
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Matt Mackall
showconfig: show source file and line with --debug
r8182 def configsource(self, section, name, untrusted=False):
Yuya Nishihara
ui: do not translate empty configsource() to 'none' (API)...
r30618 return self._data(untrusted).source(section, name)
Matt Mackall
showconfig: show source file and line with --debug
r8182
config: explicitly track the use of the standard default value...
r32958 def config(self, section, name, default=_unset, untrusted=False):
config: extract the core config logic into a private method...
r33058 """return the plain string version of a config"""
Augie Fackler
formatting: blacken the codebase...
r43346 value = self._config(
section, name, default=default, untrusted=untrusted
)
config: extract the core config logic into a private method...
r33058 if value is _unset:
return None
return value
def _config(self, section, name, default=_unset, untrusted=False):
Yuya Nishihara
configitems: relax warning about unwanted default value...
r34949 value = itemdefault = default
David Demelier
configitems: add alias support in config...
r33329 item = self._knownconfig.get(section, {}).get(name)
alternates = [(section, name)]
Raphaël Gomès
configitems: move blackbox's config items to the new configitems.toml...
r51658 if item is not None and item.in_core_extension is not None:
# Only return the default for an in-core extension item if said
# extension is enabled
if item.in_core_extension in extensions.extensions(self):
item = None
David Demelier
configitems: add alias support in config...
r33329 if item is not None:
alternates.extend(item.alias)
Yuya Nishihara
configitems: relax warning about unwanted default value...
r34949 if callable(item.default):
itemdefault = item.default()
else:
itemdefault = item.default
Boris Feld
configitems: adds a developer warning when accessing undeclared configuration...
r34859 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = b"accessing unregistered config item: '%s.%s'"
Boris Feld
configitems: adds a developer warning when accessing undeclared configuration...
r34859 msg %= (section, name)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.develwarn(msg, 2, b'warn-config-unknown')
David Demelier
configitems: add alias support in config...
r33329
if default is _unset:
if item is None:
value = default
Boris Feld
configitems: handle case were the default value is not static...
r33471 elif item.default is configitems.dynamicdefault:
value = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = b"config item requires an explicit default value: '%s.%s'"
Boris Feld
configitems: handle case were the default value is not static...
r33471 msg %= (section, name)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.develwarn(msg, 2, b'warn-config-default')
David Demelier
configitems: add alias support in config...
r33329 else:
Yuya Nishihara
configitems: relax warning about unwanted default value...
r34949 value = itemdefault
Augie Fackler
formatting: blacken the codebase...
r43346 elif (
item is not None
and item.default is not configitems.dynamicdefault
and default != itemdefault
):
msg = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"specifying a mismatched default value for a registered "
b"config item: '%s.%s' '%s'"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
ui: use pycompat.bytestr() to get a bytes-repr of config default...
r36143 msg %= (section, name, pycompat.bytestr(default))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.develwarn(msg, 2, b'warn-config-default')
configitems: issue a devel warning when overriding default config...
r32987
config: use level to properly deal with value priority...
r47368 candidates = []
config = self._data(untrusted)
David Demelier
configitems: add alias support in config...
r33329 for s, n in alternates:
config: use level to properly deal with value priority...
r47368 candidate = config.get(s, n, None)
config: extract the core config logic into a private method...
r33058 if candidate is not None:
config: use level to properly deal with value priority...
r47368 candidates.append((s, n, candidate))
if candidates:
def level(x):
return config.level(x[0], x[1])
value = max(candidates, key=level)[2]
Matt Mackall
ui: allow alternatives for config options
r15035
Matt Mackall
ui: report_untrusted fixes...
r8204 if self.debugflag and not untrusted and self._reportuntrusted:
David Demelier
configitems: add alias support in config...
r33329 for s, n in alternates:
uvalue = self._ucfg.get(s, n)
Augie Fackler
ui.config: fix bug in config alternatives from cc669e4fec95
r19536 if uvalue is not None and uvalue != value:
Augie Fackler
formatting: blacken the codebase...
r43346 self.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"ignoring untrusted configuration option "
b"%s.%s = %s\n" % (s, n, uvalue)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 return value
Alexis S. L. Carvalho
ui.py: move common code out of config and configbool
r3341
ui: add a "config_default" method...
r46893 def config_default(self, section, name):
"""return the default value for a config option
The default is returned "raw", for example if it is a callable, the
callable was not called.
"""
item = self._knownconfig.get(section, {}).get(name)
if item is None:
raise KeyError((section, name))
return item.default
config: use the new '_unset' value for 'configsuboptions'...
r32967 def configsuboptions(self, section, name, default=_unset, untrusted=False):
Gregory Szorc
ui: add method to return option and all sub-options...
r27252 """Get a config option and all sub-options.
Some config options have sub-options that are declared with the
format "key:opt = value". This method is used to return the main
option and all its declared sub-options.
Returns a 2-tuple of ``(option, sub-options)``, where `sub-options``
is a dict of defined sub-options where keys and values are strings.
"""
config: use the 'config' method in 'configsuboptions'...
r32966 main = self.config(section, name, default, untrusted=untrusted)
Gregory Szorc
ui: add method to return option and all sub-options...
r27252 data = self._data(untrusted)
sub = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix = b'%s:' % name
Gregory Szorc
ui: add method to return option and all sub-options...
r27252 for k, v in data.items(section):
if k.startswith(prefix):
Augie Fackler
formatting: blacken the codebase...
r43346 sub[k[len(prefix) :]] = v
Gregory Szorc
ui: add method to return option and all sub-options...
r27252
if self.debugflag and not untrusted and self._reportuntrusted:
for k, v in sub.items():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 uvalue = self._ucfg.get(section, b'%s:%s' % (name, k))
Gregory Szorc
ui: add method to return option and all sub-options...
r27252 if uvalue is not None and uvalue != v:
Augie Fackler
formatting: blacken the codebase...
r43346 self.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'ignoring untrusted configuration option '
b'%s:%s.%s = %s\n' % (section, name, k, uvalue)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
ui: add method to return option and all sub-options...
r27252
return main, sub
config: use the new '_unset' value for 'configpath'...
r32965 def configpath(self, section, name, default=_unset, untrusted=False):
Matt Harbison
cleanup: fix docstring formatting...
r44226 """get a path config item, expanded relative to repo root or config
file"""
Matt Mackall
ui: add configpath helper
r13238 v = self.config(section, name, default, untrusted)
Simon Heimberg
ui: providing no default value to configpath should not raise an Error
r14923 if v is None:
return None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not os.path.isabs(v) or b"://" not in v:
Matt Mackall
ui: add configpath helper
r13238 src = self.configsource(section, name, untrusted)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b':' in src:
base = os.path.dirname(src.rsplit(b':')[0])
Matt Mackall
ui: add configpath helper
r13238 v = os.path.join(base, os.path.expanduser(v))
return v
config: use the new '_unset' value for 'configbool'...
r32959 def configbool(self, section, name, default=_unset, untrusted=False):
Sune Foldager
ui: add configint function and tests
r14171 """parse a configuration element as a boolean
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u = ui(); s = b'foo'
>>> u.setconfig(s, b'true', b'yes')
>>> u.configbool(s, b'true')
Sune Foldager
ui: add configint function and tests
r14171 True
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'false', b'no')
>>> u.configbool(s, b'false')
Sune Foldager
ui: add configint function and tests
r14171 False
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.configbool(s, b'unknown')
Sune Foldager
ui: add configint function and tests
r14171 False
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.configbool(s, b'unknown', True)
Sune Foldager
ui: add configint function and tests
r14171 True
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'invalid', b'somevalue')
>>> u.configbool(s, b'invalid')
Sune Foldager
ui: add configint function and tests
r14171 Traceback (most recent call last):
...
ConfigError: foo.invalid is not a boolean ('somevalue')
"""
config: use '_config' within 'configbool'...
r33059 v = self._config(section, name, default, untrusted=untrusted)
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if v is None:
config: use '_config' within 'configbool'...
r33059 return v
if v is _unset:
config: use the new '_unset' value for 'configbool'...
r32959 if default is _unset:
return False
Matt Mackall
ui: introduce new config parser
r8144 return default
Dirkjan Ochtman
ui: just return it if it's already a bool
r10243 if isinstance(v, bool):
return v
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 b = stringutil.parsebool(v)
Augie Fackler
parsebool: create new function and use it for config parsing
r12087 if b is None:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ConfigError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"%s.%s is not a boolean ('%s')") % (section, name, v)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
parsebool: create new function and use it for config parsing
r12087 return b
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Augie Fackler
formatting: blacken the codebase...
r43346 def configwith(
self, convert, section, name, default=_unset, desc=None, untrusted=False
):
Bryan O'Sullivan
ui: add a configwith method...
r30926 """parse a configuration element with a conversion function
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u = ui(); s = b'foo'
>>> u.setconfig(s, b'float1', b'42')
>>> u.configwith(float, s, b'float1')
Bryan O'Sullivan
ui: add a configwith method...
r30926 42.0
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'float2', b'-4.25')
>>> u.configwith(float, s, b'float2')
Jun Wu
ui: fix configwith doctest...
r30932 -4.25
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.configwith(float, s, b'unknown', 7)
config: use the new '_unset' value for 'configwith'...
r32960 7.0
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'invalid', b'somevalue')
>>> u.configwith(float, s, b'invalid')
Bryan O'Sullivan
ui: add a configwith method...
r30926 Traceback (most recent call last):
...
ConfigError: foo.invalid is not a valid float ('somevalue')
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.configwith(float, s, b'invalid', desc=b'womble')
Bryan O'Sullivan
ui: add a configwith method...
r30926 Traceback (most recent call last):
...
ConfigError: foo.invalid is not a valid womble ('somevalue')
"""
config: use the new '_unset' value for 'configwith'...
r32960 v = self.config(section, name, default, untrusted)
Bryan O'Sullivan
ui: add a configwith method...
r30926 if v is None:
Augie Fackler
formatting: blacken the codebase...
r43346 return v # do not attempt to convert None
Bryan O'Sullivan
ui: add a configwith method...
r30926 try:
return convert(v)
Boris Feld
util: raise ParseError when parsing dates (BC)...
r32462 except (ValueError, error.ParseError):
Bryan O'Sullivan
ui: add a configwith method...
r30926 if desc is None:
Yuya Nishihara
py3: convert function name to bytes in ui.configwith()
r34205 desc = pycompat.sysbytes(convert.__name__)
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ConfigError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"%s.%s is not a valid %s ('%s')") % (section, name, desc, v)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Bryan O'Sullivan
ui: add a configwith method...
r30926
config: use the new '_unset' value for 'configint'...
r32961 def configint(self, section, name, default=_unset, untrusted=False):
Sune Foldager
ui: add configint function and tests
r14171 """parse a configuration element as an integer
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u = ui(); s = b'foo'
>>> u.setconfig(s, b'int1', b'42')
>>> u.configint(s, b'int1')
Sune Foldager
ui: add configint function and tests
r14171 42
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'int2', b'-42')
>>> u.configint(s, b'int2')
Sune Foldager
ui: add configint function and tests
r14171 -42
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.configint(s, b'unknown', 7)
Sune Foldager
ui: add configint function and tests
r14171 7
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'invalid', b'somevalue')
>>> u.configint(s, b'invalid')
Sune Foldager
ui: add configint function and tests
r14171 Traceback (most recent call last):
...
Bryan O'Sullivan
ui: rewrite configint in terms of configwith
r30927 ConfigError: foo.invalid is not a valid integer ('somevalue')
Sune Foldager
ui: add configint function and tests
r14171 """
Augie Fackler
formatting: blacken the codebase...
r43346 return self.configwith(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 int, section, name, default, b'integer', untrusted
Augie Fackler
formatting: blacken the codebase...
r43346 )
Sune Foldager
ui: add configint function and tests
r14171
config: use the new '_unset' value for 'configbytes'...
r32962 def configbytes(self, section, name, default=_unset, untrusted=False):
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 """parse a configuration element as a quantity in bytes
Units can be specified as b (bytes), k or kb (kilobytes), m or
mb (megabytes), g or gb (gigabytes).
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u = ui(); s = b'foo'
>>> u.setconfig(s, b'val1', b'42')
>>> u.configbytes(s, b'val1')
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 42
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'val2', b'42.5 kb')
>>> u.configbytes(s, b'val2')
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 43520
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.configbytes(s, b'unknown', b'7 MB')
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 7340032
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u.setconfig(s, b'invalid', b'somevalue')
>>> u.configbytes(s, b'invalid')
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 Traceback (most recent call last):
...
ConfigError: foo.invalid is not a byte quantity ('somevalue')
"""
config: use '_config' within 'configbytes'...
r33060 value = self._config(section, name, default, untrusted)
if value is _unset:
config: use the new '_unset' value for 'configbytes'...
r32962 if default is _unset:
default = 0
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 value = default
Augie Fackler
ui: fix configbytes isinstance check to look for bytes and not str...
r33586 if not isinstance(value, bytes):
config: use the new '_unset' value for 'configbytes'...
r32962 return value
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 try:
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 return util.sizetoint(value)
except error.ParseError:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.ConfigError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"%s.%s is not a byte quantity ('%s')")
Augie Fackler
formatting: blacken the codebase...
r43346 % (section, name, value)
)
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065
config: use the new '_unset' value for 'configlist'...
r32963 def configlist(self, section, name, default=_unset, untrusted=False):
Sune Foldager
ui: add configint function and tests
r14171 """parse a configuration element as a list of comma/space separated
strings
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u = ui(); s = b'foo'
>>> u.setconfig(s, b'list1', b'this,is "a small" ,test')
>>> u.configlist(s, b'list1')
Sune Foldager
ui: add configint function and tests
r14171 ['this', 'is', 'a small', 'test']
Augie Fackler
ui: add configlist doctest to document a bit more of the whitespace behavior...
r34958 >>> u.setconfig(s, b'list2', b'this, is "a small" , test ')
>>> u.configlist(s, b'list2')
['this', 'is', 'a small', 'test']
Sune Foldager
ui: add configint function and tests
r14171 """
Jun Wu
ui: move configlist parser to config.py...
r31481 # default is not always a list
Augie Fackler
formatting: blacken the codebase...
r43346 v = self.configwith(
parselist: move the function from config to stringutil...
r47960 stringutil.parselist, section, name, default, b'list', untrusted
Augie Fackler
formatting: blacken the codebase...
r43346 )
config: use the new '_unset' value for 'configlist'...
r32963 if isinstance(v, bytes):
parselist: move the function from config to stringutil...
r47960 return stringutil.parselist(v)
config: use the new '_unset' value for 'configlist'...
r32963 elif v is None:
return []
return v
Thomas Arendsen Hein
Added ui.configlist method to get comma/space separated lists of strings....
r2499
config: use the new '_unset' value for 'configdate'...
r32964 def configdate(self, section, name, default=_unset, untrusted=False):
Boris Feld
ui: add the possiblity to get a date config field...
r32408 """parse a configuration element as a tuple of ints
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> u = ui(); s = b'foo'
>>> u.setconfig(s, b'date', b'0 0')
>>> u.configdate(s, b'date')
Boris Feld
ui: add the possiblity to get a date config field...
r32408 (0, 0)
"""
if self.config(section, name, default, untrusted):
Augie Fackler
formatting: blacken the codebase...
r43346 return self.configwith(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dateutil.parsedate, section, name, default, b'date', untrusted
Augie Fackler
formatting: blacken the codebase...
r43346 )
config: use the new '_unset' value for 'configdate'...
r32964 if default is _unset:
return None
Boris Feld
ui: add the possiblity to get a date config field...
r32408 return default
Navaneeth Suresh
config: add defaultvalue template keyword...
r42899 def configdefault(self, section, name):
"""returns the default value of the config item"""
item = self._knownconfig.get(section, {}).get(name)
itemdefault = None
if item is not None:
if callable(item.default):
itemdefault = item.default()
else:
itemdefault = item.default
return itemdefault
Bryan O'Sullivan
config: add hasconfig method and supporting plumbing...
r27696 def hasconfig(self, section, name, untrusted=False):
return self._data(untrusted).hasitem(section, name)
Bryan O'Sullivan
ui: Rename has_config to has_section.
r4487 def has_section(self, section, untrusted=False):
Vadim Gelfer
add ui.has_config method.
r2343 '''tell whether section exists in config.'''
Matt Mackall
ui: _get_cdata -> _data
r8199 return section in self._data(untrusted)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Gregory Szorc
ui: optionally ignore sub-options from configitems()...
r27253 def configitems(self, section, untrusted=False, ignoresub=False):
Matt Mackall
ui: _get_cdata -> _data
r8199 items = self._data(untrusted).items(section)
Gregory Szorc
ui: optionally ignore sub-options from configitems()...
r27253 if ignoresub:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 items = [i for i in items if b':' not in i[0]]
Matt Mackall
ui: report_untrusted fixes...
r8204 if self.debugflag and not untrusted and self._reportuntrusted:
Dirkjan Ochtman
more whitespace cleanup and some other style nits
r8222 for k, v in self._ucfg.items(section):
Matt Mackall
ui: privatize cdata vars
r8203 if self._tcfg.get(section, k) != v:
Augie Fackler
formatting: blacken the codebase...
r43346 self.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"ignoring untrusted configuration option "
b"%s.%s = %s\n" % (section, k, v)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
ui: introduce new config parser
r8144 return items
mpm@selenic.com
ui: add configuration file support...
r285
config: add an experimental option to list all known config...
r48208 def walkconfig(self, untrusted=False, all_known=False):
defined = self._walk_config(untrusted)
if not all_known:
for d in defined:
yield d
return
known = self._walk_known()
current_defined = next(defined, None)
current_known = next(known, None)
while current_defined is not None or current_known is not None:
if current_defined is None:
yield current_known
current_known = next(known, None)
elif current_known is None:
yield current_defined
current_defined = next(defined, None)
elif current_known[0:2] == current_defined[0:2]:
yield current_defined
current_defined = next(defined, None)
current_known = next(known, None)
elif current_known[0:2] < current_defined[0:2]:
yield current_known
current_known = next(known, None)
else:
yield current_defined
current_defined = next(defined, None)
def _walk_known(self):
for section, items in sorted(self._knownconfig.items()):
for k, i in sorted(items.items()):
# We don't have a way to display generic well, so skip them
if i.generic:
continue
if callable(i.default):
default = i.default()
elif i.default is configitems.dynamicdefault:
default = b'<DYNAMIC>'
else:
default = i.default
yield section, i.name, default
def _walk_config(self, untrusted):
Matt Mackall
ui: privatize cdata vars
r8203 cfg = self._data(untrusted)
for section in cfg.sections():
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 for name, value in self.configitems(section, untrusted):
Martin Geisler
ui: yield unchanged values in walkconfig...
r13576 yield section, name, value
Bryan O'Sullivan
Add commands.debugconfig....
r1028
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def plain(self, feature: Optional[bytes] = None) -> bool:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """is plain mode active?
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325
Brodie Rao
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT...
r13849 Plain mode means that all configuration variables which affect
the behavior and output of Mercurial should be
ignored. Additionally, the output should be stable,
reproducible and suitable for use in scripts or applications.
The only way to trigger plain mode is by setting either the
`HGPLAIN' or `HGPLAINEXCEPT' environment variables.
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 The return value can either be
- False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
Yuya Nishihara
dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options...
r35180 - False if feature is disabled by default and not included in HGPLAIN
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 - True otherwise
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'HGPLAIN' not in encoding.environ
and b'HGPLAINEXCEPT' not in encoding.environ
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Brodie Rao
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT...
r13849 return False
Augie Fackler
formatting: blacken the codebase...
r43346 exceptions = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 encoding.environ.get(b'HGPLAINEXCEPT', b'').strip().split(b',')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options...
r35180 # TODO: add support for HGPLAIN=+feature,-feature syntax
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'+strictflags' not in encoding.environ.get(b'HGPLAIN', b'').split(
b','
):
exceptions.append(b'strictflags')
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 if feature and exceptions:
return feature not in exceptions
return True
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455
Boris Feld
ui: add the possibility to returns None as username in ui...
r34850 def username(self, acceptempty=False):
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 """Return default username to be used in commits.
Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
and stop searching if one of these is set.
Boris Feld
ui: add the possibility to returns None as username in ui...
r34850 If not found and acceptempty is True, returns None.
Benoit Boissinot
ui: add an option to prompt for the username when it isn't provided...
r6862 If not found and ui.askusername is True, ask the user, else use
($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
Boris Feld
ui: add the possibility to returns None as username in ui...
r34850 If no username could be found, raise an Abort error.
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 user = encoding.environ.get(b"HGUSER")
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 if user is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 user = self.config(b"ui", b"username")
Chad Dombrova
ui.username(): expand environment variables in username configuration value....
r11225 if user is not None:
user = os.path.expandvars(user)
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 if user is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 user = encoding.environ.get(b"EMAIL")
Boris Feld
ui: add the possibility to returns None as username in ui...
r34850 if user is None and acceptempty:
return user
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if user is None and self.configbool(b"ui", b"askusername"):
user = self.prompt(_(b"enter a commit username:"), default=None)
Martin Geisler
ui: only use "user@host" as username in noninteractive mode...
r9613 if user is None and not self.interactive():
Benoit Boissinot
only print a warning when no username is specified...
r3721 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 user = b'%s@%s' % (
Augie Fackler
formatting: blacken the codebase...
r43346 procutil.getuser(),
encoding.strtolocal(socket.getfqdn()),
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.warn(_(b"no username found, using '%s' instead\n") % user)
Benoit Boissinot
only print a warning when no username is specified...
r3721 except KeyError:
Thomas Arendsen Hein
Abort on empty username so specifying a username can be forced....
r4044 pass
if not user:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'no username supplied'),
hint=_(b"use 'hg config --edit' " b'to set your username'),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b"\n" in user:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"username %r contains a newline\n") % pycompat.bytestr(user)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 return user
Matt Mackall
Add username/merge/editor to .hgrc...
r608
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def shortuser(self, user: bytes) -> bytes:
Thomas Arendsen Hein
Move generating short username to display in hg/hgweb annotate to ui module.
r1129 """Return a short representation of a user name or email address."""
Matt Mackall
many, many trivial check-code fixups
r10282 if not self.verbose:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 user = stringutil.shortuser(user)
Thomas Arendsen Hein
Move generating short username to display in hg/hgweb annotate to ui module.
r1129 return user
Gregory Szorc
ui: represent paths as classes...
r24250 @util.propertycache
def paths(self):
urlutil: extract `path` related code into a new module...
r47668 return urlutil.paths(self)
mpm@selenic.com
[PATCH] Add ui.expandpath command...
r506
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 @property
def fout(self):
return self._fout
ui: keep the progress bar around when writing if stdout is not a tty
r51339 @util.propertycache
def _fout_is_a_tty(self):
self._isatty(self._fout)
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 @fout.setter
def fout(self, f):
self._fout = f
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 self._fmsgout, self._fmsgerr = _selectmsgdests(self)
ui: keep the progress bar around when writing if stdout is not a tty
r51339 if '_fout_is_a_tty' in vars(self):
del self._fout_is_a_tty
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579
@property
def ferr(self):
return self._ferr
@ferr.setter
def ferr(self, f):
self._ferr = f
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 self._fmsgout, self._fmsgerr = _selectmsgdests(self)
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579
@property
def fin(self):
return self._fin
@fin.setter
def fin(self, f):
self._fin = f
Yuya Nishihara
dispatch: pass around ui.fmsg channel...
r40623 @property
def fmsg(self):
"""Stream dedicated for status/error messages; may be None if
fout/ferr are used"""
return self._fmsg
@fmsg.setter
def fmsg(self, f):
self._fmsg = f
self._fmsgout, self._fmsgerr = _selectmsgdests(self)
Martin von Zweigbergk
ui: add a context manager for silencing the ui (pushbuffer+popbuffer)...
r48230 @contextlib.contextmanager
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def silent(
self, error: bool = False, subproc: bool = False, labeled: bool = False
):
Martin von Zweigbergk
ui: add a context manager for silencing the ui (pushbuffer+popbuffer)...
r48230 self.pushbuffer(error=error, subproc=subproc, labeled=labeled)
try:
yield
finally:
self.popbuffer()
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def pushbuffer(
self, error: bool = False, subproc: bool = False, labeled: bool = False
) -> None:
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 """install a buffer to capture standard output of the ui object
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132
Pierre-Yves David
ui: allow capture of subprocess output...
r24848 If error is True, the error output will be captured too.
If subproc is True, output from subprocesses (typically hooks) will be
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 captured too.
Brodie Rao
ui: add ui.write() output labeling API...
r10815
If labeled is True, any labels associated with buffered
output will be handled. By default, this has no effect
on the output returned, but extensions and GUI tools may
handle this argument and returned styled output. If output
is being buffered so it can be captured and parsed or
processed, labeled should not be set to True.
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 """
Matt Mackall
ui: buffers -> _buffers
r8202 self._buffers.append([])
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 self._bufferstates.append((error, subproc, labeled))
self._bufferapplylabels = labeled
Matt Mackall
add a simple nested buffering scheme to ui
r3737
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def popbuffer(self) -> bytes:
Gregory Szorc
ui: remove labeled argument from popbuffer...
r27109 '''pop the last buffer and return the buffered output'''
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 self._bufferstates.pop()
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 if self._bufferstates:
self._bufferapplylabels = self._bufferstates[-1][2]
else:
self._bufferapplylabels = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"".join(self._buffers.pop())
Matt Mackall
add a simple nested buffering scheme to ui
r3737
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _isbuffered(self, dest) -> bool:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 if dest is self._fout:
Yuya Nishihara
ui: add inner function to select write destination...
r40577 return bool(self._buffers)
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 if dest is self._ferr:
Yuya Nishihara
ui: add inner function to select write destination...
r40577 return bool(self._bufferstates and self._bufferstates[-1][0])
return False
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def canwritewithoutlabels(self) -> bool:
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 '''check if write skips the label'''
if self._buffers and not self._bufferapplylabels:
return True
return self._colormode is None
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def canbatchlabeledwrites(self) -> bool:
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 '''check if write calls with labels are batchable'''
# Windows color printing is special, see ``write``.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._colormode != b'win32'
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def write(self, *args: bytes, **opts: _MsgOpts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """write args to output
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 By default, this method simply writes to the buffer or stdout.
Color mode can be set on the UI class to have the output decorated
with color modifier before being written to stdout.
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 The color used is controlled by an optional keyword argument, "label".
This should be a string containing label names separated by space.
Label names take the form of "topic.type". For example, ui.debug()
issues a label of "ui.debug".
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Joerg Sonnenberger
ui: option to preserve the progress bar...
r43559 Progress reports via stderr are normally cleared before writing as
stdout and stderr go to the same terminal. This can be skipped with
the optional keyword argument "keepprogressbar". The progress bar
will continue to occupy a partial line on stderr in that case.
This functionality is intended when Mercurial acts as data source
in a pipe.
Brodie Rao
ui: add ui.write() output labeling API...
r10815 When labeling output for a specific command, a label of
"cmdname.type" is recommended. For example, status issues
a label of "status.modified" for modified files.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Yuya Nishihara
ui: inline _write() into write() due to performance issue...
r41376 dest = self._fout
# inlined _write() for speed
Yuya Nishihara
ui: remove unreachable branches and function calls from write() (issue6059)...
r41378 if self._buffers:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 label = opts.get('label', b'')
Yuya Nishihara
ui: inline _write() into write() due to performance issue...
r41376 if label and self._bufferapplylabels:
self._buffers[-1].extend(self.label(a, label) for a in args)
else:
self._buffers[-1].extend(args)
Yuya Nishihara
ui: inline _writenobuf() into write() due to performance issue...
r41377 return
Joerg Sonnenberger
ui: option to preserve the progress bar...
r43559 # inlined _writenobuf() for speed
ui: keep the progress bar around when writing if stdout is not a tty
r51339 if not opts.get('keepprogressbar', self._fout_is_a_tty):
Joerg Sonnenberger
ui: option to preserve the progress bar...
r43559 self._progclear()
Yuya Nishihara
ui: inline _writenobuf() into write() due to performance issue...
r41377 msg = b''.join(args)
# opencode timeblockedsection because this is a critical path
starttime = util.timer()
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._colormode == b'win32':
Yuya Nishihara
ui: inline _writenobuf() into write() due to performance issue...
r41377 # windows color printing is its own can of crab, defer to
# the color module and that is it.
color.win32print(self, dest.write, msg, **opts)
else:
if self._colormode is not None:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 label = opts.get('label', b'')
Yuya Nishihara
ui: inline _writenobuf() into write() due to performance issue...
r41377 msg = self.label(msg, label)
dest.write(msg)
except IOError as err:
raise error.StdioError(err)
finally:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._blockedtimes[b'stdio_blocked'] += (
Augie Fackler
formatting: blacken the codebase...
r43346 util.timer() - starttime
) * 1000
Yuya Nishihara
ui: add inner function to select write destination...
r40577
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def write_err(self, *args: bytes, **opts: _MsgOpts) -> None:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 self._write(self._ferr, *args, **opts)
Yuya Nishihara
ui: add inner function to select write destination...
r40577
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def _write(self, dest, *args: bytes, **opts: _MsgOpts) -> None:
Yuya Nishihara
ui: inline _write() into write() due to performance issue...
r41376 # update write() as well if you touch this code
Yuya Nishihara
ui: add inner function to select write destination...
r40577 if self._isbuffered(dest):
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 label = opts.get('label', b'')
Yuya Nishihara
ui: optimize buffered write with no label...
r41375 if label and self._bufferapplylabels:
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 self._buffers[-1].extend(self.label(a, label) for a in args)
else:
self._buffers[-1].extend(args)
Yuya Nishihara
ui: add explicit path to write prompt text bypassing buffers...
r35975 else:
Yuya Nishihara
ui: add inner function to select write destination...
r40577 self._writenobuf(dest, *args, **opts)
Yuya Nishihara
ui: add explicit path to write prompt text bypassing buffers...
r35975
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def _writenobuf(self, dest, *args: bytes, **opts: _MsgOpts) -> None:
Yuya Nishihara
ui: inline _writenobuf() into write() due to performance issue...
r41377 # update write() as well if you touch this code
ui: keep the progress bar around when writing if stdout is not a tty
r51339 if not opts.get('keepprogressbar', self._fout_is_a_tty):
Joerg Sonnenberger
ui: option to preserve the progress bar...
r43559 self._progclear()
Yuya Nishihara
ui: simply concatenate messages before applying color labels...
r40557 msg = b''.join(args)
Pierre-Yves David
ui: extract the low level part of 'write' in a dedicated function...
r31090
Yuya Nishihara
ui: remove superfluous indent in _write()
r31128 # opencode timeblockedsection because this is a critical path
starttime = util.timer()
try:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 if dest is self._ferr and not getattr(self._fout, 'closed', False):
self._fout.flush()
Yuya Nishihara
commandserver: add experimental option to use separate message channel...
r40625 if getattr(dest, 'structured', False):
# channel for machine-readable output with metadata, where
# no extra colorization is necessary.
dest.write(msg, **opts)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif self._colormode == b'win32':
Yuya Nishihara
ui: indent _writenobuf() to prepare moving bits from _write() functions
r40558 # windows color printing is its own can of crab, defer to
# the color module and that is it.
Yuya Nishihara
ui: remove _write() and _write_err() functions
r40576 color.win32print(self, dest.write, msg, **opts)
Yuya Nishihara
ui: indent _writenobuf() to prepare moving bits from _write() functions
r40558 else:
if self._colormode is not None:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 label = opts.get('label', b'')
Yuya Nishihara
ui: indent _writenobuf() to prepare moving bits from _write() functions
r40558 msg = self.label(msg, label)
Yuya Nishihara
ui: remove _write() and _write_err() functions
r40576 dest.write(msg)
Yuya Nishihara
ui: move pre/post processes from low-level write()s to _writenobuf()...
r40575 # stderr may be buffered under win32 when redirected to files,
# including stdout.
Manuel Jacob
ui: replace `self._ferr` with identical `dest`...
r45525 if dest is self._ferr and not getattr(dest, 'closed', False):
Yuya Nishihara
ui: move pre/post processes from low-level write()s to _writenobuf()...
r40575 dest.flush()
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui._write
r31961 except IOError as err:
Augie Fackler
formatting: blacken the codebase...
r43346 if dest is self._ferr and err.errno in (
errno.EPIPE,
errno.EIO,
errno.EBADF,
):
Yuya Nishihara
ui: move pre/post processes from low-level write()s to _writenobuf()...
r40575 # no way to report the error, so ignore it
return
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui._write
r31961 raise error.StdioError(err)
Yuya Nishihara
ui: remove superfluous indent in _write()
r31128 finally:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._blockedtimes[b'stdio_blocked'] += (
Augie Fackler
formatting: blacken the codebase...
r43346 util.timer() - starttime
) * 1000
mpm@selenic.com
[PATCH] Make ui.warn write to stderr...
r565
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def _writemsg(self, dest, *args: bytes, **opts: _MsgOpts) -> None:
Joerg Sonnenberger
ui: add option to timestamp status and diagnostic messages...
r45564 timestamp = self.showtimestamp and opts.get('type') in {
b'debug',
b'error',
b'note',
b'status',
b'warning',
}
if timestamp:
args = (
Joerg Sonnenberger
ui: fix Python 2.7 support for ui.timestamp-output...
r45579 b'[%s] '
% pycompat.bytestr(datetime.datetime.now().isoformat()),
Joerg Sonnenberger
ui: add option to timestamp status and diagnostic messages...
r45564 ) + args
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626 _writemsgwith(self._write, dest, *args, **opts)
Joerg Sonnenberger
ui: add option to timestamp status and diagnostic messages...
r45564 if timestamp:
dest.flush()
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def _writemsgnobuf(self, dest, *args: bytes, **opts: _MsgOpts) -> None:
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626 _writemsgwith(self._writenobuf, dest, *args, **opts)
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def flush(self) -> None:
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 # opencode timeblockedsection because this is a critical path
starttime = util.timer()
try:
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui.flush...
r31963 try:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 self._fout.flush()
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui.flush...
r31963 except IOError as err:
Gregory Szorc
ui: restore behavior to ignore some I/O errors (issue5658)...
r33859 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
raise error.StdioError(err)
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui.flush...
r31963 finally:
try:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 self._ferr.flush()
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui.flush...
r31963 except IOError as err:
Gregory Szorc
ui: restore behavior to ignore some I/O errors (issue5658)...
r33859 if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
raise error.StdioError(err)
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 finally:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._blockedtimes[b'stdio_blocked'] += (
Augie Fackler
formatting: blacken the codebase...
r43346 util.timer() - starttime
) * 1000
Vadim Gelfer
make ui flush output. this makes error happen if printing to /dev/full....
r1837
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _isatty(self, fh) -> bool:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.configbool(b'ui', b'nontty'):
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 return False
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 return procutil.isatty(fh)
Vadim Gelfer
make ui flush output. this makes error happen if printing to /dev/full....
r1837
Yuya Nishihara
ui: proxy protect/restorestdio() calls to update internal flag...
r41321 def protectfinout(self):
"""Duplicate ui streams and redirect original if they are stdio
Returns (fin, fout) which point to the original ui fds, but may be
copy of them. The returned streams can be considered "owned" in that
print(), exec(), etc. never reach to them.
"""
if self._finoutredirected:
# if already redirected, protectstdio() would just create another
# nullfd pair, which is equivalent to returning self._fin/_fout.
return self._fin, self._fout
fin, fout = procutil.protectstdio(self._fin, self._fout)
self._finoutredirected = (fin, fout) != (self._fin, self._fout)
return fin, fout
def restorefinout(self, fin, fout):
"""Restore ui streams from possibly duplicated (fin, fout)"""
if (fin, fout) == (self._fin, self._fout):
return
procutil.restorestdio(self._fin, self._fout, fin, fout)
# protectfinout() won't create more than one duplicated streams,
# so we can just turn the redirection flag off.
self._finoutredirected = False
Yuya Nishihara
ui: move protectedstdio() context manager from procutil...
r41320 @contextlib.contextmanager
def protectedfinout(self):
"""Run code block with protected standard streams"""
Yuya Nishihara
ui: proxy protect/restorestdio() calls to update internal flag...
r41321 fin, fout = self.protectfinout()
Yuya Nishihara
ui: move protectedstdio() context manager from procutil...
r41320 try:
yield fin, fout
finally:
Yuya Nishihara
ui: proxy protect/restorestdio() calls to update internal flag...
r41321 self.restorefinout(fin, fout)
Yuya Nishihara
ui: move protectedstdio() context manager from procutil...
r41320
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def disablepager(self) -> None:
Augie Fackler
ui: rename neverpager to disablepager...
r31026 self._disablepager = True
Augie Fackler
ui: introduce neverpager() call...
r30994
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def pager(self, command: bytes) -> None:
Augie Fackler
pager: move pager-initiating code into core...
r30992 """Start a pager for subsequent command output.
Commands which produce a long stream of output should call
this function to activate the user's preferred pagination
mechanism (which may be no pager). Calling this function
precludes any future use of interactive functionality, such as
prompting the user or activating curses.
Args:
command: The full, non-aliased name of the command. That is, "log"
not "history, "summary" not "summ", etc.
"""
Augie Fackler
formatting: blacken the codebase...
r43346 if self._disablepager or self.pageractive:
FUJIWARA Katsunori
ui: enable pager always for explicit --pager=on (issue5580)...
r33622 # how pager should do is already determined
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not command.startswith(b'internal-always-') and (
FUJIWARA Katsunori
ui: enable pager always for explicit --pager=on (issue5580)...
r33622 # explicit --pager=on (= 'internal-always-' prefix) should
# take precedence over disabling factors below
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 command in self.configlist(b'pager', b'ignore')
or not self.configbool(b'ui', b'paginate')
or not self.configbool(b'pager', b'attend-' + command, True)
or encoding.environ.get(b'TERM') == b'dumb'
Augie Fackler
pager: move pager-initiating code into core...
r30992 # TODO: if we want to allow HGPLAINEXCEPT=pager,
# formatted() will need some adjustment.
or not self.formatted()
or self.plain()
Jun Wu
pager: do not start pager if `ui` has been `pushbuffer`-ed...
r34023 or self._buffers
Augie Fackler
pager: move pager-initiating code into core...
r30992 # TODO: expose debugger-enabled on the UI object
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or b'--debugger' in pycompat.sysargv
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
pager: move pager-initiating code into core...
r30992 # We only want to paginate if the ui appears to be
# interactive, the user didn't say HGPLAIN or
# HGPLAINEXCEPT=pager, and the user didn't specify --debug.
return
Matt Harbison
windows: disable pager when packaged with py2exe...
r49966 # py2exe doesn't appear to be able to use legacy I/O, and nothing is
# output to the pager for paged commands. Piping to `more` in cmd.exe
# works, but is easy to forget. Just disable pager for py2exe, but
# leave it working for pyoxidizer and exewrapper builds.
if pycompat.iswindows and getattr(sys, "frozen", None) == "console_exe":
self.debug(b"pager is unavailable with py2exe packaging\n")
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pagercmd = self.config(b'pager', b'pager', rcutil.fallbackpager)
Yuya Nishihara
pager: do not try to run an empty pager command...
r31079 if not pagercmd:
return
Jun Wu
pager: set some environment variables if they're not set...
r31954 pagerenv = {}
for name, value in rcutil.defaultpagerenv().items():
if name not in encoding.environ:
pagerenv[name] = value
Augie Fackler
formatting: blacken the codebase...
r43346 self.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'starting pager for command %s\n' % stringutil.pprint(command)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
pager: flush outputs before firing pager process...
r31490 self.flush()
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690
wasformatted = self.formatted()
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(signal, "SIGPIPE"):
Augie Fackler
pager: move pager-initiating code into core...
r30992 signal.signal(signal.SIGPIPE, _catchterm)
Jun Wu
pager: set some environment variables if they're not set...
r31954 if self._runpager(pagercmd, pagerenv):
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690 self.pageractive = True
# Preserve the formatted-ness of the UI. This is important
# because we mess with stdout, which might confuse
# auto-detection of things being formatted.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.setconfig(b'ui', b'formatted', wasformatted, b'pager')
self.setconfig(b'ui', b'interactive', False, b'pager')
Matt Harbison
ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode'...
r31691
# If pagermode differs from color.mode, reconfigure color now that
# pageractive is set.
cm = self._colormode
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cm != self.config(b'color', b'pagermode', cm):
Matt Harbison
ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode'...
r31691 color.setup(self)
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690 else:
# If the pager can't be spawned in dispatch when --pager=on is
# given, don't try again when the command runs, to avoid a duplicate
# warning about a missing pager command.
self.disablepager()
Augie Fackler
pager: move pager-initiating code into core...
r30992
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _runpager(self, command: bytes, env=None) -> bool:
Augie Fackler
pager: move pager-initiating code into core...
r30992 """Actually start the pager and set up file descriptors.
This is separate in part so that extensions (like chg) can
override how a pager is invoked.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if command == b'cat':
Augie Fackler
pager: skip running the pager if it's set to 'cat'...
r31479 # Save ourselves some work.
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690 return False
Augie Fackler
pager: avoid shell=True on subprocess.Popen for better errors (issue5491)...
r31478 # If the command doesn't contain any of these characters, we
# assume it's a binary and exec it directly. This means for
# simple pager command configurations, we can degrade
# gracefully and tell the user about their broken pager.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shell = any(c in command for c in b"|&;<>()$`\\\"' \t\n*?[#~=%")
Matt Harbison
pager: improve support for various flavors of `more` on Windows...
r31624
Jun Wu
codemod: use pycompat.iswindows...
r34646 if pycompat.iswindows and not shell:
Matt Harbison
pager: improve support for various flavors of `more` on Windows...
r31624 # Window's built-in `more` cannot be invoked with shell=False, but
# its `more.com` can. Hide this implementation detail from the
# user so we can also get sane bad PAGER behavior. MSYS has
# `more.exe`, so do a cmd.exe style resolution of the executable to
# determine which one to use.
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 fullcmd = procutil.findexe(command)
Matt Harbison
pager: improve support for various flavors of `more` on Windows...
r31624 if not fullcmd:
Augie Fackler
formatting: blacken the codebase...
r43346 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"missing pager command '%s', skipping pager\n") % command
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690 return False
Matt Harbison
pager: improve support for various flavors of `more` on Windows...
r31624
command = fullcmd
Augie Fackler
pager: avoid shell=True on subprocess.Popen for better errors (issue5491)...
r31478 try:
pager = subprocess.Popen(
Augie Fackler
formatting: blacken the codebase...
r43346 procutil.tonativestr(command),
shell=shell,
bufsize=-1,
close_fds=procutil.closefds,
stdin=subprocess.PIPE,
stdout=procutil.stdout,
stderr=procutil.stderr,
env=procutil.tonativeenv(procutil.shellenviron(env)),
)
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
if not shell:
Augie Fackler
formatting: blacken the codebase...
r43346 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"missing pager command '%s', skipping pager\n") % command
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690 return False
Augie Fackler
pager: avoid shell=True on subprocess.Popen for better errors (issue5491)...
r31478 raise
Augie Fackler
pager: move pager-initiating code into core...
r30992
# back up original file descriptors
Jean-Francois Pieronne
openvms: fix the pager spawning and cleanup...
r51891 if pycompat.sysplatform != b'OpenVMS':
stdoutfd = os.dup(procutil.stdout.fileno())
stderrfd = os.dup(procutil.stderr.fileno())
Augie Fackler
pager: move pager-initiating code into core...
r30992
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 os.dup2(pager.stdin.fileno(), procutil.stdout.fileno())
if self._isatty(procutil.stderr):
os.dup2(pager.stdin.fileno(), procutil.stderr.fileno())
Augie Fackler
pager: move pager-initiating code into core...
r30992
Bryan O'Sullivan
atexit: switch to home-grown implementation
r31958 @self.atexit
Augie Fackler
pager: move pager-initiating code into core...
r30992 def killpager():
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(signal, "SIGINT"):
Augie Fackler
pager: move pager-initiating code into core...
r30992 signal.signal(signal.SIGINT, signal.SIG_IGN)
# restore original fds, closing pager.stdin copies in the process
Jean-Francois Pieronne
openvms: fix the pager spawning and cleanup...
r51891 if pycompat.sysplatform == b'OpenVMS':
pager.kill()
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 os.dup2(stdoutfd, procutil.stdout.fileno())
os.dup2(stderrfd, procutil.stderr.fileno())
Augie Fackler
pager: move pager-initiating code into core...
r30992 pager.stdin.close()
pager.wait()
Matt Harbison
ui: defer setting pager related properties until the pager has spawned...
r31690 return True
Saurabh Singh
ui: move request exit handlers to global state...
r34883 @property
def _exithandlers(self):
return _reqexithandlers
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956 def atexit(self, func, *args, **kwargs):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """register a function to run after dispatching a request
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 Handlers do not stay registered across request boundaries."""
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956 self._exithandlers.append((func, args, kwargs))
return func
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def interface(self, feature: bytes) -> bytes:
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 """what interface to use for interactive console features?
The interface is controlled by the value of `ui.interface` but also by
the value of feature-specific configuration. For example:
ui.interface.histedit = text
ui.interface.chunkselector = curses
Here the features are "histedit" and "chunkselector".
The configuration above means that the default interfaces for commands
is curses, the interface for histedit is text and the interface for
selecting chunk is crecord (the best curses interface available).
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 Consider the following example:
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 ui.interface = curses
ui.interface.histedit = text
Then histedit will use the text interface and chunkselector will use
the default curses interface (crecord at the moment).
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 alldefaults = frozenset([b"text", b"curses"])
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
featureinterfaces = {
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 b"chunkselector": [
b"text",
b"curses",
],
b"histedit": [
b"text",
b"curses",
],
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 }
# Feature-specific interface
if feature not in featureinterfaces.keys():
# Programming error, not user error
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b"Unknown feature requested %s" % feature)
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
availableinterfaces = frozenset(featureinterfaces[feature])
if alldefaults > availableinterfaces:
# Programming error, not user error. We need a use case to
# define the right thing to do here.
raise ValueError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"Feature %s does not handle all default interfaces" % feature
Augie Fackler
formatting: blacken the codebase...
r43346 )
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.plain() or encoding.environ.get(b'TERM') == b'dumb':
return b"text"
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
# Default interface for all the features
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 defaultinterface = b"text"
i = self.config(b"ui", b"interface")
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 if i in alldefaults:
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 defaultinterface = cast(bytes, i) # cast to help pytype
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 choseninterface: bytes = defaultinterface
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = self.config(b"ui", b"interface.%s" % feature)
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 if f in availableinterfaces:
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 choseninterface = cast(bytes, f) # cast to help pytype
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
if i is not None and defaultinterface != i:
if f is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.warn(_(b"invalid value for ui.interface: %s\n") % (i,))
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 else:
Augie Fackler
formatting: blacken the codebase...
r43346 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"invalid value for ui.interface: %s (using %s)\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % (i, choseninterface)
)
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 if f is not None and choseninterface != f:
Augie Fackler
formatting: blacken the codebase...
r43346 self.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"invalid value for ui.interface.%s: %s (using %s)\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % (feature, f, choseninterface)
)
Simon Farnsworth
ui: add new config flag for interface selection...
r28542
return choseninterface
Matt Mackall
ui: make interactive a method
r8208 def interactive(self):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """is interactive input allowed?
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325
An interactive session is a session where input can be reasonably read
from `sys.stdin'. If this function returns false, any attempt to read
from stdin should fail with an error, unless a sensible default has been
specified.
Interactiveness is triggered by the value of the `ui.interactive'
configuration variable or - if it is unset - when `sys.stdin' points
to a terminal device.
This function refers to input only; for output, see `ui.formatted()'.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 i = self.configbool(b"ui", b"interactive")
Patrick Mezard
ui: honor interactive=off even if isatty()
r8538 if i is None:
Idan Kamara
util: add helper function isatty(fd) to check for tty-ness
r14515 # some environments replace stdin without implementing isatty
# usually those are non-interactive
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 return self._isatty(self._fin)
Ronny Pfannschmidt
make ui.interactive() return false in case stdin lacks isatty
r10077
Patrick Mezard
ui: honor interactive=off even if isatty()
r8538 return i
Matt Mackall
ui: make interactive a method
r8208
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def termwidth(self) -> int:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """how wide is the terminal in columns?"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'COLUMNS' in encoding.environ:
Augie Fackler
termwidth: move to ui.ui from util
r12689 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return int(encoding.environ[b'COLUMNS'])
Augie Fackler
termwidth: move to ui.ui from util
r12689 except ValueError:
pass
Yuya Nishihara
scmutil: extend termwidth() to return terminal height, renamed to termsize()...
r30314 return scmutil.termsize(self)[0]
Augie Fackler
termwidth: move to ui.ui from util
r12689
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324 def formatted(self):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """should formatted output be used?
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325
It is often desirable to format the output to suite the output medium.
Examples of this are truncating long lines or colorizing messages.
However, this is not often not desirable when piping output into other
utilities, e.g. `grep'.
Formatted output is triggered by the value of the `ui.formatted'
configuration variable or - if it is unset - when `sys.stdout' points
to a terminal device. Please note that `ui.formatted' should be
considered an implementation detail; it is not intended for use outside
Mercurial or its extensions.
This function refers to output only; for input, see `ui.interactive()'.
This function always returns false when in plain mode, see `ui.plain()'.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324 if self.plain():
return False
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 i = self.configbool(b"ui", b"formatted")
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324 if i is None:
Idan Kamara
util: add helper function isatty(fd) to check for tty-ness
r14515 # some environments replace stdout without implementing isatty
# usually those are non-interactive
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 return self._isatty(self._fout)
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324
return i
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def _readline(
self,
prompt: bytes = b' ',
promptopts: Optional[Dict[str, _MsgOpts]] = None,
) -> bytes:
Yuya Nishihara
ui: do not use rawinput() when we have to replace sys.stdin/stdout...
r36813 # Replacing stdin/stdout temporarily is a hard problem on Python 3
# because they have to be text streams with *no buffering*. Instead,
# we use rawinput() only if call_readline() will be invoked by
# PyOS_Readline(), so no I/O will be made at Python layer.
Augie Fackler
formatting: blacken the codebase...
r43346 usereadline = (
self._isatty(self._fin)
and self._isatty(self._fout)
and procutil.isstdin(self._fin)
and procutil.isstdout(self._fout)
)
Yuya Nishihara
ui: do not try readline support if fin/fout aren't standard streams...
r36812 if usereadline:
Bryan O'Sullivan
ui: get readline and prompt to behave better depending on interactivity
r5036 try:
# magically add command line editing support, where
# available
import readline
Augie Fackler
formatting: blacken the codebase...
r43346
Bryan O'Sullivan
ui: get readline and prompt to behave better depending on interactivity
r5036 # force demandimport to really load the module
readline.read_history_file
Brendan Cully
issue1419: catch strange readline import error on windows
r7496 # windows sometimes raises something other than ImportError
except Exception:
Yuya Nishihara
ui: do not try readline support if fin/fout aren't standard streams...
r36812 usereadline = False
Idan Kamara
ui: use I/O descriptors internally...
r14614
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self._colormode == b'win32' or not usereadline:
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288 if not promptopts:
promptopts = {}
Augie Fackler
formatting: blacken the codebase...
r43346 self._writemsgnobuf(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._fmsgout, prompt, type=b'prompt', **promptopts
Augie Fackler
formatting: blacken the codebase...
r43346 )
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288 self.flush()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompt = b' '
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompt = self.label(prompt, b'ui.prompt') + b' '
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288
Yuya Nishihara
ui: add brief comment why raw_input() needs dummy ' ' prompt string...
r22291 # prompt ' ' must exist; otherwise readline may delete entire line
# - http://bugs.python.org/issue12833
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with self.timeblockedsection(b'stdio'):
Yuya Nishihara
ui: do not use rawinput() when we have to replace sys.stdin/stdout...
r36813 if usereadline:
Gregory Szorc
ui: flush before prompting for input with readline...
r43694 self.flush()
Denis Laxalde
py3: decode prompt string before calling rawinput...
r43388 prompt = encoding.strfromlocal(prompt)
Gregory Szorc
ui: use input() directly...
r49788 line = encoding.strtolocal(input(prompt))
Yuya Nishihara
ui: adjust Windows workaround to new _readline() code...
r36814 # When stdin is in binary mode on Windows, it can cause
Gregory Szorc
ui: use input() directly...
r49788 # input() to emit an extra trailing carriage return
Yuya Nishihara
ui: adjust Windows workaround to new _readline() code...
r36814 if pycompat.oslinesep == b'\r\n' and line.endswith(b'\r'):
line = line[:-1]
Yuya Nishihara
ui: do not use rawinput() when we have to replace sys.stdin/stdout...
r36813 else:
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288 self._fout.write(pycompat.bytestr(prompt))
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 self._fout.flush()
line = self._fin.readline()
Yuya Nishihara
ui: do not use rawinput() when we have to replace sys.stdin/stdout...
r36813 if not line:
raise EOFError
Yuya Nishihara
ui: remove any combinations of CR|LF from prompt response...
r36852 line = line.rstrip(pycompat.oslinesep)
Idan Kamara
ui: use I/O descriptors internally...
r14614
Steve Borho
workaround for raw_input() on Windows...
r5613 return line
Bryan O'Sullivan
ui: get readline and prompt to behave better depending on interactivity
r5036
pytype: import typing directly...
r52178 if typing.TYPE_CHECKING:
Matt Harbison
typing: add type hints to the prompt methods in mercurial/ui.py...
r50694
@overload
def prompt(self, msg: bytes, default: bytes) -> bytes:
pass
@overload
def prompt(self, msg: bytes, default: None) -> Optional[bytes]:
pass
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def prompt(self, msg, default=b"y"):
Simon Heimberg
ui: extract choice from prompt...
r9048 """Prompt user with msg, read response.
If ui is not interactive, the default is returned.
Kirill Smelkov
prompt: kill matchflags...
r5751 """
Yuya Nishihara
commandserver: attach prompt default and choices to message...
r40628 return self._prompt(msg, default=default)
pytype: import typing directly...
r52178 if typing.TYPE_CHECKING:
Matt Harbison
typing: add type hints to the prompt methods in mercurial/ui.py...
r50694
@overload
def _prompt(
self, msg: bytes, default: bytes, **opts: _MsgOpts
) -> bytes:
pass
@overload
def _prompt(
self, msg: bytes, default: None, **opts: _MsgOpts
) -> Optional[bytes]:
pass
Matt Harbison
ui: split the `default` arg out of **kwargs for the internal prompt method...
r50693 def _prompt(self, msg, default=b'y', **opts):
opts = {**opts, 'default': default}
Matt Mackall
ui: make interactive a method
r8208 if not self.interactive():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgout, msg, b' ', type=b'prompt', **opts)
Augie Fackler
formatting: blacken the codebase...
r43346 self._writemsg(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._fmsgout, default or b'', b"\n", type=b'promptecho'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Peter Arrenbrecht
ui: log non-interactive default response to stdout when verbose...
r7320 return default
Simon Heimberg
ui: extract choice from prompt...
r9048 try:
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288 r = self._readline(prompt=msg, promptopts=opts)
Simon Heimberg
ui: extract choice from prompt...
r9048 if not r:
Mads Kiilerich
ui: show prompt choice if input is not a tty but is forced to be interactive...
r22589 r = default
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.configbool(b'ui', b'promptecho'):
Yuya Nishihara
ui: fix echo back of ui.prompt() to not concatenate None as bytes...
r46380 self._writemsg(
self._fmsgout, r or b'', b"\n", type=b'promptecho'
)
Simon Heimberg
ui: extract choice from prompt...
r9048 return r
except EOFError:
Siddharth Agarwal
error: add structured exception for EOF at prompt...
r26896 raise error.ResponseExpected()
Simon Heimberg
ui: extract choice from prompt...
r9048
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265 @staticmethod
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def extractchoices(prompt: bytes) -> Tuple[bytes, List[_PromptChoice]]:
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265 """Extract prompt message and list of choices from specified prompt.
This returns tuple "(message, choices)", and "choices" is the
list of tuple "(response character, text without &)".
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> ui.extractchoices(b"awake? $$ &Yes $$ &No")
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392 ('awake? ', [('y', 'Yes'), ('n', 'No')])
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> ui.extractchoices(b"line\\nbreak? $$ &Yes $$ &No")
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392 ('line\\nbreak? ', [('y', 'Yes'), ('n', 'No')])
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> ui.extractchoices(b"want lots of $$money$$?$$Ye&s$$N&o")
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392 ('want lots of $$money$$?', [('s', 'Yes'), ('o', 'No')])
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265 """
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392
# Sadly, the prompt string may have been built with a filename
# containing "$$" so let's try to find the first valid-looking
# prompt to start parsing. Sadly, we also can't rely on
# choices containing spaces, ASCII, or basically anything
# except an ampersand followed by a character.
Matt Harbison
cleanup: drop redundant character escapes from `[]` character sets...
r44473 m = re.match(br'(?s)(.+?)\$\$([^$]*&[^ $].*)', prompt)
Matt Harbison
pytype: stop excluding mercurial/ui.py...
r50688
assert m is not None # help pytype
Matt Mackall
ui: try to handle $$ more robustly in prompts (issue4970)
r27392 msg = m.group(1)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 choices = [p.strip(b' ') for p in m.group(2).split(b'$$')]
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
ui: refactor extractchoices so it doesn't break on Python 3...
r33680 def choicetuple(s):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ampidx = s.index(b'&')
return s[ampidx + 1 : ampidx + 2].lower(), s.replace(b'&', b'', 1)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
ui: refactor extractchoices so it doesn't break on Python 3...
r33680 return (msg, [choicetuple(s) for s in choices])
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def promptchoice(self, prompt: bytes, default: int = 0) -> int:
Matt Mackall
ui: merge prompt text components into a singe string...
r19226 """Prompt user with a message, read response, and ensure it matches
one of the provided choices. The prompt is formatted as follows:
"would you like fries with that (Yn)? $$ &Yes $$ &No"
The index of the choice is returned. Responses are case
insensitive. If ui is not interactive, the default is
returned.
Simon Heimberg
ui: extract choice from prompt...
r9048 """
Matt Mackall
ui: merge prompt text components into a singe string...
r19226
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265 msg, choices = self.extractchoices(prompt)
resps = [r for r, t in choices]
Thomas Arendsen Hein
Make ui.prompt repeat on "unrecognized response" again (issue897)...
r5671 while True:
Yuya Nishihara
commandserver: attach prompt default and choices to message...
r40628 r = self._prompt(msg, default=resps[default], choices=choices)
Simon Heimberg
ui: extract choice from prompt...
r9048 if r.lower() in resps:
return resps.index(r.lower())
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 # TODO: shouldn't it be a warning?
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgout, _(b"unrecognized response\n"))
Simon Heimberg
ui: extract choice from prompt...
r9048
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def getpass(
self, prompt: Optional[bytes] = None, default: Optional[bytes] = None
) -> Optional[bytes]:
Matt Mackall
many, many trivial check-code fixups
r10282 if not self.interactive():
return default
Steve Borho
catch CTRL-D at password prompt...
r7798 try:
Augie Fackler
formatting: blacken the codebase...
r43346 self._writemsg(
self._fmsgerr,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompt or _(b'password: '),
type=b'prompt',
Augie Fackler
formatting: blacken the codebase...
r43346 password=True,
)
Yuya Nishihara
cmdserver: forcibly use L channel to read password input (issue3161)...
r21195 # disable getpass() only if explicitly specified. it's still valid
# to interact with tty even if fin is not a tty.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with self.timeblockedsection(b'stdio'):
if self.configbool(b'ui', b'nontty'):
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 l = self._fin.readline()
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 if not l:
raise EOFError
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return l.rstrip(b'\n')
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 else:
Matt Harbison
util: avoid echoing the password to the console on Windows py3 (issue6446)...
r47949 return util.get_password()
Steve Borho
catch CTRL-D at password prompt...
r7798 except EOFError:
Siddharth Agarwal
error: add structured exception for EOF at prompt...
r26896 raise error.ResponseExpected()
Rodrigo Damazio Bovendorp
dispatch: making all hg abortions be output with a specific label...
r38791
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def status(self, *msg: bytes, **opts: _MsgOpts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """write status message to output (if ui.quiet is False)
Brodie Rao
ui: add ui.write() output labeling API...
r10815
This adds an output label of "ui.status".
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Matt Mackall
many, many trivial check-code fixups
r10282 if not self.quiet:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgout, type=b'status', *msg, **opts)
Rodrigo Damazio Bovendorp
dispatch: making all hg abortions be output with a specific label...
r38791
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def warn(self, *msg: bytes, **opts: _MsgOpts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """write warning message to output (stderr)
Brodie Rao
ui: add ui.write() output labeling API...
r10815
This adds an output label of "ui.warning".
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgerr, type=b'warning', *msg, **opts)
Rodrigo Damazio Bovendorp
dispatch: making all hg abortions be output with a specific label...
r38791
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def error(self, *msg: bytes, **opts: _MsgOpts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """write error message to output (stderr)
Rodrigo Damazio Bovendorp
dispatch: making all hg abortions be output with a specific label...
r38791
This adds an output label of "ui.error".
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgerr, type=b'error', *msg, **opts)
Rodrigo Damazio Bovendorp
dispatch: making all hg abortions be output with a specific label...
r38791
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def note(self, *msg: bytes, **opts: _MsgOpts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """write note to output (if ui.verbose is True)
Brodie Rao
ui: add ui.write() output labeling API...
r10815
This adds an output label of "ui.note".
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Matt Mackall
many, many trivial check-code fixups
r10282 if self.verbose:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgout, type=b'note', *msg, **opts)
Rodrigo Damazio Bovendorp
dispatch: making all hg abortions be output with a specific label...
r38791
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def debug(self, *msg: bytes, **opts: _MsgOpts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """write debug message to output (if ui.debugflag is True)
Brodie Rao
ui: add ui.write() output labeling API...
r10815
This adds an output label of "ui.debug".
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Matt Mackall
many, many trivial check-code fixups
r10282 if self.debugflag:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._writemsg(self._fmsgout, type=b'debug', *msg, **opts)
Yuya Nishihara
blackbox: send debug message to logger by core ui...
r40792 self.log(b'debug', b'%s', b''.join(msg))
FUJIWARA Katsunori
cmdutil: make in-memory changes visible to external editor (issue4378)...
r26750
Gregory Szorc
ui: define (write|status|warn|note)noi18n aliases...
r43349 # Aliases to defeat check-code.
statusnoi18n = status
notenoi18n = note
warnnoi18n = warn
writenoi18n = write
Augie Fackler
formatting: blacken the codebase...
r43346 def edit(
self,
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 text: bytes,
user: bytes,
extra: Optional[Dict[bytes, Any]] = None, # TODO: value type of bytes?
Augie Fackler
formatting: blacken the codebase...
r43346 editform=None,
pending=None,
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 repopath: Optional[bytes] = None,
action: Optional[bytes] = None,
) -> bytes:
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030 if action is None:
Augie Fackler
formatting: blacken the codebase...
r43346 self.develwarn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'action is None but will soon be a required '
b'parameter to ui.edit()'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Jordi Gutiérrez Hermoso
edit: allow to configure the suffix of the temporary filename...
r28635 extra_defaults = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'prefix': b'editor',
b'suffix': b'.txt',
Jordi Gutiérrez Hermoso
edit: allow to configure the suffix of the temporary filename...
r28635 }
Mykola Nikishov
ui: allow open editor with custom filename...
r27153 if extra is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if extra.get(b'suffix') is not None:
Augie Fackler
formatting: blacken the codebase...
r43346 self.develwarn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'extra.suffix is not None but will soon be '
b'ignored by ui.edit()'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mykola Nikishov
ui: allow open editor with custom filename...
r27153 extra_defaults.update(extra)
extra = extra_defaults
Sean Farley
ui: add a parameter to set the temporary directory for edit...
r30835
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if action == b'diff':
suffix = b'.diff'
Michael Bolin
editor: file created for diff action should have .diff suffix...
r34056 elif action:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 suffix = b'.%s.hg.txt' % action
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 suffix = extra[b'suffix']
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030
Sean Farley
ui: rename tmpdir parameter to more specific repopath...
r30848 rdir = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.configbool(b'experimental', b'editortmpinhg'):
Sean Farley
ui: rename tmpdir parameter to more specific repopath...
r30848 rdir = repopath
Augie Fackler
formatting: blacken the codebase...
r43346 (fd, name) = pycompat.mkstemp(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix=b'hg-' + extra[b'prefix'] + b'-', suffix=suffix, dir=rdir
Augie Fackler
formatting: blacken the codebase...
r43346 )
Thomas Arendsen Hein
Improved ui.edit():...
r1984 try:
Matt Harbison
ui: use a context manager to handle file streams in edit()...
r44328 with os.fdopen(fd, 'wb') as f:
f.write(util.tonativeeol(text))
Thomas Arendsen Hein
Improved ui.edit():...
r1984
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 environ = {b'HGUSER': user}
if b'transplant_source' in extra:
environ.update(
{b'HGREVISION': hex(extra[b'transplant_source'])}
)
for label in (b'intermediate-source', b'source', b'rebase_source'):
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 if label in extra:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 environ.update({b'HGREVISION': extra[label]})
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 break
FUJIWARA Katsunori
ui: invoke editor for committing with HGEDITFORM environment variable...
r22205 if editform:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 environ.update({b'HGEDITFORM': editform})
FUJIWARA Katsunori
cmdutil: make in-memory changes visible to external editor (issue4378)...
r26750 if pending:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 environ.update({b'HG_PENDING': pending})
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605
Osku Salerma
Use VISUAL in addition to EDITOR when choosing the editor to use.
r5660 editor = self.geteditor()
mpm@selenic.com
Move ui class to its own module...
r207
Augie Fackler
formatting: blacken the codebase...
r43346 self.system(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"%s \"%s\"" % (editor, name),
Augie Fackler
formatting: blacken the codebase...
r43346 environ=environ,
Martin von Zweigbergk
errors: introduce CanceledError and use it in a few places...
r46489 onerr=error.CanceledError,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 errprefix=_(b"edit failed"),
blockedtag=b'editor',
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
Add username/merge/editor to .hgrc...
r608
Matt Harbison
ui: use a context manager to handle file streams in edit()...
r44328 with open(name, 'rb') as f:
t = util.fromnativeeol(f.read())
Thomas Arendsen Hein
Improved ui.edit():...
r1984 finally:
os.unlink(name)
Radoslaw "AstralStorm" Szkodzinski
Pass username to hgeditor, remove temporary file...
r662
mpm@selenic.com
Move ui class to its own module...
r207 return t
Vadim Gelfer
move mail sending code into core, so extensions can share it....
r2200
Augie Fackler
formatting: blacken the codebase...
r43346 def system(
self,
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 cmd: bytes,
Augie Fackler
formatting: blacken the codebase...
r43346 environ=None,
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 cwd: Optional[bytes] = None,
onerr: Optional[Callable[[bytes], Exception]] = None,
errprefix: Optional[bytes] = None,
blockedtag: Optional[bytes] = None,
) -> int:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """execute shell command with appropriate output stream. command
Yuya Nishihara
ui: introduce util.system() wrapper to make sure ui.fout is used...
r23269 output will be redirected if fout is not stdout.
Yuya Nishihara
chg: deduplicate error handling of ui.system()...
r31108
if command fails and onerr is None, return status, else raise onerr
object as exception.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Simon Farnsworth
ui: time calls to ui.system...
r30979 if blockedtag is None:
Simon Farnsworth
ui: restrict length of autogenerated blocked tags...
r31535 # Long cmds tend to be because of an absolute path on cmd. Keep
# the tail end instead
cmdsuffix = cmd.translate(None, _keepalnum)[-85:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 blockedtag = b'unknown_system_' + cmdsuffix
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 out = self._fout
Augie Fackler
cleanup: use __builtins__.any instead of util.any...
r25149 if any(s[1] for s in self._bufferstates):
Pierre-Yves David
ui: allow capture of subprocess output...
r24848 out = self
Simon Farnsworth
ui: time calls to ui.system...
r30979 with self.timeblockedsection(blockedtag):
Yuya Nishihara
chg: deduplicate error handling of ui.system()...
r31108 rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
if rc and onerr:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 errmsg = b'%s %s' % (
Micha Wiedenmann
ui: use "procutil.shellsplit" to parse command...
r45072 procutil.shellsplit(cmd)[0],
Augie Fackler
formatting: blacken the codebase...
r43346 procutil.explainexit(rc),
)
Yuya Nishihara
chg: deduplicate error handling of ui.system()...
r31108 if errprefix:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 errmsg = b'%s: %s' % (errprefix, errmsg)
Yuya Nishihara
chg: deduplicate error handling of ui.system()...
r31108 raise onerr(errmsg)
return rc
Yuya Nishihara
chg: refactor ui.system() to be partly overridden...
r31107
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _runsystem(self, cmd: bytes, environ, cwd: Optional[bytes], out) -> int:
Yuya Nishihara
chg: refactor ui.system() to be partly overridden...
r31107 """actually execute the given shell command (can be overridden by
extensions like chg)"""
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 return procutil.system(cmd, environ=environ, cwd=cwd, out=out)
Yuya Nishihara
ui: introduce util.system() wrapper to make sure ui.fout is used...
r23269
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def traceback(self, exc=None, force: bool = False):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """print exception traceback if traceback printing enabled or forced.
Vadim Gelfer
add ui.print_exc(), make all traceback printing central.
r2335 only to call in exception handler. returns true if traceback
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 printed."""
Matt Harbison
ui: add 'force' parameter to traceback() to override the current print setting...
r18966 if self.tracebackflag or force:
Matt Harbison
ui: add support for fully printing chained exception stacks in ui.traceback()...
r18965 if exc is None:
exc = sys.exc_info()
cause = getattr(exc[1], 'cause', None)
if cause is not None:
causetb = traceback.format_tb(cause[2])
exctb = traceback.format_tb(exc[2])
exconly = traceback.format_exception_only(cause[0], cause[1])
# exclude frame where 'exc' was chained and rethrown from exctb
Augie Fackler
formatting: blacken the codebase...
r43346 self.write_err(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'Traceback (most recent call last):\n',
Matt Harbison
ui: convert exception data to bytes when printing chained exception info...
r44329 encoding.strtolocal(''.join(exctb[:-1])),
encoding.strtolocal(''.join(causetb)),
encoding.strtolocal(''.join(exconly)),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
ui: add support for fully printing chained exception stacks in ui.traceback()...
r18965 else:
Matt Harbison
ui: flush stderr after printing a non-chained exception for Windows...
r25568 output = traceback.format_exception(exc[0], exc[1], exc[2])
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 self.write_err(encoding.strtolocal(''.join(output)))
Matt Harbison
ui: add 'force' parameter to traceback() to override the current print setting...
r18966 return self.tracebackflag or force
Osku Salerma
Use VISUAL in addition to EDITOR when choosing the editor to use.
r5660
def geteditor(self):
'''return editor to use'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pycompat.sysplatform == b'plan9':
Steven Stallion
plan9: initial support for plan 9 from bell labs...
r16383 # vi is the MIPS instruction simulator on Plan 9. We
# instead default to E to plumb commit messages to
# avoid confusion.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 editor = b'E'
Kyle Lippincott
darwin: use vim, not vi, to avoid data-loss inducing posix behavior...
r45085 elif pycompat.isdarwin:
# vi on darwin is POSIX compatible to a fault, and that includes
# exiting non-zero if you make any mistake when running an ex
# command. Proof: `vi -c ':unknown' -c ':qa'; echo $?` produces 1,
# while s/vi/vim/ doesn't.
editor = b'vim'
Steven Stallion
plan9: initial support for plan 9 from bell labs...
r16383 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 editor = b'vi'
return encoding.environ.get(b"HGEDITOR") or self.config(
b"ui", b"editor", editor
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
Add ui.progress API
r9153
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 @util.propertycache
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 def _progbar(self) -> Optional[progress.progbar]:
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 """setup the progbar singleton to the ui object"""
Augie Fackler
formatting: blacken the codebase...
r43346 if (
self.quiet
or self.debugflag
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or self.configbool(b'progress', b'disable')
Augie Fackler
formatting: blacken the codebase...
r43346 or not progress.shouldprint(self)
):
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 return None
return getprogbar(self)
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 def _progclear(self) -> None:
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 """clear progress bar output if any. use it before any output"""
Augie Fackler
formatting: blacken the codebase...
r43346 if not haveprogbar(): # nothing loaded yet
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 return
if self._progbar is not None and self._progbar.printed:
self._progbar.clear()
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 def makeprogress(
self, topic: bytes, unit: bytes = b"", total: Optional[int] = None
) -> scmutil.progress:
Yuya Nishihara
progress: specify updatebar() function by constructor argument...
r41246 """Create a progress helper for the specified topic"""
if getattr(self._fmsgerr, 'structured', False):
# channel for machine-readable output with metadata, just send
# raw information
# TODO: consider porting some useful information (e.g. estimated
# time) from progbar. we might want to support update delay to
# reduce the cost of transferring progress messages.
def updatebar(topic, pos, item, unit, total):
Augie Fackler
formatting: blacken the codebase...
r43346 self._fmsgerr.write(
None,
type=b'progress',
topic=topic,
pos=pos,
item=item,
unit=unit,
total=total,
)
Yuya Nishihara
progress: specify updatebar() function by constructor argument...
r41246 elif self._progbar is not None:
updatebar = self._progbar.progress
else:
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
progress: specify updatebar() function by constructor argument...
r41246 def updatebar(topic, pos, item, unit, total):
pass
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
progress: specify updatebar() function by constructor argument...
r41246 return scmutil.progress(self, updatebar, topic, unit, total)
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 def getlogger(self, name):
"""Returns a logger of the given name; or None if not registered"""
return self._loggers.get(name)
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def setlogger(self, name, logger) -> None:
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 """Install logger which can be identified later by the given name
More than one loggers can be registered. Use extension or module
name to uniquely identify the logger instance.
"""
self._loggers[name] = logger
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def log(self, event, msgfmt, *msgargs, **opts) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """hook for logging facility extensions
Matt Mackall
ui: add logging hook
r11984
Yuya Nishihara
ui: unify argument name of ui.log()...
r40714 event should be a readily-identifiable subsystem, which will
Matt Mackall
ui: add logging hook
r11984 allow filtering.
Augie Fackler
ui: improve docs on ui.log...
r26235
Yuya Nishihara
ui: pass in formatted message to logger.log()...
r40793 msgfmt should be a newline-terminated format string to log, and
*msgargs are %-formatted into it.
Augie Fackler
ui: improve docs on ui.log...
r26235
**opts currently has no defined meanings.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 if not self._loggers:
return
Gregory Szorc
py3: replace pycompat.itervalues(x) with x.values()...
r49790 activeloggers = [l for l in self._loggers.values() if l.tracked(event)]
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 if not activeloggers:
return
Yuya Nishihara
ui: pass in formatted message to logger.log()...
r40793 msg = msgfmt % msgargs
Yuya Nishihara
ui: pass in bytes opts dict to logger.log()...
r40794 opts = pycompat.byteskwargs(opts)
Yuya Nishihara
blackbox: send debug message to logger by core ui...
r40792 # guard against recursion from e.g. ui.debug()
registeredloggers = self._loggers
self._loggers = {}
try:
for logger in activeloggers:
logger.log(self, event, msg, opts)
finally:
self._loggers = registeredloggers
Matt Mackall
ui: add logging hook
r11984
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def label(self, msg: bytes, label: bytes) -> bytes:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """style msg based on supplied label
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Pierre-Yves David
color: move the 'colorlabel' call to the core 'ui' class...
r31087 If some color mode is enabled, this will add the necessary control
characters to apply such color. In addition, 'debug' color mode adds
markup showing which label affects a piece of text.
Brodie Rao
ui: add ui.write() output labeling API...
r10815
ui.write(s, 'label') is equivalent to
ui.write(ui.label(s, 'label')).
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Pierre-Yves David
color: move the 'colorlabel' call to the core 'ui' class...
r31087 if self._colormode is not None:
return color.colorlabel(self, msg, label)
Brodie Rao
ui: add ui.write() output labeling API...
r10815 return msg
Gregory Szorc
ui: represent paths as classes...
r24250
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def develwarn(
self, msg: bytes, stacklevel: int = 1, config: Optional[bytes] = None
) -> None:
Pierre-Yves David
ui: add a 'stacklevel' argument to 'develwarn'...
r27274 """issue a developer warning message
Use 'stacklevel' to report the offender some layers further up in the
stack.
"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not self.configbool(b'devel', b'all-warnings'):
if config is None or not self.configbool(b'devel', config):
Pierre-Yves David
develwarn: move config gating inside the develwarn function...
r29095 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = b'devel-warn: ' + msg
Augie Fackler
formatting: blacken the codebase...
r43346 stacklevel += 1 # get in develwarn
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629 if self.tracebackflag:
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 util.debugstacktrace(msg, stacklevel, self._ferr, self._fout)
Augie Fackler
formatting: blacken the codebase...
r43346 self.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'develwarn',
b'%s at:\n%s'
% (msg, b''.join(util.getstackframes(stacklevel))),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629 else:
curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 2)
Augie Fackler
ui: convert stack traces to sysbytes before logging...
r36144 fname, lineno, fmsg = calframe[stacklevel][1:4]
fname, fmsg = pycompat.sysbytes(fname), pycompat.sysbytes(fmsg)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.write_err(b'%s at: %s:%d (%s)\n' % (msg, fname, lineno, fmsg))
Augie Fackler
formatting: blacken the codebase...
r43346 self.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'develwarn', b'%s at: %s:%d (%s)\n', msg, fname, lineno, fmsg
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
ui: delete local variables instead of setting to `None`...
r44443
# avoid cycles
del curframe
del calframe
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def deprecwarn(
style: rewrap `ui.deprecwarn` declaration...
r51148 self,
msg: bytes,
version: bytes,
stacklevel: int = 2,
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 ) -> None:
Pierre-Yves David
ui: add a 'deprecwarn' helper to issue deprecation warnings...
r27275 """issue a deprecation warning
- msg: message explaining what is deprecated and how to upgrade,
- version: last version where the API will be supported,
"""
Augie Fackler
formatting: blacken the codebase...
r43346 if not (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.configbool(b'devel', b'all-warnings')
or self.configbool(b'devel', b'deprec-warn')
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Pierre-Yves David
deprecation: gate deprecation warning behind devel configuration...
r29082 return
Augie Fackler
formatting: blacken the codebase...
r43346 msg += (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"\n(compatibility will be dropped after Mercurial-%s,"
b" update your code.)"
Augie Fackler
formatting: blacken the codebase...
r43346 ) % version
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.develwarn(msg, stacklevel=stacklevel, config=b'deprec-warn')
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629
Matt Harbison
ui: introduce an experimental dict of exportable environment variables...
r30832 def exportableenviron(self):
"""The environment variables that are safe to export, e.g. through
hgweb.
"""
return self._exportableenviron
Kostia Balytskyi
ui: add configoverride context manager...
r30480 @contextlib.contextmanager
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def configoverride(self, overrides: _ConfigItems, source: bytes = b""):
Kostia Balytskyi
ui: add configoverride context manager...
r30480 """Context manager for temporary config overrides
`overrides` must be a dict of the following structure:
{(section, name) : value}"""
backups = {}
Gregory Szorc
ui: use try..finally in configoverride...
r30537 try:
for (section, name), value in overrides.items():
backups[(section, name)] = self.backupconfig(section, name)
self.setconfig(section, name, value, source)
yield
finally:
for __, backup in backups.items():
self.restoreconfig(backup)
# just restoring ui.quiet config to the previous value is not enough
# as it does not update ui.quiet class member
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if (b'ui', b'quiet') in overrides:
self.fixconfig(section=b'ui')
Kostia Balytskyi
ui: add configoverride context manager...
r30480
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def estimatememory(self) -> Optional[int]:
Joerg Sonnenberger
util: provide a helper function to estimate RAM size...
r45621 """Provide an estimate for the available system memory in Bytes.
This can be overriden via ui.available-memory. It returns None, if
no estimate can be computed.
"""
value = self.config(b'ui', b'available-memory')
if value is not None:
try:
return util.sizetoint(value)
except error.ParseError:
raise error.ConfigError(
_(b"ui.available-memory value is invalid ('%s')") % value
)
return util._estimatememory()
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
progress: move the singleton logic to the ui module...
r25498 # we instantiate one globally shared progress bar to avoid
# competing progress bars when multiple UI objects get created
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 _progresssingleton: Optional[progress.progbar] = None
Pierre-Yves David
progress: move the singleton logic to the ui module...
r25498
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 def getprogbar(ui: ui) -> progress.progbar:
Pierre-Yves David
progress: move the singleton logic to the ui module...
r25498 global _progresssingleton
if _progresssingleton is None:
# passing 'ui' object to the singleton is fishy,
# this is how the extension used to work but feel free to rework it.
_progresssingleton = progress.progbar(ui)
return _progresssingleton
Mark Thomas
ui: check for progress singleton when clearing progress bar (issue5684)...
r34346
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints related to progress bars in mercurial/ui.py...
r50689 def haveprogbar() -> bool:
Mark Thomas
ui: check for progress singleton when clearing progress bar (issue5684)...
r34346 return _progresssingleton is not None
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add trivial type hints to mercurial/ui.py...
r50692 def _selectmsgdests(ui: ui):
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 name = ui.config(b'ui', b'message-output')
Yuya Nishihara
commandserver: add experimental option to use separate message channel...
r40625 if name == b'channel':
if ui.fmsg:
return ui.fmsg, ui.fmsg
else:
# fall back to ferr if channel isn't ready so that status/error
# messages can be printed
return ui.ferr, ui.ferr
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 if name == b'stdio':
return ui.fout, ui.ferr
if name == b'stderr':
return ui.ferr, ui.ferr
raise error.Abort(b'invalid ui.message-output destination: %s' % name)
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
typing: add type hints related to message output in mercurial/ui.py...
r50690 def _writemsgwith(write, dest, *args: bytes, **opts: _MsgOpts) -> None:
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626 """Write ui message with the given ui._write*() function
The specified message type is translated to 'ui.<type>' label if the dest
isn't a structured channel, so that the message will be colorized.
"""
# TODO: maybe change 'type' to a mandatory option
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if 'type' in opts and not getattr(dest, 'structured', False):
opts['label'] = opts.get('label', b'') + b' ui.%s' % opts.pop('type')
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626 write(dest, *args, **opts)