Before this changeset, the value was carried by the class to work around
limitation of the extensions initialisation. Now that the initialisation is
cleanly handled in 'dispatch', we can drop this work around.
This is similar to what we needed for 'write', we move the logic from the
extension to the core class. Beside the dispatch to 'win32print', we just apply
label to the argument.
That subcall to 'self.write' is never doing actual write but only store things
in buffers. So we do not need to protect it for exception not to time its
execution.
This will make it easier to extract a '_write_err' function as we did for
'write'.
One more step, the support for writing color is not directly in core. No
behavior change for the default case ('_colormode' = None).
Here are the details of what we have to change to the core method:
* apply to 'self.label' to input in the buffered case
* dispatch to 'win32print' when applicable
* apply to 'self.label' to input when applicable
We are about to add some extra logic related to color. That logic will need to
access the low level layer of ui doing the actual write to a stream. (eg:
'win32print'). We extract this logic into a private method for this purpose.
This bring us closer to supporting color in core natively. Core already have a
'label' method that was a no-op. We update its to call the new 'colorlabel'
function. Behavior is unchanged when colormode = None.
Having all 'ui' objects aware of 'color' allows us to update the core code to
handle color. The mode will stay 'None' in the default case so that will not
introduce any changes.
This closes the last feature gap other than the attend list from the
extension. For now, I'm leaving the attend list in the extension,
because I'm unsure it has merit in a world where commands have been
updated to take advantage of the modern API.
I'm about to add direct paging support to some commands, and as a
result we need a way to communicate from the higher layers of dispatch
that paging is explicitly disabled.
No functionality change.
A previous version of this API had a category argument on
ui.pager(). As I migrated the commands in core, I couldn't come up
with good enough consistency in any categorization scheme so I just
scrapped the whole idea. It may be worth revisiting in the future.
We know that calls to ui.editor() always block on the user's configured editor.
Use a blocking tag that ensures that we don't see a huge variety of editor
options in our logging.
We use a wrapper around Mercurial at Facebook that logs key statistics (like
elpased time) to our standard performance tooling.
This is less useful than it could be, because we currently can't tell when a
command is slow because we need to fix Mercurial versus when a command is
slow because the user isn't interacting quickly.
Teach Mercurial to log the time it spends blocked, so that our tooling can
pick it up and submit it with the elapsed time - we can then do the math in
our tooling to see if Mercurial is slow, or if the user simply failed to
interact.
Combining this with the command duration log means that we can ensure that
we concentrate performance efforts on the things that bite Facebook users.
The perfwrite microbenchmark shifts from:
Linux:
! wall 3.213560 comb 0.410000 user 0.350000 sys 0.060000 (best of 4)
Mac:
! wall 0.342325 comb 0.180000 user 0.110000 sys 0.070000 (best of 20)
before this change to:
! wall 3.478070 comb 0.500000 user 0.420000 sys 0.080000 (best of 3)
Mac:
! wall 0.218112 comb 0.220000 user 0.150000 sys 0.070000 (best of 15)
showing a small hit in comb time, but firmly in the noise on wall time.
We want to log the time Mercurial spends trapped in things outside
programmatic control. Provide a mechanism to give us both command runtime
and as many different sources of blocking as we deem useful.
Before this change, urllib2 was brought in when constructing the ui object, and
that added ~5ms on my Linux workstation to the hg startup time for every
command, bringing the time for 'HGRCPATH=/dev/null hg root' from 46ms to 40ms.
Now, we construct a single proxy object per initial ui creation (so that if the
ui is copied they share the object), but defer the actual instantiation of it
and the import of urllib2 until it's needed.
# no-check-commit
4.2 cannot be expressed with IEEE floating point losslessly, and could
cause test failure on some platform:
File ".../mercurial/ui.py", line 414, in mercurial.ui.ui.configwith
Failed example:
u.configwith(float, s, 'float2')
Expected:
-4.2
Got:
-4.2000000000000002
This patch fixes that by changing the number to 4.25, which can be expressed
by the binary number 100.01.
Until callsites are updated, this will have no effect. Once callsites
are updated, specifying experimental.editortmpinhg will create editor
temporary files in a subdirectory of .hg, which will make it easier
for tool integrations to determine what repository is in play when
they're asked to edit an hg-related file.
Care needs to be taken to prevent leaking potentially sensitive environment
variables through hgweb, if template support for environment variables is to be
introduced. There are a few ideas about the API for preventing accidental
leaking [1]. Option 3 seems best from the POV of not needing to configure
anything in the normal case. I couldn't figure out how to do that, so guard it
with an experimental option for now.
[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-January/092383.html
readline() returns '' only when EOF is encountered, in which case, Python's
getpass() raises EOFError. We should do the same to abort the session as
"response expected."
This bug was reported to
https://bitbucket.org/tortoisehg/thg/issues/4659/
sys.platform returns unicode on python 3 world. Our code base has most of the
things bytes because of the transformer. So we have a bytes version of this as
pycompat.sysplatform. This series of 2 patches replaces occurences of
sys.platform with pycompat.sysplatform.
"In this case, result is a source variable of a list to be returned, it
shouldn't be unicode. Hence we can use bytes instead of basestring here." -Yuya
This allows us to write doctests depending on a ui object, but not on global
configs.
ui.load() is a class method so we can do wsgiui.load(). All ui() calls but
for doctests are replaced with ui.load(). Some of them could be changed to
not load configs later.
@contextmanager almost always have their "yield" inside a try..finally
block. This is because if the calling code inside the activated
context manager raises, the code after the "yield" won't get
executed. A "finally" block, however, will get executed in this
scenario.
I feel like this idea might've been discussed before, so please
feel free to point me to the right mailing list entry to read
about why it should not be done.
We have a common pattern of the following code:
backup = ui.backupconfig(section, name)
try:
ui.setconfig(section, name, temporaryvalue, source)
do_something()
finally:
ui.restoreconfig(backup)
IMO, this looks better:
with ui.configoverride({(section, name): temporaryvalue}, source):
do_something()
Especially this becomes more convenient when one has to backup multiple
config values before doing something. In such case, adding a new value
to backup requires codemod in three places.
Almost all sys.stdin/out/err in hgext/ and mercurial/ are replaced by util's.
There are a few exceptions:
- lsprof.py and statprof.py are untouched since they are a kind of vendor
code and they never import mercurial modules right now.
- ui._readline() needs to replace sys.stdin and stdout to pass them to
raw_input(). We'll need another workaround here.
It appears crecord.py has its own termsize() function. I want to get rid of it.
The fallback height is chosen from the default of cmd.exe on Windows, and
VT100 on Unix.
I'm going to get rid of sys.stderr|out|in references from posix.termwidth().
In order to do that, termwidth() needs to take a ui, but functions in util.py
shouldn't depend on a ui object. So moves termwidth() to scmutil.py.
Using source transformer we add b'' everywhere. So there are no chances
that those bytes string will work with os.environ on Py3 as that returns a
dict of unicodes. We are relying on the errors, even though no error is raised
even in future, these pieces of codes will tend to do wrong things.
if statements can result in wrong boolean and certain errors can be raised
while using this piece of code. Let's not wait for them to happen, fix what is
wrong. If this patch goes in, I will try to do it for all the cases.
Leaving it as it is buggy.
"f = inspect.currentframe()" instantly creates a cycle because
"f.f_locals['f']" is "f" itself.
This patch explicitly sets those frame objects to None to avoid cycles.
Now that we have a mechanism for declaring path sub-options, we can
start to pile on features!
Many power users have expressed frustration that bare `hg push`
attempts to push all local revisions to the remote. This patch
introduces the "pushrev" path sub-option to control which revisions
are pushed when no "-r" argument is specified.
The value of this sub-option is a revset, naturally.
A future feature addition could potentially introduce a "pushnames"
sub-options that declares the list of names (branches, bookmarks,
topics, etc) to push by default. The entire "what to push by default"
feature should probably be considered before this patch lands.
As part of developing a subsequent patch I discovered that sub-option
values like "." were getting converted to paths. This is because the
[paths] section is treated specially during config loading.
This patch prevents post-processing sub-options from the [paths]
section.
This makes http password database stored in ui object.
It allows reusing authentication information when we
use this database for creating password manager for
the new connection.