Commit Graph

1412 Commits

Author SHA1 Message Date
Matt Mackall
9b5bba3207 check-config: add config option checker
This script scans files for lines that look like either ui.config
usage or config variable documentation. It then ensures:

- ui.config calls for each option agree on types and defaults
- every option appears to be mentioned in documentation

It doesn't complain about devel/experimental options and allows
marking options that are not intended to be public.

Since we haven't been able to come up with a good scheme for
documenting config options at point of use, this will help close the
loop of making sure all options that should be documented are.
2015-06-25 17:34:53 -05:00
Yuya Nishihara
879585e8e1 import-checker: exclude mercurial packages installed into the system path
If mercurial was installed into a directory other than the site-packages,
test-module-imports.t failed as 'mercurial.node' was listed in stdlib_modules:

  testpackage/latesymbolimport.py relative import of stdlib module

Instead, we should exclude our packages explicitly.
2015-07-04 10:56:37 +09:00
Yuya Nishihara
cfcee215a8 import-checker: recurse into subtree of sys.path only if __init__.py exists
We can't assume that the site-packages is the only directory that has Python
files but is not handled as a package. For example, we have dist-packages
directory on Debian.
2015-07-04 10:54:03 +09:00
FUJIWARA Katsunori
4bae7bb820 import-checker.py: exit with code 0 if no error is detected
Before this patch, `import-checker.py` exits with non-0 code, if no
error is detected. This is unusual as Unix command.

This change may be a one of preparations for issue4677, because this
can avoid extra explanation about unusual exit code of
`import-checker.py` for third party tool developers.
2015-07-03 06:56:03 +09:00
Gregory Szorc
5fe42b2975 import-checker: establish modern import convention
We introduce a new convention for declaring imports and enforce it via
the import checker script.

The new convention is only active when absolute imports are used, which is
currently nowhere. Keying off "from __future__ import absolute_import" to
engage the new import convention seems like the easiest solution. It is
also beneficial for Mercurial to use this mode because it means less work
and ambiguity for the importer and potentially better performance due to
fewer stat() system calls because the importer won't look for modules in
relative paths unless explicitly asked.

Once all files are converted to use absolute import, we can refactor
this code to again only have a single import convention and we can
require use of absolute import in the style checker.

The rules for the new convention are documented in the docstring of the
added function. Tests have been added to test-module-imports.t. Some
tests are sensitive to newlines and source column position, which makes
docstring testing difficult and/or impossible.
2015-06-28 12:46:34 -07:00
Gregory Szorc
1553443b44 import-checker: establish new function for verifying import conventions
A future patch will formalize the modern import convention. In
preparation for that, introduce a new wrapper function that will invoke
the proper function.
2015-06-28 12:28:48 -07:00
Gregory Szorc
1159e64c84 import-checker: resolve relative imports
"from . import X" will produce an ImportFrom ast node with .module =
None. This resulted in a run-time error from attempting to concatenate
None with a str.

Another problem with relative imports is that the prefix may be dynamic
based on the "level" attribute of the import. e.g. "from ." has level 1
and "from .." has level 2.

We teach the "fromlocal" function how to cope with relative imports.
Where appropriate, the consumer passes in the level so relative module
names may be resolved properly.
2015-06-28 09:36:58 -07:00
Gregory Szorc
7a107e3b4a check-code: detect legacy exception syntax
We just rewrote all files to use modern exception syntax. Ban the old
form.

This will detect the "except type, instance" and
"except (type1, type2), instance" forms.
2015-06-23 22:20:01 -07:00
Gregory Szorc
5380dea2a7 global: mass rewrite to use modern exception syntax
Python 2.6 introduced the "except type as instance" syntax, replacing
the "except type, instance" syntax that came before. Python 3 dropped
support for the latter syntax. Since we no longer support Python 2.4 or
2.5, we have no need to continue supporting the "except type, instance".

This patch mass rewrites the exception syntax to be Python 2.6+ and
Python 3 compatible.

This patch was produced by running `2to3 -f except -w -n .`.
2015-06-23 22:20:08 -07:00
Gregory Szorc
82ea02abcf check-code: detect legacy octal syntax
Now that we have mass rewriting all files to use the modern octal
syntax, detect and ban the legacy syntax, which is no longer supported
in Python 3.
2015-06-23 22:38:21 -07:00
Pierre-Yves David
9c4de6ba91 revset: improves time complexity of 'roots(xxx)'
The canonical way of doing 'roots(X)' is 'X - children(X)'. This is what the
implementation used to be. However, computing children is expensive because it
is unbounded. Any changesets in the repository may be a children of '0' so you
have to look at all changesets in the repository to compute children(0).
Moreover the current revsets implementation for children is not lazy, leading to
bad performance when fetching the first result.


There is a more restricted algorithm to compute roots:

    roots(X) = [r for r in X if not parents(r) & X]

This achieve the same result while only looking for parent/children relation in
the X set itself, making the algorithm 'O(len(X))' membership operation.
Another advantages is that it turns the check into a simple filter, preserving
all laziness property of the underlying revsets.

The speed is very significant and some laziness is restored.

-) revset without 'roots(...)' to compare to base line
0) before this change
1) after this change

revset #0: roots((tip~100::) - (tip~100::tip))
   plain         min           last
-) 0.001082      0.000993      0.000790
0) 0.001366      0.001385      0.001339
1) 0.001257  92% 0.001028  74% 0.000821  61%

revset #1: roots((0::) - (0::tip))
   plain         min           last
-) 0.134551      0.144682      0.068453
0) 0.161822      0.171786      0.157683
1) 0.137583  85% 0.146204  85% 0.070012  44%

revset #2: roots(tip~100:)
   plain         min           first         last
-) 0.000219      0.000225      0.000231      0.000229
0) 0.000513      0.000529      0.000507      0.000539
1) 0.000463  90% 0.000269  50% 0.000267  52% 0.000463  85%

revset #3: roots(:42)
   plain         min           first         last
-) 0.000119      0.000146      0.000146      0.000146
0) 0.000231      0.000254      0.000253      0.000260
1) 0.000216  93% 0.000186  73% 0.000184  72% 0.000244  93%

revset #4: roots(not public())
   plain         min           first
-) 0.000478      0.000502      0.000504
0) 0.000611      0.000639      0.000634
1) 0.000604      0.000560  87% 0.000558

revset #5: roots((0:tip)::)
   plain         min           max           first         last
-) 0.057795      0.004905      0.058260      0.004908      0.038812
0) 0.132845      0.118931      0.130306      0.114280      0.127742
1) 0.111659  84% 0.005023   4% 0.111658  85% 0.005022   4% 0.092490  72%

revset #6: roots(0::tip)
   plain         min           max           first         last
-) 0.032971      0.033947      0.033460      0.032350      0.033125
0) 0.083671      0.081953      0.084074      0.080364      0.086069
1) 0.074720  89% 0.035547  43% 0.077025  91% 0.033729  41% 0.083197

revset #7: 42:68 and roots(42:tip)
   plain         min           max           first         last
-) 0.006827      0.000251      0.006830      0.000254      0.006771
0) 0.000337      0.000353      0.000366      0.000350      0.000366
1) 0.000318  94% 0.000297  84% 0.000353      0.000293  83% 0.000351

revset #8: roots(0:tip)
   plain         min           max           first         last
-) 0.002119      0.000145      0.000147      0.000147      0.000147
0) 0.047441      0.040660      0.045662      0.040284      0.043435
1) 0.038057  80% 0.000187   0% 0.034919  76% 0.000186   0% 0.035097  80%

revset #0: roots(:42 + tip~42:)
   plain         min           max           first         last          sort
-) 0.000321      0.000317      0.000319      0.000308      0.000369      0.000343
0) 0.000772      0.000751      0.000811      0.000750      0.000802      0.000783
1) 0.000632  81% 0.000369  49% 0.000617  76% 0.000358  47% 0.000601  74% 0.000642  81%
2015-06-22 10:19:12 -07:00
Pierre-Yves David
7a8996fad4 revsetbenchmark: do not abort on failure to run a revset
Instead of aborting the whole process, we just skip entry for revset that
failed to run.
2015-06-20 16:22:10 -07:00
Yuya Nishihara
a0be3c41c2 check-commit: catch both patterns of double empty lines 2015-06-21 15:18:49 +09:00
Pierre-Yves David
0b5134f913 revsetbenchmarks: ignore empty lines
Before this change, empty lines were seen as an entry and the benchmark tried
to run benchmark for "".
2015-06-20 04:13:25 -07:00
Pierre-Yves David
da0f39bd8a revset: make use of natively-computed set for 'draft()' and 'secret()'
If the computation of a set for each phase (done in C) is available,
we use it directly instead of applying a simple filter. This give a
massive speed-up in the vast majority of cases.

On my mercurial repo with about 15000 out of 40000 draft changesets:

revset: draft()
   plain         min           first         last
0) 0.011201      0.019950      0.009844      0.000074
1) 0.000284   2% 0.000312   1% 0.000314   3% 0.000315 x4.3

Bad performance for "last" come from the handling of the 15000 elements set
(memory allocation, filtering hidden changesets (99% of it) etc. compared to
applying the filter only on a handfuld of revisions (the first draft changesets
being close of tip).

This is not seen as an issue since:

* Timing is still pretty good and in line with all the other one,
* Current user of Vanilla Mercurial will not have 1/3 of their repo draft,

This bad effect disappears when phase's set is smaller. (about 200 secrets):

revset: secret()
   plain         min           first         last
0) 0.011181      0.022228      0.010851      0.000452
1) 0.000058   0% 0.000084   0% 0.000087   0% 0.000087  19%
2015-06-10 19:18:51 -07:00
Pierre-Yves David
7dc4b61365 revset: translate node directly with changelog in 'head'
Using 'repo[X]' is much slower because it creates a 'changectx' object and goes
though multiple layers of code to do so. It is also error prone if there is
tags, bookmarks, branch or other names that could map to a node hash and take
precedence (user are wicked).

This provides a significant performance boost on repository with a lot of
heads.  Benchmark result for a repo with 1181 heads.

revset: head()
   plain         min           last          reverse
0) 0.014853      0.014371      0.014350      0.015161
1) 0.001402   9% 0.000975   6% 0.000874   6% 0.001415   9%

revset: head() - public()
   plain         min           last          reverse
0) 0.015121      0.014420      0.014560      0.015028
1) 0.001674  11% 0.001109   7% 0.000980   6% 0.001693  11%

revset: draft() and head()
   plain         min           last          reverse
0) 0.015976      0.014490      0.014214      0.015892
1) 0.002335  14% 0.001018   7% 0.000887   6% 0.002340  14%

The speed up is visible even when other more costly revset are in use

revset: head() and author("mpm")
   plain         min           last          reverse
0) 0.105419      0.090046      0.017169      0.108180
1) 0.090721  86% 0.077602  86% 0.003556  20% 0.093324  86%
2015-06-16 19:47:46 -07:00
Pierre-Yves David
9b78f27d7c contrib: clean up all-revsets.txt file
I forgot to cleanup a handful of them when I originally created the file.
2015-06-17 16:29:46 -07:00
Pierre-Yves David
916b1666b3 contrib: introduce an all-revsets.txt file
This file should gather all revsets ever thought interesting by
anyone. That way one can check the impact of a change when touching
something revset-ish. See inline comments for details.

