D5237: fix: add suboption for configuring execution order of tools
hooper updated this revision to Diff 12461. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5237?vs=12460=12461 REVISION DETAIL https://phab.mercurial-scm.org/D5237 AFFECTED FILES hgext/fix.py tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -165,6 +165,26 @@ [fix] failure = abort + When multiple tools are configured to affect a file, they execute in an order + defined by the :priority suboption. The priority suboption has a default value + of zero for each tool. Tools are executed in order of ascending priority. The + execution order of tools with equal priority is unspecified. For example, you + could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers + in a text file by ensuring that 'sort' runs before 'head': + +[fix] +sort:command = sort --numeric-sort +head:command = head --lines=10 +sort:pattern = numbers.txt +head:pattern = numbers.txt +sort:priority = 1 +head:priority = 2 + + To account for changes made by each tool, the line numbers used for + incremental formatting are recomputed before executing the next tool. So, each + tool may see different values for the arguments added by the :linerange + suboption. + list of commands: fix rewrite file content in changesets or working directory @@ -1127,3 +1147,51 @@ first $ cd .. + +The execution order of tools can be controlled. This example doesn't work if +you sort after truncating, but the config defines the correct order while the +definitions are out of order (which might imply the incorrect order given the +implementation of fix). The goal is to use multiple tools to select the lowest +5 numbers in the file. + + $ hg init priorityexample + $ cd priorityexample + + $ cat >> .hg/hgrc < [fix] + > head:command = head --lines=5 + > head:pattern = numbers.txt + > head:priority = 2 + > sort:command = sort --numeric-sort + > sort:pattern = numbers.txt + > sort:priority = 1 + > EOF + + $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt + $ hg add -q + $ hg fix -w + $ cat numbers.txt + 0 + 1 + 2 + 3 + 4 + +And of course we should be able to break this by reversing the execution order. +Test negative priorities while we're at it. + + $ cat >> .hg/hgrc < [fix] + > head:priority = -2 + > sort:priority = -1 + > EOF + $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt + $ hg fix -w + $ cat numbers.txt + 2 + 3 + 6 + 7 + 8 + + $ cd .. diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -54,6 +54,24 @@ [fix] failure = abort +When multiple tools are configured to affect a file, they execute in an order +defined by the :priority suboption. The priority suboption has a default value +of zero for each tool. Tools are executed in order of ascending priority. The +execution order of tools with equal priority is unspecified. For example, you +could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers +in a text file by ensuring that 'sort' runs before 'head':: + + [fix] + sort:command = sort --numeric-sort + head:command = head --lines=10 + sort:pattern = numbers.txt + head:pattern = numbers.txt + sort:priority = 1 + head:priority = 2 + +To account for changes made by each tool, the line numbers used for incremental +formatting are recomputed before executing the next tool. So, each tool may see +different values for the arguments added by the :linerange suboption. """ from __future__ import absolute_import @@ -100,10 +118,16 @@ configitem = registrar.configitem(configtable) # Register the suboptions allowed for each configured fixer. -FIXER_ATTRS = ('command', 'linerange', 'fileset', 'pattern') +FIXER_ATTRS = { +'command': None, +'linerange': None, +'fileset': None, +'pattern': None, +'priority': 0, +} -for key in FIXER_ATTRS: -configitem('fix', '.*(:%s)?' % key, default=None, generic=True) +for key, default in FIXER_ATTRS.items(): +configitem('fix', '.*(:%s)?' % key, default=default, generic=True) # A good default size allows most source code files to be fixed, but avoids # letting fixer tools choke on huge inputs, which could be surprising to the @@ -602,18 +626,20 @@ Each value is a Fixer object with methods that implement the behavior of the fixer's config suboptions. Does not validate the config values. """ -result = {} +fixers = {} for name in fixernames(ui): -result[name] = Fixer() +fixers[name] = Fixer() attrs = ui.configsuboptions('fix', name)[1] if 'fileset' in attrs and 'pattern' not in attrs: ui.warn(_('the fix.tool:fileset config name is deprecated; ' 'please rename it to fix.tool:pattern\n')) attrs['pattern'] = attrs['fileset'] -for key in FIXER_ATTRS: -
D5237: fix: add suboption for configuring execution order of tools
hooper created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This could be accomplished by using wrapper scripts, but that would diminish the usefulness of the incremental formatting logic. Configuring execution order along with other things in the hgrc is probably more convenient anyway. This change highlights some awkwardness with suboptions and default values, which should be addressed separately. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5237 AFFECTED FILES hgext/fix.py tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -165,6 +165,26 @@ [fix] failure = abort + When multiple tools are configured to affect a file, they execute in an order + defined by the :priority suboption. The priority suboption has a default value + of zero for each tool. Tools are executed in order of ascending priority. The + execution order of tools with equal priority is unspecified. For example, you + could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers + in a text file by ensuring that 'sort' runs before 'head': + +[fix] +sort:command = sort --numeric-sort +head:command = head --lines=10 +sort:pattern = numbers.txt +head:pattern = numbers.txt +sort:priority = 1 +head:priority = 2 + + To account for changes made by each tool, the line numbers used for + incremental formatting are recomputed before executing the next tool. So, each + tool may see different values for the arguments added by the :linerange + suboption. + list of commands: fix rewrite file content in changesets or working directory @@ -1127,3 +1147,52 @@ first $ cd .. + +The execution order of tools can be controlled. This example doesn't work if +you sort after truncating, but the config defines the correct order while the +definitions are out of order (which might imply the incorrect order given the +implementation of fix). The goal is to use multiple tools to select the lowest +5 numbers in the file. + + $ hg init priorityexample + $ cd priorityexample + + $ cat >> .hg/hgrc < [fix] + > head:command = head --lines=5 + > head:pattern = numbers.txt + > head:priority = 2 + > sort:command = sort --numeric-sort + > sort:pattern = numbers.txt + > sort:priority = 1 + > EOF + + $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt + $ hg add -q + $ hg fix -w + $ cat numbers.txt + 0 + 1 + 2 + 3 + 4 + +And of course we should be able to break this by reversing the execution order. +Test negative priorities while we're at it. + + $ cat >> .hg/hgrc < [fix] + > head:priority = -2 + > sort:priority = -1 + > EOF + $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt + $ hg fix -w + $ cat numbers.txt + 2 + 3 + 6 + 7 + 8 + + + $ cd .. diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -54,6 +54,24 @@ [fix] failure = abort +When multiple tools are configured to affect a file, they execute in an order +defined by the :priority suboption. The priority suboption has a default value +of zero for each tool. Tools are executed in order of ascending priority. The +execution order of tools with equal priority is unspecified. For example, you +could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers +in a text file by ensuring that 'sort' runs before 'head':: + + [fix] + sort:command = sort --numeric-sort + head:command = head --lines=10 + sort:pattern = numbers.txt + head:pattern = numbers.txt + sort:priority = 1 + head:priority = 2 + +To account for changes made by each tool, the line numbers used for incremental +formatting are recomputed before executing the next tool. So, each tool may see +different values for the arguments added by the :linerange suboption. """ from __future__ import absolute_import @@ -100,10 +118,16 @@ configitem = registrar.configitem(configtable) # Register the suboptions allowed for each configured fixer. -FIXER_ATTRS = ('command', 'linerange', 'fileset', 'pattern') +FIXER_ATTRS = { +'command': None, +'linerange': None, +'fileset': None, +'pattern': None, +'priority': 0, +} -for key in FIXER_ATTRS: -configitem('fix', '.*(:%s)?' % key, default=None, generic=True) +for key, default in FIXER_ATTRS.items(): +configitem('fix', '.*(:%s)?' % key, default=default, generic=True) # A good default size allows most source code files to be fixed, but avoids # letting fixer tools choke on huge inputs, which could be surprising to the @@ -602,18 +626,20 @@ Each value is a Fixer object with methods that implement the behavior of the fixer's config suboptions. Does not validate the config values. """ -result = {} +fixers = {} for name in fixernames(ui): -result[name] = Fixer() +
mercurial@40493: 20 new changesets
20 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/2891ee3fcb86 changeset: 40474:2891ee3fcb86 parent: 40471:844a40687d83 user:Yuya Nishihara date:Fri Oct 26 21:28:20 2018 +0900 summary: templatekw: extract internal "{rev}:{node|formatnode}" template to constant https://www.mercurial-scm.org/repo/hg/rev/8fa26f3baf30 changeset: 40475:8fa26f3baf30 user:Yuya Nishihara date:Fri Oct 19 21:11:30 2018 +0900 summary: templater: add wrapper for a single template mapping https://www.mercurial-scm.org/repo/hg/rev/539efc88513b changeset: 40476:539efc88513b user:Yuya Nishihara date:Fri Oct 26 21:43:20 2018 +0900 summary: templatekw: add p1/p2 keywords which switches the current ctx https://www.mercurial-scm.org/repo/hg/rev/592feb3f88b1 changeset: 40477:592feb3f88b1 user:Yuya Nishihara date:Fri Oct 26 21:46:37 2018 +0900 summary: templatekw: deprecate p1rev/p2rev/p1node/p2node in favor of p1/p2 https://www.mercurial-scm.org/repo/hg/rev/86dfae98a3a2 changeset: 40478:86dfae98a3a2 user:Kyle Lippincott date:Sat Oct 13 07:49:20 2018 -0700 summary: merge-tools: when calling external merge tool, describe the resolve inputs https://www.mercurial-scm.org/repo/hg/rev/176c26a21123 changeset: 40479:176c26a21123 user:Augie Fackler date:Thu Nov 01 15:47:26 2018 -0400 summary: tests: add a critical flush() to run-tests.py to make output stable on py3 https://www.mercurial-scm.org/repo/hg/rev/99d5424eedc8 changeset: 40480:99d5424eedc8 user:Augie Fackler date:Thu Nov 01 15:43:43 2018 -0400 summary: contrib: fix import-checker to not b'' module names on Python 3 https://www.mercurial-scm.org/repo/hg/rev/90517fad4293 changeset: 40481:90517fad4293 user:Augie Fackler date:Thu Nov 01 15:58:01 2018 -0400 summary: contrib: tweak import-checker to always use bytes for module names https://www.mercurial-scm.org/repo/hg/rev/07b87ee2ea75 changeset: 40482:07b87ee2ea75 user:Augie Fackler date:Thu Nov 01 16:13:01 2018 -0400 summary: tests: skip wireproto clientreactor tests on Python 3.6.0-3.6.3 inclusive https://www.mercurial-scm.org/repo/hg/rev/4e6ffcb5b9fc changeset: 40483:4e6ffcb5b9fc user:Augie Fackler date:Thu Nov 01 17:09:55 2018 -0400 summary: tests: add some helpful `|| cat` bits to test-profile.t https://www.mercurial-scm.org/repo/hg/rev/93501a5fd62b changeset: 40484:93501a5fd62b user:Augie Fackler date:Thu Nov 01 17:11:31 2018 -0400 summary: statprof: add a couple of asserts to avoid storing unicodes https://www.mercurial-scm.org/repo/hg/rev/8664fdc1cfb3 changeset: 40485:8664fdc1cfb3 user:Augie Fackler date:Thu Nov 01 17:12:22 2018 -0400 summary: statprof: clean up unicode/bytes a little https://www.mercurial-scm.org/repo/hg/rev/ff37b1712fa5 changeset: 40486:ff37b1712fa5 user:Matt Harbison date:Sat Nov 03 20:50:04 2018 -0400 summary: tests: conditonalize a difference in test-merge-tools.t on Windows https://www.mercurial-scm.org/repo/hg/rev/78e5b9d815fa changeset: 40487:78e5b9d815fa user:Sangeet Kumar Mishra date:Sat Nov 03 23:24:15 2018 +0530 summary: test: fix self._testdir to use the right mercurial library during testing https://www.mercurial-scm.org/repo/hg/rev/d95358143ce6 changeset: 40488:d95358143ce6 user:Kyle Lippincott date:Thu Nov 01 16:44:32 2018 -0700 summary: catapult: fix broken run-tests catapult tracing https://www.mercurial-scm.org/repo/hg/rev/a9e00c48c5ef changeset: 40489:a9e00c48c5ef user:Kyle Lippincott date:Thu Nov 01 16:44:37 2018 -0700 summary: catapult: rename 'active' to 'activetrace'; this isn't storing a boolean state https://www.mercurial-scm.org/repo/hg/rev/889424be7ad2 changeset: 40490:889424be7ad2 user:Kyle Lippincott date:Thu Nov 01 16:44:02 2018 -0700 summary: catapult: introduce HGTESTCATAPULTSERVERPIPE to control run-tests' tracing https://www.mercurial-scm.org/repo/hg/rev/c311424ea579 changeset: 40491:c311424ea579 user:Kyle Lippincott date:Thu Nov 01 16:51:21 2018 -0700 summary: catapult: add a bit more documentation on how to use catapult tracing https://www.mercurial-scm.org/repo/hg/rev/440f5b65be57 changeset: 40492:440f5b65be57 user:Pulkit Goyal date:Tue Oct 16 17:53:26 2018 +0300 summary: exchange: pass includepats and excludepats as arguments to getbundle() https://www.mercurial-scm.org/repo/hg/rev/a2c4502e409b changeset: 40493:a2c4502e409b bookmark:@ tag: tip user:Pulkit Goyal date:Wed Oct 17 17:24:55 2018 +0300 summary: narrow: only send includepats and excludepats if they are not empty -- Repository URL: https://www.mercurial-scm.org/repo/hg
[Bug 6021] New: fastannotate doesn't work on hgweb
https://bz.mercurial-scm.org/show_bug.cgi?id=6021 Bug ID: 6021 Summary: fastannotate doesn't work on hgweb Product: Mercurial Version: 4.8 Hardware: All OS: All Status: UNCONFIRMED Severity: bug Priority: normal Component: Mercurial Assignee: bugzi...@mercurial-scm.org Reporter: gregory.sz...@gmail.com CC: mercurial-devel@mercurial-scm.org The monkeypatch of hgweb.webutil.annotate in support.py:_hgwebannotate() accepts the wrong number of arguments, leading to a crash at runtime if you enable the "hgweb" mode of fastannotate. In addition, the first line of _hgwebanntoate() should be calling webutil.difffeatureopts() to resolve diff options. In related news, it appears we have 0 test coverage of the fastannotate hgweb feature :/ -- You are receiving this mail because: You are on the CC list for the bug. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5236: py3: ratchet caught two more passing tests
durin42 created this revision. Herald added a reviewer: pulkit. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5236 AFFECTED FILES contrib/python3-whitelist CHANGE DETAILS diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist --- a/contrib/python3-whitelist +++ b/contrib/python3-whitelist @@ -193,6 +193,7 @@ test-export.t test-extdata.t test-extdiff.t +test-extension-timing.t test-extensions-afterloaded.t test-extensions-wrapfunction.py test-extra-filelog-entry.t @@ -217,6 +218,7 @@ test-graft.t test-grep.t test-hardlinks.t +test-help-hide.t test-help.t test-hg-parseurl.py test-hghave.t To: durin42, pulkit, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5224: revlog: check if PyInt_AS_LONG failed before using result
durin42 added a comment. In https://phab.mercurial-scm.org/D5224#78093, @yuja wrote: > > In this case, I suspect something really weird because `PyInt_AS_LONG()` doesn't exist on Python 3 and the docs for Python 2 say it performs no error checking. So the fact that it is setting an exception on Python 3 causes me to raise an eyebrow. > > It's `#define PyLong_AS_LONG(op) PyLong_AsLong(op)`, sigh. And the reason > of the lack of `PyLong_AS_LONG(op)` would be that Python 3 has no bounded > integer type. > > + if (PyInt_Check(value)) { > + long arg = PyInt_AS_LONG(value); > > > In this case, we'll probably have to replace `PyInt_Check() + PyInt_AS_LONG()` > with `PyInt_AsLong() + PyErr_Occurred()`. Ugh, good catch. How about this: https://phab.mercurial-scm.org/D5235 I'm not super in love with it, but it feels somewhat better encapsulated this way. Seems to work right on both versions... REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5224 To: durin42, #hg-reviewers, indygreg Cc: yuja, indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5235: revlog: replace PyInt_AS_LONG with a more portable helper function
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY PyInt_AS_LONG disappears on Python, and our previous #define was producing some problems on Python 3. Let's give up and make an inline helper function that makes this more sane. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5235 AFFECTED FILES mercurial/cext/revlog.c mercurial/cext/util.h CHANGE DETAILS diff --git a/mercurial/cext/util.h b/mercurial/cext/util.h --- a/mercurial/cext/util.h +++ b/mercurial/cext/util.h @@ -58,4 +58,12 @@ return _PyDict_NewPresized(((1 + expected_size) / 2) * 3); } +/* Convert a PyInt or PyLong to a long. Returns false if there is an + error, in which case an exception will already have been set. */ +static inline bool pylong_to_long(PyObject *pylong, long *out) +{ + *out = PyLong_AsLong(pylong); + return PyErr_Occurred() == NULL; +} + #endif /* _HG_UTIL_H_ */ diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -24,7 +24,6 @@ #define PyInt_Check PyLong_Check #define PyInt_FromLong PyLong_FromLong #define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_AS_LONG PyLong_AS_LONG #define PyInt_AsLong PyLong_AsLong #endif @@ -161,10 +160,17 @@ int maxrev) { if (rev >= self->length) { + long tmp; PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); - ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); - ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6)); + if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 5), )) { + return -1; + } + ps[0] = (int)tmp; + if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 6), )) { + return -1; + } + ps[1] = (int)tmp; } else { const char *data = index_deref(self, rev); ps[0] = getbe32(data + 24); @@ -464,7 +470,9 @@ if (iter == NULL) return -2; while ((iter_item = PyIter_Next(iter))) { - iter_item_long = PyInt_AS_LONG(iter_item); + if (!pylong_to_long(iter_item, _item_long)) { + return -1; + } Py_DECREF(iter_item); if (iter_item_long < min_idx) min_idx = iter_item_long; @@ -853,7 +861,11 @@ if (rev >= self->length) { PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); - return (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 3)); + long ret; + if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 3), )) { + return -2; + } + return (int)ret; } else { data = index_deref(self, rev); if (data == NULL) { @@ -1384,8 +1396,13 @@ char *node; int rev; - if (PyInt_Check(value)) - return index_get(self, PyInt_AS_LONG(value)); + if (PyInt_Check(value)) { + long idx; + if (!pylong_to_long(value, )) { + return NULL; + } + return index_get(self, idx); + } if (node_check(value, ) == -1) return NULL; @@ -1516,7 +1533,10 @@ char *node; if (PyInt_Check(value)) { - long rev = PyInt_AS_LONG(value); + long rev; + if (!pylong_to_long(value, )) { + return -1; + } return rev >= -1 && rev < index_length(self); } @@ -2404,10 +2424,11 @@ static int rustla_contains(rustlazyancestorsObject *self, PyObject *rev) { - if (!(PyInt_Check(rev))) { + long lrev; + if (!pylong_to_long(rev, )) { return 0; } - return rustlazyancestors_contains(self->iter, PyInt_AS_LONG(rev)); + return rustlazyancestors_contains(self->iter, lrev); } static PySequenceMethods rustla_sequence_methods = { To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5234: revlog: give formatting to clang-format
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This has two lines that are poorly formatted, both right after PyObject_HEAD macros. It's possible that in the future there will be a feature to tell clang-format that a token includes an end-of-line character (in this case the ;), but for now I'm willing to live with two poorly-formatted lines in a struct definition in exchange for not thinking about how this file is formatted. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5234 AFFECTED FILES contrib/clang-format-ignorelist mercurial/cext/revlog.c CHANGE DETAILS diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -44,15 +44,15 @@ typedef struct { indexObject *index; nodetreenode *nodes; - unsigned length; /* # nodes in use */ - unsigned capacity; /* # nodes allocated */ - int depth; /* maximum depth of tree */ - int splits; /* # splits performed */ + unsigned length; /* # nodes in use */ + unsigned capacity; /* # nodes allocated */ + int depth; /* maximum depth of tree */ + int splits;/* # splits performed */ } nodetree; typedef struct { PyObject_HEAD /* ; */ - nodetree nt; + nodetree nt; } nodetreeObject; /* @@ -69,21 +69,21 @@ */ struct indexObjectStruct { PyObject_HEAD - /* Type-specific fields go here. */ - PyObject *data;/* raw bytes of index */ - Py_buffer buf; /* buffer of data */ - PyObject **cache; /* cached tuples */ - const char **offsets; /* populated on demand */ - Py_ssize_t raw_length; /* original number of elements */ - Py_ssize_t length; /* current number of elements */ - PyObject *added; /* populated on demand */ - PyObject *headrevs;/* cache, invalidated on changes */ - PyObject *filteredrevs;/* filtered revs set */ - nodetree nt; /* base-16 trie */ - int ntinitialized; /* 0 or 1 */ - int ntrev; /* last rev scanned */ - int ntlookups; /* # lookups */ - int ntmisses; /* # lookups that miss the cache */ + /* Type-specific fields go here. */ + PyObject *data; /* raw bytes of index */ + Py_buffer buf; /* buffer of data */ + PyObject **cache; /* cached tuples */ + const char **offsets; /* populated on demand */ + Py_ssize_t raw_length; /* original number of elements */ + Py_ssize_t length; /* current number of elements */ + PyObject *added;/* populated on demand */ + PyObject *headrevs; /* cache, invalidated on changes */ + PyObject *filteredrevs; /* filtered revs set */ + nodetree nt;/* base-16 trie */ + int ntinitialized; /* 0 or 1 */ + int ntrev; /* last rev scanned */ + int ntlookups; /* # lookups */ + int ntmisses; /* # lookups that miss the cache */ int inlined; }; @@ -126,7 +126,7 @@ errclass = PyDict_GetItemString(dict, "RevlogError"); if (errclass == NULL) { PyErr_SetString(PyExc_SystemError, - "could not find RevlogError"); + "could not find RevlogError"); goto cleanup; } @@ -146,7 +146,7 @@ if (self->inlined && pos > 0) { if (self->offsets == NULL) { self->offsets = PyMem_Malloc(self->raw_length * -sizeof(*self->offsets)); +sizeof(*self->offsets)); if (self->offsets == NULL) return (const char *)PyErr_NoMemory(); inline_scan(self, self->offsets); @@ -157,11 +157,12 @@ return (const char *)(self->buf.buf) + pos * v1_hdrsize; } -static inline int index_get_parents(indexObject *self, Py_ssize_t rev, - int *ps, int maxrev) +static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps, +int maxrev) { if (rev >= self->length) { - PyObject *tuple = PyList_GET_ITEM(self->added, rev - self->length); + PyObject *tuple = + PyList_GET_ITEM(self->added, rev - self->length); ps[0] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 5)); ps[1] = (int)PyInt_AS_LONG(PyTuple_GET_ITEM(tuple, 6)); } else { @@ -178,7 +179,6 @@ return 0; } - /* * RevlogNG format (all in big endian, data may be inlined): *6 bytes: offset @@ -248,9 +248,9 @@
D5233: revlog: add blank line in comment to help clang-format
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5233 AFFECTED FILES mercurial/cext/revlog.c CHANGE DETAILS diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -508,6 +508,7 @@ /* Internal data structure: * tovisit: array of length len+1 (all revs + nullrev), filled upto lentovisit +* * revstates: array of length len+1 (all revs + nullrev) */ int *tovisit = NULL; long lentovisit = 0; To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5232: revlog: add a comment to help clang-format produce less-awful results
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5232 AFFECTED FILES mercurial/cext/revlog.c CHANGE DETAILS diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -51,7 +51,7 @@ } nodetree; typedef struct { - PyObject_HEAD + PyObject_HEAD /* ; */ nodetree nt; } nodetreeObject; To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5230: remotefilelog: fix various whitespace issues in docstring
This revision was automatically updated to reflect the committed changes. Closed by commit rHG040447dc3c62: remotefilelog: fix various whitespace issues in docstring (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5230?vs=12451=12453 REVISION DETAIL https://phab.mercurial-scm.org/D5230 AFFECTED FILES hgext/remotefilelog/__init__.py CHANGE DETAILS diff --git a/hgext/remotefilelog/__init__.py b/hgext/remotefilelog/__init__.py --- a/hgext/remotefilelog/__init__.py +++ b/hgext/remotefilelog/__init__.py @@ -20,70 +20,106 @@ Configs: ``packs.maxchainlen`` specifies the maximum delta chain length in pack files + ``packs.maxpacksize`` specifies the maximum pack file size + ``packs.maxpackfilecount`` specifies the maximum number of packs in the shared cache (trees only for now) + ``remotefilelog.backgroundprefetch`` runs prefetch in background when True + ``remotefilelog.bgprefetchrevs`` specifies revisions to fetch on commit and update, and on other commands that use them. Different from pullprefetch. + ``remotefilelog.gcrepack`` does garbage collection during repack when True + ``remotefilelog.nodettl`` specifies maximum TTL of a node in seconds before it is garbage collected + ``remotefilelog.repackonhggc`` runs repack on hg gc when True + ``remotefilelog.prefetchdays`` specifies the maximum age of a commit in days after which it is no longer prefetched. + ``remotefilelog.prefetchdelay`` specifies delay between background prefetches in seconds after operations that change the working copy parent + ``remotefilelog.data.gencountlimit`` constraints the minimum number of data pack files required to be considered part of a generation. In particular, minimum number of packs files > gencountlimit. + ``remotefilelog.data.generations`` list for specifying the lower bound of each generation of the data pack files. For example, list ['100MB','1MB'] or ['1MB', '100MB'] will lead to three generations: [0, 1MB), [ 1MB, 100MB) and [100MB, infinity). + ``remotefilelog.data.maxrepackpacks`` the maximum number of pack files to include in an incremental data repack. + ``remotefilelog.data.repackmaxpacksize`` the maximum size of a pack file for it to be considered for an incremental data repack. + ``remotefilelog.data.repacksizelimit`` the maximum total size of pack files to include in an incremental data repack. + ``remotefilelog.history.gencountlimit`` constraints the minimum number of history pack files required to be considered part of a generation. In particular, minimum number of packs files > gencountlimit. + ``remotefilelog.history.generations`` list for specifying the lower bound of each generation of the historhy pack files. For example, list [ '100MB', '1MB'] or ['1MB', '100MB'] will lead to three generations: [ 0, 1MB), [1MB, 100MB) and [100MB, infinity). + ``remotefilelog.history.maxrepackpacks`` the maximum number of pack files to include in an incremental history repack. + ``remotefilelog.history.repackmaxpacksize`` the maximum size of a pack file for it to be considered for an incremental history repack. + ``remotefilelog.history.repacksizelimit`` the maximum total size of pack files to include in an incremental history repack. + ``remotefilelog.backgroundrepack`` automatically consolidate packs in the background + ``remotefilelog.cachepath`` path to cache + ``remotefilelog.cachegroup`` if set, make cache directory sgid to this group + ``remotefilelog.cacheprocess`` binary to invoke for fetching file data + ``remotefilelog.debug`` turn on remotefilelog-specific debug output + ``remotefilelog.excludepattern`` pattern of files to exclude from pulls -``remotefilelog.includepattern``pattern of files to include in pulls + +``remotefilelog.includepattern`` pattern of files to include in pulls + ``remotefilelog.fetchwarning``: message to print when too many single-file fetches occur + ``remotefilelog.getfilesstep`` number of files to request in a single RPC + ``remotefilelog.getfilestype`` if set to 'threaded' use threads to fetch files, otherwise use optimistic fetching + ``remotefilelog.pullprefetch`` revset for selecting files that should be eagerly downloaded rather than lazily + ``remotefilelog.reponame`` name of the repo. If set, used to partition data from other repos in a shared store. + ``remotefilelog.server`` if true, enable server-side functionality + ``remotefilelog.servercachepath`` path for caching blobs on the server + ``remotefilelog.serverexpiration`` number of days to keep cached server blobs + ``remotefilelog.validatecache`` if set,
D5231: tests: fix config knob in test-narrow-clone-stream.t
This revision was automatically updated to reflect the committed changes. Closed by commit rHGd6ec45b79277: tests: fix config knob in test-narrow-clone-stream.t (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5231?vs=12452=12454 REVISION DETAIL https://phab.mercurial-scm.org/D5231 AFFECTED FILES tests/test-narrow-clone-stream.t CHANGE DETAILS diff --git a/tests/test-narrow-clone-stream.t b/tests/test-narrow-clone-stream.t --- a/tests/test-narrow-clone-stream.t +++ b/tests/test-narrow-clone-stream.t @@ -36,8 +36,8 @@ Enable stream clone on the server - $ echo "[experimental.server]" >> master/.hg/hgrc - $ echo "stream-narrow-clones=True" >> master/.hg/hgrc + $ echo "[experimental]" >> master/.hg/hgrc + $ echo "server.stream-narrow-clones=True" >> master/.hg/hgrc Cloning a specific file when stream clone is supported To: durin42, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5231: tests: fix config knobb in test-narrow-clone-stream.t
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Two patches landed in parallel and had a semantic conflict. This resolves the mess and leaves us with passing tests. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5231 AFFECTED FILES tests/test-narrow-clone-stream.t CHANGE DETAILS diff --git a/tests/test-narrow-clone-stream.t b/tests/test-narrow-clone-stream.t --- a/tests/test-narrow-clone-stream.t +++ b/tests/test-narrow-clone-stream.t @@ -36,8 +36,8 @@ Enable stream clone on the server - $ echo "[experimental.server]" >> master/.hg/hgrc - $ echo "stream-narrow-clones=True" >> master/.hg/hgrc + $ echo "[experimental]" >> master/.hg/hgrc + $ echo "server.stream-narrow-clones=True" >> master/.hg/hgrc Cloning a specific file when stream clone is supported To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5230: remotefilelog: fix various whitespace issues in docstring
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5230 AFFECTED FILES hgext/remotefilelog/__init__.py CHANGE DETAILS diff --git a/hgext/remotefilelog/__init__.py b/hgext/remotefilelog/__init__.py --- a/hgext/remotefilelog/__init__.py +++ b/hgext/remotefilelog/__init__.py @@ -20,70 +20,106 @@ Configs: ``packs.maxchainlen`` specifies the maximum delta chain length in pack files + ``packs.maxpacksize`` specifies the maximum pack file size + ``packs.maxpackfilecount`` specifies the maximum number of packs in the shared cache (trees only for now) + ``remotefilelog.backgroundprefetch`` runs prefetch in background when True + ``remotefilelog.bgprefetchrevs`` specifies revisions to fetch on commit and update, and on other commands that use them. Different from pullprefetch. + ``remotefilelog.gcrepack`` does garbage collection during repack when True + ``remotefilelog.nodettl`` specifies maximum TTL of a node in seconds before it is garbage collected + ``remotefilelog.repackonhggc`` runs repack on hg gc when True + ``remotefilelog.prefetchdays`` specifies the maximum age of a commit in days after which it is no longer prefetched. + ``remotefilelog.prefetchdelay`` specifies delay between background prefetches in seconds after operations that change the working copy parent + ``remotefilelog.data.gencountlimit`` constraints the minimum number of data pack files required to be considered part of a generation. In particular, minimum number of packs files > gencountlimit. + ``remotefilelog.data.generations`` list for specifying the lower bound of each generation of the data pack files. For example, list ['100MB','1MB'] or ['1MB', '100MB'] will lead to three generations: [0, 1MB), [ 1MB, 100MB) and [100MB, infinity). + ``remotefilelog.data.maxrepackpacks`` the maximum number of pack files to include in an incremental data repack. + ``remotefilelog.data.repackmaxpacksize`` the maximum size of a pack file for it to be considered for an incremental data repack. + ``remotefilelog.data.repacksizelimit`` the maximum total size of pack files to include in an incremental data repack. + ``remotefilelog.history.gencountlimit`` constraints the minimum number of history pack files required to be considered part of a generation. In particular, minimum number of packs files > gencountlimit. + ``remotefilelog.history.generations`` list for specifying the lower bound of each generation of the historhy pack files. For example, list [ '100MB', '1MB'] or ['1MB', '100MB'] will lead to three generations: [ 0, 1MB), [1MB, 100MB) and [100MB, infinity). + ``remotefilelog.history.maxrepackpacks`` the maximum number of pack files to include in an incremental history repack. + ``remotefilelog.history.repackmaxpacksize`` the maximum size of a pack file for it to be considered for an incremental history repack. + ``remotefilelog.history.repacksizelimit`` the maximum total size of pack files to include in an incremental history repack. + ``remotefilelog.backgroundrepack`` automatically consolidate packs in the background + ``remotefilelog.cachepath`` path to cache + ``remotefilelog.cachegroup`` if set, make cache directory sgid to this group + ``remotefilelog.cacheprocess`` binary to invoke for fetching file data + ``remotefilelog.debug`` turn on remotefilelog-specific debug output + ``remotefilelog.excludepattern`` pattern of files to exclude from pulls -``remotefilelog.includepattern``pattern of files to include in pulls + +``remotefilelog.includepattern`` pattern of files to include in pulls + ``remotefilelog.fetchwarning``: message to print when too many single-file fetches occur + ``remotefilelog.getfilesstep`` number of files to request in a single RPC + ``remotefilelog.getfilestype`` if set to 'threaded' use threads to fetch files, otherwise use optimistic fetching + ``remotefilelog.pullprefetch`` revset for selecting files that should be eagerly downloaded rather than lazily + ``remotefilelog.reponame`` name of the repo. If set, used to partition data from other repos in a shared store. + ``remotefilelog.server`` if true, enable server-side functionality + ``remotefilelog.servercachepath`` path for caching blobs on the server + ``remotefilelog.serverexpiration`` number of days to keep cached server blobs + ``remotefilelog.validatecache`` if set, check cache entries for corruption before returning blobs + ``remotefilelog.validatecachelog`` if set, check cache entries for corruption before returning
Re: [PATCH 7 of 7] ui: add config knob to redirect status messages to stderr (API)
> On Nov 6, 2018, at 09:21, Yuya Nishihara wrote: > > # HG changeset patch > # User Yuya Nishihara > # Date 1541241770 -32400 > # Sat Nov 03 19:42:50 2018 +0900 > # Node ID e58976bff0817c9a61e3a7511b19e9bcadbf7be3 > # Parent 6e2134679a54abbbc686df205d721bd69740c33c > ui: add config knob to redirect status messages to stderr (API) queued these, thanks ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 7] ui: add config knob to redirect status messages to stderr (API)
# HG changeset patch # User Yuya Nishihara # Date 1541241770 -32400 # Sat Nov 03 19:42:50 2018 +0900 # Node ID e58976bff0817c9a61e3a7511b19e9bcadbf7be3 # Parent 6e2134679a54abbbc686df205d721bd69740c33c ui: add config knob to redirect status messages to stderr (API) This option can be used to isolate structured output from status messages. For now, "stdio" (stdout/err pair) and "stderr" are supported. In future patches, I'll add the "channel" option which will send status messages to a separate command-server channel with some metadata attached, maybe in CBOR encoding. This is a part of the generic templating plan: https://www.mercurial-scm.org/wiki/GenericTemplatingPlan#Sanity_check_output .. api:: Status messages may be sent to a dedicated stream depending on configuration. Don't use ``ui.status()``, etc. as a shorthand for conditional writes. Use ``ui.write()`` for data output. diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -1181,6 +1181,9 @@ coreconfigitem('ui', 'mergemarkertemplat '{ifeq(branch, "default", "", "{branch} ")}' '- {author|user}: {desc|firstline}') ) +coreconfigitem('ui', 'message-output', +default='stdio', +) coreconfigitem('ui', 'nontty', default=False, ) diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -2246,6 +2246,14 @@ User interface controls. Can be overridden per-merge-tool, see the ``[merge-tools]`` section. +``message-output`` +Where to write status and error messages. (default: ``stdio``) + +``stderr`` + Everything to stderr. +``stdio`` + Status to stdout, and error to stderr. + ``origbackuppath`` The path to a directory used to store generated .orig files. If the path is not a directory, one will be created. If set, files stored in this diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -234,6 +234,8 @@ class ui(object): self._fout = src._fout self._ferr = src._ferr self._fin = src._fin +self._fmsgout = src._fmsgout +self._fmsgerr = src._fmsgerr self._finoutredirected = src._finoutredirected self.pageractive = src.pageractive self._disablepager = src._disablepager @@ -259,6 +261,8 @@ class ui(object): self._fout = procutil.stdout self._ferr = procutil.stderr self._fin = procutil.stdin +self._fmsgout = self.fout # configurable +self._fmsgerr = self.ferr # configurable self._finoutredirected = False self.pageractive = False self._disablepager = False @@ -416,7 +420,7 @@ class ui(object): if self.plain(): for k in ('debug', 'fallbackencoding', 'quiet', 'slash', - 'logtemplate', 'statuscopies', 'style', + 'logtemplate', 'message-output', 'statuscopies', 'style', 'traceback', 'verbose'): if k in cfg['ui']: del cfg['ui'][k] @@ -469,6 +473,7 @@ class ui(object): if section in (None, 'ui'): # update ui options +self._fmsgout, self._fmsgerr = _selectmsgdests(self) self.debugflag = self.configbool('ui', 'debug') self.verbose = self.debugflag or self.configbool('ui', 'verbose') self.quiet = not self.debugflag and self.configbool('ui', 'quiet') @@ -891,6 +896,7 @@ class ui(object): @fout.setter def fout(self, f): self._fout = f +self._fmsgout, self._fmsgerr = _selectmsgdests(self) @property def ferr(self): @@ -899,6 +905,7 @@ class ui(object): @ferr.setter def ferr(self, f): self._ferr = f +self._fmsgout, self._fmsgerr = _selectmsgdests(self) @property def fin(self): @@ -1364,17 +1371,18 @@ class ui(object): If ui is not interactive, the default is returned. """ if not self.interactive(): -self.write(msg, ' ', label='ui.prompt') -self.write(default or '', "\n", label='ui.promptecho') +self._write(self._fmsgout, msg, ' ', label='ui.prompt') +self._write(self._fmsgout, default or '', "\n", +label='ui.promptecho') return default -self._writenobuf(self._fout, msg, label='ui.prompt') +self._writenobuf(self._fmsgout, msg, label='ui.prompt') self.flush() try: r = self._readline() if not r: r = default if self.configbool('ui', 'promptecho'): -self.write(r, "\n", label='ui.promptecho') +self._write(self._fmsgout, r, "\n", label='ui.promptecho') return r except
[PATCH 6 of 7] ui: hide fin/fout/ferr attributes behind @property functions
# HG changeset patch # User Yuya Nishihara # Date 1541246011 -32400 # Sat Nov 03 20:53:31 2018 +0900 # Node ID 6e2134679a54abbbc686df205d721bd69740c33c # Parent 81e0f45f2a46571e7e3946c39f4617ba9b7bb26b ui: hide fin/fout/ferr attributes behind @property functions This allows keeping references to fout/ferr/fin which are updated when these properties are changed. See the next patch. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -231,9 +231,9 @@ class ui(object): self._uninterruptible = False if src: -self.fout = src.fout -self.ferr = src.ferr -self.fin = src.fin +self._fout = src._fout +self._ferr = src._ferr +self._fin = src._fin self._finoutredirected = src._finoutredirected self.pageractive = src.pageractive self._disablepager = src._disablepager @@ -256,9 +256,9 @@ class ui(object): self.httppasswordmgrdb = src.httppasswordmgrdb self._blockedtimes = src._blockedtimes else: -self.fout = procutil.stdout -self.ferr = procutil.stderr -self.fin = procutil.stdin +self._fout = procutil.stdout +self._ferr = procutil.stderr +self._fin = procutil.stdin self._finoutredirected = False self.pageractive = False self._disablepager = False @@ -884,6 +884,30 @@ class ui(object): def paths(self): return paths(self) +@property +def fout(self): +return self._fout + +@fout.setter +def fout(self, f): +self._fout = f + +@property +def ferr(self): +return self._ferr + +@ferr.setter +def ferr(self, f): +self._ferr = f + +@property +def fin(self): +return self._fin + +@fin.setter +def fin(self, f): +self._fin = f + def pushbuffer(self, error=False, subproc=False, labeled=False): """install a buffer to capture standard output of the ui object @@ -914,9 +938,9 @@ class ui(object): return "".join(self._buffers.pop()) def _isbuffered(self, dest): -if dest is self.fout: +if dest is self._fout: return bool(self._buffers) -if dest is self.ferr: +if dest is self._ferr: return bool(self._bufferstates and self._bufferstates[-1][0]) return False @@ -947,10 +971,10 @@ class ui(object): "cmdname.type" is recommended. For example, status issues a label of "status.modified" for modified files. ''' -self._write(self.fout, *args, **opts) +self._write(self._fout, *args, **opts) def write_err(self, *args, **opts): -self._write(self.ferr, *args, **opts) +self._write(self._ferr, *args, **opts) def _write(self, dest, *args, **opts): if self._isbuffered(dest): @@ -969,8 +993,8 @@ class ui(object): # opencode timeblockedsection because this is a critical path starttime = util.timer() try: -if dest is self.ferr and not getattr(self.fout, 'closed', False): -self.fout.flush() +if dest is self._ferr and not getattr(self._fout, 'closed', False): +self._fout.flush() if self._colormode == 'win32': # windows color printing is its own can of crab, defer to # the color module and that is it. @@ -982,10 +1006,10 @@ class ui(object): dest.write(msg) # stderr may be buffered under win32 when redirected to files, # including stdout. -if dest is self.ferr and not getattr(self.ferr, 'closed', False): +if dest is self._ferr and not getattr(self._ferr, 'closed', False): dest.flush() except IOError as err: -if (dest is self.ferr +if (dest is self._ferr and err.errno in (errno.EPIPE, errno.EIO, errno.EBADF)): # no way to report the error, so ignore it return @@ -999,13 +1023,13 @@ class ui(object): starttime = util.timer() try: try: -self.fout.flush() +self._fout.flush() except IOError as err: if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): raise error.StdioError(err) finally: try: -self.ferr.flush() +self._ferr.flush() except IOError as err: if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): raise error.StdioError(err) @@ -1255,7 +1279,7 @@ class ui(object): if i is None: # some environments replace stdin without implementing isatty # usually those are
[PATCH 5 of 7] ui: label prompt and echo messages
# HG changeset patch # User Yuya Nishihara # Date 1421570573 -32400 # Sun Jan 18 17:42:53 2015 +0900 # Node ID 81e0f45f2a46571e7e3946c39f4617ba9b7bb26b # Parent 5b469a4ae6a18816801259a0a4899e2739179f4a ui: label prompt and echo messages I'm going to add a dedicated command-server channel for status messages, which carries metadata alongside a message text. 'ui.*' label provides a hint how message text should be processed. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -1340,7 +1340,8 @@ class ui(object): If ui is not interactive, the default is returned. """ if not self.interactive(): -self.write(msg, ' ', default or '', "\n") +self.write(msg, ' ', label='ui.prompt') +self.write(default or '', "\n", label='ui.promptecho') return default self._writenobuf(self.fout, msg, label='ui.prompt') self.flush() @@ -1349,7 +1350,7 @@ class ui(object): if not r: r = default if self.configbool('ui', 'promptecho'): -self.write(r, "\n") +self.write(r, "\n", label='ui.promptecho') return r except EOFError: raise error.ResponseExpected() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 7] ui: add inner function to select write destination
# HG changeset patch # User Yuya Nishihara # Date 1541236650 -32400 # Sat Nov 03 18:17:30 2018 +0900 # Node ID 5b469a4ae6a18816801259a0a4899e2739179f4a # Parent a4353cb008c9ca70dc347b6c151f9252ba30d82e ui: add inner function to select write destination I'm going to add a config knob to redirect any status messages to stderr. This function helps to switch underlying file objects. # no-check-commit because of existing write_err() function diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -913,6 +913,13 @@ class ui(object): return "".join(self._buffers.pop()) +def _isbuffered(self, dest): +if dest is self.fout: +return bool(self._buffers) +if dest is self.ferr: +return bool(self._bufferstates and self._bufferstates[-1][0]) +return False + def canwritewithoutlabels(self): '''check if write skips the label''' if self._buffers and not self._bufferapplylabels: @@ -940,14 +947,20 @@ class ui(object): "cmdname.type" is recommended. For example, status issues a label of "status.modified" for modified files. ''' -if self._buffers: +self._write(self.fout, *args, **opts) + +def write_err(self, *args, **opts): +self._write(self.ferr, *args, **opts) + +def _write(self, dest, *args, **opts): +if self._isbuffered(dest): if self._bufferapplylabels: label = opts.get(r'label', '') self._buffers[-1].extend(self.label(a, label) for a in args) else: self._buffers[-1].extend(args) else: -self._writenobuf(self.fout, *args, **opts) +self._writenobuf(dest, *args, **opts) def _writenobuf(self, dest, *args, **opts): self._progclear() @@ -981,12 +994,6 @@ class ui(object): self._blockedtimes['stdio_blocked'] += \ (util.timer() - starttime) * 1000 -def write_err(self, *args, **opts): -if self._bufferstates and self._bufferstates[-1][0]: -self.write(*args, **opts) -else: -self._writenobuf(self.ferr, *args, **opts) - def flush(self): # opencode timeblockedsection because this is a critical path starttime = util.timer() diff --git a/tests/test-rollback.t b/tests/test-rollback.t --- a/tests/test-rollback.t +++ b/tests/test-rollback.t @@ -278,11 +278,12 @@ I/O errors on stdio are handled properly > > def uisetup(ui): > class badui(ui.__class__): - > def write_err(self, *args, **kwargs): + > def _write(self, dest, *args, **kwargs): > olderr = self.ferr > try: - > self.ferr = fdproxy(self, olderr) - > return super(badui, self).write_err(*args, **kwargs) + > if dest is self.ferr: + > self.ferr = dest = fdproxy(self, olderr) + > return super(badui, self)._write(dest, *args, **kwargs) > finally: > self.ferr = olderr > ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 7] ui: remove _write() and _write_err() functions
# HG changeset patch # User Yuya Nishihara # Date 1541235862 -32400 # Sat Nov 03 18:04:22 2018 +0900 # Node ID a4353cb008c9ca70dc347b6c151f9252ba30d82e # Parent c90197c485ea4a9bf33259050ecbb0480f443003 ui: remove _write() and _write_err() functions diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -951,12 +951,6 @@ class ui(object): def _writenobuf(self, dest, *args, **opts): self._progclear() -if dest is self.fout: -write = self._write -elif dest is self.ferr: -write = self._write_err -else: -raise error.ProgrammingError('unsupported file to write') msg = b''.join(args) # opencode timeblockedsection because this is a critical path @@ -967,12 +961,12 @@ class ui(object): if self._colormode == 'win32': # windows color printing is its own can of crab, defer to # the color module and that is it. -color.win32print(self, write, msg, **opts) +color.win32print(self, dest.write, msg, **opts) else: if self._colormode is not None: label = opts.get(r'label', '') msg = self.label(msg, label) -write(msg) +dest.write(msg) # stderr may be buffered under win32 when redirected to files, # including stdout. if dest is self.ferr and not getattr(self.ferr, 'closed', False): @@ -987,18 +981,12 @@ class ui(object): self._blockedtimes['stdio_blocked'] += \ (util.timer() - starttime) * 1000 -def _write(self, data): -self.fout.write(data) - def write_err(self, *args, **opts): if self._bufferstates and self._bufferstates[-1][0]: self.write(*args, **opts) else: self._writenobuf(self.ferr, *args, **opts) -def _write_err(self, data): -self.ferr.write(data) - def flush(self): # opencode timeblockedsection because this is a critical path starttime = util.timer() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 7] ui: move pre/post processes from low-level write()s to _writenobuf()
# HG changeset patch # User Yuya Nishihara # Date 1541235789 -32400 # Sat Nov 03 18:03:09 2018 +0900 # Node ID c90197c485ea4a9bf33259050ecbb0480f443003 # Parent 678a5ecd68c74a760449b7c0297b93d98f1af429 ui: move pre/post processes from low-level write()s to _writenobuf() This helps adding a dedicated stream for status/error messages. I don't want to add _write*() function per stream. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -962,6 +962,8 @@ class ui(object): # opencode timeblockedsection because this is a critical path starttime = util.timer() try: +if dest is self.ferr and not getattr(self.fout, 'closed', False): +self.fout.flush() if self._colormode == 'win32': # windows color printing is its own can of crab, defer to # the color module and that is it. @@ -971,15 +973,22 @@ class ui(object): label = opts.get(r'label', '') msg = self.label(msg, label) write(msg) +# stderr may be buffered under win32 when redirected to files, +# including stdout. +if dest is self.ferr and not getattr(self.ferr, 'closed', False): +dest.flush() +except IOError as err: +if (dest is self.ferr +and err.errno in (errno.EPIPE, errno.EIO, errno.EBADF)): +# no way to report the error, so ignore it +return +raise error.StdioError(err) finally: self._blockedtimes['stdio_blocked'] += \ (util.timer() - starttime) * 1000 def _write(self, data): -try: -self.fout.write(data) -except IOError as err: -raise error.StdioError(err) +self.fout.write(data) def write_err(self, *args, **opts): if self._bufferstates and self._bufferstates[-1][0]: @@ -988,18 +997,7 @@ class ui(object): self._writenobuf(self.ferr, *args, **opts) def _write_err(self, data): -try: -if True: -if not getattr(self.fout, 'closed', False): -self.fout.flush() -self.ferr.write(data) -# stderr may be buffered under win32 when redirected to files, -# including stdout. -if not getattr(self.ferr, 'closed', False): -self.ferr.flush() -except IOError as inst: -if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): -raise error.StdioError(inst) +self.ferr.write(data) def flush(self): # opencode timeblockedsection because this is a critical path ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 7] ui: pass in file object to _writenobuf()
# HG changeset patch # User Yuya Nishihara # Date 1541235377 -32400 # Sat Nov 03 17:56:17 2018 +0900 # Node ID 678a5ecd68c74a760449b7c0297b93d98f1af429 # Parent cbd251d479bb67d77f9b77a017a22632af2f77da ui: pass in file object to _writenobuf() See the subsequent patches for why. The "if" block in _writenobuf() will be removed soon. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -947,10 +947,16 @@ class ui(object): else: self._buffers[-1].extend(args) else: -self._writenobuf(self._write, *args, **opts) +self._writenobuf(self.fout, *args, **opts) -def _writenobuf(self, write, *args, **opts): +def _writenobuf(self, dest, *args, **opts): self._progclear() +if dest is self.fout: +write = self._write +elif dest is self.ferr: +write = self._write_err +else: +raise error.ProgrammingError('unsupported file to write') msg = b''.join(args) # opencode timeblockedsection because this is a critical path @@ -979,7 +985,7 @@ class ui(object): if self._bufferstates and self._bufferstates[-1][0]: self.write(*args, **opts) else: -self._writenobuf(self._write_err, *args, **opts) +self._writenobuf(self.ferr, *args, **opts) def _write_err(self, data): try: @@ -1343,7 +1349,7 @@ class ui(object): if not self.interactive(): self.write(msg, ' ', default or '', "\n") return default -self._writenobuf(self._write, msg, label='ui.prompt') +self._writenobuf(self.fout, msg, label='ui.prompt') self.flush() try: r = self._readline() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@40473: new changeset (1 on stable)
New changeset (1 on stable) in mercurial: https://www.mercurial-scm.org/repo/hg/rev/8239d4e5d05f changeset: 40473:8239d4e5d05f branch: stable tag: tip user:Kyle Lippincott date:Mon Nov 05 15:01:45 2018 -0800 summary: tweakdefaults: remove commands.resolve.mark-check=abort, it is too broken -- Repository URL: https://www.mercurial-scm.org/repo/hg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5224: revlog: check if PyInt_AS_LONG failed before using result
yuja added a comment. > In this case, I suspect something really weird because `PyInt_AS_LONG()` doesn't exist on Python 3 and the docs for Python 2 say it performs no error checking. So the fact that it is setting an exception on Python 3 causes me to raise an eyebrow. It's `#define PyLong_AS_LONG(op) PyLong_AsLong(op)`, sigh. And the reason of the lack of `PyLong_AS_LONG(op)` would be that Python 3 has no bounded integer type. + if (PyInt_Check(value)) { + long arg = PyInt_AS_LONG(value); In this case, we'll probably have to replace `PyInt_Check() + PyInt_AS_LONG()` with `PyInt_AsLong() + PyErr_Occurred()`. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5224 To: durin42, #hg-reviewers, indygreg Cc: yuja, indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D5224: revlog: check if PyInt_AS_LONG failed before using result
> In this case, I suspect something really weird because `PyInt_AS_LONG()` > doesn't exist on Python 3 and the docs for Python 2 say it performs no error > checking. So the fact that it is setting an exception on Python 3 causes me > to raise an eyebrow. It's `#define PyLong_AS_LONG(op) PyLong_AsLong(op)`, sigh. And the reason of the lack of `PyLong_AS_LONG(op)` would be that Python 3 has no bounded integer type. ``` + if (PyInt_Check(value)) { + long arg = PyInt_AS_LONG(value); ``` In this case, we'll probably have to replace `PyInt_Check() + PyInt_AS_LONG()` with `PyInt_AsLong() + PyErr_Occurred()`. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D5227: pycompat: adding Linux detection and fixing Mac
On Tue, Nov 06, 2018 at 03:54:20AM +, rdamazio (Rodrigo Damazio Bovendorp) wrote: > REVISION SUMMARY > Python 3 recommends detecting OSs with the prefix of the platform, but we > were > comparing the full string for macOS. We also didn't have Linux detection, > which > is convenient for extensions to use (rather than have some OSs detected by > hg > and some by the extension). I'm actually quite against islinux. What reasons should *any* code have to test specifically for Linux and not a platform feature? Joerg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5228: perf: fix perfrevlogrevisions --reverse
This revision was automatically updated to reflect the committed changes. Closed by commit rHGcbd251d479bb: perf: fix perfrevlogrevisions --reverse (authored by lothiraldan, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5228?vs=12442=12450 REVISION DETAIL https://phab.mercurial-scm.org/D5228 AFFECTED FILES contrib/perf.py CHANGE DETAILS diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1553,7 +1553,7 @@ dist = opts[b'dist'] if reverse: -beginrev, endrev = endrev, beginrev +beginrev, endrev = endrev - 1, beginrev - 1 dist = -1 * dist for x in _xrange(beginrev, endrev, dist): To: lothiraldan, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5221: localrepo: extract loading of hgrc files to standalone function
This revision was automatically updated to reflect the committed changes. Closed by commit rHG473510bf0575: localrepo: extract loading of hgrc files to standalone function (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5221?vs=12430=12448 REVISION DETAIL https://phab.mercurial-scm.org/D5221 AFFECTED FILES mercurial/localrepo.py CHANGE DETAILS diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -451,14 +451,8 @@ # The .hg/hgrc file may load extensions or contain config options # that influence repository construction. Attempt to load it and # process any new extensions that it may have pulled in. -try: -ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base) -# Run this before extensions.loadall() so extensions can be -# automatically enabled. +if loadhgrc(ui, wdirvfs, hgvfs, requirements): afterhgrcload(ui, wdirvfs, hgvfs, requirements) -except IOError: -pass -else: extensions.loadall(ui) # Set of module names of extensions loaded for this repository. @@ -582,6 +576,24 @@ features=features, intents=intents) +def loadhgrc(ui, wdirvfs, hgvfs, requirements): +"""Load hgrc files/content into a ui instance. + +This is called during repository opening to load any additional +config files or settings relevant to the current repository. + +Returns a bool indicating whether any additional configs were loaded. + +Extensions should monkeypatch this function to modify how per-repo +configs are loaded. For example, an extension may wish to pull in +configs from alternate files or sources. +""" +try: +ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base) +return True +except IOError: +return False + def afterhgrcload(ui, wdirvfs, hgvfs, requirements): """Perform additional actions after .hg/hgrc is loaded. To: indygreg, #hg-reviewers Cc: lothiraldan, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5229: runbgcommand: import concerns about creationflags on Windows from D1701
This revision was automatically updated to reflect the committed changes. Closed by commit rHG1d3bed7d2923: procutil: import concerns about creationflags on Windows from D1701 (authored by lothiraldan, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5229?vs=12444=12449 REVISION DETAIL https://phab.mercurial-scm.org/D5229 AFFECTED FILES mercurial/utils/procutil.py CHANGE DETAILS diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -474,6 +474,9 @@ # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx # No stdlib constant exists for this value DETACHED_PROCESS = 0x0008 +# Following creation flags might create a console GUI window. +# Using subprocess.CREATE_NEW_CONSOLE might helps. +# See https://phab.mercurial-scm.org/D1701 for discussion _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP def runbgcommand(script, env, shell=False, stdout=None, stderr=None): To: lothiraldan, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5220: revsets: make bookmark/named('re:nonexistent') revset not abort (issue6018)
This revision was automatically updated to reflect the committed changes. Closed by commit rHG7ed611c60168: revsets: make bookmark/named(re:nonexistent) not abort (issue6018) (BC) (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5220?vs=12400=12447 REVISION DETAIL https://phab.mercurial-scm.org/D5220 AFFECTED FILES mercurial/revset.py tests/test-bookmarks.t tests/test-revset2.t CHANGE DETAILS diff --git a/tests/test-revset2.t b/tests/test-revset2.t --- a/tests/test-revset2.t +++ b/tests/test-revset2.t @@ -669,8 +669,6 @@ abort: namespace 'unknown' does not exist! [255] $ log 'named("re:unknown")' - abort: no namespace exists that match 'unknown'! - [255] $ log 'present(named("unknown"))' $ log 'present(named("re:unknown"))' diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t --- a/tests/test-bookmarks.t +++ b/tests/test-bookmarks.t @@ -202,8 +202,6 @@ abort: bookmark 'unknown' does not exist! [255] $ hg log -r 'bookmark("re:unknown")' - abort: no bookmarks exist that match 'unknown'! - [255] $ hg log -r 'present(bookmark("literal:unknown"))' $ hg log -r 'present(bookmark("re:unknown"))' diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -466,9 +466,6 @@ for name, bmrev in repo._bookmarks.iteritems(): if matcher(name): matchrevs.add(bmrev) -if not matchrevs: -raise error.RepoLookupError(_("no bookmarks exist" - " that match '%s'") % pattern) for bmrev in matchrevs: bms.add(repo[bmrev].rev()) else: @@ -1330,9 +1327,6 @@ for name, ns in repo.names.iteritems(): if matcher(name): namespaces.add(ns) -if not namespaces: -raise error.RepoLookupError(_("no namespace exists" - " that match '%s'") % pattern) names = set() for ns in namespaces: To: martinvonz, #hg-reviewers, foozy Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5226: fix: rename :fileset subconfig to :pattern
This revision was automatically updated to reflect the committed changes. Closed by commit rHG2ecf5c24d0cd: fix: rename :fileset subconfig to :pattern (authored by hooper, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5226?vs=12437=12446 REVISION DETAIL https://phab.mercurial-scm.org/D5226 AFFECTED FILES hgext/fix.py tests/test-fix-clang-format.t tests/test-fix-topology.t tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -66,10 +66,10 @@ > evolution.allowunstable=True > [fix] > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all - > uppercase-whole-file:fileset=set:**.whole + > uppercase-whole-file:pattern=set:**.whole > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY > uppercase-changed-lines:linerange={first}-{last} - > uppercase-changed-lines:fileset=set:**.changed + > uppercase-changed-lines:pattern=set:**.changed > EOF Help text for fix. @@ -126,7 +126,7 @@ [fix] clang-format:command=clang-format --assume-filename={rootpath} clang-format:linerange=--lines={first}:{last} -clang-format:fileset=set:**.cpp or **.hpp +clang-format:pattern=set:**.cpp or **.hpp The :command suboption forms the first part of the shell command that will be used to fix a file. The content of the file is passed on standard input, and @@ -147,9 +147,9 @@ {first} The 1-based line number of the first line in the modified range {last}The 1-based line number of the last line in the modified range - The :fileset suboption determines which files will be passed through each - configured tool. See 'hg help fileset' for possible values. If there are file - arguments to 'hg fix', the intersection of these filesets is used. + The :pattern suboption determines which files will be passed through each + configured tool. See 'hg help patterns' for possible values. If there are file + arguments to 'hg fix', the intersection of these patterns is used. There is also a configurable limit for the maximum size of file that will be processed by 'hg fix': @@ -371,7 +371,7 @@ $ hg --config "fix.fail:command=echo" \ >--config "fix.fail:linerange={first}:{last}" \ - >--config "fix.fail:fileset=foo.txt" \ + >--config "fix.fail:pattern=foo.txt" \ >fix --working-dir $ cat foo.txt 1:1 4:6 8:8 @@ -534,7 +534,7 @@ > exit 0 # success despite the stderr output > EOF $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \ - >--config "fix.work:fileset=hello.txt" \ + >--config "fix.work:pattern=hello.txt" \ >fix --working-dir [wdir] work: hello.txt: some [wdir] work: error that didn't stop the tool @@ -551,7 +551,7 @@ > exit 42 # success despite the stdout output > EOF $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \ - >--config "fix.fail:fileset=hello.txt" \ + >--config "fix.fail:pattern=hello.txt" \ >--config "fix.failure=abort" \ >fix --working-dir [wdir] fail: hello.txt: some @@ -565,7 +565,7 @@ foo $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \ - >--config "fix.fail:fileset=hello.txt" \ + >--config "fix.fail:pattern=hello.txt" \ >fix --working-dir [wdir] fail: hello.txt: some [wdir] fail: error that did stop the tool @@ -575,7 +575,7 @@ FOO $ hg --config "fix.fail:command=exit 42" \ - >--config "fix.fail:fileset=hello.txt" \ + >--config "fix.fail:pattern=hello.txt" \ >fix --working-dir [wdir] fail: exited with status 42 @@ -1027,7 +1027,7 @@ adding foo/bar $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \ >--config "fix.fail:linerange='{first}' '{last}'" \ - >--config "fix.fail:fileset=foo/bar" \ + >--config "fix.fail:pattern=foo/bar" \ >fix --working-dir $ cat foo/bar foo/bar @@ -1105,3 +1105,25 @@ FOO2 $ cd .. + +The :fileset subconfig was a misnomer, so we renamed it to :pattern. We will +still accept :fileset by itself as if it were :pattern, but this will issue a +warning. + + $ hg init filesetispattern + $ cd filesetispattern + + $ printf "foo\n" > foo.whole + $ printf "first\nsecond\n" > bar.txt + $ hg add -q + $ hg fix -w --config fix.sometool:fileset=bar.txt \ + > --config fix.sometool:command=tac + the fix.tool:fileset config name is deprecated; please rename it to fix.tool:pattern + + $ cat foo.whole + FOO + $ cat bar.txt + second + first + + $ cd .. diff --git a/tests/test-fix-topology.t b/tests/test-fix-topology.t --- a/tests/test-fix-topology.t +++ b/tests/test-fix-topology.t @@ -23,7 +23,7 @@ > fix = > [fix] > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY - > uppercase-whole-file:fileset=set:** + > uppercase-whole-file:pattern=set:** > EOF This tests the only behavior
D5200: fix: add a config to abort when a fixer tool fails
This revision was automatically updated to reflect the committed changes. Closed by commit rHG93bab80993f4: fix: add a config to abort when a fixer tool fails (authored by hooper, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5200?vs=12435=12445 REVISION DETAIL https://phab.mercurial-scm.org/D5200 AFFECTED FILES hgext/fix.py tests/test-fix.t CHANGE DETAILS diff --git a/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -130,9 +130,11 @@ The :command suboption forms the first part of the shell command that will be used to fix a file. The content of the file is passed on standard input, and - the fixed file content is expected on standard output. If there is any output - on standard error, the file will not be affected. Some values may be - substituted into the command: + the fixed file content is expected on standard output. Any output on standard + error will be displayed as a warning. If the exit status is not zero, the file + will not be affected. A placeholder warning is displayed if there is a non- + zero exit status but no standard error output. Some values may be substituted + into the command: {rootpath} The path of the file being fixed, relative to the repo root {basename} The name of the file being fixed, without the directory path @@ -153,7 +155,15 @@ processed by 'hg fix': [fix] -maxfilesize=2MB +maxfilesize = 2MB + + Normally, execution of configured tools will continue after a failure + (indicated by a non-zero exit status). It can also be configured to abort + after the first such failure, so that no files will be affected if any tool + fails. This abort will also cause 'hg fix' to exit with a non-zero status: + +[fix] +failure = abort list of commands: @@ -508,40 +518,61 @@ on stderr and nothing on stdout, which would cause us the clear the file, except that they also exit with a non-zero code. We show the user which fixer emitted the stderr, and which revision, but we assume that the fixer will print -the filename if it is relevant (since the issue may be non-specific). +the filename if it is relevant (since the issue may be non-specific). There is +also a config to abort (without affecting any files whatsoever) if we see any +tool with a non-zero exit status. $ hg init showstderr $ cd showstderr $ printf "hello\n" > hello.txt $ hg add adding hello.txt - $ cat > $TESTTMP/fail.sh <<'EOF' + $ cat > $TESTTMP/work.sh <<'EOF' > printf 'HELLO\n' - > printf "$@: some\nerror" >&2 + > printf "$@: some\nerror that didn't stop the tool" >&2 > exit 0 # success despite the stderr output > EOF + $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \ + >--config "fix.work:fileset=hello.txt" \ + >fix --working-dir + [wdir] work: hello.txt: some + [wdir] work: error that didn't stop the tool + $ cat hello.txt + HELLO + + $ printf "goodbye\n" > hello.txt + $ printf "foo\n" > foo.whole + $ hg add + adding foo.whole + $ cat > $TESTTMP/fail.sh <<'EOF' + > printf 'GOODBYE\n' + > printf "$@: some\nerror that did stop the tool\n" >&2 + > exit 42 # success despite the stdout output + > EOF + $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \ + >--config "fix.fail:fileset=hello.txt" \ + >--config "fix.failure=abort" \ + >fix --working-dir + [wdir] fail: hello.txt: some + [wdir] fail: error that did stop the tool + abort: no fixes will be applied + (use --config fix.failure=continue to apply any successful fixes anyway) + [255] + $ cat hello.txt + goodbye + $ cat foo.whole + foo + $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \ >--config "fix.fail:fileset=hello.txt" \ >fix --working-dir [wdir] fail: hello.txt: some - [wdir] fail: error - $ cat hello.txt - HELLO - - $ printf "goodbye\n" > hello.txt - $ cat > $TESTTMP/work.sh <<'EOF' - > printf 'GOODBYE\n' - > printf "$@: some\nerror\n" >&2 - > exit 42 # success despite the stdout output - > EOF - $ hg --config "fix.fail:command=sh $TESTTMP/work.sh {rootpath}" \ - >--config "fix.fail:fileset=hello.txt" \ - >fix --working-dir - [wdir] fail: hello.txt: some - [wdir] fail: error + [wdir] fail: error that did stop the tool $ cat hello.txt goodbye + $ cat foo.whole + FOO $ hg --config "fix.fail:command=exit 42" \ >--config "fix.fail:fileset=hello.txt" \ diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -19,9 +19,11 @@ The :command suboption forms the first part of the shell command that will be used to fix a file. The content of the file is passed on standard input, and the -fixed file content is expected on standard output. If there is any output on -standard error, the file will not be affected. Some values may be substituted -into the command:: +fixed file content
D5220: revsets: make bookmark/named('re:nonexistent') revset not abort (issue6018)
yuja added a comment. Flagged as (BC) and queued, thanks. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5220 To: martinvonz, #hg-reviewers, foozy Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5226: fix: rename :fileset subconfig to :pattern
yuja added a comment. > This name was always inaccurate, since the config accepts any pattern. > Hopefully so few people use this right now that it won't matter, but there will > now be a warning if the old config name is used. Sounds good as the fix is still an experimental extension. Queued, thanks. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5226 To: hooper, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D5220: revsets: make bookmark/named('re:nonexistent') revset not abort (issue6018)
Flagged as (BC) and queued, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D5226: fix: rename :fileset subconfig to :pattern
> This name was always inaccurate, since the config accepts any pattern. > Hopefully so few people use this right now that it won't matter, but there > will > now be a warning if the old config name is used. Sounds good as the fix is still an experimental extension. Queued, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH STABLE] tests: require SQLite 3.8.3+ as sqlitestore relies on "WITH" clause
This patch seems to have been queued and is part of the 4.8 release. On 02/11/2018 13:49, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1541161535 -32400 > # Fri Nov 02 21:25:35 2018 +0900 > # Branch stable > # Node ID d12b6941f9ac56cebc165fa83ad982db202335a2 > # Parent 41f48262b845632a1fca09e79d72fdb8eb1eb624 > tests: require SQLite 3.8.3+ as sqlitestore relies on "WITH" clause > > The test fails on gcc112 because the SQLite is too old. > > https://sqlite.org/changes.html#version_3_8_3 > > diff --git a/tests/hghave.py b/tests/hghave.py > --- a/tests/hghave.py > +++ b/tests/hghave.py > @@ -791,10 +791,14 @@ def has_repofncache(): > def has_sqlite(): > try: > import sqlite3 > -sqlite3.sqlite_version > +version = sqlite3.sqlite_version_info > except ImportError: > return False > > +if version < (3, 8, 3): > +# WITH clause not supported > +return False > + > return matchoutput('sqlite3 -version', b'^3\.\d+') > > @check('vcr', 'vcr http mocking library') > diff --git a/tests/test-storage.py b/tests/test-storage.py > --- a/tests/test-storage.py > +++ b/tests/test-storage.py > @@ -25,6 +25,14 @@ except ImportError: > sqlitestore = None > > try: > +import sqlite3 > +if sqlite3.sqlite_version_info < (3, 8, 3): > +# WITH clause not supported > +sqlitestore = None > +except ImportError: > +pass > + > +try: > from mercurial import zstd > zstd.__version__ > except ImportError: > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 3] perf: measure slicing time in perfrevlogrevision
On Tue, 06 Nov 2018 11:34:23 +0100, Boris Feld wrote: > # HG changeset patch > # User Boris Feld > # Date 1541498713 -3600 > # Tue Nov 06 11:05:13 2018 +0100 > # Node ID 71b1cbf7a7b59d06972b18c9f3cab27019b2cb0e > # Parent 59d548edb4ce2dafb989ffc2d0a95fb4bb19d2ee > # EXP-Topic sparse-prefrevlogrevision > # Available At https://bitbucket.org/octobus/mercurial-devel/ > # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r > 71b1cbf7a7b5 > perf: measure slicing time in perfrevlogrevision Queued the series, thanks. I've fixed a couple of typos in docstring. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH V2] obsutil: clarify the access to "repo"
On Tue, 06 Nov 2018 11:03:23 +0100, Boris Feld wrote: > # HG changeset patch > # User Boris Feld > # Date 1526995577 -7200 > # Tue May 22 15:26:17 2018 +0200 > # Node ID 44b4391b6b68291e408fc7c42a477f893244cdd8 > # Parent e0dea186ab6edfab124b1dfd84237a4b8142f13b > # EXP-Topic gratuitous-cleanup > # Available At https://bitbucket.org/octobus/mercurial-devel/ > # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r > 44b4391b6b68 > obsutil: clarify the access to "repo" Queued, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 9 of 9 V3] perf: add a lazydeltabase option to perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1541429851 -3600 # Mon Nov 05 15:57:31 2018 +0100 # Node ID 38a806e71d59917d4af67d159368ed75d3939fdd # Parent d3de1f9690311ba4558a19fd70bcd88e74ffd60b # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 38a806e71d59 perf: add a lazydeltabase option to perfrevlogwrite The option controls if we'll test the provided delta first. This is the current default behavior for unbundle. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1573,6 +1573,7 @@ def perfrevlogrevisions(ui, repo, file_= (b'', b'count', 3, b'last revision to write'), (b'', b'details', False, b'print timing for every revisions tested'), (b'', b'source', b'full', b'the kind of data feed in the revlog'), + (b'', b'lazydeltabase', True, b'try the provided delta first'), ], b'-c|-m|FILE') def perfrevlogwrite(ui, repo, file_=None, startrev=1000, stoprev=-1, **opts): @@ -1595,6 +1596,7 @@ def perfrevlogwrite(ui, repo, file_=None if stoprev < 0: stoprev = rllen + stoprev +lazydeltabase = opts['lazydeltabase'] source = opts['source'] validsource = (b'full', b'parent-1', b'parent-2', b'parent-smallest', b'storage') @@ -1607,7 +1609,8 @@ def perfrevlogwrite(ui, repo, file_=None raise error.Abort('invalide run count: %d' % count) allresults = [] for c in range(count): -timing = _timeonewrite(ui, rl, source, startrev, stoprev, c + 1) +timing = _timeonewrite(ui, rl, source, startrev, stoprev, c + 1, + lazydeltabase=lazydeltabase) allresults.append(timing) ### consolidate the results in a single list @@ -1670,10 +1673,12 @@ class _faketr(object): def add(s, x, y, z=None): return None -def _timeonewrite(ui, orig, source, startrev, stoprev, runidx=None): +def _timeonewrite(ui, orig, source, startrev, stoprev, runidx=None, + lazydeltabase=True): timings = [] tr = _faketr() with _temprevlog(ui, orig, startrev) as dest: +dest._lazydeltabase = lazydeltabase revs = list(orig.revs(startrev, stoprev)) total = len(revs) topic = 'adding' ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 8 of 9 V3] perf: add `storage` as possible source for perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1541427849 -3600 # Mon Nov 05 15:24:09 2018 +0100 # Node ID d3de1f9690311ba4558a19fd70bcd88e74ffd60b # Parent 0c64116c5e5da0c6cece45a68ff1fa2fec2318ba # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r d3de1f969031 perf: add `storage` as possible source for perfrevlogwrite This source will use the stored delta. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1584,6 +1584,7 @@ def perfrevlogwrite(ui, repo, file_=None * `parent-2`: add from a delta to the second parent if it exists (use a delta from the first parent otherwise) * `parent-smallest`: add from the smallest delta (either p1 or p2) +* `storage`: add from the existing precomputed deltas """ opts = _byteskwargs(opts) @@ -1595,7 +1596,8 @@ def perfrevlogwrite(ui, repo, file_=None stoprev = rllen + stoprev source = opts['source'] -validsource = (b'full', b'parent-1', b'parent-2', b'parent-smallest') +validsource = (b'full', b'parent-1', b'parent-2', b'parent-smallest', + b'storage') if source not in validsource: raise error.Abort('invalid source type: %s' % source) @@ -1719,6 +1721,9 @@ def _getrevisionseed(orig, rev, tr, sour diff = p2diff baserev = orig.rev(parent) cachedelta = (baserev, diff) +elif source == b'storage': +baserev = orig.deltaparent(rev) +cachedelta = (baserev, orig.revdiff(orig.node(baserev), rev)) return ((text, tr, linkrev, p1, p2), {'node': node, 'flags':flags, 'cachedelta': cachedelta}) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 9 V3] perf: add `parent-smallest` as possible source for perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1541427584 -3600 # Mon Nov 05 15:19:44 2018 +0100 # Node ID 0c64116c5e5da0c6cece45a68ff1fa2fec2318ba # Parent cb7f6cc58b0e41617189b4c473a17f309bb598b5 # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 0c64116c5e5d perf: add `parent-smallest` as possible source for perfrevlogwrite This source will use the smallest of the possible diff against parent. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1583,6 +1583,7 @@ def perfrevlogwrite(ui, repo, file_=None * `parent-1`: add from a delta to the first parent * `parent-2`: add from a delta to the second parent if it exists (use a delta from the first parent otherwise) +* `parent-smallest`: add from the smallest delta (either p1 or p2) """ opts = _byteskwargs(opts) @@ -1594,7 +1595,7 @@ def perfrevlogwrite(ui, repo, file_=None stoprev = rllen + stoprev source = opts['source'] -validsource = (b'full', b'parent-1', b'parent-2') +validsource = (b'full', b'parent-1', b'parent-2', b'parent-smallest') if source not in validsource: raise error.Abort('invalid source type: %s' % source) @@ -1707,6 +1708,17 @@ def _getrevisionseed(orig, rev, tr, sour parent = p1 baserev = orig.rev(parent) cachedelta = (baserev, orig.revdiff(parent, rev)) +elif source == b'parent-smallest': +p1diff = orig.revdiff(p1, rev) +parent = p1 +diff = p1diff +if p2 != nullid: +p2diff = orig.revdiff(p2, rev) +if len(p1diff) > len(p2diff): +parent = p2 +diff = p2diff +baserev = orig.rev(parent) +cachedelta = (baserev, diff) return ((text, tr, linkrev, p1, p2), {'node': node, 'flags':flags, 'cachedelta': cachedelta}) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 5 of 9 V3] perf: add `parent-1` as possible source for perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1541427302 -3600 # Mon Nov 05 15:15:02 2018 +0100 # Node ID 934e67cf46a673a89aac27a846977c808b23e071 # Parent e7f2594431ac5fba43ae345b345d3aab1a4ab47c # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 934e67cf46a6 perf: add `parent-1` as possible source for perfrevlogwrite This source will use a diff against p1 in all case. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1580,6 +1580,7 @@ def perfrevlogwrite(ui, repo, file_=None Possible source value are: * `full`: add from a full text (default). +* `parent-1`: add from a delta to the first parent """ opts = _byteskwargs(opts) @@ -1591,7 +1592,7 @@ def perfrevlogwrite(ui, repo, file_=None stoprev = rllen + stoprev source = opts['source'] -validsource = (b'full',) +validsource = (b'full', b'parent-1') if source not in validsource: raise error.Abort('invalid source type: %s' % source) @@ -1693,6 +1694,9 @@ def _getrevisionseed(orig, rev, tr, sour if source == b'full': text = orig.revision(rev) +elif source == b'parent-1': +baserev = orig.rev(p1) +cachedelta = (baserev, orig.revdiff(p1, rev)) return ((text, tr, linkrev, p1, p2), {'node': node, 'flags':flags, 'cachedelta': cachedelta}) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 9 V3] perf: add `parent-2` as possible source for perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1541427318 -3600 # Mon Nov 05 15:15:18 2018 +0100 # Node ID cb7f6cc58b0e41617189b4c473a17f309bb598b5 # Parent 934e67cf46a673a89aac27a846977c808b23e071 # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r cb7f6cc58b0e perf: add `parent-2` as possible source for perfrevlogwrite This source will use a diff against p2 if it exists and fall back to p1 otherwise. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1581,6 +1581,8 @@ def perfrevlogwrite(ui, repo, file_=None Possible source value are: * `full`: add from a full text (default). * `parent-1`: add from a delta to the first parent +* `parent-2`: add from a delta to the second parent if it exists + (use a delta from the first parent otherwise) """ opts = _byteskwargs(opts) @@ -1592,7 +1594,7 @@ def perfrevlogwrite(ui, repo, file_=None stoprev = rllen + stoprev source = opts['source'] -validsource = (b'full', b'parent-1') +validsource = (b'full', b'parent-1', b'parent-2') if source not in validsource: raise error.Abort('invalid source type: %s' % source) @@ -1685,6 +1687,8 @@ def _timeonewrite(ui, orig, source, star return timings def _getrevisionseed(orig, rev, tr, source): +from mercurial.node import nullid + linkrev = orig.linkrev(rev) node = orig.node(rev) p1, p2 = orig.parents(node) @@ -1697,6 +1701,12 @@ def _getrevisionseed(orig, rev, tr, sour elif source == b'parent-1': baserev = orig.rev(p1) cachedelta = (baserev, orig.revdiff(p1, rev)) +elif source == b'parent-2': +parent = p2 +if p2 == nullid: +parent = p1 +baserev = orig.rev(parent) +cachedelta = (baserev, orig.revdiff(parent, rev)) return ((text, tr, linkrev, p1, p2), {'node': node, 'flags':flags, 'cachedelta': cachedelta}) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 9 V3] perf: only display the total time for perfrevlogwrite if quiet
# HG changeset patch # User Boris Feld # Date 1541462254 -3600 # Tue Nov 06 00:57:34 2018 +0100 # Node ID 24f71fdc0551dffb59ad2c29c1183d747122ab64 # Parent fd1ce4514534dc539c2f00afb4340e0ae575d30f # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 24f71fdc0551 perf: only display the total time for perfrevlogwrite if quiet This provide a simple way to get an overview of the total performance. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1632,10 +1632,11 @@ def perfrevlogwrite(ui, repo, file_=None ("99%", resultcount * 99 // 100), ("max", -1), ] -for name, idx in relevants: -data = results[idx] -title = '%s of %d, rev %d' % (name, resultcount, data[0]) -formatone(fm, data[1], title=title, displayall=displayall) +if not ui.quiet: +for name, idx in relevants: +data = results[idx] +title = '%s of %d, rev %d' % (name, resultcount, data[0]) +formatone(fm, data[1], title=title, displayall=displayall) # XXX summing that many float will not be very precise, we ignore this fact # for now ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 9 V3] perf: add the notion of "source" to perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1539962609 -7200 # Fri Oct 19 17:23:29 2018 +0200 # Node ID e7f2594431ac5fba43ae345b345d3aab1a4ab47c # Parent 24f71fdc0551dffb59ad2c29c1183d747122ab64 # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r e7f2594431ac perf: add the notion of "source" to perfrevlogwrite We want to test performance associated witch various way to add a new revision. They will be specified using this new argument. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1572,10 +1572,14 @@ def perfrevlogrevisions(ui, repo, file_= (b'', b'stoprev', -1, b'last revision to write'), (b'', b'count', 3, b'last revision to write'), (b'', b'details', False, b'print timing for every revisions tested'), + (b'', b'source', b'full', b'the kind of data feed in the revlog'), ], b'-c|-m|FILE') def perfrevlogwrite(ui, repo, file_=None, startrev=1000, stoprev=-1, **opts): """Benchmark writing a series of revisions to a revlog. + +Possible source value are: +* `full`: add from a full text (default). """ opts = _byteskwargs(opts) @@ -1586,13 +1590,19 @@ def perfrevlogwrite(ui, repo, file_=None if stoprev < 0: stoprev = rllen + stoprev +source = opts['source'] +validsource = (b'full',) +if source not in validsource: +raise error.Abort('invalid source type: %s' % source) + ### actually gather results count = opts['count'] if count <= 0: raise error.Abort('invalide run count: %d' % count) allresults = [] for c in range(count): -allresults.append(_timeonewrite(ui, rl, startrev, stoprev, c + 1)) +timing = _timeonewrite(ui, rl, source, startrev, stoprev, c + 1) +allresults.append(timing) ### consolidate the results in a single list results = [] @@ -1654,7 +1664,7 @@ class _faketr(object): def add(s, x, y, z=None): return None -def _timeonewrite(ui, orig, startrev, stoprev, runidx=None): +def _timeonewrite(ui, orig, source, startrev, stoprev, runidx=None): timings = [] tr = _faketr() with _temprevlog(ui, orig, startrev) as dest: @@ -1665,7 +1675,7 @@ def _timeonewrite(ui, orig, startrev, st topic += ' (run #%d)' % runidx for idx, rev in enumerate(revs): ui.progress(topic, idx, unit='revs', total=total) -addargs, addkwargs = _getrevisionseed(orig, rev, tr) +addargs, addkwargs = _getrevisionseed(orig, rev, tr, source) with timeone() as r: dest.addrawrevision(*addargs, **addkwargs) timings.append((rev, r[0])) @@ -1673,13 +1683,16 @@ def _timeonewrite(ui, orig, startrev, st ui.progress(topic, None, unit='revs', total=total) return timings -def _getrevisionseed(orig, rev, tr): +def _getrevisionseed(orig, rev, tr, source): linkrev = orig.linkrev(rev) node = orig.node(rev) p1, p2 = orig.parents(node) flags = orig.flags(rev) cachedelta = None -text = orig.revision(rev) +text = None + +if source == b'full': +text = orig.revision(rev) return ((text, tr, linkrev, p1, p2), {'node': node, 'flags':flags, 'cachedelta': cachedelta}) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 9 V3] perf: introduce a perfrevlogwrite command
# HG changeset patch # User Boris Feld # Date 1538556809 -7200 # Wed Oct 03 10:53:29 2018 +0200 # Node ID 1d1bc06187e9296430045aa39c3d3e2d12f61875 # Parent 909c31805f54628ab5bf22cd92418c8ac9c09277 # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 1d1bc06187e9 perf: introduce a perfrevlogwrite command The command record times taken by adding many revisions to a revlog. Timing each addition, individually. The "added revision" are recreations of the original ones. To time each addition individually, we have to handle the timing and the reporting ourselves. This command is introduced to track the impact of sparse-revlog format on delta computations at initial storage time. It starts with the full text, a situation similar to the "commit". Additions from an existing delta are better timed with bundles. The complaints from `check-perf-code.py` are not relevant. We are accessing and "revlog" opener, not a repository opener. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -24,8 +24,10 @@ import functools import gc import os import random +import shutil import struct import sys +import tempfile import threading import time from mercurial import ( @@ -1565,6 +1567,161 @@ def perfrevlogrevisions(ui, repo, file_= timer(d) fm.end() +@command(b'perfrevlogwrite', revlogopts + formatteropts + + [(b's', b'startrev', 1000, b'revision to start writing at'), + (b'', b'stoprev', -1, b'last revision to write'), + (b'', b'count', 3, b'last revision to write'), + ], + b'-c|-m|FILE') +def perfrevlogwrite(ui, repo, file_=None, startrev=1000, stoprev=-1, **opts): +"""Benchmark writing a series of revisions to a revlog. +""" +opts = _byteskwargs(opts) + +rl = cmdutil.openrevlog(repo, b'perfrevlogwrite', file_, opts) +rllen = getlen(ui)(rl) +if startrev < 0: +startrev = rllen + startrev +if stoprev < 0: +stoprev = rllen + stoprev + +### actually gather results +count = opts['count'] +if count <= 0: +raise error.Abort('invalide run count: %d' % count) +allresults = [] +for c in range(count): +allresults.append(_timeonewrite(ui, rl, startrev, stoprev, c + 1)) + +### consolidate the results in a single list +results = [] +for idx, (rev, t) in enumerate(allresults[0]): +ts = [t] +for other in allresults[1:]: +orev, ot = other[idx] +assert orev == rev +ts.append(ot) +results.append((rev, ts)) +resultcount = len(results) + +### Compute and display relevant statistics + +# get a formatter +fm = ui.formatter(b'perf', opts) +displayall = ui.configbool(b"perf", b"all-timing", False) + +# sorts results by median time +results.sort(key=lambda x: sorted(x[1])[len(x[1]) // 2]) +# list of (name, index) to display) +relevants = [ +("min", 0), +("10%", resultcount * 10 // 100), +("25%", resultcount * 25 // 100), +("50%", resultcount * 70 // 100), +("75%", resultcount * 75 // 100), +("90%", resultcount * 90 // 100), +("95%", resultcount * 95 // 100), +("99%", resultcount * 99 // 100), +("max", -1), +] +for name, idx in relevants: +data = results[idx] +title = '%s of %d, rev %d' % (name, resultcount, data[0]) +formatone(fm, data[1], title=title, displayall=displayall) + +# XXX summing that many float will not be very precise, we ignore this fact +# for now +totaltime = [] +for item in allresults: +totaltime.append((sum(x[1][0] for x in item), + sum(x[1][1] for x in item), + sum(x[1][2] for x in item),) +) +formatone(fm, totaltime, title="total time (%d revs)" % resultcount, + displayall=displayall) +fm.end() + +class _faketr(object): +def add(s, x, y, z=None): +return None + +def _timeonewrite(ui, orig, startrev, stoprev, runidx=None): +timings = [] +tr = _faketr() +with _temprevlog(ui, orig, startrev) as dest: +revs = list(orig.revs(startrev, stoprev)) +total = len(revs) +topic = 'adding' +if runidx is not None: +topic += ' (run #%d)' % runidx +for idx, rev in enumerate(revs): +ui.progress(topic, idx, unit='revs', total=total) +addargs, addkwargs = _getrevisionseed(orig, rev, tr) +with timeone() as r: +dest.addrawrevision(*addargs, **addkwargs) +timings.append((rev, r[0])) +ui.progress(topic, total, unit='revs', total=total) +ui.progress(topic, None, unit='revs', total=total) +return timings + +def _getrevisionseed(orig, rev, tr): +linkrev = orig.linkrev(rev) +node =
[PATCH 2 of 9 V3] perf: offer full details in perfrevlogwrite
# HG changeset patch # User Boris Feld # Date 1538557497 -7200 # Wed Oct 03 11:04:57 2018 +0200 # Node ID fd1ce4514534dc539c2f00afb4340e0ae575d30f # Parent 1d1bc06187e9296430045aa39c3d3e2d12f61875 # EXP-Topic revlog-perf # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r fd1ce4514534 perf: offer full details in perfrevlogwrite This will be useful for people who want to study the timing pattern more closely. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1571,6 +1571,7 @@ def perfrevlogrevisions(ui, repo, file_= [(b's', b'startrev', 1000, b'revision to start writing at'), (b'', b'stoprev', -1, b'last revision to write'), (b'', b'count', 3, b'last revision to write'), + (b'', b'details', False, b'print timing for every revisions tested'), ], b'-c|-m|FILE') def perfrevlogwrite(ui, repo, file_=None, startrev=1000, stoprev=-1, **opts): @@ -1610,6 +1611,13 @@ def perfrevlogwrite(ui, repo, file_=None fm = ui.formatter(b'perf', opts) displayall = ui.configbool(b"perf", b"all-timing", False) +# print individual details if requested +if opts['details']: +for idx, item in enumerate(results, 1): +rev, data = item +title = 'revisions #%d of %d, rev %d' % (idx, resultcount, rev) +formatone(fm, data, title=title, displayall=displayall) + # sorts results by median time results.sort(key=lambda x: sorted(x[1])[len(x[1]) // 2]) # list of (name, index) to display) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5229: runbgcommand: import concerns about creationflags on Windows from D1701
lothiraldan created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY I don't have the need anymore for the change in https://phab.mercurial-scm.org/D1701 nor the time to investigate the changes on all supported Windows platforms. I import the stuff I learned on https://phab.mercurial-scm.org/D1701 in the `runbgcommand` so the next people working on it can starts from there. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5229 AFFECTED FILES mercurial/utils/procutil.py CHANGE DETAILS diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -474,6 +474,9 @@ # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx # No stdlib constant exists for this value DETACHED_PROCESS = 0x0008 +# Following creation flags might create a console GUI window. +# Using subprocess.CREATE_NEW_CONSOLE might helps. +# See https://phab.mercurial-scm.org/D1701 for discussion _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP def runbgcommand(script, env, shell=False, stdout=None, stderr=None): To: lothiraldan, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3] perf: teach perfrevlogrevision about sparse reading
# HG changeset patch # User Boris Feld # Date 1541498663 -3600 # Tue Nov 06 11:04:23 2018 +0100 # Node ID 59d548edb4ce2dafb989ffc2d0a95fb4bb19d2ee # Parent 92466f201ed80783a2e1d37ad4fd1ff80df1f36a # EXP-Topic sparse-prefrevlogrevision # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 59d548edb4ce perf: teach perfrevlogrevision about sparse reading Before this change, chunks were always read in a single block. Even in the sparse-read/sparse-revlog case. This gave a false view of the performance and could lead to memory consumption issue. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1723,17 +1723,18 @@ def perfrevlogrevision(ui, repo, file_, inline = r._inline iosize = r._io.size buffer = util.buffer -offset = start(chain[0]) chunks = [] ladd = chunks.append - -for rev in chain: -chunkstart = start(rev) -if inline: -chunkstart += (rev + 1) * iosize -chunklength = length(rev) -ladd(buffer(data, chunkstart - offset, chunklength)) +for idx, item in enumerate(chain): +offset = start(item[0]) +bits = data[idx] +for rev in item: +chunkstart = start(rev) +if inline: +chunkstart += (rev + 1) * iosize +chunklength = length(rev) +ladd(buffer(bits, chunkstart - offset, chunklength)) return chunks @@ -1745,7 +1746,8 @@ def perfrevlogrevision(ui, repo, file_, def doread(chain): if not cache: r.clearcaches() -segmentforrevs(chain[0], chain[-1]) +for item in slicedchain: +segmentforrevs(item[0], item[-1]) def dorawchunks(data, chain): if not cache: @@ -1772,9 +1774,20 @@ def perfrevlogrevision(ui, repo, file_, r.clearcaches() r.revision(node) +try: +from mercurial.revlogutils.deltas import slicechunk +except ImportError: +slicechunk = getattr(revlog, '_slicechunk', None) + + +size = r.length(rev) chain = r._deltachain(rev)[0] -data = segmentforrevs(chain[0], chain[-1])[1] -rawchunks = getrawchunks(data, chain) +if not getattr(r, '_withsparseread', False): +slicedchain = (chain,) +else: +slicedchain = tuple(slicechunk(r, chain, targetsize=size)) +data = [segmentforrevs(seg[0], seg[-1])[1] for seg in slicedchain] +rawchunks = getrawchunks(data, slicedchain) bins = r._chunks(chain) text = bytes(bins[0]) bins = bins[1:] @@ -1784,7 +1797,7 @@ def perfrevlogrevision(ui, repo, file_, (lambda: dorevision(), b'full'), (lambda: dodeltachain(rev), b'deltachain'), (lambda: doread(chain), b'read'), -(lambda: dorawchunks(data, chain), b'rawchunks'), +(lambda: dorawchunks(data, slicedchain), b'rawchunks'), (lambda: dodecompress(rawchunks), b'decompress'), (lambda: dopatch(text, bins), b'patch'), (lambda: dohash(text), b'hash'), ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3] perf: use the same timer for all section of perfrevlogrevision
# HG changeset patch # User Boris Feld # Date 1541499211 -3600 # Tue Nov 06 11:13:31 2018 +0100 # Node ID 92466f201ed80783a2e1d37ad4fd1ff80df1f36a # Parent c2a0bc6412dbbcbba20517e250b0fcd2fc79b0e7 # EXP-Topic sparse-prefrevlogrevision # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 92466f201ed8 perf: use the same timer for all section of perfrevlogrevision Otherwise the -T json output is invalid. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1790,10 +1790,10 @@ def perfrevlogrevision(ui, repo, file_, (lambda: dohash(text), b'hash'), ] +timer, fm = gettimer(ui, opts) for fn, title in benches: -timer, fm = gettimer(ui, opts) timer(fn, title=title) -fm.end() +fm.end() @command(b'perfrevset', [(b'C', b'clear', False, b'clear volatile cache between each call.'), ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 3] perf: measure slicing time in perfrevlogrevision
# HG changeset patch # User Boris Feld # Date 1541498713 -3600 # Tue Nov 06 11:05:13 2018 +0100 # Node ID 71b1cbf7a7b59d06972b18c9f3cab27019b2cb0e # Parent 59d548edb4ce2dafb989ffc2d0a95fb4bb19d2ee # EXP-Topic sparse-prefrevlogrevision # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 71b1cbf7a7b5 perf: measure slicing time in perfrevlogrevision Slicing a sparse delta chain can be expensive. We now benchmark the associated time. diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1692,10 +1692,11 @@ def perfrevlogrevision(ui, repo, file_, Obtaining a revlog revision consists of roughly the following steps: 1. Compute the delta chain -2. Obtain the raw chunks for that delta chain -3. Decompress each raw chunk -4. Apply binary patches to obtain fulltext -5. Verify hash of fulltext +2. slice the delta chain if applicatble +3. Obtain the raw chunks for that delta chain +4. Decompress each raw chunk +5. Apply binary patches to obtain fulltext +6. Verify hash of fulltext This command measures the time spent in each of these phases. """ @@ -1749,6 +1750,10 @@ def perfrevlogrevision(ui, repo, file_, for item in slicedchain: segmentforrevs(item[0], item[-1]) +def doslice(r, chain, size): +for s in slicechunk(r, chain, targetsize=size): +pass + def dorawchunks(data, chain): if not cache: r.clearcaches() @@ -1797,11 +1802,18 @@ def perfrevlogrevision(ui, repo, file_, (lambda: dorevision(), b'full'), (lambda: dodeltachain(rev), b'deltachain'), (lambda: doread(chain), b'read'), +] + +if getattr(r, '_withsparseread', False): +slicing = (lambda: doslice(r, chain, size), b'slice-sparse-chain') +benches.append(slicing) + +benches.extend([ (lambda: dorawchunks(data, slicedchain), b'rawchunks'), (lambda: dodecompress(rawchunks), b'decompress'), (lambda: dopatch(text, bins), b'patch'), (lambda: dohash(text), b'hash'), -] +]) timer, fm = gettimer(ui, opts) for fn, title in benches: ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH V2] obsutil: clarify the access to "repo"
# HG changeset patch # User Boris Feld # Date 1526995577 -7200 # Tue May 22 15:26:17 2018 +0200 # Node ID 44b4391b6b68291e408fc7c42a477f893244cdd8 # Parent e0dea186ab6edfab124b1dfd84237a4b8142f13b # EXP-Topic gratuitous-cleanup # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 44b4391b6b68 obsutil: clarify the access to "repo" We use the variable multiple times and we might use it even more in the future. We use a temporary variable instead. diff --git a/mercurial/obsutil.py b/mercurial/obsutil.py --- a/mercurial/obsutil.py +++ b/mercurial/obsutil.py @@ -396,12 +396,14 @@ def _cmpdiff(leftctx, rightctx): This is a first and basic implementation, with many shortcoming. """ -diffopts = diffutil.diffallopts(leftctx.repo().ui, {'git': True}) +# lefctx.repo() and right_ctx.repo() are the same here +repo = leftctx.repo() +diffopts = diffutil.diffallopts(repo.ui, {'git': True}) # Leftctx or right ctx might be filtered, so we need to use the contexts # with an unfiltered repository to safely compute the diff -leftunfi = leftctx._repo.unfiltered()[leftctx.rev()] +leftunfi = repo.unfiltered()[leftctx.rev()] leftdiff = leftunfi.diff(opts=diffopts) -rightunfi = rightctx._repo.unfiltered()[rightctx.rev()] +rightunfi = repo.unfiltered()[rightctx.rev()] rightdiff = rightunfi.diff(opts=diffopts) left, right = (0, 0) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5227: pycompat: adding Linux detection and fixing Mac
This revision was automatically updated to reflect the committed changes. Closed by commit rHG1b49b84d5ed5: pycompat: adding Linux detection and fixing Mac (authored by rdamazio, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D5227?vs=12439=12443 REVISION DETAIL https://phab.mercurial-scm.org/D5227 AFFECTED FILES mercurial/pycompat.py CHANGE DETAILS diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py --- a/mercurial/pycompat.py +++ b/mercurial/pycompat.py @@ -403,7 +403,8 @@ isjython = sysplatform.startswith(b'java') -isdarwin = sysplatform == b'darwin' +isdarwin = sysplatform.startswith(b'darwin') +islinux = sysplatform.startswith(b'linux') isposix = osname == b'posix' iswindows = osname == b'nt' To: rdamazio, #hg-reviewers, lothiraldan Cc: lothiraldan, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5227: pycompat: adding Linux detection and fixing Mac
lothiraldan accepted this revision. lothiraldan added a comment. LGTM and seems to be what psutil is doing also: https://github.com/giampaolo/psutil/blob/master/psutil/_common.py#L75 REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5227 To: rdamazio, #hg-reviewers, lothiraldan Cc: lothiraldan, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5228: perf: fix perfrevlogrevisions --reverse
lothiraldan created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Currently, 'endrev' equals `len(revlog)`, a revision that does not exist. When asking for the reverse order, the arguments passed to xrange are `xrange(len(revlog), startrev)` which then crash. We need to offset 'endrev' by one so we don't crash anymore. Also, we offset 'startrev' to ensure we get the same number of revisions with and without the `--reverse` option. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5228 AFFECTED FILES contrib/perf.py CHANGE DETAILS diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1553,7 +1553,7 @@ dist = opts[b'dist'] if reverse: -beginrev, endrev = endrev, beginrev +beginrev, endrev = endrev - 1, beginrev - 1 dist = -1 * dist for x in _xrange(beginrev, endrev, dist): To: lothiraldan, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5221: localrepo: extract loading of hgrc files to standalone function
lothiraldan added a comment. LGTM. As you looked at those extension that needed this feature, would it be useful to contact their authors and give them an opportunity to give their opinion on this series? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5221 To: indygreg, #hg-reviewers Cc: lothiraldan, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel