Commit Graph

29443 Commits

Author SHA1 Message Date
FUJIWARA Katsunori
d6bb7010bd tests: introduce check-perf-code.py to add extra checks on perf.py
This patch introduces tests/check-perf-code.py as a preparation for
adding extra checks on contrib/perf.py in subsequent patches (mainly,
for historical portability).

At this change, check-perf-code.py doesn't add any extra check, and is
equal to check-code.py. This makes subsequent patch focus only on
adding an extra check on perf.py check-perf-code.py.

check-perf-code.py adds extra checks on perf.py by wrapping
contrib/check-code.py, because "filtering" by check-code.py (e.g.
normalize characters in string literal or comment line) is useful to
simplify regexp for check, and avoid false positive matching.
2016-05-20 09:47:35 +09:00
FUJIWARA Katsunori
9dfb60275e check-code: move fixing up regexp into main procedure
This patch makes an extra check pattern to be prepared by
"_preparepats()" as similarly as existing patterns, if it is added to
"checks" array before invocation of "main()" in check-code.py.

This is a part of preparation for adding check-code.py extra checks by
another python script in subsequent patch.

This is also useful for SkeletonExtensionPlan.

    https://www.mercurial-scm.org/wiki/SkeletonExtensionPlan
2016-05-20 09:47:35 +09:00
FUJIWARA Katsunori
0a9f5e8b83 check-code: factor out boot procedure into main
This is a part of preparation for adding check-code.py extra checks by
another python script in subsequent patch.

This is also useful for SkeletonExtensionPlan.

    https://www.mercurial-scm.org/wiki/SkeletonExtensionPlan
2016-05-20 09:47:35 +09:00
FUJIWARA Katsunori
8bd5aefb64 perf: import newer modules separately for earlier Mercurial
demandimport of early Mercurial loads an imported module immediately,
if a module is imported absolutely by "from a import b" style. Recent
perf.py satisfies this condition, because it does:

  - have "from __future__ import absolute_import" line
  - use "from a import b" style for modules in "mercurial" package

Before this patch, importing modules below prevents perf.py from being
loaded by earlier Mercurial, because these aren't available in such
Mercurial, even though there are some code paths for Mercurial earlier
than 1.9.

  - branchmap 2.5 (or e3354ba12eef)
  - repoview  2.5 (or 7d207cb7e38a)
  - obsolete  2.3 (or b50a017cd9ac)
  - scmutil   1.9 (or 065064cdde5f)

For example, setting "_prereadsize" attribute in perfindex() and
perfnodelookup() is effective only with Mercurial earlier than 1.8 (or
1299f0c14572).

After this patch, "mercurial.error" is the only blocker in "from
mercurial import" statement for loading perf.py with Mercurial earlier
than 1.2. This patch ignores it, because just importing it separately
isn't enough.
2016-05-20 09:47:35 +09:00
Pulkit Goyal
6b3bc52b40 py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
The BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer has been merged into
http.server in python 3. All of them has been merged as util.httpserver to use
in both python 2 and 3. This patch adds a regex to check-code to warn against
the use of BaseHTTPServer. Moreover this patch also includes updates to lower
part of test-check-py3-compat.t which used to remain unchanged.
2016-07-13 23:38:29 +05:30
Pulkit Goyal
ad5a0af23f py3: re-implement the BaseHTTPServer.test() function
The function is changed in python 3. So the latest version of function is
re-implemented. One can look at https://hg.python.org/cpython/file/3.5/Lib/http/server.py#l1184
 and https://hg.python.org/cpython/file/2.7/Lib/BaseHTTPServer.py#l590 to see the change
2016-07-15 23:00:31 +05:30
Augie Fackler
7a264ee86d test-http: use sed instead of fixed-with cut for reading access.log
Some systems (like FreeBSD jails) use something other than 127.0.0.1
for localhost, and it's not safe to assume it'll always be the same
width. Using sed with a replacement like this sidesteps the problem.
2016-07-15 12:39:36 -04:00
Augie Fackler
1f1c387b60 test-serve: add missing globs
check-code missed this because of the closing ) in the "bound to" message.
2016-07-15 12:34:15 -04:00
Augie Fackler
afe4cc8905 tests: glob whitespace between path and OK in unzip(1) output
FreeBSD's unzip(1) uses tabs instead of a run of spaces.
2016-07-15 12:49:58 -04:00
Gregory Szorc
9f52df0840 sslutil: print a warning when using TLS 1.0 on legacy Python
Mercurial now requires TLS 1.1+ when TLS 1.1+ is supported by the
client. Since we made the decision to require TLS 1.1+ when running
with modern Python versions, it makes sense to do something for
legacy Python versions that only support TLS 1.0.

