##// END OF EJS Templates
split: preserve phase of commit that is being split...
split: preserve phase of commit that is being split With this change, hg split will preserve the phase of the commit that is being split, ignoring the phases.new-commit setting. Previously, we would use whatever phases.new-commit was set to (unless our parent was secret, then we would be secret even if phases.new-commit=draft). Now, splitting a draft commit with phases.new-commit=secret does not cause the new commits to become secret, and splitting a secret commit with phases.new-commit=draft and a draft parent does not cause the new commits to become draft. Test cases and commit message taken from Kyle Lippincott's D2016 (thanks!). Differential Revision: https://phab.mercurial-scm.org/D3819

File last commit:

r38364:bec1212e default
r38443:4f885770 default
Show More
ui.py
1873 lines | 68.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
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,
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
Yuya Nishihara
py3: factor out bytechr() function...
r31253 _keepalnum = ''.join(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
Augie Fackler
ui: add support for a tweakdefaults knob...
r32872
[commands]
# Make `hg status` emit cwd-relative paths by default.
status.relative = yes
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
Augie Fackler
status: add default of --terse=u to tweakdefaults (BC)...
r38113 # Collapse entire directories that contain only unknown files
status.terse = u
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
ui: add support for a tweakdefaults knob...
r32872 """
Matt Mackall
ui: move samplehgrcs from config...
r22419 samplehgrcs = {
'user':
Yuya Nishihara
py3: use bytes IO to write sample hgrc...
r33650 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]
# uncomment these lines 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 #
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
Jordi Gutiérrez Hermoso
config: use the same hgrc for a cloned repo as for an uninitted repo...
r22837 'cloned':
Yuya Nishihara
py3: use bytes IO to write sample hgrc...
r33650 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>
""",
Matt Mackall
ui: move samplehgrcs from config...
r22419 'local':
Yuya Nishihara
py3: use bytes IO to write sample hgrc...
r33650 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 """,
'global':
Yuya Nishihara
py3: use bytes IO to write sample hgrc...
r33650 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]
# uncomment these lines 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
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483 def _maybestrurl(maybebytes):
Yuya Nishihara
py3: factor out helpers to apply string conversion recursively
r35918 return util.rapply(pycompat.strurl, maybebytes)
Augie Fackler
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483
def _maybebytesurl(maybestr):
Yuya Nishihara
py3: factor out helpers to apply string conversion recursively
r35918 return util.rapply(pycompat.bytesurl, maybestr)
Kyle Lippincott
ui: remove urllib2 from being imported early...
r30945
class httppasswordmgrdbproxy(object):
"""Delays loading urllib2 until it's needed."""
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(
Yuya Nishihara
py3: factor out helpers to apply string conversion recursively
r35918 _maybestrurl(realm), _maybestrurl(uris),
Augie Fackler
ui: convert to/from Optional[bytes] to Optional[str] in password manager...
r34483 _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()
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
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 = []
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
Matt Mackall
ui: privatize cdata vars
r8203 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 = {}
Matt Mackall
ui: refactor option setting...
r8136
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 if src:
Idan Kamara
ui: add I/O descriptors
r14612 self.fout = src.fout
self.ferr = src.ferr
self.fin = src.fin
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
procutil: bulk-replace util.std* to point to new module
r37137 self.fout = procutil.stdout
self.ferr = procutil.stderr
self.fin = procutil.stdin
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
Matt Harbison
ui: introduce an experimental dict of exportable environment variables...
r30832 allowed = self.configlist('experimental', 'exportableenviron')
if '*' in allowed:
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():
if t == 'path':
u.readconfig(f, trust=True)
Jun Wu
rcutil: let environ override system configs (BC)...
r31685 elif t == 'items':
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:
raise error.ProgrammingError('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):
if not self.configbool('ui', 'tweakdefaults'):
return
if self._tweaked or self.plain('tweakdefaults'):
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()
tmpcfg.parse('<tweakdefaults>', tweakrc)
for section in tmpcfg:
for name, value in tmpcfg.items(section):
if not self.hasconfig(section, name):
self.setconfig(section, name, value, "<tweakdefaults>")
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:
self._blockedtimes[key + '_blocked'] += \
(util.timer() - starttime) * 1000
Yuya Nishihara
ui: provide official way to reset internal state per command...
r29366
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
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 if '*' in tusers or '*' in tgroups:
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:
Martin Geisler
ui: lowercase "not trusting file" warning message
r16939 self.warn(_('not trusting file %s from untrusted '
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 'user %s, group %s\n') % (f, user, group))
return False
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551
Matt Mackall
ui: assumetrusted -> trust
r8200 def readconfig(self, filename, root=None, trust=False,
Alexander Solovyov
hgwebdir: read --webdir-conf as actual configuration to ui (issue1586)...
r8345 sections=None, remap=None):
Matt Mackall
ui: fold readsections into readconfig...
r8142 try:
Augie Fackler
ui: explicitly open config files in binary mode...
r30348 fp = open(filename, u'rb')
Matt Mackall
ui: fold readsections into readconfig...
r8142 except IOError:
if not sections: # ignore unless we were looking for something
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()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.ConfigError as inst:
Matt Mackall
ui: fold readsections into readconfig...
r8142 if trusted:
Matt Mackall
ui: introduce new config parser
r8144 raise
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 self.warn(_("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():
Brodie Rao
ui: unset ui.slash when HGPLAIN is set
r10507 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
Mathias De Maré
commands: add ui.statuscopies config knob...
r24663 'logtemplate', 'statuscopies', 'style',
Brodie Rao
ui: unset ui.slash when HGPLAIN is set
r10507 'traceback', 'verbose'):
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 if k in cfg['ui']:
del cfg['ui'][k]
"Yann E. MORIN"
ui: enable alias exception when reading config in plain mode...
r14373 for k, v in cfg.items('defaults'):
del cfg['defaults'][k]
Martin von Zweigbergk
plain: ignore [commands] config...
r31588 for k, v in cfg.items('commands'):
del cfg['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
if self.plain('alias'):
Brodie Rao
ui: suppress aliases when HGPLAIN is set
r10506 for k, v in cfg.items('alias'):
del cfg['alias'][k]
Siddharth Agarwal
ui: disable revsetaliases in plain mode (BC)...
r24883 if self.plain('revsetalias'):
for k, v in cfg.items('revsetalias'):
del cfg['revsetalias'][k]
Yuya Nishihara
ui: drop template aliases by HGPLAIN...
r28958 if self.plain('templatealias'):
for k, v in cfg.items('templatealias'):
del cfg['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:
root = os.path.expanduser('~')
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):
if section in (None, 'paths'):
# expand vars and ~
# translate paths relative to root (or home) into absolute paths
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 root = root or pycompat.getcwd()
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 for c in self._tcfg, self._ucfg, self._ocfg:
for n, p in c.items('paths'):
Gregory Szorc
ui: don't fixup [paths] sub-options...
r29412 # Ignore sub-options.
if ':' in n:
continue
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if not p:
continue
if '%%' in p:
Yuya Nishihara
ui: do not translate empty configsource() to 'none' (API)...
r30618 s = self.configsource('paths', n) or 'none'
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
Yuya Nishihara
ui: do not translate empty configsource() to 'none' (API)...
r30618 % (n, p, s))
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 p = p.replace('%%', '%')
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))
c.set("paths", n, p)
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if section in (None, 'ui'):
# update ui options
self.debugflag = self.configbool('ui', 'debug')
self.verbose = self.debugflag or self.configbool('ui', 'verbose')
self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
if self.verbose and self.quiet:
self.quiet = self.verbose = False
Ry4an Brase
ui: always report untrusted hgrc files when debug enabled...
r13493 self._reportuntrusted = self.debugflag or self.configbool("ui",
Jun Wu
codemod: register core configitems using a script...
r33499 "report_untrusted")
self.tracebackflag = self.configbool('ui', 'traceback')
Simon Farnsworth
ui: provide a mechanism to track and log blocked time...
r30976 self.logblockedtimes = self.configbool('ui', 'logblockedtimes')
Alexis S. L. Carvalho
update ui.quiet/verbose/debug/interactive every time the config changes...
r3350
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if section in (None, 'trusted'):
# update trust information
self._trustusers.update(self.configlist('trusted', 'users'))
self._trustgroups.update(self.configlist('trusted', 'groups'))
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 def backupconfig(self, section, item):
return (self._ocfg.backup(section, item),
self._tcfg.backup(section, item),
self._ucfg.backup(section, item),)
def restoreconfig(self, data):
self._ocfg.restore(data[0])
self._tcfg.restore(data[1])
self._ucfg.restore(data[2])
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 def setconfig(self, section, name, value, source=''):
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"""
value = self._config(section, name, default=default,
untrusted=untrusted)
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:
msg = ("accessing unregistered config item: '%s.%s'")
msg %= (section, name)
self.develwarn(msg, 2, '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
msg = "config item requires an explicit default value: '%s.%s'"
msg %= (section, name)
self.develwarn(msg, 2, '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
Boris Feld
configitems: handle case were the default value is not static...
r33471 elif (item is not None
Yuya Nishihara
configitems: relax warning about unwanted default value...
r34949 and item.default is not configitems.dynamicdefault
and default != itemdefault):
msg = ("specifying a mismatched default value for a registered "
David Demelier
configitems: add alias support in config...
r33329 "config item: '%s.%s' '%s'")
Augie Fackler
ui: use pycompat.bytestr() to get a bytes-repr of config default...
r36143 msg %= (section, name, pycompat.bytestr(default))
David Demelier
configitems: add alias support in config...
r33329 self.develwarn(msg, 2, '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
David Demelier
configitems: add alias support in config...
r33329 section = s
Matt Mackall
ui: allow alternatives for config options
r15035 name = n
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:
self.debug("ignoring untrusted configuration option "
David Demelier
configitems: add alias support in config...
r33329 "%s.%s = %s\n" % (s, n, uvalue))
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 = {}
prefix = '%s:' % name
for k, v in data.items(section):
if k.startswith(prefix):
sub[k[len(prefix):]] = v
if self.debugflag and not untrusted and self._reportuntrusted:
for k, v in sub.items():
uvalue = self._ucfg.get(section, '%s:%s' % (name, k))
if uvalue is not None and uvalue != v:
self.debug('ignoring untrusted configuration option '
'%s:%s.%s = %s\n' % (section, name, k, uvalue))
return main, sub
config: use the new '_unset' value for 'configpath'...
r32965 def configpath(self, section, name, default=_unset, untrusted=False):
Simon Heimberg
ui: config path relative to repo root
r14924 '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
Matt Mackall
ui: add configpath helper
r13238 if not os.path.isabs(v) or "://" not in v:
src = self.configsource(section, name, untrusted)
if ':' in src:
Simon Heimberg
ui: fix error, base can not be a list
r14922 base = os.path.dirname(src.rsplit(':')[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:
Sune Foldager
ui: add configint function and tests
r14171 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
Matt Mackall
ui: introduce new config parser
r8144 % (section, name, v))
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
config: use the new '_unset' value for 'configwith'...
r32960 def configwith(self, convert, section, name, default=_unset,
Bryan O'Sullivan
ui: add a configwith method...
r30926 desc=None, untrusted=False):
"""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:
config: use the new '_unset' value for 'configwith'...
r32960 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__)
Bryan O'Sullivan
ui: add a configwith method...
r30926 raise error.ConfigError(_("%s.%s is not a valid %s ('%s')")
% (section, name, desc, v))
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 """
Bryan O'Sullivan
ui: rewrite configint in terms of configwith
r30927 return self.configwith(int, section, name, default, 'integer',
untrusted)
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:
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 % (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
config: use the new '_unset' value for 'configlist'...
r32963 v = self.configwith(config.parselist, section, name, default,
Jun Wu
ui: move configlist parser to config.py...
r31481 'list', untrusted)
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):
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 return self.configwith(dateutil.parsedate, section, name, default,
Boris Feld
ui: add the possiblity to get a date config field...
r32408 'date', untrusted)
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
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:
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 items = [i for i in items if ':' 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:
David Soria Parra
i18n: remove translation of debug messages
r14708 self.debug("ignoring untrusted configuration option "
"%s.%s = %s\n" % (section, k, v))
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 '''
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 if ('HGPLAIN' not in encoding.environ and
'HGPLAINEXCEPT' not in encoding.environ):
Brodie Rao
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT...
r13849 return False
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 exceptions = encoding.environ.get('HGPLAINEXCEPT',
'').strip().split(',')
Yuya Nishihara
dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options...
r35180 # TODO: add support for HGPLAIN=+feature,-feature syntax
if '+strictflags' not in encoding.environ.get('HGPLAIN', '').split(','):
exceptions.append('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 """
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 user = encoding.environ.get("HGUSER")
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 if user is None:
David Demelier
configitems: add alias support in config...
r33329 user = self.config("ui", "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:
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 user = encoding.environ.get("EMAIL")
Boris Feld
ui: add the possibility to returns None as username in ui...
r34850 if user is None and acceptempty:
return user
Benoit Boissinot
ui: add an option to prompt for the username when it isn't provided...
r6862 if user is None and self.configbool("ui", "askusername"):
Martin Geisler
lowercase prompts...
r7600 user = self.prompt(_("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:
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 user = '%s@%s' % (procutil.getuser(),
Yuya Nishihara
py3: fix type of default username
r36802 encoding.strtolocal(socket.getfqdn()))
Martin Geisler
ui: lowercase "no username" warning
r16940 self.warn(_("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:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no username supplied'),
timeless
config: use single quotes around command hint...
r28962 hint=_("use 'hg config --edit' "
Matt Mackall
ui: fix extra space in username abort
r20580 'to set your username'))
Matt Mackall
ui: disallow newlines in usernames (issue1034)
r6351 if "\n" in user:
Pulkit Goyal
py3: use pycompat.bytestr to convert str to bytes...
r36246 raise error.Abort(_("username %r contains a newline\n")
% pycompat.bytestr(user))
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
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
Matt Mackall
ui: buffers -> _buffers
r8202 return "".join(self._buffers.pop())
Matt Mackall
add a simple nested buffering scheme to ui
r3737
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``.
return self._colormode != 'win32'
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
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: add explicit path to write prompt text bypassing buffers...
r35975 if self._buffers:
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 if self._bufferapplylabels:
Pulkit Goyal
py3: handle keyword arguments correctly in ui.py...
r35374 label = opts.get(r'label', '')
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:
self._writenobuf(*args, **opts)
def _writenobuf(self, *args, **opts):
if self._colormode == 'win32':
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 # windows color printing is its own can of crab, defer to
# the color module and that is it.
Pierre-Yves David
color: pass 'ui' to 'win32print'...
r31114 color.win32print(self, self._write, *args, **opts)
Matt Mackall
add a simple nested buffering scheme to ui
r3737 else:
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 msgs = args
if self._colormode is not None:
Pulkit Goyal
py3: handle keyword arguments correctly in ui.py...
r35374 label = opts.get(r'label', '')
Pierre-Yves David
color: move 'write' logic to the core ui class...
r31091 msgs = [self.label(a, label) for a in args]
self._write(*msgs, **opts)
Pierre-Yves David
ui: extract the low level part of 'write' in a dedicated function...
r31090
def _write(self, *msgs, **opts):
Yuya Nishihara
ui: remove superfluous indent in _write()
r31128 self._progclear()
# opencode timeblockedsection because this is a critical path
starttime = util.timer()
try:
Joerg Sonnenberger
ui: improve performance for multi-component writes...
r35907 self.fout.write(''.join(msgs))
Bryan O'Sullivan
stdio: raise StdioError if something goes wrong in ui._write
r31961 except IOError as err:
raise error.StdioError(err)
Yuya Nishihara
ui: remove superfluous indent in _write()
r31128 finally:
self._blockedtimes['stdio_blocked'] += \
(util.timer() - starttime) * 1000
mpm@selenic.com
[PATCH] Make ui.warn write to stderr...
r565
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def write_err(self, *args, **opts):
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 self._progclear()
Pierre-Yves David
ui: extract buffer write from protect and timed 'write_err' output...
r31092 if self._bufferstates and self._bufferstates[-1][0]:
Pierre-Yves David
color: move 'write-err' logic to the core ui class...
r31094 self.write(*args, **opts)
elif self._colormode == 'win32':
# windows color printing is its own can of crab, defer to
# the color module and that is it.
Pierre-Yves David
color: pass 'ui' to 'win32print'...
r31114 color.win32print(self, self._write_err, *args, **opts)
Pierre-Yves David
color: move 'write-err' logic to the core ui class...
r31094 else:
msgs = args
if self._colormode is not None:
Pulkit Goyal
py3: handle keyword arguments correctly in ui.py...
r35374 label = opts.get(r'label', '')
Pierre-Yves David
color: move 'write-err' logic to the core ui class...
r31094 msgs = [self.label(a, label) for a in args]
self._write_err(*msgs, **opts)
Pierre-Yves David
ui: extract low level part of 'write_err' in its own method...
r31093
def _write_err(self, *msgs, **opts):
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 try:
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 with self.timeblockedsection('stdio'):
if not getattr(self.fout, 'closed', False):
self.fout.flush()
Pierre-Yves David
ui: extract low level part of 'write_err' in its own method...
r31093 for a in msgs:
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 self.ferr.write(a)
# stderr may be buffered under win32 when redirected to files,
# including stdout.
if not getattr(self.ferr, 'closed', False):
self.ferr.flush()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Gregory Szorc
ui: restore behavior to ignore some I/O errors (issue5658)...
r33859 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
raise error.StdioError(inst)
mpm@selenic.com
[PATCH] Make ui.warn write to stderr...
r565
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:
self.fout.flush()
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:
self.ferr.flush()
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:
self._blockedtimes['stdio_blocked'] += \
(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):
Jun Wu
codemod: register core configitems using a script...
r33499 if self.configbool('ui', '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
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
ui: rename neverpager to disablepager...
r31026 if (self._disablepager
FUJIWARA Katsunori
ui: enable pager always for explicit --pager=on (issue5580)...
r33622 or self.pageractive):
# how pager should do is already determined
return
if not command.startswith('internal-always-') and (
# explicit --pager=on (= 'internal-always-' prefix) should
# take precedence over disabling factors below
command in self.configlist('pager', 'ignore')
Jun Wu
codemod: register core configitems using a script...
r33499 or not self.configbool('ui', 'paginate')
Augie Fackler
ui: respect historic pager.attend-$COMMAND=no...
r30997 or not self.configbool('pager', 'attend-' + command, True)
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
ui: check for --debugger in sys.argv using r-string to avoid bytes on py3...
r31341 or '--debugger' in pycompat.sysargv):
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
Yuya Nishihara
pager: use less as a fallback on Unix...
r32078 pagercmd = self.config('pager', '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
Yuya Nishihara
pager: do not try to run an empty pager command...
r31079 self.debug('starting pager for command %r\n' % command)
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
pager: move pager-initiating code into core...
r30992 if util.safehasattr(signal, "SIGPIPE"):
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.
self.setconfig('ui', 'formatted', wasformatted, 'pager')
self.setconfig('ui', 'interactive', False, '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
if cm != self.config('color', 'pagermode', cm):
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
pager: skip running the pager if it's set to 'cat'...
r31479 if command == 'cat':
# 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.
shell = any(c in command for c in "|&;<>()$`\\\"' \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:
self.warn(_("missing pager command '%s', skipping pager\n")
% command)
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(
command, shell=shell, bufsize=-1,
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 close_fds=procutil.closefds, stdin=subprocess.PIPE,
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 stdout=procutil.stdout, stderr=procutil.stderr,
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 env=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:
self.warn(_("missing pager command '%s', skipping pager\n")
% command)
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():
if util.safehasattr(signal, "SIGINT"):
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).
"""
alldefaults = frozenset(["text", "curses"])
featureinterfaces = {
"chunkselector": [
"text",
"curses",
]
}
# Feature-specific interface
if feature not in featureinterfaces.keys():
# Programming error, not user error
raise ValueError("Unknown feature requested %s" % feature)
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(
"Feature %s does not handle all default interfaces" %
feature)
if self.plain():
return "text"
# Default interface for all the features
defaultinterface = "text"
Jun Wu
codemod: register core configitems using a script...
r33499 i = self.config("ui", "interface")
Simon Farnsworth
ui: add new config flag for interface selection...
r28542 if i in alldefaults:
defaultinterface = i
choseninterface = defaultinterface
Boris Feld
configitems: register the 'ui.interface.chunkselector' config
r34617 f = self.config("ui", "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:
self.warn(_("invalid value for ui.interface: %s\n") %
(i,))
else:
self.warn(_("invalid value for ui.interface: %s (using %s)\n") %
(i, choseninterface))
if f is not None and choseninterface != f:
self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n") %
(feature, f, choseninterface))
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()'.
'''
configitems: register 'ui.interactive'...
r33061 i = self.configbool("ui", "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
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 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?
'''
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 if 'COLUMNS' in encoding.environ:
Augie Fackler
termwidth: move to ui.ui from util
r12689 try:
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 return int(encoding.environ['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
Jun Wu
codemod: register core configitems using a script...
r33499 i = self.configbool("ui", "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
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 return self._isatty(self.fout)
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324
return i
Yuya Nishihara
ui: write prompt text in ui.prompt(), not in ui._readline()...
r35974 def _readline(self):
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.
Yuya Nishihara
ui: do not try readline support if fin/fout aren't standard streams...
r36812 usereadline = (self._isatty(self.fin) and self._isatty(self.fout)
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 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
# 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
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
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 with self.timeblockedsection('stdio'):
Yuya Nishihara
ui: do not use rawinput() when we have to replace sys.stdin/stdout...
r36813 if usereadline:
Yuya Nishihara
ui: inline util.bytesinput() into ui._readline()...
r36809 line = encoding.strtolocal(pycompat.rawinput(r' '))
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:
self.fout.write(b' ')
self.fout.flush()
line = self.fin.readline()
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
Simon Heimberg
ui: extract choice from prompt...
r9048 def prompt(self, msg, default="y"):
"""Prompt user with msg, read response.
If ui is not interactive, the default is returned.
Kirill Smelkov
prompt: kill matchflags...
r5751 """
Matt Mackall
ui: make interactive a method
r8208 if not self.interactive():
Yuya Nishihara
ui: fix crash by non-interactive prompt echo for user name...
r28039 self.write(msg, ' ', default or '', "\n")
Peter Arrenbrecht
ui: log non-interactive default response to stdout when verbose...
r7320 return default
Yuya Nishihara
ui: add explicit path to write prompt text bypassing buffers...
r35975 self._writenobuf(msg, label='ui.prompt')
Yuya Nishihara
ui: write prompt text in ui.prompt(), not in ui._readline()...
r35974 self.flush()
Simon Heimberg
ui: extract choice from prompt...
r9048 try:
Yuya Nishihara
ui: write prompt text in ui.prompt(), not in ui._readline()...
r35974 r = self._readline()
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
Yuya Nishihara
ui: separate option to show prompt echo, enabled only in tests (issue4417)...
r23053 if self.configbool('ui', 'promptecho'):
Mads Kiilerich
ui: show prompt choice if input is not a tty but is forced to be interactive...
r22589 self.write(r, "\n")
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)
choices = [p.strip(' ') for p in m.group(2).split('$$')]
Augie Fackler
ui: refactor extractchoices so it doesn't break on Python 3...
r33680 def choicetuple(s):
ampidx = s.index('&')
return s[ampidx + 1:ampidx + 2].lower(), s.replace('&', '', 1)
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:
Simon Heimberg
ui: extract choice from prompt...
r9048 r = self.prompt(msg, resps[default])
if r.lower() in resps:
return resps.index(r.lower())
self.write(_("unrecognized response\n"))
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:
Matt Mackall
ui: send password prompts to stderr again (issue4056)
r19880 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
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.
Simon Farnsworth
ui: log time spent blocked on stdio...
r30978 with self.timeblockedsection('stdio'):
if self.configbool('ui', 'nontty'):
l = self.fin.readline()
if not l:
raise EOFError
return l.rstrip('\n')
else:
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()
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
ui: fix opts labeling on ui.warn et al for Python 3...
r31177 opts[r'label'] = opts.get(r'label', '') + ' ui.status'
Brodie Rao
ui: add ui.write() output labeling API...
r10815 self.write(*msg, **opts)
def warn(self, *msg, **opts):
'''write warning message to output (stderr)
This adds an output label of "ui.warning".
'''
Augie Fackler
ui: fix opts labeling on ui.warn et al for Python 3...
r31177 opts[r'label'] = opts.get(r'label', '') + ' ui.warning'
Brodie Rao
ui: add ui.write() output labeling API...
r10815 self.write_err(*msg, **opts)
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
ui: fix opts labeling on ui.warn et al for Python 3...
r31177 opts[r'label'] = opts.get(r'label', '') + ' ui.note'
Brodie Rao
ui: add ui.write() output labeling API...
r10815 self.write(*msg, **opts)
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
ui: fix opts labeling on ui.warn et al for Python 3...
r31177 opts[r'label'] = opts.get(r'label', '') + ' ui.debug'
Brodie Rao
ui: add ui.write() output labeling API...
r10815 self.write(*msg, **opts)
FUJIWARA Katsunori
cmdutil: make in-memory changes visible to external editor (issue4378)...
r26750
Sean Farley
ui: add a parameter to set the temporary directory for edit...
r30835 def edit(self, text, user, extra=None, editform=None, pending=None,
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030 repopath=None, action=None):
if action is None:
self.develwarn('action is None but will soon be a required '
'parameter to ui.edit()')
Jordi Gutiérrez Hermoso
edit: allow to configure the suffix of the temporary filename...
r28635 extra_defaults = {
'prefix': 'editor',
'suffix': '.txt',
}
Mykola Nikishov
ui: allow open editor with custom filename...
r27153 if extra is not None:
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030 if extra.get('suffix') is not None:
self.develwarn('extra.suffix is not None but will soon be '
'ignored by ui.edit()')
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
Michael Bolin
editor: file created for diff action should have .diff suffix...
r34056 if action == 'diff':
suffix = '.diff'
elif action:
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030 suffix = '.%s.hg.txt' % action
else:
suffix = extra['suffix']
Sean Farley
ui: rename tmpdir parameter to more specific repopath...
r30848 rdir = None
Sean Farley
ui: add a parameter to set the temporary directory for edit...
r30835 if self.configbool('experimental', 'editortmpinhg'):
Sean Farley
ui: rename tmpdir parameter to more specific repopath...
r30848 rdir = repopath
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 (fd, name) = pycompat.mkstemp(prefix='hg-' + extra['prefix'] + '-',
Michael Bolin
editor: use an unambiguous path suffix for editor files...
r34030 suffix=suffix,
Sean Farley
ui: rename tmpdir parameter to more specific repopath...
r30848 dir=rdir)
Thomas Arendsen Hein
Improved ui.edit():...
r1984 try:
Yuya Nishihara
ui: use bytes IO and convert EOL manually in ui.editor()...
r31778 f = os.fdopen(fd, r'wb')
f.write(util.tonativeeol(text))
Thomas Arendsen Hein
Improved ui.edit():...
r1984 f.close()
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 environ = {'HGUSER': user}
Alexander Drozdov
ui: edit(): transplant: set HGREVISION environment variable for an editor...
r20606 if 'transplant_source' in extra:
environ.update({'HGREVISION': hex(extra['transplant_source'])})
Alexander Drozdov
editor: prefer 'intermediate-source' extra to use for HGREVISION environment variable...
r24687 for label in ('intermediate-source', 'source', 'rebase_source'):
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 if label in extra:
environ.update({'HGREVISION': extra[label]})
break
FUJIWARA Katsunori
ui: invoke editor for committing with HGEDITFORM environment variable...
r22205 if editform:
environ.update({'HGEDITFORM': editform})
FUJIWARA Katsunori
cmdutil: make in-memory changes visible to external editor (issue4378)...
r26750 if pending:
environ.update({'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
Yuya Nishihara
ui: introduce util.system() wrapper to make sure ui.fout is used...
r23269 self.system("%s \"%s\"" % (editor, name),
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 environ=environ,
Simon Farnsworth
ui: give editor() a tag of its own...
r30980 onerr=error.Abort, errprefix=_("edit failed"),
blockedtag='editor')
Matt Mackall
Add username/merge/editor to .hgrc...
r608
Yuya Nishihara
ui: use bytes IO and convert EOL manually in ui.editor()...
r31778 f = open(name, r'rb')
t = util.fromnativeeol(f.read())
Thomas Arendsen Hein
Improved ui.edit():...
r1984 f.close()
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
Simon Farnsworth
ui: time calls to ui.system...
r30979 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:]
blockedtag = 'unknown_system_' + cmdsuffix
Pierre-Yves David
ui: allow capture of subprocess output...
r24848 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:
errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
Yuya Nishihara
procutil: make explainexit() simply return a message (API)...
r37481 procutil.explainexit(rc))
Yuya Nishihara
chg: deduplicate error handling of ui.system()...
r31108 if errprefix:
errmsg = '%s: %s' % (errprefix, errmsg)
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
self.write_err('Traceback (most recent call last):\n',
''.join(exctb[:-1]),
''.join(causetb),
''.join(exconly))
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])
Yuya Nishihara
py3: replace "if ispy3" by encoding.strtolocal()
r35915 self.write_err(encoding.strtolocal(r''.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'''
Pulkit Goyal
py3: replace sys.platform with pycompat.sysplatform (part 1 of 2)...
r30641 if pycompat.sysplatform == '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.
editor = 'E'
else:
editor = 'vi'
Pulkit Goyal
py3: use encoding.environ in ui.py...
r30277 return (encoding.environ.get("HGEDITOR") or
Jun Wu
ui: simplify geteditor...
r31687 self.config("ui", "editor", editor))
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"""
if (self.quiet or self.debugflag
Jun Wu
codemod: register core configitems using a script...
r33499 or self.configbool('progress', 'disable')
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 or not progress.shouldprint(self)):
return None
return getprogbar(self)
def _progclear(self):
"""clear progress bar output if any. use it before any output"""
Mark Thomas
ui: check for progress singleton when clearing progress bar (issue5684)...
r34346 if not haveprogbar(): # nothing loaded yet
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 return
if self._progbar is not None and self._progbar.printed:
self._progbar.clear()
Matt Mackall
Add ui.progress API
r9153 def progress(self, topic, pos, item="", unit="", total=None):
'''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 '''
Pierre-Yves David
progress: move all logic altering the ui object logic in mercurial.ui...
r25499 if self._progbar is not None:
self._progbar.progress(topic, pos, item=item, unit=unit,
total=total)
Pierre-Yves David
progress: get the extremely verbose output out of default debug...
r25125 if pos is None or not self.configbool('progress', 'debug'):
Matt Mackall
Add ui.progress API
r9153 return
Brodie Rao
ui: fix NameError in ui.progress due to unit/units typo
r9398 if unit:
unit = ' ' + unit
Matt Mackall
Add ui.progress API
r9153 if item:
item = ' ' + item
if total:
pct = 100.0 * pos / total
Augie Fackler
ui: fix progress debug log format strings to work on Python 3
r34272 self.debug('%s:%s %d/%d%s (%4.2f%%)\n'
Brodie Rao
ui: fix NameError in ui.progress due to unit/units typo
r9398 % (topic, item, pos, total, unit, pct))
Matt Mackall
Add ui.progress API
r9153 else:
Augie Fackler
ui: fix progress debug log format strings to work on Python 3
r34272 self.debug('%s:%s %d%s\n' % (topic, item, pos, unit))
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Martin von Zweigbergk
progress: create helper class for incrementing progress...
r38364 def makeprogress(self, topic, unit="", total=None):
'''exists only so low-level modules won't need to import scmutil'''
return scmutil.progress(self, topic, unit, total)
Durham Goode
blackbox: adds a blackbox extension...
r18669 def log(self, service, *msg, **opts):
Matt Mackall
ui: add logging hook
r11984 '''hook for logging facility extensions
service should be a readily-identifiable subsystem, which will
allow filtering.
Augie Fackler
ui: improve docs on ui.log...
r26235
*msg should be a newline-terminated format string to log, and
then any values to %-format into that format string.
**opts currently has no defined meanings.
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.
"""
Pierre-Yves David
develwarn: move config gating inside the develwarn function...
r29095 if not self.configbool('devel', 'all-warnings'):
Kyle Lippincott
develwarn: do not emit warning if "config" is unspecified...
r35125 if config is None or not self.configbool('devel', config):
Pierre-Yves David
develwarn: move config gating inside the develwarn function...
r29095 return
Pierre-Yves David
devel-warn: move the develwarn function as a method of the ui object...
r25629 msg = 'devel-warn: ' + msg
Pierre-Yves David
ui: add a 'stacklevel' argument to 'develwarn'...
r27274 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:
Pierre-Yves David
ui: add a 'stacklevel' argument to 'develwarn'...
r27274 util.debugstacktrace(msg, stacklevel, self.ferr, self.fout)
timeless
ui: log devel warnings
r28498 self.log('develwarn', '%s at:\n%s' %
(msg, ''.join(util.getstackframes(stacklevel))))
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)
self.write_err('%s at: %s:%d (%s)\n'
% (msg, fname, lineno, fmsg))
self.log('develwarn', '%s at: %s:%d (%s)\n',
msg, fname, lineno, fmsg)
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,
"""
Pierre-Yves David
deprecation: gate deprecation warning behind devel configuration...
r29082 if not (self.configbool('devel', 'all-warnings')
or self.configbool('devel', 'deprec-warn')):
return
Pierre-Yves David
ui: add a 'deprecwarn' helper to issue deprecation warnings...
r27275 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
" update your code.)") % version
Matt Harbison
cmdutil: convert _revertprefetch() to a generic stored file hook (API)...
r35941 self.develwarn(msg, stacklevel=stacklevel, config='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
def configoverride(self, overrides, source=""):
"""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
if ('ui', 'quiet') in overrides:
self.fixconfig(section='ui')
Kostia Balytskyi
ui: add configoverride context manager...
r30480
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.
"""
def __init__(self, ui):
dict.__init__(self)
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 for name, loc in ui.configitems('paths', ignoresub=True):
Gregory Szorc
ui: represent paths as classes...
r24250 # No location is the same as not existing.
if not loc:
continue
Gregory Szorc
ui: support declaring path push urls as sub-options...
r27266 loc, sub = ui.configsuboptions('paths', name)
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:
Gregory Szorc
ui: change default path fallback mechanism (issue4796)...
r26189 raise error.RepoError(_('repository %s does not exist') %
name)
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 = {}
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.
"""
def register(func):
_pathsuboptions[option] = (attr, func)
return func
return register
@pathsuboption('pushurl', 'pushloc')
def pushurlpathoption(ui, path, value):
u = util.url(value)
# Actually require a URL.
if not u.scheme:
ui.warn(_('(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
return None
# Don't support the #foo syntax in the push URL to declare branch to
# push.
if u.fragment:
ui.warn(_('("#fragment" in paths.%s:pushurl not supported; '
'ignoring)\n') % path.name)
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
Gregory Szorc
ui: path option to declare which revisions to push by default...
r29413 @pathsuboption('pushrev', 'pushrev')
def pushrevpathoption(ui, path, value):
return value
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:
raise ValueError('rawloc must be defined')
# 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
ui: portably bytestring-ify url object
r31350 self.loc = '%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):
Gregory Szorc
ui: move URL and path detection into path API...
r26056 raise ValueError('location is not a URL or path to a local '
'repo: %s' % rawloc)
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.
for suboption, (attr, func) in _pathsuboptions.iteritems():
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)."""
return os.path.isdir(os.path.join(path, '.hg'))
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 = {}
for subopt, (attr, _func) in _pathsuboptions.iteritems():
value = getattr(self, attr)
if value is not None:
d[subopt] = value
return d
Gregory Szorc
ui: capture push location on path instances...
r26064
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
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
def haveprogbar():
return _progresssingleton is not None