##// END OF EJS Templates
config: catch intended exception when failing to parse config...
config: catch intended exception when failing to parse config When a new config parser was introduced in fca54469480e (ui: introduce new config parser, 2009-04-23), the reading side would raise a ConfigError which was then caught in the ui code. Then, in 2123aad24d56 (error: add new ParseError for various parsing errors, 2010-06-04), a ParseError was raised instead, but the call site was not updated. Let's start catching that ParseError. We still don't print it in a friendly way, but that's not worse than before. Differential Revision: https://phab.mercurial-scm.org/D7625

File last commit:

r44361:dbaf9aab default
r44361:dbaf9aab default
Show More
ui.py
2309 lines | 80.4 KiB | text/x-python | PythonLexer
mpm@selenic.com
Move ui class to its own module...
r207 # ui.py - user interface bits for mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@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
Gregory Szorc
ui: use absolute_import...
r25989 from __future__ import absolute_import
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
Gregory Szorc
ui: use absolute_import...
r25989 import errno
import getpass
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
from .i18n import _
from .node import hex
Gregory Szorc
py3: manually import pycompat.setattr where it is needed...
r43357 from .pycompat import (
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 getattr,
Gregory Szorc
py3: manually import pycompat.setattr where it is needed...
r43357 open,
setattr,
)
Gregory Szorc
ui: use absolute_import...
r25989
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,
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,
Jun Wu
rcutil: move scmutil.*rcpath to rcutil (API)...
r31679 rcutil,
Gregory Szorc
ui: use absolute_import...
r25989 scmutil,
util,
)
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,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
)
mpm@selenic.com
Move ui class to its own module...
r207
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _keepalnum = 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.
Pulkit Goyal
py3: add b'' to tweakdefaults config string...
r35929 tweakrc = 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 Mackall
ui: move samplehgrcs from config...
r22419 samplehgrcs = {
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
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945 class httppasswordmgrdbproxy(object):
"""Delays loading urllib2 until it's needed."""
Augie Fackler
formatting: blacken the codebase...
r43346
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945 def __init__(self):
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
Augie Fackler
pager: move pager-initiating code into core...
r30992 def _catchterm(*args):
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
_reqexithandlers = []
Augie Fackler
formatting: blacken the codebase...
r43346
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class ui(object):
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 def __init__(self, src=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
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
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
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]
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 @classmethod
def load(cls):
"""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
Jun Wu
rcutil: let rccomponents return different types of configs (API)...
r31683 for 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)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif t == b'items':
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()
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 return u
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872 def _maybetweakdefaults(self):
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 Mackall
ui: replace parentui mechanism with repo.baseui
r8189 def copy(self):
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
Yuya Nishihara
ui: provide official way to reset internal state per command...
r29366 def resetstate(self):
"""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
def timeblockedsection(self, key):
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 Mackall
ui: add formatter method
r16135 def formatter(self, topic, 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 Mackall
ui: rename _is_trusted to _trusted...
r14859 def _trusted(self, fp, f):
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
Augie Fackler
formatting: blacken the codebase...
r43346 def readconfig(
self, filename, root=None, trust=False, sections=None, remap=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 Mackall
ui: privatize cdata vars
r8203 cfg = config.config()
Matt Mackall
ui: rename _is_trusted to _trusted...
r14859 trusted = sections or trust or self._trusted(fp, filename)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Matt Mackall
ui: fold readsections into readconfig...
r8142 try:
Alexander Solovyov
hgwebdir: read --webdir-conf as actual configuration to ui (issue1586)...
r8345 cfg.read(filename, fp, sections=sections, remap=remap)
Matt Mackall
misc: adding missing file close() calls...
r15407 fp.close()
Martin von Zweigbergk
config: catch intended exception when failing to parse config...
r44361 except error.ParseError as inst:
Matt Mackall
ui: fold readsections into readconfig...
r8142 if trusted:
Matt Mackall
ui: introduce new config parser
r8144 raise
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.warn(_(b"ignored: %s\n") % stringutil.forcebytestr(inst))
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
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]
"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
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 def fixconfig(self, root=None, section=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'):
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:
s = self.configsource(b'paths', n) or b'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'%')
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 p = util.expandpath(p)
Brodie Rao
url: move URL parsing functions into util to improve startup time...
r14076 if not util.hasscheme(p) and not os.path.isabs(p):
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 p = os.path.normpath(os.path.join(root, p))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 c.set(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 )
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),
)
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 def restoreconfig(self, data):
self._ocfg.restore(data[0])
self._tcfg.restore(data[1])
self._ucfg.restore(data[2])
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def setconfig(self, section, name, value, source=b''):
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)]
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
David Demelier
configitems: add alias support in config...
r33329 for s, n in alternates:
candidate = self._data(untrusted).get(s, n, None)
config: extract the core config logic into a private method...
r33058 if candidate is not None:
value = candidate
Matt Mackall
ui: allow alternatives for config options
r15035 break
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
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(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 config.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):
return config.parselist(v)
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
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 def walkconfig(self, untrusted=False):
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
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 def plain(self, feature=None):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''is plain mode active?
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
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''
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
Thomas Arendsen Hein
Move generating short username to display in hg/hgweb annotate to ui module.
r1129 def shortuser(self, user):
"""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
Vadim Gelfer
push, outgoing, bundle: fall back to "default" if "default-push" not defined
r2494 def expandpath(self, loc, default=None):
Thomas Arendsen Hein
Directory names take precedence over symbolic names consistently....
r1892 """Return repository location relative to cwd or from [paths]"""
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189 try:
p = self.paths.getpath(loc)
if p:
return p.rawloc
except error.RepoError:
pass
if default:
try:
p = self.paths.getpath(default)
if p:
return p.rawloc
except error.RepoError:
pass
Gregory Szorc
ui: represent paths as classes...
r24250 return loc
@util.propertycache
def paths(self):
return 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
@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)
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)
Gregory Szorc
ui: track label expansion when creating buffers...
r27106 def pushbuffer(self, error=False, subproc=False, labeled=False):
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
Gregory Szorc
ui: remove labeled argument from popbuffer...
r27109 def popbuffer(self):
'''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
Yuya Nishihara
ui: add inner function to select write destination...
r40577 def _isbuffered(self, dest):
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
Joerg Sonnenberger
diff: improve ui.write performance when not coloring on Windows...
r35979 def canwritewithoutlabels(self):
'''check if write skips the label'''
if self._buffers and not self._bufferapplylabels:
return True
return self._colormode is None
def canbatchlabeledwrites(self):
'''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
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def write(self, *args, **opts):
'''write args to output
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.
'''
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
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if not opts.get('keepprogressbar', False):
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
def write_err(self, *args, **opts):
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
def _write(self, dest, *args, **opts):
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
Yuya Nishihara
ui: pass in file object to _writenobuf()...
r40574 def _writenobuf(self, dest, *args, **opts):
Yuya Nishihara
ui: inline _writenobuf() into write() due to performance issue...
r41377 # update write() as well if you touch this code
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 if not opts.get('keepprogressbar', False):
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.
Yuya Nishihara
ui: hide fin/fout/ferr attributes behind @property functions...
r40579 if dest is self._ferr and not getattr(self._ferr, '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
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626 def _writemsg(self, dest, *args, **opts):
_writemsgwith(self._write, dest, *args, **opts)
def _writemsgnobuf(self, dest, *args, **opts):
_writemsgwith(self._writenobuf, dest, *args, **opts)
Vadim Gelfer
make ui flush output. this makes error happen if printing to /dev/full....
r1837 def flush(self):
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 Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 def _isatty(self, fh):
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
Augie Fackler
ui: rename neverpager to disablepager...
r31026 def disablepager(self):
self._disablepager = True
Augie Fackler
ui: introduce neverpager() call...
r30994
Augie Fackler
pager: move pager-initiating code into core...
r30992 def pager(self, command):
"""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
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()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(signal, b"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
Jun Wu
pager: set some environment variables if they're not set...
r31954 def _runpager(self, command, env=None):
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)),
)
Augie Fackler
pager: avoid shell=True on subprocess.Popen for better errors (issue5491)...
r31478 except OSError as e:
if e.errno == errno.ENOENT and 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
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 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():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(signal, b"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
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):
'''register a function to run after dispatching a request
Handlers do not stay registered across request boundaries.'''
self._exithandlers.append((func, args, kwargs))
return func
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 def interface(self, feature):
"""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
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 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:
defaultinterface = i
choseninterface = 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:
choseninterface = f
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):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''is interactive input allowed?
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
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
Augie Fackler
termwidth: move to ui.ui from util
r12689 def termwidth(self):
'''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):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''should formatted output be used?
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()'.
'''
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def _readline(self, prompt=b' ', promptopts=None):
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)
Kyle Lippincott
readline: provide styled prompt to readline (issue6070)...
r42288 line = encoding.strtolocal(pycompat.rawinput(prompt))
Yuya Nishihara
ui: adjust Windows workaround to new _readline() code...
r36814 # When stdin is in binary mode on Windows, it can cause
# raw_input() to emit an extra trailing carriage return
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
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)
def _prompt(self, msg, **opts):
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 default = opts['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'):
self._writemsg(self._fmsgout, r, 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
def extractchoices(prompt):
"""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.
Pulkit Goyal
py3: add b'' to make the regex pattern bytes
r33096 m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
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 Mackall
ui: merge prompt text components into a singe string...
r19226 def promptchoice(self, prompt, default=0):
"""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
Vadim Gelfer
prompt user for http authentication info...
r2281 def getpass(self, prompt=None, default=None):
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:
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 return getpass.getpass('')
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
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def status(self, *msg, **opts):
'''write status message to output (if ui.quiet is False)
This adds an output label of "ui.status".
'''
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
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def warn(self, *msg, **opts):
'''write warning message to output (stderr)
This adds an output label of "ui.warning".
'''
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
def error(self, *msg, **opts):
'''write error message to output (stderr)
This adds an output label of "ui.error".
'''
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
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def note(self, *msg, **opts):
'''write note to output (if ui.verbose is True)
This adds an output label of "ui.note".
'''
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
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def debug(self, *msg, **opts):
'''write debug message to output (if ui.debugflag is True)
This adds an output label of "ui.debug".
'''
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,
text,
user,
extra=None,
editform=None,
pending=None,
repopath=None,
action=None,
):
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,
onerr=error.Abort,
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,
cmd,
environ=None,
cwd=None,
onerr=None,
errprefix=None,
blockedtag=None,
):
Yuya Nishihara
ui: introduce util.system() wrapper to make sure ui.fout is used...
r23269 '''execute shell command with appropriate output stream. command
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.
Yuya Nishihara
ui: introduce util.system() wrapper to make sure ui.fout is used...
r23269 '''
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' % (
Augie Fackler
formatting: blacken the codebase...
r43346 os.path.basename(cmd.split(None, 1)[0]),
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
Yuya Nishihara
chg: deduplicate error handling of ui.system()...
r31108 def _runsystem(self, cmd, environ, cwd, out):
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
ui: add 'force' parameter to traceback() to override the current print setting...
r18966 def traceback(self, exc=None, force=False):
'''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
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'
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
def _progbar(self):
"""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)
def _progclear(self):
"""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()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def progress(self, topic, pos, item=b"", unit=b"", total=None):
Matt Mackall
Add ui.progress API
r9153 '''show a progress message
timeless
progress: update comment to reflect implementation...
r28598 By default a textual progress bar will be displayed if an operation
takes too long. 'topic' is the current operation, 'item' is a
Mads Kiilerich
fix trivial spelling errors
r17424 non-numeric marker of the current position (i.e. the currently
in-process file), 'pos' is the current numeric position (i.e.
Brodie Rao
ui: fix NameError in ui.progress due to unit/units typo
r9398 revision, bytes, etc.), unit is a corresponding unit label,
Matt Mackall
Add ui.progress API
r9153 and total is the highest expected pos.
Augie Fackler
ui.progress: clarify termination requirement
r10425 Multiple nested topics may be active at a time.
All topics should be marked closed by setting pos to None at
termination.
Matt Mackall
Add ui.progress API
r9153 '''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.deprecwarn(
b"use ui.makeprogress() instead of ui.progress()", b"5.1"
)
Martin von Zweigbergk
progress: write ui.progress() in terms of ui.makeprogress()...
r41178 progress = self.makeprogress(topic, unit, total)
if pos is not None:
progress.update(pos, item=item)
Matt Mackall
Add ui.progress API
r9153 else:
Martin von Zweigbergk
progress: write ui.progress() in terms of ui.makeprogress()...
r41178 progress.complete()
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def makeprogress(self, topic, unit=b"", total=None):
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)
def setlogger(self, name, logger):
"""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
Yuya Nishihara
ui: pass in formatted message to logger.log()...
r40793 def log(self, event, msgfmt, *msgargs, **opts):
Matt Mackall
ui: add logging hook
r11984 '''hook for logging facility extensions
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.
Matt Mackall
ui: add logging hook
r11984 '''
Yuya Nishihara
ui: manage logger instances and event filtering by core ui...
r40761 if not self._loggers:
return
Augie Fackler
formatting: blacken the codebase...
r43346 activeloggers = [
Gregory Szorc
py3: define and use pycompat.itervalues()...
r43374 l for l in pycompat.itervalues(self._loggers) if l.tracked(event)
Augie Fackler
formatting: blacken the codebase...
r43346 ]
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
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def label(self, msg, label):
'''style msg based on supplied label
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')).
'''
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
Pierre-Yves David
develwarn: move config gating inside the develwarn function...
r29095 def develwarn(self, msg, stacklevel=1, config=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 )
Jun Wu
ui: drop values returned by inspect.*frame*() to avoid cycles...
r29762 curframe = calframe = None # avoid cycles
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629
Matt Harbison
cmdutil: convert _revertprefetch() to a generic stored file hook (API)...
r35941 def deprecwarn(self, msg, version, stacklevel=2):
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def configoverride(self, overrides, source=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
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: represent paths as classes...
r24250 class paths(dict):
"""Represents a collection of paths and their configs.
Data is initially derived from ui instances and the config files they have
loaded.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: represent paths as classes...
r24250 def __init__(self, ui):
dict.__init__(self)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for name, loc in ui.configitems(b'paths', ignoresub=True):
Gregory Szorc
ui: represent paths as classes...
r24250 # No location is the same as not existing.
if not loc:
continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 loc, sub = ui.configsuboptions(b'paths', name)
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 self[name] = path(ui, name, rawloc=loc, suboptions=sub)
Gregory Szorc
ui: represent paths as classes...
r24250
def getpath(self, name, default=None):
Yuya Nishihara
paths: make getpath() accept multiple defaults...
r27561 """Return a ``path`` from a string, falling back to default.
Gregory Szorc
ui: move URL and path detection into path API...
r26056
``name`` can be a named path or locations. Locations are filesystem
paths or URIs.
Gregory Szorc
ui: represent paths as classes...
r24250
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189 Returns None if ``name`` is not a registered path, a URI, or a local
path to a repo.
Gregory Szorc
ui: represent paths as classes...
r24250 """
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189 # Only fall back to default if no path was requested.
if name is None:
Yuya Nishihara
paths: make getpath() accept multiple defaults...
r27561 if not default:
default = ()
elif not isinstance(default, (tuple, list)):
default = (default,)
for k in default:
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189 try:
Yuya Nishihara
paths: make getpath() accept multiple defaults...
r27561 return self[k]
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189 except KeyError:
Yuya Nishihara
paths: make getpath() accept multiple defaults...
r27561 continue
return None
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189
# Most likely empty string.
# This may need to raise in the future.
if not name:
return None
Gregory Szorc
ui: represent paths as classes...
r24250 try:
return self[name]
except KeyError:
Gregory Szorc
ui: move URL and path detection into path API...
r26056 # Try to resolve as a local path or URI.
try:
Gregory Szorc
ui: pass ui instance to path.__init__...
r27265 # We don't pass sub-options in, so no need to pass ui instance.
return path(None, None, rawloc=name)
Gregory Szorc
ui: move URL and path detection into path API...
r26056 except ValueError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.RepoError(_(b'repository %s does not exist') % name)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: move URL and path detection into path API...
r26056
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 _pathsuboptions = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 def pathsuboption(option, attr):
"""Decorator used to declare a path sub-option.
Arguments are the sub-option name and the attribute it should set on
``path`` instances.
The decorated function will receive as arguments a ``ui`` instance,
``path`` instance, and the string value of this option from the config.
The function should return the value that will be set on the ``path``
instance.
This decorator can be used to perform additional verification of
sub-options and to change the type of sub-options.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 def register(func):
_pathsuboptions[option] = (attr, func)
return func
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 return register
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pathsuboption(b'pushurl', b'pushloc')
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 def pushurlpathoption(ui, path, value):
u = util.url(value)
# Actually require a URL.
if not u.scheme:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.warn(_(b'(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 return None
# Don't support the #foo syntax in the push URL to declare branch to
# push.
if u.fragment:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(
b'("#fragment" in paths.%s:pushurl not supported; '
b'ignoring)\n'
)
Augie Fackler
formatting: blacken the codebase...
r43346 % path.name
)
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 u.fragment = None
Yuya Nishihara
py3: don't use str() to stringify pushloc
r36749 return bytes(u)
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @pathsuboption(b'pushrev', b'pushrev')
Gregory Szorc
ui: path option to declare which revisions to push by default...
r29413 def pushrevpathoption(ui, path, value):
return value
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
ui: represent paths as classes...
r24250 class path(object):
"""Represents an individual path and its configuration."""
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 def __init__(self, ui, name, rawloc=None, suboptions=None):
Gregory Szorc
ui: represent paths as classes...
r24250 """Construct a path from its config options.
Gregory Szorc
ui: pass ui instance to path.__init__...
r27265 ``ui`` is the ``ui`` instance the path is coming from.
Gregory Szorc
ui: represent paths as classes...
r24250 ``name`` is the symbolic name of the path.
``rawloc`` is the raw location, as defined in the config.
Gregory Szorc
ui: capture push location on path instances...
r26064 ``pushloc`` is the raw locations pushes should be made to.
Gregory Szorc
ui: move URL and path detection into path API...
r26056
If ``name`` is not defined, we require that the location be a) a local
filesystem path with a .hg directory or b) a URL. If not,
``ValueError`` is raised.
Gregory Szorc
ui: represent paths as classes...
r24250 """
Gregory Szorc
ui: move URL and path detection into path API...
r26056 if not rawloc:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise ValueError(b'rawloc must be defined')
Gregory Szorc
ui: move URL and path detection into path API...
r26056
# Locations may define branches via syntax <base>#<branch>.
u = util.url(rawloc)
branch = None
if u.fragment:
branch = u.fragment
u.fragment = None
self.url = u
self.branch = branch
Gregory Szorc
ui: represent paths as classes...
r24250 self.name = name
Gregory Szorc
ui: move URL and path detection into path API...
r26056 self.rawloc = rawloc
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.loc = b'%s' % u
Gregory Szorc
ui: move URL and path detection into path API...
r26056
# When given a raw location but not a symbolic name, validate the
# location is valid.
Durham Goode
paths: move path validation logic to its own function...
r26076 if not name and not u.scheme and not self._isvalidlocalpath(self.loc):
Augie Fackler
formatting: blacken the codebase...
r43346 raise ValueError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'location is not a URL or path to a local '
b'repo: %s' % rawloc
Augie Fackler
formatting: blacken the codebase...
r43346 )
Pierre-Yves David
progress: move the singleton logic to the ui module...
r25498
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 suboptions = suboptions or {}
# Now process the sub-options. If a sub-option is registered, its
# attribute will always be present. The value will be None if there
# was no valid sub-option.
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for suboption, (attr, func) in pycompat.iteritems(_pathsuboptions):
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 if suboption not in suboptions:
setattr(self, attr, None)
continue
value = func(ui, self, suboptions[suboption])
setattr(self, attr, value)
Durham Goode
paths: move path validation logic to its own function...
r26076 def _isvalidlocalpath(self, path):
"""Returns True if the given path is a potentially valid repository.
This is its own function so that extensions can change the definition of
'valid' in this case (like when pulling from a git repo into a hg
one)."""
Gregory Szorc
hg: raise Abort on invalid path...
r41625 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return os.path.isdir(os.path.join(path, b'.hg'))
Gregory Szorc
hg: raise Abort on invalid path...
r41625 # Python 2 may return TypeError. Python 3, ValueError.
except (TypeError, ValueError):
return False
Durham Goode
paths: move path validation logic to its own function...
r26076
Gregory Szorc
ui: capture push location on path instances...
r26064 @property
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 def suboptions(self):
"""Return sub-options and their values for this path.
This is intended to be used for presentation purposes.
"""
d = {}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for subopt, (attr, _func) in pycompat.iteritems(_pathsuboptions):
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 value = getattr(self, attr)
if value is not None:
d[subopt] = value
return d
Gregory Szorc
ui: capture push location on path instances...
r26064
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
_progresssingleton = None
Augie Fackler
formatting: blacken the codebase...
r43346
Pierre-Yves David
progress: move the singleton logic to the ui module...
r25498 def getprogbar(ui):
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
Mark Thomas
ui: check for progress singleton when clearing progress bar (issue5684)...
r34346 def haveprogbar():
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
Yuya Nishihara
ui: add config knob to redirect status messages to stderr (API)...
r40580 def _selectmsgdests(ui):
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
Yuya Nishihara
ui: extract helpers to write message with type or label...
r40626 def _writemsgwith(write, dest, *args, **opts):
"""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)