Feature parity would be to prevent TLS 1.0 connections out of the
box and require a config option to enable them. However, this is
extremely user hostile since Mercurial wouldn't talk to https://
by default in these installations! I can easily see how someone
would do something foolish like use "--insecure" instead - and
that would be worse than allowing TLS 1.0!

This patch takes the compromise position of printing a warning when
performing TLS 1.0 connections when running on old Python
versions. While this warning is no more annoying than the
CA certificate / fingerprint warnings in Mercurial 3.8, we provide
a config option to disable the warning because to many people
upgrading Python to make the warning go away is not an available
recourse (unlike pinning fingerprints is for the CA warning).

The warning appears as optional output in a lot of tests.
2016-07-13 21:49:17 -07:00
Gregory Szorc
91047cde9d sslutil: require TLS 1.1+ when supported
Currently, Mercurial will use TLS 1.0 or newer when connecting to
remote servers, selecting the highest TLS version supported by both
peers. On older Pythons, only TLS 1.0 is available. On newer Pythons,
TLS 1.1 and 1.2 should be available.

Security professionals recommend avoiding TLS 1.0 if possible.
PCI DSS 3.1 "strongly encourages" the use of TLS 1.2.

Known attacks like BEAST and POODLE exist against TLS 1.0 (although
mitigations are available and properly configured servers aren't
vulnerable).

I asked Eric Rescorla - Mozilla's resident crypto expert - whether
Mercurial should drop support for TLS 1.0. His response was
"if you can get away with it." Essentially, a number of servers on
the Internet don't support TLS 1.1+. This is why web browsers
continue to support TLS 1.0 despite desires from security experts.

This patch changes Mercurial's default behavior on modern Python
versions to require TLS 1.1+, thus avoiding known security issues
with TLS 1.0 and making Mercurial more secure by default. Rather
than drop TLS 1.0 support wholesale, we still allow TLS 1.0 to be
used if configured. This is a compromise solution - ideally we'd
disallow TLS 1.0. However, since we're not sure how many Mercurial
servers don't support TLS 1.1+ and we're not sure how much user
inconvenience this change will bring, I think it is prudent to ship
an escape hatch that still allows usage of TLS 1.0. In the default
case our users get better security. In the worst case, they are no
worse off than before this patch.

This patch has no effect when running on Python versions that don't
support TLS 1.1+.

As the added test shows, connecting to a server that doesn't
support TLS 1.1+ will display a warning message with a link to
our wiki, where we can guide people to configure their client to
allow less secure connections.
2016-07-13 21:35:54 -07:00
Gregory Szorc
0ed5c4ca7f sslutil: config option to specify TLS protocol version
Currently, Mercurial will use TLS 1.0 or newer when connecting to
remote servers, selecting the highest TLS version supported by both
peers. On older Pythons, only TLS 1.0 is available. On newer Pythons,
TLS 1.1 and 1.2 should be available.

Security-minded people may want to not take any risks running
TLS 1.0 (or even TLS 1.1). This patch gives those people a config
option to explicitly control which TLS versions Mercurial should use.
By providing this option, one can require newer TLS versions
before they are formally deprecated by Mercurial/Python/OpenSSL/etc
and lower their security exposure. This option also provides an
easy mechanism to change protocol policies in Mercurial. If there
is a 0-day and TLS 1.0 is completely broken, we can act quickly
without changing much code.

Because setting the minimum TLS protocol is something you'll likely
want to do globally, this patch introduces a global config option under
[hostsecurity] for that purpose.

wrapserversocket() has been taught a hidden config option to define
the explicit protocol to use. This is queried in this function and
not passed as an argument because I don't want to expose this dangerous
option as part of the Python API. There is a risk someone could footgun
themselves. But the config option is a devel option, has a warning
comment, and I doubt most people are using `hg serve` to run a
production HTTPS server (I would have something not Mercurial/Python
handle TLS). If this is problematic, we can go back to using a
custom extension in tests to coerce the server into bad behavior.
2016-07-14 20:47:22 -07:00
Gregory Szorc
db0188e347 sslutil: prevent CRIME
ssl.create_default_context() disables compression on the TLS channel
in order to prevent CRIME. I think we should follow CPython's lead
and attempt to disable channel compression in order to help prevent
information leakage.

Sadly, I don't think there is anything we can do on Python versions
that don't have an SSLContext, as there is no way to set channel
options with the limited ssl API.
2016-07-14 20:07:10 -07:00
Gregory Szorc
739785c6a0 sslutil: update comment about create_default_context()
While ssl.create_default_context() creates a SSLContext with
reasonable default options, we can't use it because it conflicts with
our CA loading controls. So replace the comment with reality.