This file have been refilled with all the entry I could automatically
find from changeset descriptions. I assume we missed some not using
'revsetbenchmarks.py' output.
2015-06-16 22:15:30 -07:00
Pierre-Yves David
e4f090319c contrib: rename revsetbenchmarks.txt to 'base-revsets.txt'
We rename the file and document its purpose. We'll be introducing another file
gathering revsets useful for benchmark of the predicate themsleves in a coming
changesets.
2015-06-16 20:36:00 -07:00
Pierre-Yves David
254ba0361d revsetbenchmarks: add main documention for the script
This allow us to document the fact we can use comment in the file listing revsets.
2015-06-16 20:24:37 -07:00
Yuya Nishihara
5ddbe8ee34 check-code: ban use of '[[ ]]' in tests 2015-06-16 23:06:30 +09:00
Pierre-Yves David
a58cb283b6 revsetbenchmarks: also display tag when printing a revision
This is usually more useful information than the commit message.
2015-06-10 17:33:57 -07:00
Pierre-Yves David
86d12c3327 revsetbenchmarks: clean up revsets that achieved with default variants
We remove revset making use of min and max as this is covered by the variants.
We could use variant for roots too, but it is not in the default so keep it
here.
2014-10-27 13:40:12 +01:00
Pierre-Yves David
4bf2a1c663 revsetbenchmarks: use combination variants in default set
Now that we have them, let's make use of them.
2015-06-09 23:49:07 -07:00
Pierre-Yves David
1a88814277 revsetbenchmarks: support combining variants with "+"
We need more advanced variants in some cases. For example, "The last
rev of the sorted version".

We introduce a syntax for this: `reverse+last` means `last(reverse(REVSET))`.
2015-06-09 23:45:34 -07:00
Pierre-Yves David
6f731a872c revsetbenchmarks: use many more variants by default
So far the variants feature was introduced, but not used by
default. We now use a set of basic variants by default.
2015-06-09 21:10:44 -07:00
Pierre-Yves David
3e785ae2da revsetbenchmarks: display even more compact timing result
We now use an 8 char display for timing (from 10), we add some logic to drop
precision if the number grows too large (as we do not care about sub-0 digit
in this case). This allow to pack more variants in a single screen.
2015-06-09 21:20:54 -07:00
Pierre-Yves David
abd025e2f3 revsetbenchmarks: allow running multiple variants per revset
The current benchmarks were only testing the whole iteration. This is suboptimal
because some changes are meaningful for things like first result, minimum or
sorting.

We introduce a "variants" feature that let you systematically add some variants
to all revsets tested.

A typical variants value would be 'plain,min,last,sort'. When testing 'all()' it
will also provide testing for:
- all()
- min(all())
- last(all())
- sort(sort)

and output:

   plain         min            last           sort
0) 0.034568      0.037857       0.000074       0.034238
1) 0.011358  32% 0.020181  53%  0.000080 108%  0.011405  33%

Using revsets (who hit the API) instead of the internal API add some overhead,
but the overhead should be the same everywhere so it still allow comparison.
This is is more simple to implement and allows comparison with older versions
who do not have the same API.
2014-10-27 11:59:39 +01:00
Pierre-Yves David
dd891bab9c revsetbenchmarks: display relative change when meaningful
If the time difference is more than 5% from the previous run, we'll display
relative information. This makes it much simpler to spot performance changes in
a sea of benchmarks.
2015-06-09 21:30:04 -07:00
Pierre-Yves David
c7c66491f5 revsetbenchmarks: improve revision printing
We now print the revision number and short hash inline. As a result we drop the
crappy list printing.
2015-06-09 18:53:04 -07:00
Pierre-Yves David
e5f0537065 revsetbenchmarks: hide most timing under a --verbose flag
We mostly only care about total time. Dropping this output give us some room to
display more useful information (like percentage different) in future
changesets.
2015-06-09 18:40:06 -07:00
Pierre-Yves David
f130bcfaa1 revsetbenchmarks: drop outdated comment
We are no longer testing against system mercurial for quite some time.
2015-06-09 18:32:47 -07:00
Pierre-Yves David
d6c409833b revsetbenchmarks: fix argument parsing
The file doc was saying something, the code was doing something else, the
argument validation was doing a third thing.

Doc and behavior now comply with the argument defined in the code.
2015-06-09 18:39:55 -07:00
Pierre-Yves David
3f8df9e038 revsetbenchmarks: use a more compact output format with a header
We change the output from:

  revset #0: draft()
  0) wall 0.011989 comb 0.010000 user 0.000000 sys 0.010000 (best of 177)
  1) wall 0.012226 comb 0.010000 user 0.000000 sys 0.010000 (best of 193)
  2) wall 0.011838 comb 0.020000 user 0.000000 sys 0.020000 (best of 208)

