util: add a file object proxy that can notify observers
There are various places in Mercurial where we may want to
instrument low-level I/O. The use cases I can think of all
involve development-type activities like monitoring the raw
bytes passing through a file (for testing and debugging),
counting the number of I/O function calls (for performance
monitoring), and changing the behavior of I/O function calls
(e.g. simulating a failure) (to facilitate testing).
This commit invents a mechanism to wrap a file object so we
can observe activity on it. We have similar functionality in
badserverext.py. But that's a test-only extension and is pretty
specific to the HTTP server. I would like a mechanism in core
that is sufficiently generic so it can be used by multiple
consumers, including `hg debug*` commands.
The added code consists of a proxy type for file objects.
It is bound to an "observer," which receives callbacks whenever
I/O methods are called.
We also add an implementation of an observer that logs specific
I/O events. This observer will be used in an upcoming commit
to record low-level wire protocol activity.
A helper function to convert a file object into an observed
file object has also been implemented.
I don't anticipate any critical functionality in core using
these types. So I don't think explicit test coverage is
worth implementing.
Differential Revision: https://phab.mercurial-scm.org/D2462
# Base Revsets to be used with revsetbenchmarks.py script
#
# The goal of this file is to gather a limited amount of revsets that allow a
# good coverage of the internal revsets mechanisms. Revsets included should not
# be selected for their individual implementation, but for what they reveal of
# the internal implementation of smartsets classes (and their interactions).
#
# Use and update this file when you change internal implementation of these
# smartsets classes. Please include a comment explaining what each of your
# addition is testing. Also check if your changes to the smartset class makes
# some of the tests inadequate and replace them with a new one testing the same
# behavior.
#
# If you want to benchmark revsets predicate itself, check 'all-revsets.txt'.
#
# The current content of this file is currently likely not reaching this goal
# entirely, feel free, to audit its content and comment on each revset to
# highlight what internal mechanisms they test.
all()
draft()
::tip
draft() and ::tip
::tip and draft()
0::tip
roots(0::tip)
author(lmoscovicz)
author(mpm)
author(lmoscovicz) or author(mpm)
author(mpm) or author(lmoscovicz)
tip:0
0::
# those two `roots(...)` inputs are close to what phase movement use.
roots((tip~100::) - (tip~100::tip))
roots((0::) - (0::tip))
42:68 and roots(42:tip)
::p1(p1(tip))::
public()
:10000 and public()
draft()
:10000 and draft()
roots((0:tip)::)
(not public() - obsolete())
(_intlist('20000\x0020001')) and merge()
parents(20000)
(20000::) - (20000)
# The one below is used by rebase
(children(ancestor(tip~5, tip)) and ::(tip~5))::