(FWIW the comment was written before the existing CA loading code
was in place.)
2016-07-14 19:56:39 -07:00
Gregory Szorc
f0c46756f9 tests: use sslutil.wrapserversocket()
Like the built-in HTTPS server, this code was using the ssl module
directly and only using TLS 1.0. Like the built-in HTTPS server,
we switch it to use sslutil.wrapserversocket() so it can follow better
practices.
2016-07-13 20:41:07 -07:00
Gregory Szorc
c023f774e6 hgweb: use sslutil.wrapserversocket()
This patch transitions the built-in HTTPS server to use sslutil for
creating the server socket.

As part of this transition, we implement developer-only config options
to control CA loading and whether to require client certificates. This
eliminates the need for the custom extension in test-https.t to define
these.

There is a slight change in behavior with regards to protocol
selection. Before, we would always use the TLS 1.0 constant to define
the protocol version. This would *only* use TLS 1.0. sslutil defaults
to TLS 1.0+. So this patch improves the security of `hg serve` out of
the box by allowing it to use TLS 1.1 and 1.2 (if available).
2016-07-12 23:12:03 -07:00
Gregory Szorc
60b5c4f506 sslutil: implement wrapserversocket()
wrapsocket() is heavily tailored towards client use. In preparation
for converting the built-in server to use sslutil (as opposed to
the ssl module directly), we add wrapserversocket() for wrapping
a socket to be used on servers.
2016-07-14 20:14:19 -07:00
Gregory Szorc
6052136b07 hgweb: pass ui into preparehttpserver
Upcoming patches will need the built-in HTTPS server to be more
configurable.
2016-07-13 00:14:50 -07:00
Kostia Balytskyi
847780e6fe rebase: remove sortedstate-related confusion
The following rebase implementation details are frustrating:
- storing a list of sorted revision numbers in a field named sortedstate
- having sortedstate be a field of the rebaseruntime class
- using sortedstate[-1] as opposed to a more intuitive max(self.state) to
  compute the latest revision in the state

This commit fixes those imperfections.
2016-07-14 03:12:09 -07:00
Kostia Balytskyi
1c4ad1d1d3 rebase: replace extrafn field with _makeextrafn invocations
As per Yuya's advice, we would like to slightly reduce the amount of state
which is stored in rebaseruntime class. In this case, we don't need to store
extrafn field, as we can produce the necessary value by calling _makeextrafn
and the perf overhead is negligible.
2016-07-14 02:59:27 -07:00
Gregory Szorc
2125e5d7d4 mercurial: implement a source transforming module loader on Python 3
The most painful part of ensuring Python code runs on both Python 2
and 3 is string encoding. Making this difficult is that string
literals in Python 2 are bytes and string literals in Python 3 are
unicode. So, to ensure consistent types are used, you have to
use "from __future__ import unicode_literals" and/or prefix literals
with their type (e.g. b'foo' or u'foo').

Nearly every string in Mercurial is bytes. So, to use the same source
code on both Python 2 and 3 would require prefixing nearly every
string literal with "b" to make it a byte literal. This is ugly and
not something mpm is willing to do at this point in time.

This patch implements a custom module loader on Python 3 that performs
source transformation to convert string literals (unicode in Python 3)
to byte literals. In effect, it changes Python 3's string literals to
behave like Python 2's.

In addition, the module loader recognizes well-known built-in
functions (getattr, setattr, hasattr) and methods (encode and decode)
that barf when bytes are used and prevents these from being rewritten.
This prevents excessive source changes to accommodate this change
(we would have to rewrite every occurrence of these functions passing
string literals otherwise).

The module loader is only used on Python packages belonging to
Mercurial.

The loader works by tokenizing the loaded source and replacing
"string" tokens if necessary. The modified token stream is
untokenized back to source and loaded like normal. This does add some
overhead. However, this all occurs before caching: .pyc files will
cache the transformed version. This means the transformation penalty
is only paid on first load.

As the extensive inline comments explain, the presence of a custom
source transformer invalidates assumptions made by Python's built-in
bytecode caching mechanism. So, we have to wrap bytecode loading and
writing and add an additional header to bytecode files to facilitate
additional cache validation when the source transformations
change in the future.

There are still a few things this code doesn't handle well, namely
support for zip files as module sources and for extensions. Since
Mercurial doesn't officially support Python 3 yet, I'm inclined to
leave these as to-do items: getting a basic module loading mechanism
in place to unblock further Python 3 porting effort is more important
than comprehensive module importing support.