to:

  revset #0: draft()
       wall       comb       user       sys       count
  0)   0.012028   0.010000   0.000000   0.010000    170
  1)   0.012218   0.010000   0.000000   0.010000    157
  2)   0.012622   0.010000   0.000000   0.010000    189

This opens the road to more useful output.
2015-06-09 17:15:48 -07:00
Augie Fackler
ada9978856 revsetbenchmarks: clarify comment based on irc discussion 2015-06-12 16:42:07 -04:00
Pierre-Yves David
59a81fd7b3 revsetbenchmarks: ensure all indexes have the same width
This avoids an alignment glitch.
2015-06-11 10:55:02 -07:00
Pierre-Yves David
1cc4521b8c revsetbenchmarks: factor out result output into a function
This will make update of the output easier.
2015-06-09 16:57:18 -07:00
Pierre-Yves David
db08ff2e74 revsetbenchmarks: parse perfrevset output into actual number
We cannot just ask perfrevset to provide debug output because we usually want
to compare output from old version of Mercurial that do not support it. So, we
are using a regular expression.

(/we now have \d problems/).
2015-06-09 16:48:29 -07:00
Pierre-Yves David
bb398f89a5 revsetbenchmarks: improve error output in case of failure
This helps with diagnostics.
2015-06-09 15:58:48 -07:00
Pierre-Yves David
d9d7ac3a22 revsetbenchmarks: extract call to mercurial into a function
This is a gratuitous change to make the code easier to look at.
2015-06-09 15:49:14 -07:00
Pierre-Yves David
a4580cc28e perf: support -T for every perf commands
We are already building a formatter, we can now pass it options the official
way.
2015-06-09 15:18:47 -07:00
Steve Borho
a761baa73e wix: move library.zip and all *.pyd into a lib/ folder
This makes the root install folder (on Windows) nice and tidy. The
only files left in the root folder are:

hg.exe
python27.dll
COPYING.rtf
ReadMe.html

the last of which was probably out-of-date 7 years ago
2015-06-03 14:31:19 -05:00
Gregory Szorc
61c827dff1 check-commit: make foo_bar naming regexp less greedy
\s is equivalent to the character class [ \t\n\r\f\v]. Using \s+ in
a regular expression against input with multiple lines may match across
multiple lines.

For the regexp in question, "\+\s+" would match "+\n " and similar
sequences, leading to false positives for functions that were included
in diff context, after a modified hunk.
2015-05-31 17:41:35 -07:00
Matt Mackall
2a25c01621 check-code: reintroduce str.format() ban for 3.x porting
In their infinite wisdom, the Python maintainers stripped bytes of its
% and format() methods for 3.x. They've now added % back to 3.5, but
format() is still missing. Since we don't have any particular need for
it, we should keep avoiding it.
2015-05-19 08:41:04 -05:00
Pierre-Yves David
cb4db56d2a check-code: drop ban of 'val if cond else otherval' construct
We now have access to this horrible but less bad than
'cond and val or otherval' syntax.
2015-05-18 16:18:18 -05:00
Pierre-Yves David
624cc99b09 check-code: drop the 'format' built-in
I'm not clear what it is doing, but one who knows what it is about can now make
use of it.
2015-05-18 16:11:44 -05:00
Pierre-Yves David
b59fc6f804 check-code: drop ban of str.format
After discussion with Augie and Matt, we are fine with it being introduced in
the code base.
2015-05-18 16:09:05 -05:00
Augie Fackler
f95a6caba1 extensions: document that testedwith = 'internal' is special
Extension authors (notably at companies using hg) have been
cargo-culting the `testedwith = 'internal'` bit from hg's own
extensions, which then defeats our "file bugs over here" logic in
dispatch. Let's be more aggressive about trying to give extension
authors a hint about what testedwith should say.
2015-04-28 16:44:37 -04:00
Pierre-Yves David
d5a6426866 check-code: drop ban of BaseException
Lets go back to the basic. It is available in Python 2.6.
2015-05-18 13:20:19 -05:00
Pierre-Yves David
2d3ab51ced check-code: drop the yield inside try/finally ban
This is now possible with Python 2.6.
2015-05-18 12:56:59 -05:00