Wed, 21 Jun 2017 10:46:18 +0200 profiling: cope with configwith default value handling changes
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 21 Jun 2017 10:46:18 +0200] rev 32996
profiling: cope with configwith default value handling changes Changeset 6ff6eb33f353 change 'configwith' behavior so that the default value is run through the conversion function. In parallel a new user of 'configwith' got introduced unaware of this coming behavior change. This broke profiling. We resolve the situation by having the new conversion function cope with a default value already using the right type.
Tue, 20 Jun 2017 14:00:41 -0700 py3: catch StopIteration from next() in generatorset
Martin von Zweigbergk <martinvonz@google.com> [Tue, 20 Jun 2017 14:00:41 -0700] rev 32995
py3: catch StopIteration from next() in generatorset IIUC, letting the StopIteration through would not cause any bugs, but not doing it makes the test-py3-commands.t pass. I have also diligently gone through all uses of next() in our code base. They either: * are not called from a generator * pass a default value to next() * catch StopException * work on infinite iterators * request a fixed number of items that matches the generated number * are about batching in wireproto which I didn't quite follow I'd appreciate if Augie or someone else could take a look at the wireproto batching and convince themselves that the next(batchable) calls there will not raise a StopIteration.
Tue, 20 Jun 2017 23:23:45 -0400 tests: adjust quoting to keep Windows happy with recent $PYTHON change
Matt Harbison <matt_harbison@yahoo.com> [Tue, 20 Jun 2017 23:23:45 -0400] rev 32994
tests: adjust quoting to keep Windows happy with recent $PYTHON change I tried adding quotes to the $PYTHON variable, and also tried converting the path from the current 'c:/Python/python.exe' form to '/c/python/python.exe', but neither worked. I'm not sure why one of these needs '\"' around the variable and the other doesn't.
Tue, 20 Jun 2017 16:33:13 -0700 bundle2: don't use debug message "no-transaction" with transaction
Martin von Zweigbergk <martinvonz@google.com> [Tue, 20 Jun 2017 16:33:13 -0700] rev 32993
bundle2: don't use debug message "no-transaction" with transaction
Wed, 21 Jun 2017 02:20:34 +0530 py3: use pycompat.bytestr() in place of str()
Pulkit Goyal <7895pulkit@gmail.com> [Wed, 21 Jun 2017 02:20:34 +0530] rev 32992
py3: use pycompat.bytestr() in place of str()
Wed, 21 Jun 2017 02:13:34 +0530 py3: use r'' to access values from kwargs where keys are str
Pulkit Goyal <7895pulkit@gmail.com> [Wed, 21 Jun 2017 02:13:34 +0530] rev 32991
py3: use r'' to access values from kwargs where keys are str These are the cases where either args is again passed as keyword argument or 1 or 2 elements are accessed. So it's better to add an r'' to prevent it converting to bytes rather than doing the conversion of args.
Wed, 21 Jun 2017 02:10:25 +0530 py3: convert keys of kwargs in template keywords functions to bytes
Pulkit Goyal <7895pulkit@gmail.com> [Wed, 21 Jun 2017 02:10:25 +0530] rev 32990
py3: convert keys of kwargs in template keywords functions to bytes This patch converts the args argument keys' to bytes wherever necessary as there are some places where either args is not used or using r'' is better or args is again passed as keyword arguments.
Tue, 20 Jun 2017 23:50:50 +0530 py3: make sure the commands name are bytes in test-devel-warnings.t
Pulkit Goyal <7895pulkit@gmail.com> [Tue, 20 Jun 2017 23:50:50 +0530] rev 32989
py3: make sure the commands name are bytes in test-devel-warnings.t
Tue, 20 Jun 2017 23:46:18 +0530 py3: replace str with bytes in isinstance()
Pulkit Goyal <7895pulkit@gmail.com> [Tue, 20 Jun 2017 23:46:18 +0530] rev 32988
py3: replace str with bytes in isinstance() We were using str because on Python 2, str were bytes but now we have to use bytes. Otherwise the if conditions fails and we have weird results from commands on Python 3.
Tue, 20 Jun 2017 22:11:46 +0530 py3: catch binascii.Error raised from binascii.unhexlify
Pulkit Goyal <7895pulkit@gmail.com> [Tue, 20 Jun 2017 22:11:46 +0530] rev 32987
py3: catch binascii.Error raised from binascii.unhexlify Before Python 3, binsacii.unhexlify used to raise TypeError, now it raises binascii.Error.
Tue, 20 Jun 2017 23:39:59 -0700 shelve: allow unlimited shelved changes per name
Jun Wu <quark@fb.com> [Tue, 20 Jun 2017 23:39:59 -0700] rev 32986
shelve: allow unlimited shelved changes per name Previously, there is a 100 changes limit per name (bookmark or named branch). And the user will get "too many shelved changes named %s" when they are trying to shelve the 101th change. I hit that error message today. This limit was introduced by the shelve extension since the beginning. The function generating the names was called "gennames", under "getshelvename". There is another "gennames" under "backupfilename": def backupfilename(self): def gennames(base): yield base base, ext = base.rsplit('.', 1) for i in itertools.count(1): yield '%s-%d.%s' % (base, i, ext) "itertools.count" is an endless counter. Since the other "gennames" generates unlimited number of names, and the changeset introducing the limit (49d4919d21) does not say why the limit is useful. It seems safe to just remove the limit. The format "%02d" was kept intentionally so existing shelved changes won't break.
Sat, 17 Jun 2017 12:51:37 +0200 config: use the new '_unset' value for 'configsuboptions'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:51:37 +0200] rev 32985
config: use the new '_unset' value for 'configsuboptions' This should let configsuboptions delegate all special processing of the default config value to the main 'config' method.
Sat, 17 Jun 2017 18:28:20 +0200 config: use the 'config' method in 'configsuboptions'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 18:28:20 +0200] rev 32984
config: use the 'config' method in 'configsuboptions' There was unnecessary code duplication. It was getting in the way of the unification of the default value logic.
Sat, 17 Jun 2017 12:52:02 +0200 config: use the new '_unset' value for 'configpath'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:52:02 +0200] rev 32983
config: use the new '_unset' value for 'configpath' This should let 'configpath' delegate all special processing of the default config value to the main 'config' method.
Sat, 17 Jun 2017 12:54:45 +0200 config: use the new '_unset' value for 'configdate'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:54:45 +0200] rev 32982
config: use the new '_unset' value for 'configdate' This should let 'configdate' delegate all special processing of the default config value to the main 'config' method. The default value for date (None) is still enforced in this method if no other default were passed.
Sat, 17 Jun 2017 12:54:04 +0200 config: use the new '_unset' value for 'configlist'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:54:04 +0200] rev 32981
config: use the new '_unset' value for 'configlist' This should let 'configlist' delegate all special processing of the default config value to the main 'config' method. The default config value ([]) is still handled in this method.
Sat, 17 Jun 2017 12:53:51 +0200 config: use the new '_unset' value for 'configbytes'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:53:51 +0200] rev 32980
config: use the new '_unset' value for 'configbytes' This should let 'configbytes' delegates all special processing of the default config value to the main 'config' method.
Sat, 17 Jun 2017 12:53:40 +0200 config: use the new '_unset' value for 'configint'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:53:40 +0200] rev 32979
config: use the new '_unset' value for 'configint' This should let 'configint' delegates all special processing of the default config value to the main 'config' method.
Sat, 17 Jun 2017 12:52:31 +0200 config: use the new '_unset' value for 'configwith'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:52:31 +0200] rev 32978
config: use the new '_unset' value for 'configwith' This should let 'configwith' delegate all special processing of the default config value to the main 'config' method. This changeset introduce a small change in behavior since the default value is run through the 'convert' function. This does not seems harmful and no actual test break. This small change make the code simpler so I'm keeping it.
Sat, 17 Jun 2017 12:52:16 +0200 config: use the new '_unset' value for 'configbool'
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:52:16 +0200] rev 32977
config: use the new '_unset' value for 'configbool' This should let 'configbool' delegate all special processing of the default config value to the main 'config' method. The default value for bool (False) is still enforced in this method if no other default were passed.
Sat, 17 Jun 2017 12:51:11 +0200 config: explicitly track the use of the standard default value
Pierre-Yves David <pierre-yves.david@octobus.net> [Sat, 17 Jun 2017 12:51:11 +0200] rev 32976
config: explicitly track the use of the standard default value We introduce a small object used to detect that no specific default value has been passed to 'ui.config'. We need this explicit special value since "None" is a valid and common default value. The end goal here is to make progress on a centralised and explicit declaration of the available config option. A first good usecase for this are "default" value. Before starting looking further down this alley we needs to rework the handling of default value in the 'ui' object to have all configxyz methods going through the same logic. This is the first changeset on this trek.
Mon, 19 Jun 2017 22:14:37 -0700 clonebundle: update hook arguments (BC)
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 22:14:37 -0700] rev 32975
clonebundle: update hook arguments (BC) By calling applybundle() with 'clonebundles' and the url instead of calling processbundle(), the hooks will get different arguments: HG_SOURCE will be 'clonebundles' instead of 'bundle2' and HG_URL will be the url instead of 'bundle2'. This is consistent with the bundle1 behavior and seems like a bug fix, but I'm marking it BC anyway.
Sat, 10 Jun 2017 23:42:38 -0700 commands: move checkconflict to bookmarks module
Sean Farley <sean@farley.io> [Sat, 10 Jun 2017 23:42:38 -0700] rev 32974
commands: move checkconflict to bookmarks module Again, commands.bookmark is getting too large. checkconflict already has a lot of state and putting it in the bmstore makes more sense than having it as a closure. This also allows extensions a place to override this behavior. While we're here, add a documentation string because, well, we should be documenting more of our methods.
Sat, 10 Jun 2017 23:32:58 -0700 commands: move checkformat to bookmarks module
Sean Farley <sean@farley.io> [Sat, 10 Jun 2017 23:32:58 -0700] rev 32973
commands: move checkformat to bookmarks module commands.bookmark has grown quite large with two closures already. Let's split this up (and in the process allow extensions to override the default behavior).
Tue, 20 Jun 2017 14:35:53 -0700 tests: tell pip not to check for a newer version
Danek Duvall <danek.duvall@oracle.com> [Tue, 20 Jun 2017 14:35:53 -0700] rev 32972
tests: tell pip not to check for a newer version pip will check to see if it's the latest version, and complain if it isn't. The --no-index flag implies the --disable-pip-version-check flag, and makes the warning (and any associated network activity) go away.
Sat, 22 Apr 2017 21:16:08 +0900 changeset_templater: backport parts map of [templates] section from formatter
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:16:08 +0900] rev 32971
changeset_templater: backport parts map of [templates] section from formatter
Sat, 22 Apr 2017 21:29:00 +0900 formatter: add support for parts map of [templates] section
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:29:00 +0900] rev 32970
formatter: add support for parts map of [templates] section Unlike a mapfile whose template is looked up by spec -> mapfile -> topic, [templates] section is global. We use :sub-section syntax to define parts per template.
Sat, 17 Jun 2017 16:32:20 +0900 changeset_templater: backport separator template from formatter
Yuya Nishihara <yuya@tcha.org> [Sat, 17 Jun 2017 16:32:20 +0900] rev 32969
changeset_templater: backport separator template from formatter As commented, this should be used with docheader and docfooter, not with header nor footer. That's one reason why no props are passed to templater when rendering a separator. (See map-cmdline.changelog to understand what the "header" is.)
Sat, 22 Apr 2017 21:50:51 +0900 formatter: add support for separator template
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:50:51 +0900] rev 32968
formatter: add support for separator template This seems useful for writing JSON template.
Sat, 22 Apr 2017 21:46:14 +0900 formatter: add support for docheader and docfooter templates
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:46:14 +0900] rev 32967
formatter: add support for docheader and docfooter templates templatepartsmap() is a minimal copy of changeset_templater.__init__(). I tried to factor out a common function, but it was unnecessarily complicated.
Sat, 22 Apr 2017 21:38:08 +0900 formatter: extract helper function to render template
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:38:08 +0900] rev 32966
formatter: extract helper function to render template
Sat, 22 Apr 2017 21:09:07 +0900 changeset_templater: do not enable verbosity postfix for [templates] section
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:09:07 +0900] rev 32965
changeset_templater: do not enable verbosity postfix for [templates] section Since this postfix hack exists only for backward compatibility, we don't need it for new [templates] section. This isn't a BC as templates defined in [templates] section weren't loaded until recently.
Sat, 22 Apr 2017 21:06:11 +0900 changeset_templater: simplify handling of verbosity postfix
Yuya Nishihara <yuya@tcha.org> [Sat, 22 Apr 2017 21:06:11 +0900] rev 32964
changeset_templater: simplify handling of verbosity postfix
Tue, 20 Jun 2017 16:33:46 -0400 merge with stable
Augie Fackler <augie@google.com> [Tue, 20 Jun 2017 16:33:46 -0400] rev 32963
merge with stable
Mon, 19 Jun 2017 16:08:20 -0700 tests: don't touch the network when using virtualenv
Danek Duvall <danek.duvall@oracle.com> [Mon, 19 Jun 2017 16:08:20 -0700] rev 32962
tests: don't touch the network when using virtualenv
Sat, 03 Jun 2017 17:32:52 -0700 tests: removed ReportedTest exception
Gregory Szorc <gregory.szorc@gmail.com> [Sat, 03 Jun 2017 17:32:52 -0700] rev 32961
tests: removed ReportedTest exception The only call site called addFailure before raising, which is exactly what the failure exception handler does. So this complexity is not needed. We have test coverage of this "server failed to start" scenario and nothing appeared to change.
Sat, 03 Jun 2017 17:22:45 -0700 tests: remove support for warned tests
Gregory Szorc <gregory.szorc@gmail.com> [Sat, 03 Jun 2017 17:22:45 -0700] rev 32960
tests: remove support for warned tests The previous changeset removed the last caller of addWarn(). So, we rip out that method and all the code related to tracking warned tests in the results system. There was even a comment saying we may want to fold warned tests into the "failed" state, which is what the previous changeset did.
Tue, 20 Jun 2017 09:49:43 -0400 contrib: add check-code rule to enforce non-use of `python` in tests
Augie Fackler <augie@google.com> [Tue, 20 Jun 2017 09:49:43 -0400] rev 32959
contrib: add check-code rule to enforce non-use of `python` in tests
Tue, 20 Jun 2017 09:45:02 -0400 cleanup: use $PYTHON to run python in many more tests
Augie Fackler <augie@google.com> [Tue, 20 Jun 2017 09:45:02 -0400] rev 32958
cleanup: use $PYTHON to run python in many more tests Spotted one of these, then wrote a check-code rule that caught them all. It will be the next change.
Thu, 15 Jun 2017 14:22:39 -0400 tests: enforce use of $PYTHON in tests
Augie Fackler <augie@google.com> [Thu, 15 Jun 2017 14:22:39 -0400] rev 32957
tests: enforce use of $PYTHON in tests
Thu, 15 Jun 2017 14:27:52 -0400 tests: use $PYTHON in #! so we always use the right Python
Augie Fackler <augie@google.com> [Thu, 15 Jun 2017 14:27:52 -0400] rev 32956
tests: use $PYTHON in #! so we always use the right Python
Tue, 20 Jun 2017 09:33:19 -0400 tests: sed away python #! in test-run-tests.t to avoid some upcoming insanity
Augie Fackler <augie@google.com> [Tue, 20 Jun 2017 09:33:19 -0400] rev 32955
tests: sed away python #! in test-run-tests.t to avoid some upcoming insanity
Tue, 20 Jun 2017 08:44:56 -0400 tests: remove #! from primes.py in test-highlight.t
Augie Fackler <augie@google.com> [Tue, 20 Jun 2017 08:44:56 -0400] rev 32954
tests: remove #! from primes.py in test-highlight.t It's about to be a source of trouble, but removing it changes a ton of test lines, so doing this change as a standalone commit.
Tue, 20 Jun 2017 12:51:36 +0100 keyword: use context manager for rollback locking
Christian Ebert <blacktrash@gmx.net> [Tue, 20 Jun 2017 12:51:36 +0100] rev 32953
keyword: use context manager for rollback locking
Sat, 03 Jun 2017 17:13:35 -0700 tests: remove WarnTest
Gregory Szorc <gregory.szorc@gmail.com> [Sat, 03 Jun 2017 17:13:35 -0700] rev 32952
tests: remove WarnTest We would raise this if a test didn't return a result code. AFAICT this can only occur if there is a logic error in the test harness itself. I don't think it is worth the code complexity to distinguish this failure scenario from a regular test failure.
Sat, 03 Jun 2017 17:09:13 -0700 tests: remove unused IgnoreTest exception
Gregory Szorc <gregory.szorc@gmail.com> [Sat, 03 Jun 2017 17:09:13 -0700] rev 32951
tests: remove unused IgnoreTest exception AFAICT its last use was removed in d839e4820da7.
Sat, 03 Jun 2017 17:04:42 -0700 tests: use unittest.SkipTest
Gregory Szorc <gregory.szorc@gmail.com> [Sat, 03 Jun 2017 17:04:42 -0700] rev 32950
tests: use unittest.SkipTest unittest.SkipTest was introduced in Python 2.7. We previously defined it with our own class so we could run on Python 2.6.
Thu, 15 Jun 2017 23:23:47 -0700 changegroup: delete "if True" and reflow
Martin von Zweigbergk <martinvonz@google.com> [Thu, 15 Jun 2017 23:23:47 -0700] rev 32949
changegroup: delete "if True" and reflow
Thu, 15 Jun 2017 22:46:38 -0700 changegroup: let callers pass in transaction to apply() (API)
Martin von Zweigbergk <martinvonz@google.com> [Thu, 15 Jun 2017 22:46:38 -0700] rev 32948
changegroup: let callers pass in transaction to apply() (API) I think passing in the transaction makes it a little clearer and more consistent with bundle2.
Thu, 15 Jun 2017 23:09:14 -0700 repair: create transaction for bundle1 unbundling earlier
Martin von Zweigbergk <martinvonz@google.com> [Thu, 15 Jun 2017 23:09:14 -0700] rev 32947
repair: create transaction for bundle1 unbundling earlier See earlier patch for motivation.
Thu, 15 Jun 2017 22:18:21 -0700 unbundle: create transaction for bundle1 unbundling earlier
Martin von Zweigbergk <martinvonz@google.com> [Thu, 15 Jun 2017 22:18:21 -0700] rev 32946
unbundle: create transaction for bundle1 unbundling earlier See earlier patch for motivation.
Thu, 15 Jun 2017 16:10:53 -0700 exchange: create transaction for bundle1 unbundling earlier
Martin von Zweigbergk <martinvonz@google.com> [Thu, 15 Jun 2017 16:10:53 -0700] rev 32945
exchange: create transaction for bundle1 unbundling earlier changegroup.apply() currently creates a transation if there isn't already one. Having the callers of that method pass in an existing transaction seems a little cleaner. To do that, we need to make sure all callers have a transaction. Since the transaction name is used as a hook argument (HG_TXNNAME), we need to match the name from changegroup.apply().
Mon, 19 Jun 2017 00:06:23 -0700 changegroup: inline 'publishing' variable in apply()
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 00:06:23 -0700] rev 32944
changegroup: inline 'publishing' variable in apply()
Mon, 19 Jun 2017 11:24:49 -0700 repair: remove unnecessary locking for bookmarks
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:24:49 -0700] rev 32943
repair: remove unnecessary locking for bookmarks The caller has already locked the repo.
Mon, 19 Jun 2017 13:18:00 -0700 repair: move check for existing transaction earlier
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 13:18:00 -0700] rev 32942
repair: move check for existing transaction earlier Several benefits: * Gets close the comment describing it * Splits off unrelated comment about "backup" argument * Error checking is customarily done early * If we added an early return to the method, it would still consistently fail if there was an existing transaction (so we would find and fix that case quickly) One test needs updating with for this change, because we no longer create the backup bundle before we fail. I don't see much reason to create that backup bundle. If some command was adding content and then trying to strip it as well within the transaction, we would have a backup for the user, but the risk of that not being discovered in development seems very small.
Mon, 19 Jun 2017 13:13:28 -0700 strip: remove unncessary "del" and inline variable
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 13:13:28 -0700] rev 32941
strip: remove unncessary "del" and inline variable
Mon, 19 Jun 2017 11:24:21 -0700 repair: clarify in comment that caller must take lock, but not transaction
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:24:21 -0700] rev 32940
repair: clarify in comment that caller must take lock, but not transaction I have checked that all callers have already taken the lock (and if they hadn't, we should have seen tests fail thanks to the 'transaction requires locking' devel warning in localrepo.transaction()).
Mon, 19 Jun 2017 11:21:37 -0700 amend: use context manager for locking
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:21:37 -0700] rev 32939
amend: use context manager for locking
Mon, 19 Jun 2017 11:20:29 -0700 strip: use context manager for locking and transaction in stripcmd()
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:20:29 -0700] rev 32938
strip: use context manager for locking and transaction in stripcmd()
Mon, 19 Jun 2017 11:17:31 -0700 strip: use context manager for locking in strip()
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:17:31 -0700] rev 32937
strip: use context manager for locking in strip()
Mon, 19 Jun 2017 11:18:12 -0700 rebase: use context manager for locking in pullrebase()
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:18:12 -0700] rev 32936
rebase: use context manager for locking in pullrebase()
Mon, 19 Jun 2017 11:18:05 -0700 rebase: use context manager for locking in rebase()
Martin von Zweigbergk <martinvonz@google.com> [Mon, 19 Jun 2017 11:18:05 -0700] rev 32935
rebase: use context manager for locking in rebase()
Mon, 19 Jun 2017 21:53:54 -0400 test-http-proxy: redirect proxy stdout to /dev/null
Matt Harbison <matt_harbison@yahoo.com> [Mon, 19 Jun 2017 21:53:54 -0400] rev 32934
test-http-proxy: redirect proxy stdout to /dev/null This output hasn't been getting flushed, but would alter the log if it ever grew large enough. See 23b07333a8b2.
Mon, 19 Jun 2017 21:44:23 -0400 test-logtoprocess: don't run on Windows
Matt Harbison <matt_harbison@yahoo.com> [Mon, 19 Jun 2017 21:44:23 -0400] rev 32933
test-logtoprocess: don't run on Windows Several bits of output were missing[1], unless the DETACHED_PROCESS flag is _not_ passed to subprocess.Popen(). The problem with that is it briefly opens and closes several cmd.exe windows on screen. Foozy also mentioned some other issues in that thread. With this, the last of the long standing Windows failures fixed, the test suite now runs cleanly (536 ran, 67 skipped) on Windows 7 x64, with python 2.7.13. \o/ [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-April/096987.html
(0) -30000 -10000 -3000 -1000 -300 -100 -64 +64 +100 +300 +1000 +3000 +10000 tip