check-py3-compat.py has been updated to ignore frames. This is
necessary because CPython has built-in code to strip frames from the
built-in importer. When our custom code is present, this doesn't work
and the frames get all messed up. The new code is not perfect. It
works for now. But once you start chasing import failures you find
some edge cases where the files aren't being printed properly. This
only burdens people doing future Python 3 porting work so I'm inclined
to punt on the issue: the most important thing is for the source
transforming module loader to land.

There was a bit of churn in test-check-py3-compat.t because we now
trip up on str/unicode/bytes failures as a result of source
transformation. This is unfortunate but what are you going to do.

It's worth noting that other approaches were investigated.

We considered using a custom file encoding whose decode() would
apply source transformations. This was rejected because it would
require each source file to declare its custom Mercurial encoding.
Furthermore, when changing the source transformation we'd need to
version bump the encoding name otherwise the module caching layer
wouldn't know the .pyc file was invalidated. This would mean mass
updating every file when the source transformation changes. Yuck.

We also considered transforming at the AST layer. However, Python's
ast module is quite gnarly and doing AST transforms is quite
complicated, even for trivial rewrites. There are whole Python packages
that exist to make AST transformations usable. AST transforms would
still require import machinery, so the choice was basically to
perform source-level, token-level, or ast-level transforms.

Token-level rewriting delivers the metadata we need to rewrite
intelligently while being relatively easy to understand. So it won.

General consensus seems to be that this approach is the best available
to avoid bulk rewriting of '' to b''. However, we aren't confident
that this approach will never be a future maintenance burden. This
approach does unblock serious Python 3 porting efforts. So we can
re-evaulate once more work is done to support Python 3.
2016-07-04 11:18:03 -07:00
Yuya Nishihara
5c185fa427 compat: define ssize_t as int on 32bit Windows, silences C4142 warning
It appears Python.h provides ssize_t, which is aliased to int.

https://hg.python.org/cpython/file/v2.7.11/PC/pyconfig.h#l205
2016-07-15 23:54:56 +09:00
Yuya Nishihara
076cc2bdc1 commandserver: drop old unixservice implementation
It's been superseded by unixforkingservice.
2016-05-22 13:45:09 +09:00
Yuya Nishihara
cbf8b420cf chgserver: switch to new forking service
Threading and complex classes are no longer necessary. _autoexitloop() has
been replaced by polling cycle in the main thread.
2016-05-22 13:36:37 +09:00
Yuya Nishihara
ad9977e54c chgserver: extract stub factory of service object
The class inheritance will be replaced by composition. See the next patch
for details.
2016-05-22 13:13:04 +09:00
Yuya Nishihara
692e073582 chgserver: reorder service classes to make future patches readable
Includes no functional change.
2016-05-22 13:08:30 +09:00
Yuya Nishihara
2857a87cb4 commandserver: add new forking server implemented without using SocketServer
SocketServer.ForkingMixIn of Python 2.x has a couple of issues, such as:

 - race condition that leads to 100% CPU usage (Python 2.6)
   https://bugs.python.org/issue21491
 - can't wait for children belonging to different process groups (Python 2.6)
 - leaves at least one zombie process (Python 2.6, 2.7)
   https://bugs.python.org/issue11109

The first two are critical because we do setpgid(0, 0) in child process to
isolate terminal signals. The last one isn't, but ForkingMixIn seems to be
doing silly. So there are two choices:

 a) backport and maintain SocketServer until we can drop support for Python 2.x
 b) replace SocketServer by simpler one and eliminate glue codes

I chose (b) because it's great time for getting rid of utterly complicated
SocketServer stuff, and preparing for future move towards prefork service.

New unixforkingservice is implemented loosely based on chg 531f8ef64be6. It
is monolithic but much simpler than SocketServer. unixservicehandler provides
customizing points for chg, and it will be shared with future prefork service.

Old unixservice class is still used by chgserver. It will be removed later.

Thanks to Jun Wu for investigating these issues.
2016-05-22 11:43:18 +09:00
Yuya Nishihara
d298dc2539 commandserver: extract function that serves for the current connection
This will be used by new server implementation.
2016-05-22 12:49:22 +09:00
Yuya Nishihara
be6319726b commandserver: manually create file objects from socket
Prepares for moving away from SocketServer. See the subsequent patches for
why.
2016-05-22 12:44:25 +09:00
Maciej Fijalkowski
04dfc79402 bdiff: split bdiff into cpy-aware and cpy-agnostic part 2016-07-13 10:46:26 +02:00
Maciej Fijalkowski
99c86205e7 bdiff: rename functions and structs to be amenable for later exporting 2016-07-13 10:07:17 +02:00
Maciej Fijalkowski
020e7f27ca bdiff: use ssize_t in favor of Py_ssize_t in cpython-unaware locations
This function and struct will be exposed via cffi, so we need to
remove the cpython API dependency they currently have.
2016-07-13 09:36:24 +02:00
Anton Shestakov
2f0cc33284 hgweb: enumerate lines in loop header, not before
Doing this will allow access to the lines in arbitrary order (because the
result of enumerate() is an iterator), and that will help calculating rowspan
for annotate blocks.
2016-07-14 12:33:44 +08:00
Gregory Szorc
9cc195a913 sslutil: add assertion to prevent accidental CA usage on Windows
Yuya suggested we add this check to ensure we don't accidentally try
to load user-writable paths on Windows if we change the control
flow of this function later.
2016-07-13 19:33:52 -07:00
Kostia Balytskyi
e27abece5f shelve: make unshelve be able to abort in any case 2016-07-13 16:16:18 +01:00
Augie Fackler
c36830f5df osx: explicitly build hg with /usr/bin/python2.7
This should help avoid creating a package that depends on a custom
Python, as happened when I built a package for 3.8.
2016-07-13 10:39:33 -04:00
Augie Fackler
ceba27d835 osx: correct comment about ordering of welcome page 2016-07-13 11:26:44 -04:00
Augie Fackler
7db40cdbbf osx: jettison outdated build instructions 2016-07-13 11:24:31 -04:00
Yuya Nishihara
53e19881da commandserver: extract _cleanup() hook to clarify chg is doing differently
This makes it clear that chg needs its own way to unlink closed socket file.
I made a mistake in draft patches without noting the difference.
2016-05-22 11:21:11 +09:00
Yuya Nishihara
278af8b465 chgserver: drop repo at chgunixservice.__init__()
Since it isn't expensive operation, we don't have to delay it to init().
2016-05-21 17:06:39 +09:00
Yuya Nishihara
9531323bdb chgserver: extract utility to bind unix domain socket to long path
This is common problem of using sockaddr_un.
2016-05-21 16:52:04 +09:00
Yuya Nishihara
e524ae5976 chgserver: narrow scope of chdir() to socket.bind()
This helps extracting a utility function.
2016-05-21 16:42:59 +09:00
Denis Laxalde
399b84e4b1 annotate: handle empty files earlier
Rather than looping on funcmap and then checking for non-zero `l`
continue if the result of fctx.annotate is empty.
2016-07-11 15:45:34 +02:00
Denis Laxalde
873ac38beb context: eliminate handling of linenumber being None in annotate
I could not find any use of this parameter value. And it arguably makes
understanding of the function more difficult. Setting the parameter default
value to False.
2016-07-11 14:44:19 +02:00
Gregory Szorc
a17406014b tests: regenerate x509 test certificates
The old x509 test certificates were using cryptographic settings
that are ancient by today's standards, namely 512 bit RSA keys.
To put things in perspective, browsers have been dropping support
for 1024 bit RSA keys.

I think it is important that tests match the realities of the times.
And 2048 bit RSA keys with SHA-2 hashing are what the world is
moving to.

This patch replaces all the x509 certificates with new versions using
modern best practices. In addition, the docs for generating the
keys have been updated, as the existing docs left out a few steps,
namely how to generate certs that were not active yet or expired.
2016-07-12 22:26:04 -07:00
Denis Laxalde
349c6778aa hgweb: add a link on node id in annotate hover-box
The link pointing the annotate view at this revision, just like the one in the
left-column but accessible from anywhere.
2016-07-12 15:09:07 +02:00
Denis Laxalde
0986e60532 hgweb: move author information from left-column to hover-box in annotate view
And display the full author information since there is enough space there.
2016-07-12 15:07:37 +02:00
Denis Laxalde
81b6a5375a hgweb: add links to diff and changeset in hover-box on annotate view 2016-06-14 11:01:30 +02:00
Denis Laxalde
07a35f6357 hgweb: add link to parents of annotated revision in annotate view
The link is embedded into a div with class="annotate-info" that only shows up
upon hover of the annotate column. To avoid duplicate hover-overs (this new
one and the one coming from link's title), drop "title" attribute from a
element and put it in the annotate-info element.
2016-06-28 11:42:42 +02:00
Maciej Fijalkowski
99f034fe89 compat: provide a declaration of ssize_t, for MS windows 2016-07-11 13:53:35 +02:00