D6271: rust-filepatterns: add a Rust implementation of pattern-related utils
martinvonz added inline comments. INLINE COMMENTS > martinvonz wrote in lib.rs:21 > I get the following from `HGWITHRUSTEXT= make local`: > > error[E0583]: file not found for module `filepatterns` > --> hg-core/src/lib.rs:21:5 > | > 21 | mod filepatterns; > | > | > = help: name the file either filepatterns.rs or filepatterns/mod.rs > inside the directory "hg-core/src" > > error: aborting due to previous error > > For more information about this error, try `rustc --explain E0583`. > error: Could not compile `hg-core`. > > Also, the command modifies the `rust/Cargo.lock`, which is really annoying. > Is there a way to fix that? Or does it only happen when the build fails, so > it's not really a problem? I guess I'll drop this patch until that's fixed. Sorry. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6271 To: Alphare, #hg-reviewers, kevincox, durin42 Cc: martinvonz, durin42, kevincox, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6271: rust-filepatterns: add a Rust implementation of pattern-related utils
martinvonz added inline comments. INLINE COMMENTS > lib.rs:21 > }; > +mod filepatterns; > + I get the following from `HGWITHRUSTEXT= make local`: error[E0583]: file not found for module `filepatterns` --> hg-core/src/lib.rs:21:5 | 21 | mod filepatterns; | | = help: name the file either filepatterns.rs or filepatterns/mod.rs inside the directory "hg-core/src" error: aborting due to previous error For more information about this error, try `rustc --explain E0583`. error: Could not compile `hg-core`. Also, the command modifies the `rust/Cargo.lock`, which is really annoying. Is there a way to fix that? Or does it only happen when the build fails, so it's not really a problem? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6271 To: Alphare, #hg-reviewers, kevincox, durin42 Cc: martinvonz, durin42, kevincox, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[Bug 6140] New: AssertionError during rename-heavy merge: assert sf not in data['diverge'].
https://bz.mercurial-scm.org/show_bug.cgi?id=6140 Bug ID: 6140 Summary: AssertionError during rename-heavy merge: assert sf not in data['diverge']. Product: Mercurial Version: 5.0 Hardware: PC OS: Mac OS Status: UNCONFIRMED Severity: feature Priority: wish Component: Mercurial Assignee: bugzi...@mercurial-scm.org Reporter: kissl...@oberon.ch CC: mercurial-devel@mercurial-scm.org When trying to merge a revision containing a lot of renamed files (through SourceTree, or through CLI) I run into an assertion. Never had issues with the repository (~1 GB, about 25000 commits). I updated the CLI Mercurial from v4.9 to v5.0 (macOS Homebrew installation), but the error was still there. Re-cloning the repository does not fix the problem. The problematic revision I want to merge contains a lot of renamed files that already exist on the merge destination (possibly also having conflicts, but the merge fails before seeing the conflicts). All descendants of this revision fail with the same assertion error. Unfortunately, the repo is private and cannot be shared, but if there is a way to enable extended logging I would happily provide those logs. A workaround would also be kindly appreciated, as no descendant of the problematic revision is mergeable due to this error. $ hg merge ** unknown exception encountered, please report by visiting ** https://mercurial-scm.org/wiki/BugTracker ** Python 2.7.16 (default, Apr 12 2019, 15:32:40) [GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.46.3)] ** Mercurial Distributed SCM (version 5.0) ** Extensions loaded: churn, convert, histedit, strip, mq, purge Traceback (most recent call last): File "/usr/local/bin/hg", line 43, in dispatch.run() File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 99, in run status = dispatch(req) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 225, in dispatch ret = _runcatch(req) or 0 File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 376, in _runcatch return _callcatch(ui, _runcatchfunc) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 384, in _callcatch return scmutil.callcatch(ui, func) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/scmutil.py", line 167, in callcatch return func() File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 367, in _runcatchfunc return _dispatch(req) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 1021, in _dispatch cmdpats, cmdoptions) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 756, in runcommand ret = _runcommand(ui, options, cmd, d) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 1030, in _runcommand return cmdfunc() File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/dispatch.py", line 1018, in d = lambda: util.checksignature(func)(ui, *args, **strcmdopt) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/util.py", line 1680, in check return func(*args, **kwargs) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/util.py", line 1680, in check return func(*args, **kwargs) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/hgext/mq.py", line 3631, in mqcommand return orig(ui, repo, *args, **kwargs) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/util.py", line 1680, in check return func(*args, **kwargs) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/commands.py", line 4037, in merge labels=labels, abort=abort) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/hg.py", line 961, in merge mergeforce=mergeforce, labels=labels) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/merge.py", line 2075, in update followcopies, matcher=matcher, mergeforce=mergeforce) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/merge.py", line 1342, in calculateupdates acceptremote, followcopies) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/merge.py", line 1146, in manifestmerge ret = copies.mergecopies(repo, wctx, p2, pa) File "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages/mercurial/copies.py", line 505, in mergecopies return _fullcopytracing(repo, c1, c2, base) File
D6392: rust-cpython: build for py3, Windows and MacOSX
gracinet updated this revision to Diff 15157. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6392?vs=15156=15157 REVISION DETAIL https://phab.mercurial-scm.org/D6392 AFFECTED FILES rust/hg-cpython/src/lib.rs setup.py CHANGE DETAILS diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ ]) import sys, platform +import sysconfig if sys.version_info[0] >= 3: printf = eval('print') libdir_escape = 'unicode_escape' @@ -104,6 +105,12 @@ printf(error, file=sys.stderr) sys.exit(1) +if sys.version_info[0] >= 3: +DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX'] +else: +# deprecated in Python 3 +DYLIB_SUFFIX = sysconfig.get_config_vars()['SO'] + # Solaris Python packaging brain damage try: import hashlib @@ -1147,6 +1154,19 @@ for fname in fnames if os.path.splitext(fname)[1] == '.rs') +@staticmethod +def rustdylibsuffix(): +"""Return the suffix for shared libraries produced by rustc. + +See also: https://doc.rust-lang.org/reference/linkage.html +""" +if sys.platform == 'darwin': +return '.dylib' +elif os.name == 'nt': +return '.dll' +else: +return '.so' + def rustbuild(self): if hgrustext is None: return @@ -1168,6 +1188,9 @@ if sys.version_info[0] == 3 and self.py3_features is not None: cargocmd.extend(('--features', self.py3_features, '--no-default-features')) +if sys.platform == 'darwin': +env['RUSTFLAGS'] = ("-C link-arg=-undefined " +"-C link-arg=dynamic_lookup") try: subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir) except OSError as exc: @@ -1212,9 +1235,9 @@ self.rustbuild() target = [target_dir] target.extend(self.name.split('.')) -ext = '.so' # TODO Unix only -target[-1] += ext -shutil.copy2(os.path.join(self.rusttargetdir, self.dylibname + ext), +target[-1] += DYLIB_SUFFIX +shutil.copy2(os.path.join(self.rusttargetdir, + self.dylibname + self.rustdylibsuffix()), os.path.join(*target)) diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -23,7 +23,6 @@ extern crate cpython; extern crate hg; extern crate libc; -extern crate python27_sys; pub mod ancestors; mod cindex; To: gracinet, #hg-reviewers Cc: durin42, kevincox, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6392: rust-cpython: build for py3, Windows and MacOSX
gracinet updated this revision to Diff 15156. gracinet edited the summary of this revision. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6392?vs=15155=15156 REVISION DETAIL https://phab.mercurial-scm.org/D6392 AFFECTED FILES rust/hg-cpython/src/lib.rs setup.py CHANGE DETAILS diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ ]) import sys, platform +import sysconfig if sys.version_info[0] >= 3: printf = eval('print') libdir_escape = 'unicode_escape' @@ -104,6 +105,12 @@ printf(error, file=sys.stderr) sys.exit(1) +if sys.version_info[0] >= 3: +DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX'] +else: +# deprecated in Python 3 +DYLIB_SUFFIX = sysconfig.get_config_vars()['SO'] + # Solaris Python packaging brain damage try: import hashlib @@ -1147,6 +1154,19 @@ for fname in fnames if os.path.splitext(fname)[1] == '.rs') +@staticmethod +def rust_dylib_suffix(): +"""Return the suffix for shared libraries produced by rustc. + +See also: https://doc.rust-lang.org/reference/linkage.html +""" +if sys.platform == 'darwin': +return '.dylib' +elif os.name == 'nt': +return '.dll' +else: +return '.so' + def rustbuild(self): if hgrustext is None: return @@ -1168,6 +1188,9 @@ if sys.version_info[0] == 3 and self.py3_features is not None: cargocmd.extend(('--features', self.py3_features, '--no-default-features')) +if sys.platform == 'darwin': +env['RUSTFLAGS'] = ("-C link-arg=-undefined " +"-C link-arg=dynamic_lookup") try: subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir) except OSError as exc: @@ -1212,9 +1235,9 @@ self.rustbuild() target = [target_dir] target.extend(self.name.split('.')) -ext = '.so' # TODO Unix only -target[-1] += ext -shutil.copy2(os.path.join(self.rusttargetdir, self.dylibname + ext), +target[-1] += DYLIB_SUFFIX +shutil.copy2(os.path.join(self.rusttargetdir, + self.dylibname + self.rust_dylib_suffix()), os.path.join(*target)) diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -23,7 +23,6 @@ extern crate cpython; extern crate hg; extern crate libc; -extern crate python27_sys; pub mod ancestors; mod cindex; To: gracinet, #hg-reviewers Cc: durin42, kevincox, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6392: rust-cpython: build for py3, Windows and MacOSX
gracinet created this revision. Herald added subscribers: mercurial-devel, kevincox, durin42. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Before this changeset, the shared library objects suffixes were both (rustc output and Python input) hardcoded to '.so', which is wrong for Python3 and non Linux targets. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6392 AFFECTED FILES rust/hg-cpython/src/lib.rs setup.py CHANGE DETAILS diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ ]) import sys, platform +import sysconfig if sys.version_info[0] >= 3: printf = eval('print') libdir_escape = 'unicode_escape' @@ -104,6 +105,12 @@ printf(error, file=sys.stderr) sys.exit(1) +if sys.version_info[0] >= 3: +DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX'] +else: +# deprecated in Python 3 +DYLIB_SUFFIX = sysconfig.get_config_vars()['SO'] + # Solaris Python packaging brain damage try: import hashlib @@ -1147,6 +1154,19 @@ for fname in fnames if os.path.splitext(fname)[1] == '.rs') +@staticmethod +def rust_dylib_suffix(): +"""Return the suffix for shared libraries produced by rustc. + +See also: https://doc.rust-lang.org/reference/linkage.html +""" +if sys.platform == 'darwin': +return '.dylib' +elif os.name == 'nt': +return '.dll' +else: +return '.so' + def rustbuild(self): if hgrustext is None: return @@ -1212,9 +1232,9 @@ self.rustbuild() target = [target_dir] target.extend(self.name.split('.')) -ext = '.so' # TODO Unix only -target[-1] += ext -shutil.copy2(os.path.join(self.rusttargetdir, self.dylibname + ext), +target[-1] += DYLIB_SUFFIX +shutil.copy2(os.path.join(self.rusttargetdir, + self.dylibname + self.rust_dylib_suffix()), os.path.join(*target)) diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -23,7 +23,6 @@ extern crate cpython; extern crate hg; extern crate libc; -extern crate python27_sys; pub mod ancestors; mod cindex; To: gracinet, #hg-reviewers Cc: durin42, kevincox, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6391: py3: make contrib/testparseutil.py to work on str(unicodes)
pulkit created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY contrib/check-code work on unicodes and call functions from testparseutil.py which before this patch used to work on bytes. This path removes that inconsistency and make testparseutil.py work on unicodes. This makes test-check-code.t and test-contrib-check-code.t work on Python 3 again. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6391 AFFECTED FILES contrib/testparseutil.py CHANGE DETAILS diff --git a/contrib/testparseutil.py b/contrib/testparseutil.py --- a/contrib/testparseutil.py +++ b/contrib/testparseutil.py @@ -54,7 +54,7 @@ return s.decode(u'latin-1') def opentext(f): -return open(f, 'rb') +return open(f, 'r') else: stdin = sys.stdin stdout = sys.stdout @@ -164,14 +164,14 @@ ... self.matchfunc = matchfunc ... def startsat(self, line): ... return self.matchfunc(line) ->>> ambig1 = ambigmatcher(b'ambiguous #1', -... lambda l: l.startswith(b' $ cat ')) ->>> ambig2 = ambigmatcher(b'ambiguous #2', -... lambda l: l.endswith(b'<< EOF\\n')) ->>> lines = [b' $ cat > foo.py << EOF\\n'] +>>> ambig1 = ambigmatcher('ambiguous #1', +... lambda l: l.startswith(' $ cat ')) +>>> ambig2 = ambigmatcher('ambiguous #2', +... lambda l: l.endswith('<< EOF\\n')) +>>> lines = [' $ cat > foo.py << EOF\\n'] >>> errors = [] >>> matchers = [ambig1, ambig2] ->>> list(t for t in embedded(b'', lines, errors, matchers)) +>>> list(t for t in embedded('', lines, errors, matchers)) [] >>> b2s(errors) [':1: ambiguous line for "ambiguous #1", "ambiguous #2"'] @@ -181,21 +181,21 @@ ctx = filename = code = startline = None # for pyflakes for lineno, line in enumerate(lines, 1): -if not line.endswith(b'\n'): -line += b'\n' # to normalize EOF line +if not line.endswith('\n'): +line += '\n' # to normalize EOF line if matcher: # now, inside embedded code if matcher.endsat(ctx, line): codeatend = matcher.codeatend(ctx, line) if codeatend is not None: code.append(codeatend) if not matcher.ignores(ctx): -yield (filename, startline, lineno, b''.join(code)) +yield (filename, startline, lineno, ''.join(code)) matcher = None # DO NOT "continue", because line might start next fragment elif not matcher.isinside(ctx, line): # this is an error of basefile # (if matchers are implemented correctly) -errors.append(b'%s:%d: unexpected line for "%s"' +errors.append('%s:%d: unexpected line for "%s"' % (basefile, lineno, matcher.desc)) # stop extracting embedded code by current 'matcher', # because appearance of unexpected line might mean @@ -218,9 +218,9 @@ if matched: if len(matched) > 1: # this is an error of matchers, maybe -errors.append(b'%s:%d: ambiguous line for %s' % +errors.append('%s:%d: ambiguous line for %s' % (basefile, lineno, - b', '.join([b'"%s"' % m.desc + ', '.join(['"%s"' % m.desc for m, c in matched]))) # omit extracting embedded code, because choosing # arbitrary matcher from matched ones might fail to @@ -239,68 +239,68 @@ if matcher: # examine whether EOF ends embedded code, because embedded # code isn't yet ended explicitly -if matcher.endsat(ctx, b'\n'): -codeatend = matcher.codeatend(ctx, b'\n') +if matcher.endsat(ctx, '\n'): +codeatend = matcher.codeatend(ctx, '\n') if codeatend is not None: code.append(codeatend) if not matcher.ignores(ctx): -yield (filename, startline, lineno + 1, b''.join(code)) +yield (filename, startline, lineno + 1, ''.join(code)) else: # this is an error of basefile # (if matchers are implemented correctly) -errors.append(b'%s:%d: unexpected end of file for "%s"' +errors.append('%s:%d: unexpected end of file for "%s"' % (basefile, lineno, matcher.desc)) # heredoc limit mark to ignore embedded code at check-code.py or so -heredocignorelimit = b'NO_CHECK_EOF' +heredocignorelimit = 'NO_CHECK_EOF' # the pattern to match against cases below, and to return a limit mark #
mercurial@42319: 24 new changesets
24 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/df2f22befdc8 changeset: 42296:df2f22befdc8 user:Martin von Zweigbergk date:Fri May 10 22:51:33 2019 -0700 summary: context: let caller pass in branch to committablectx.__init__() https://www.mercurial-scm.org/repo/hg/rev/62bb49a1d05d changeset: 42297:62bb49a1d05d user:Martin von Zweigbergk date:Fri May 10 22:24:47 2019 -0700 summary: context: default to using branch from dirstate only in workingctx https://www.mercurial-scm.org/repo/hg/rev/9c7f58180878 changeset: 42298:9c7f58180878 user:timeless date:Fri May 03 16:07:57 2019 -0400 summary: unshelve: add space to help https://www.mercurial-scm.org/repo/hg/rev/80a213f9ed87 changeset: 42299:80a213f9ed87 user:timeless date:Mon May 13 14:19:36 2019 -0400 summary: rebase: hide help for revisions.Predicates._destautoorphanrebase https://www.mercurial-scm.org/repo/hg/rev/278dcb24e535 changeset: 42300:278dcb24e535 user:Martin von Zweigbergk date:Tue Apr 23 13:29:13 2019 -0700 summary: copies: write empty entries in changeset when also writing to filelog https://www.mercurial-scm.org/repo/hg/rev/2a7109cc5a28 changeset: 42301:2a7109cc5a28 user:Martin von Zweigbergk date:Tue May 14 22:56:58 2019 -0700 summary: changelog: define changelogrevision.p[12]copies for null revision https://www.mercurial-scm.org/repo/hg/rev/d1786c1d34fa changeset: 42302:d1786c1d34fa user:Raphaël Gomès date:Mon May 06 22:48:09 2019 +0200 summary: rust-dirstate: add rust implementation of `parse_dirstate` and `pack_dirstate` https://www.mercurial-scm.org/repo/hg/rev/e240bec26626 changeset: 42303:e240bec26626 user:Raphaël Gomès date:Mon May 06 22:50:34 2019 +0200 summary: rust-dirstate: add rust-cpython bindings to the new parse/pack functions https://www.mercurial-scm.org/repo/hg/rev/9c6c0f736e1d changeset: 42304:9c6c0f736e1d user:Raphaël Gomès date:Mon May 06 22:51:10 2019 +0200 summary: rust-dirstate: call parse/pack bindings from Python https://www.mercurial-scm.org/repo/hg/rev/eefe3d669beb changeset: 42305:eefe3d669beb user:Pulkit Goyal <7895pul...@gmail.com> date:Wed May 15 20:37:39 2019 +0300 summary: py3: add a r'' to prevent transformer adding b'' https://www.mercurial-scm.org/repo/hg/rev/181583d30539 changeset: 42306:181583d30539 user:Pulkit Goyal <7895pul...@gmail.com> date:Wed May 15 21:02:32 2019 +0300 summary: py3: add 5 new passing tests https://www.mercurial-scm.org/repo/hg/rev/264a2cbb25d0 changeset: 42307:264a2cbb25d0 user:Kyle Lippincott date:Tue Oct 16 04:59:36 2018 -0700 summary: graphmod: remove support for graph lines mixing parent/grandparent styles (BC) https://www.mercurial-scm.org/repo/hg/rev/1ce46f0ee218 changeset: 42308:1ce46f0ee218 user:Martin von Zweigbergk date:Tue May 14 09:13:39 2019 -0700 summary: log: remove an unnecessary "and opts.get('rev')" condition https://www.mercurial-scm.org/repo/hg/rev/604c086ddde6 changeset: 42309:604c086ddde6 user:Martin von Zweigbergk date:Wed May 01 09:34:47 2019 -0700 summary: log: add config for making `hg log -G` always topo-sorted https://www.mercurial-scm.org/repo/hg/rev/21eda240be07 changeset: 42310:21eda240be07 user:timeless date:Wed May 15 10:54:36 2019 -0400 summary: bisect: do not crash with rewritten commits https://www.mercurial-scm.org/repo/hg/rev/ec5bd3ab26bf changeset: 42311:ec5bd3ab26bf user:Martin von Zweigbergk date:Wed May 15 10:13:29 2019 -0700 summary: bookmarks: use context manager when writing files https://www.mercurial-scm.org/repo/hg/rev/2b77183ac477 changeset: 42312:2b77183ac477 user:Martin von Zweigbergk date:Wed May 15 10:19:36 2019 -0700 summary: bookmarks: use vfs.tryread() instead of reimplementing it https://www.mercurial-scm.org/repo/hg/rev/81ece800576a changeset: 42313:81ece800576a user:Martin von Zweigbergk date:Wed May 15 11:38:45 2019 -0700 summary: tests: separate out bookmarks tests from test-share.t https://www.mercurial-scm.org/repo/hg/rev/314056e438a9 changeset: 42314:314056e438a9 user:Martin von Zweigbergk date:Wed May 15 11:53:22 2019 -0700 summary: tests: fix share test to actually share the repo https://www.mercurial-scm.org/repo/hg/rev/c77857693005 changeset: 42315:c77857693005 user:Martin von Zweigbergk date:Wed May 15 23:26:05 2019 -0700 summary: help: add missing blank line, making "revlog-compression" show up https://www.mercurial-scm.org/repo/hg/rev/c07dcf7a0247 changeset: 42316:c07dcf7a0247 user:Augie Fackler date:Wed May 15 17:18:57 2019 -0400 summary: exthelper: add some semi-useful trace logs
D6390: commit: move sorting of added and removed files list to lower level
martinvonz added a comment. In https://phab.mercurial-scm.org/D6390#92963, @pulkit wrote: > The changes looks okay but I can't think why you want to do that. Can you add some details about the motivation for this change to commit message? It was mostly just consistency, but I'll add a bit more REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6390 To: martinvonz, #hg-reviewers Cc: pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6368: tests: add test for {file_mods}, {file_adds}, {file_dels} on merge commit
martinvonz updated this revision to Diff 15152. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6368?vs=15080=15152 REVISION DETAIL https://phab.mercurial-scm.org/D6368 AFFECTED FILES mercurial/context.py tests/test-template-keywords.t CHANGE DETAILS diff --git a/tests/test-template-keywords.t b/tests/test-template-keywords.t --- a/tests/test-template-keywords.t +++ b/tests/test-template-keywords.t @@ -798,6 +798,23 @@ fourth third +Test files lists on merge commit: + + $ hg co '.^' -q + $ touch c + $ hg add c + $ hg ci -qm 'add file' + $ hg merge 10 -q + $ hg ci -m 'merge' + $ hg log -l1 -T '{files}\n' + a fourth + $ hg log -l1 -T '{file_mods}\n' + third + $ hg log -l1 -T '{file_adds}\n' + b fifth + $ hg log -l1 -T '{file_dels}\n' + a fourth + Test file copies dict: $ hg log -r8 -T '{join(file_copies, " ")}\n' @@ -818,7 +835,7 @@ Test file attributes: - $ hg log -l1 -T '{files % "{status} {pad(size, 3, left=True)} {path}\n"}' + $ hg log -r10 -T '{files % "{status} {pad(size, 3, left=True)} {path}\n"}' R a A 0 b A 7 fifth @@ -834,7 +851,7 @@ Test index keyword: - $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n' + $ hg log -r 10:9 -T '{index + 10}{files % " {index}:{file}"}\n' 10 0:a 1:b 2:fifth 3:fourth 4:third 11 0:a diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -465,8 +465,8 @@ return self._changeset.files def filesmodified(self): modified = set(self.files()) -modified.difference_update(self.added()) -modified.difference_update(self.removed()) +modified.difference_update(self.filesadded()) +modified.difference_update(self.filesremoved()) return sorted(modified) def filesadded(self): added = [] To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6369: templatekw: get file_{adds, mods, dels} directly from context (issue4292)
martinvonz updated this revision to Diff 15153. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6369?vs=15082=15153 REVISION DETAIL https://phab.mercurial-scm.org/D6369 AFFECTED FILES mercurial/templatekw.py relnotes/next tests/test-template-keywords.t CHANGE DETAILS diff --git a/tests/test-template-keywords.t b/tests/test-template-keywords.t --- a/tests/test-template-keywords.t +++ b/tests/test-template-keywords.t @@ -809,9 +809,9 @@ $ hg log -l1 -T '{files}\n' a fourth $ hg log -l1 -T '{file_mods}\n' - third + $ hg log -l1 -T '{file_adds}\n' - b fifth + $ hg log -l1 -T '{file_dels}\n' a fourth diff --git a/relnotes/next b/relnotes/next --- a/relnotes/next +++ b/relnotes/next @@ -15,9 +15,22 @@ == Bug Fixes == + * issue4292: "hg log and {files} {file_adds} {file_mods} {file_dels} + in template show wrong files on merged revision". See details in + "Backwards Compatibility Changes". + == Backwards Compatibility Changes == + * Template keyword `{file_mods}`, `{file_adds}`, and `{file_dels}` + have changed behavior on merge commits. They used to be relative to + the first parent, but they now consider both parents. `{file_adds}` + shows files that exists in the commit but did not exist in either + parent. `{file_dels}` shows files that do not exist in the commit + but existed in either parent. `{file_mods}` show the remaining + files from `{files}` that were not in the other two + sets. + == Internal API Changes == diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -290,11 +290,6 @@ statmap.update((f, char) for f in files) return revcache['filestatusmap'] # {path: statchar} -def _showfilesbystat(context, mapping, name, index): -stat = _getfilestatus(context, mapping) -files = stat[index] -return templateutil.compatfileslist(context, mapping, name, files) - @templatekeyword('file_copies', requires={'repo', 'ctx', 'cache', 'revcache'}) def showfilecopies(context, mapping): @@ -332,17 +327,23 @@ @templatekeyword('file_adds', requires={'ctx', 'revcache'}) def showfileadds(context, mapping): """List of strings. Files added by this changeset.""" -return _showfilesbystat(context, mapping, 'file_add', 1) +ctx = context.resource(mapping, 'ctx') +return templateutil.compatfileslist(context, mapping, 'file_add', +ctx.filesadded()) @templatekeyword('file_dels', requires={'ctx', 'revcache'}) def showfiledels(context, mapping): """List of strings. Files removed by this changeset.""" -return _showfilesbystat(context, mapping, 'file_del', 2) +ctx = context.resource(mapping, 'ctx') +return templateutil.compatfileslist(context, mapping, 'file_del', +ctx.filesremoved()) @templatekeyword('file_mods', requires={'ctx', 'revcache'}) def showfilemods(context, mapping): """List of strings. Files modified by this changeset.""" -return _showfilesbystat(context, mapping, 'file_mod', 0) +ctx = context.resource(mapping, 'ctx') +return templateutil.compatfileslist(context, mapping, 'file_mod', +ctx.filesmodified()) @templatekeyword('files', requires={'ctx'}) def showfiles(context, mapping): To: martinvonz, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6367: context: add ctx.files{modified,added,removed}() methods
martinvonz updated this revision to Diff 15151. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6367?vs=15079=15151 REVISION DETAIL https://phab.mercurial-scm.org/D6367 AFFECTED FILES mercurial/context.py CHANGE DETAILS diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -463,6 +463,24 @@ return self._changeset.date def files(self): return self._changeset.files +def filesmodified(self): +modified = set(self.files()) +modified.difference_update(self.added()) +modified.difference_update(self.removed()) +return sorted(modified) +def filesadded(self): +added = [] +for f in self.files(): +if not any(f in p for p in self.parents()): +added.append(f) +return added +def filesremoved(self): +removed = [] +for f in self.files(): +if f not in self: +removed.append(f) +return removed + @propertycache def _copies(self): source = self._repo.ui.config('experimental', 'copies.read-from') @@ -1170,6 +1188,10 @@ return self._status.removed def deleted(self): return self._status.deleted +filesmodified = modified +filesadded = added +filesremoved = removed + def branch(self): return encoding.tolocal(self._extra['branch']) def closesbranch(self): To: martinvonz, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6390: commit: move sorting of added and removed files list to lower level
pulkit added a comment. The changes looks okay but I can't think why you want to do that. Can you add some details about the motivation for this change to commit message? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6390 To: martinvonz, #hg-reviewers Cc: pulkit, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6390: commit: move sorting of added and removed files list to lower level
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY localrepo.commitctx() has lists of all changed files, as well as lists of added and removed files. The list of all files is unsorted and changelog.add() will sort it. Let's also sort the lists of added and removed files at a lower level (manifestrevlog.add()) for consistency. I don't think this will be a performance problem (someone should have fixed the sorting in changelog.add() if it were). REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6390 AFFECTED FILES mercurial/localrepo.py mercurial/manifest.py CHANGE DETAILS diff --git a/mercurial/manifest.py b/mercurial/manifest.py --- a/mercurial/manifest.py +++ b/mercurial/manifest.py @@ -1486,8 +1486,8 @@ _checkforbidden(added) # combine the changed lists into one sorted iterator -work = heapq.merge([(x, False) for x in added], - [(x, True) for x in removed]) +work = heapq.merge([(x, False) for x in sorted(added)], + [(x, True) for x in sorted(removed)]) arraytext, deltatext = m.fastdelta(self.fulltextcache[p1], work) cachedelta = self._revlog.rev(p1), deltatext diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2615,8 +2615,8 @@ raise # update manifest -removed = [f for f in sorted(removed) if f in m1 or f in m2] -drop = [f for f in removed if f in m] +removed = [f for f in removed if f in m1 or f in m2] +drop = sorted([f for f in removed if f in m]) for f in drop: del m[f] files = changed + removed To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6272: rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
This revision was automatically updated to reflect the committed changes. Closed by commit rHG611b8953c93c: rust-filepatterns: add `rust-cpython` bindings for `filepatterns` (authored by Alphare, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6272?vs=15142=15148 REVISION DETAIL https://phab.mercurial-scm.org/D6272 AFFECTED FILES rust/hg-cpython/src/ancestors.rs rust/hg-cpython/src/exceptions.rs rust/hg-cpython/src/filepatterns.rs rust/hg-cpython/src/lib.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -32,6 +32,7 @@ pub mod discovery; pub mod exceptions; pub mod dirstate; +pub mod filepatterns; py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| { m.add( @@ -45,6 +46,9 @@ m.add(py, "dagop", dagops::init_module(py, _name)?)?; m.add(py, "discovery", discovery::init_module(py, _name)?)?; m.add(py, "dirstate", dirstate::init_module(py, _name)?)?; +m.add(py, "filepatterns", filepatterns::init_module(py, _name)?)?; m.add(py, "GraphError", py.get_type::())?; +m.add(py, "PatternFileError", py.get_type::())?; +m.add(py, "PatternError", py.get_type::())?; Ok(()) }); diff --git a/rust/hg-cpython/src/ancestors.rs b/rust/hg-cpython/src/filepatterns.rs copy from rust/hg-cpython/src/ancestors.rs copy to rust/hg-cpython/src/filepatterns.rs --- a/rust/hg-cpython/src/ancestors.rs +++ b/rust/hg-cpython/src/filepatterns.rs @@ -1,220 +1,115 @@ -// ancestors.rs +// filepatterns.rs // -// Copyright 2018 Georges Racinet +// Copyright 2019, Georges Racinet , +// Raphaël Gomès // // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. -//! Bindings for the `hg::ancestors` module provided by the -//! `hg-core` crate. From Python, this will be seen as `rustext.ancestor` -//! and can be used as replacement for the the pure `ancestor` Python module. -//! -//! # Classes visible from Python: -//! - [`LazyAncestors`] is the Rust implementation of -//! `mercurial.ancestor.lazyancestors`. The only difference is that it is -//! instantiated with a C `parsers.index` instance instead of a parents -//! function. -//! -//! - [`MissingAncestors`] is the Rust implementation of -//! `mercurial.ancestor.incrementalmissingancestors`. +//! Bindings for the `hg::filepatterns` module provided by the +//! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns` +//! and can be used as replacement for the the pure `filepatterns` Python module. //! -//! API differences: -//!+ it is instantiated with a C `parsers.index` -//! instance instead of a parents function. -//!+ `MissingAncestors.bases` is a method returning a tuple instead of -//! a set-valued attribute. We could return a Python set easily if our -//! [PySet PR](https://github.com/dgrunwald/rust-cpython/pull/165) -//! is accepted. -//! -//! - [`AncestorsIterator`] is the Rust counterpart of the -//! `ancestor._lazyancestorsiter` Python generator. From Python, instances of -//! this should be mainly obtained by calling `iter()` on a [`LazyAncestors`] -//! instance. -//! -//! [`LazyAncestors`]: struct.LazyAncestors.html -//! [`MissingAncestors`]: struct.MissingAncestors.html -//! [`AncestorsIterator`]: struct.AncestorsIterator.html -use crate::conversion::{py_set, rev_pyiter_collect}; -use cindex::Index; use cpython::{ -ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, PyResult, -Python, PythonObject, ToPyObject, +exc, PyDict, PyErr, PyModule, PyResult, PyString, PyTuple, Python, +ToPyObject, }; -use exceptions::GraphError; -use hg::Revision; -use hg::{ -AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy, -MissingAncestors as CoreMissing, +use hg::{build_single_regex, read_pattern_file, PatternTuple}; +use exceptions::{ +PatternError, +PatternFileError, }; -use std::cell::RefCell; -use std::collections::HashSet; -py_class!(pub class AncestorsIterator |py| { -data inner: RefCell>>; - -def __next__() -> PyResult> { -match self.inner(py).borrow_mut().next() { -Some(Err(e)) => Err(GraphError::pynew(py, e)), -None => Ok(None), -Some(Ok(r)) => Ok(Some(r)), +/// Rust does not like functions with different return signatures. +/// The 3-tuple version is always returned by the hg-core function, +/// the (potential) conversion is handled at this level since it is not likely +/// to have any measurable impact on performance. +/// +/// The Python implementation passes a function reference for `warn` instead +/// of a boolean that is used to emit warnings while parsing. The Rust +/// implementation chooses to accumulate the warnings and propagate them to +/// Python upon completion. See the `readpatternfile`
D6271: rust-filepatterns: add a Rust implementation of pattern-related utils
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb05c1041de8f: rust-filepatterns: add a Rust implementation of pattern-related utils (authored by Alphare, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D6271?vs=15141=15147#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6271?vs=15141=15147 REVISION DETAIL https://phab.mercurial-scm.org/D6271 AFFECTED FILES rust/Cargo.lock rust/hg-core/Cargo.toml rust/hg-core/src/ancestors.rs rust/hg-core/src/lib.rs CHANGE DETAILS diff --git a/rust/hg-core/src/lib.rs b/rust/hg-core/src/lib.rs --- a/rust/hg-core/src/lib.rs +++ b/rust/hg-core/src/lib.rs @@ -4,6 +4,9 @@ // GNU General Public License version 2 or any later version. extern crate byteorder; extern crate memchr; +#[macro_use] +extern crate lazy_static; +extern crate regex; mod ancestors; pub mod dagops; @@ -15,6 +18,11 @@ pack_dirstate, parse_dirstate, CopyVec, CopyVecEntry, DirstateEntry, DirstateParents, DirstateVec, }; +mod filepatterns; + +pub use filepatterns::{ +build_single_regex, read_pattern_file, PatternSyntax, PatternTuple, +}; /// Mercurial revision numbers /// @@ -42,6 +50,8 @@ fn parents(, Revision) -> Result<[Revision; 2], GraphError>; } +pub type LineNumber = usize; + #[derive(Clone, Debug, PartialEq)] pub enum GraphError { ParentOutOfRange(Revision), @@ -73,3 +83,20 @@ DirstateParseError::CorruptedEntry(e.to_string()) } } + +#[derive(Debug)] +pub enum PatternError { +UnsupportedSyntax(String), +} + +#[derive(Debug)] +pub enum PatternFileError { +IO(std::io::Error), +Pattern(PatternError, LineNumber), +} + +impl From for PatternFileError { +fn from(e: std::io::Error) -> Self { +PatternFileError::IO(e) +} +} diff --git a/rust/hg-core/src/ancestors.rs b/rust/hg-core/src/ancestors.rs --- a/rust/hg-core/src/ancestors.rs +++ b/rust/hg-core/src/ancestors.rs @@ -8,9 +8,9 @@ //! Rust versions of generic DAG ancestors algorithms for Mercurial use super::{Graph, GraphError, Revision, NULL_REVISION}; +use crate::dagops; use std::cmp::max; use std::collections::{BinaryHeap, HashSet}; -use crate::dagops; /// Iterator over the ancestors of a given list of revisions /// This is a generic type, defined and implemented for any Graph, so that diff --git a/rust/hg-core/Cargo.toml b/rust/hg-core/Cargo.toml --- a/rust/hg-core/Cargo.toml +++ b/rust/hg-core/Cargo.toml @@ -9,6 +9,8 @@ [dependencies] byteorder = "1.3.1" +lazy_static = "1.3.0" memchr = "2.2.0" rand = "> 0.6.4" rand_pcg = "> 0.1.0" +regex = "^1.1" diff --git a/rust/Cargo.lock b/rust/Cargo.lock --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -50,9 +50,11 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -76,7 +78,7 @@ [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; [[package]] @@ -262,7 +264,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -302,7 +304,7 @@ "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940" "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" =
D6273: rust-filepatterns: call new Rust implementations from Python
This revision was automatically updated to reflect the committed changes. Closed by commit rHG89770f21aac3: rust-filepatterns: call new Rust implementations from Python (authored by Alphare, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6273?vs=15143=15149 REVISION DETAIL https://phab.mercurial-scm.org/D6273 AFFECTED FILES mercurial/match.py tests/common-pattern.py CHANGE DETAILS diff --git a/tests/common-pattern.py b/tests/common-pattern.py --- a/tests/common-pattern.py +++ b/tests/common-pattern.py @@ -115,6 +115,11 @@ # Various platform error strings, keyed on a common replacement string _errors = { br'$ENOENT$': ( +# IOError in Python does not have the same error message +# than in Rust, and automatic conversion is not possible +# because of module member privacy. +br'No such file or directory \(os error 2\)', + # strerror() br'No such file or directory', diff --git a/mercurial/match.py b/mercurial/match.py --- a/mercurial/match.py +++ b/mercurial/match.py @@ -24,6 +24,12 @@ stringutil, ) +try: +from . import rustext +rustext.__name__ # force actual import (see hgdemandimport) +except ImportError: +rustext = None + allpatternkinds = ('re', 'glob', 'path', 'relglob', 'relpath', 'relre', 'rootglob', 'listfile', 'listfile0', 'set', 'include', 'subinclude', @@ -1175,8 +1181,22 @@ return res def _regex(kind, pat, globsuffix): -'''Convert a (normalized) pattern of any kind into a regular expression. +'''Convert a (normalized) pattern of any kind into a +regular expression. globsuffix is appended to the regexp of globs.''' + +if rustext is not None: +try: +return rustext.filepatterns.build_single_regex( +kind, +pat, +globsuffix +) +except rustext.filepatterns.PatternError: +raise error.ProgrammingError( +'not a regex pattern: %s:%s' % (kind, pat) +) + if not pat: return '' if kind == 're': @@ -1418,9 +1438,24 @@ pattern# pattern of the current default type if sourceinfo is set, returns a list of tuples: -(pattern, lineno, originalline). This is useful to debug ignore patterns. +(pattern, lineno, originalline). +This is useful to debug ignore patterns. ''' +if rustext is not None: +result, warnings = rustext.filepatterns.read_pattern_file( +filepath, +bool(warn), +sourceinfo, +) + +for warning_params in warnings: +# Can't be easily emitted from Rust, because it would require +# a mechanism for both gettext and calling the `warn` function. +warn(_("%s: ignoring invalid syntax '%s'\n") % warning_params) + +return result + syntaxes = { 're': 'relre:', 'regexp': 'relre:', To: Alphare, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6257: rust-discovery: core implementation for take_quick_sample()
This revision was automatically updated to reflect the committed changes. Closed by commit rHGd09bdb2a1f75: rust-discovery: core implementation for take_quick_sample() (authored by gracinet, committed by ). CHANGED PRIOR TO COMMIT https://phab.mercurial-scm.org/D6257?vs=15021=15145#toc REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6257?vs=15021=15145 REVISION DETAIL https://phab.mercurial-scm.org/D6257 AFFECTED FILES rust/hg-core/Cargo.toml rust/hg-core/src/discovery.rs CHANGE DETAILS diff --git a/rust/hg-core/src/discovery.rs b/rust/hg-core/src/discovery.rs --- a/rust/hg-core/src/discovery.rs +++ b/rust/hg-core/src/discovery.rs @@ -10,23 +10,95 @@ //! This is a Rust counterpart to the `partialdiscovery` class of //! `mercurial.setdiscovery` -use super::{Graph, GraphError, Revision}; +extern crate rand; +extern crate rand_pcg; +use self::rand::seq::SliceRandom; +use self::rand::{thread_rng, RngCore, SeedableRng}; +use super::{Graph, GraphError, Revision, NULL_REVISION}; use crate::ancestors::MissingAncestors; use crate::dagops; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet, VecDeque}; + +type Rng = self::rand_pcg::Pcg32; pub struct PartialDiscovery { target_heads: Option>, graph: G, // plays the role of self._repo common: MissingAncestors, undecided: Option>, missing: HashSet, +rng: Rng, } pub struct DiscoveryStats { pub undecided: Option, } +/// Update an existing sample to match the expected size +/// +/// The sample is updated with revisions exponentially distant from each +/// element of `heads`. +/// +/// If a target size is specified, the sampling will stop once this size is +/// reached. Otherwise sampling will happen until roots of the set are +/// reached. +/// +/// - `revs`: set of revs we want to discover (if None, `assume` the whole dag +/// represented by `parentfn` +/// - `heads`: set of DAG head revs +/// - `sample`: a sample to update +/// - `parentfn`: a callable to resolve parents for a revision +/// - `quicksamplesize`: optional target size of the sample +fn update_sample( +revs: Option<>, +heads: impl IntoIterator, +sample: HashSet, +parentsfn: impl Fn(Revision) -> Result<[Revision; 2], GraphError>, +quicksamplesize: Option, +) -> Result<(), GraphError> { +let mut distances: HashMap = HashMap::new(); +let mut visit: VecDeque = heads.into_iter().collect(); +let mut factor: u32 = 1; +let mut seen: HashSet = HashSet::new(); +loop { +let current = match visit.pop_front() { +None => { +break; +} +Some(r) => r, +}; +if !seen.insert(current) { +continue; +} + +let d = *distances.entry(current).or_insert(1); +if d > factor { +factor *= 2; +} +if d == factor { +sample.insert(current); +if let Some(sz) = quicksamplesize { +if sample.len() >= sz { +return Ok(()); +} +} +} +for in (current)? { +if p == NULL_REVISION { +continue; +} +if let Some(revs) = revs { +if !revs.contains() { +continue; +} +} +distances.entry(p).or_insert(d + 1); +visit.push_back(p); +} +} +Ok(()) +} + impl PartialDiscovery { /// Create a PartialDiscovery object, with the intent /// of comparing our `::` revset to the contents of another @@ -39,15 +111,47 @@ /// we'll have to make it a type argument of `PartialDiscovery` or a trait /// object since we'll keep it in the meanwhile pub fn new(graph: G, target_heads: Vec) -> Self { +let mut seed: [u8; 16] = [0; 16]; +thread_rng().fill_bytes( seed); +Self::new_with_seed(graph, target_heads, seed) +} + +pub fn new_with_seed( +graph: G, +target_heads: Vec, +seed: [u8; 16], +) -> Self { PartialDiscovery { undecided: None, target_heads: Some(target_heads), graph: graph.clone(), common: MissingAncestors::new(graph, vec![]), missing: HashSet::new(), +rng: Rng::from_seed(seed), } } +/// Extract at most `size` random elements from sample and return them +/// as a vector +fn limit_sample( + self, +mut sample: Vec, +size: usize, +) -> Vec { +let sample_len = sample.len(); +if sample_len <= size { +return sample; +} +let rng = self.rng; +let dropped_size = sample_len - size; +let limited_slice = if size < dropped_size { +sample.partial_shuffle(rng, size).0 +} else { +sample.partial_shuffle(rng,
D6260: rust-discovery: takefullsample() core implementation
This revision was automatically updated to reflect the committed changes. gracinet marked an inline comment as done. Closed by commit rHG6a8aec3f03df: rust-discovery: takefullsample() core implementation (authored by gracinet, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6260?vs=15022=15146 REVISION DETAIL https://phab.mercurial-scm.org/D6260 AFFECTED FILES rust/hg-core/src/discovery.rs CHANGE DETAILS diff --git a/rust/hg-core/src/discovery.rs b/rust/hg-core/src/discovery.rs --- a/rust/hg-core/src/discovery.rs +++ b/rust/hg-core/src/discovery.rs @@ -26,6 +26,7 @@ graph: G, // plays the role of self._repo common: MissingAncestors, undecided: Option>, +children_cache: Option>>, missing: HashSet, rng: Rng, } @@ -49,13 +50,16 @@ /// - `sample`: a sample to update /// - `parentfn`: a callable to resolve parents for a revision /// - `quicksamplesize`: optional target size of the sample -fn update_sample( +fn update_sample( revs: Option<>, heads: impl IntoIterator, sample: HashSet, -parentsfn: impl Fn(Revision) -> Result<[Revision; 2], GraphError>, +parentsfn: impl Fn(Revision) -> Result, quicksamplesize: Option, -) -> Result<(), GraphError> { +) -> Result<(), GraphError> +where +I: Iterator, +{ let mut distances: HashMap = HashMap::new(); let mut visit: VecDeque = heads.into_iter().collect(); let mut factor: u32 = 1; @@ -83,10 +87,7 @@ } } } -for in (current)? { -if p == NULL_REVISION { -continue; -} +for p in parentsfn(current)? { if let Some(revs) = revs { if !revs.contains() { continue; @@ -99,6 +100,39 @@ Ok(()) } +struct ParentsIterator { +parents: [Revision; 2], +cur: usize, +} + +impl ParentsIterator { +fn graph_parents( +graph: Graph, +r: Revision, +) -> Result { +Ok(ParentsIterator { +parents: graph.parents(r)?, +cur: 0, +}) +} +} + +impl Iterator for ParentsIterator { +type Item = Revision; + +fn next( self) -> Option { +if self.cur > 1 { +return None; +} +let rev = self.parents[self.cur]; +self.cur += 1; +if rev == NULL_REVISION { +return self.next(); +} +Some(rev) +} +} + impl PartialDiscovery { /// Create a PartialDiscovery object, with the intent /// of comparing our `::` revset to the contents of another @@ -123,6 +157,7 @@ ) -> Self { PartialDiscovery { undecided: None, +children_cache: None, target_heads: Some(target_heads), graph: graph.clone(), common: MissingAncestors::new(graph, vec![]), @@ -228,6 +263,22 @@ Ok(()) } +fn ensure_children_cache( self) -> Result<(), GraphError> { +if self.children_cache.is_some() { +return Ok(()); +} +self.ensure_undecided()?; + +let mut children: HashMap> = HashMap::new(); +for in self.undecided.as_ref().unwrap() { +for p in ParentsIterator::graph_parents(, rev)? { +children.entry(p).or_insert_with(|| Vec::new()).push(rev); +} +} +self.children_cache = Some(children); +Ok(()) +} + /// Provide statistics about the current state of the discovery process pub fn stats() -> DiscoveryStats { DiscoveryStats { @@ -255,11 +306,104 @@ None, headrevs, sample, -|r| self.graph.parents(r), +|r| ParentsIterator::graph_parents(, r), Some(size), )?; Ok(sample.into_iter().collect()) } + +/// Extract a sample from `self.undecided`, going from its heads and roots. +/// +/// The `size` parameter is used to avoid useless computations if +/// it turns out to be bigger than the whole set of undecided Revisions. +/// +/// The sample is taken by using `update_sample` from the heads, then +/// from the roots, working on the reverse DAG, +/// expressed by `self.children_cache`. +/// +/// No effort is being made to complete or limit the sample to `size` +fn bidirectional_sample( + self, +size: usize, +) -> Result, GraphError> { +self.ensure_undecided()?; +{ +// we don't want to compute children_cache before this +// but doing it after extracting self.undecided takes a mutable +// ref to self while a shareable one is still active. +let undecided = self.undecided.as_ref().unwrap(); +if undecided.len() <= size { +return Ok(undecided.clone()); +} +} + +self.ensure_children_cache()?; +let revs =
D6389: rust-dirstate: create dirstate submodule
Alphare created this revision. Herald added subscribers: mercurial-devel, kevincox, durin42. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This change is here to facilitate a future patch that is written in a different file. I expect this module to grow a few different files. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6389 AFFECTED FILES rust/hg-core/src/dirstate.rs rust/hg-core/src/dirstate/mod.rs rust/hg-core/src/dirstate/parsers.rs rust/hg-core/src/lib.rs CHANGE DETAILS diff --git a/rust/hg-core/src/lib.rs b/rust/hg-core/src/lib.rs --- a/rust/hg-core/src/lib.rs +++ b/rust/hg-core/src/lib.rs @@ -16,6 +16,9 @@ pub mod testing; // unconditionally built, for use from integration tests pub use dirstate::{ pack_dirstate, parse_dirstate, CopyVec, CopyVecEntry, DirstateEntry, +parsers::{pack_dirstate, parse_dirstate}, +CopyVec, +CopyVecEntry, DirstateEntry, DirsIterable, DirstateParents, DirstateVec, }; mod filepatterns; diff --git a/rust/hg-core/src/dirstate/parsers.rs b/rust/hg-core/src/dirstate/parsers.rs new file mode 100644 --- /dev/null +++ b/rust/hg-core/src/dirstate/parsers.rs @@ -0,0 +1,388 @@ +// Copyright 2019 Raphaël Gomès +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; +use std::collections::{HashMap, HashSet}; +use std::io::Cursor; +use { +CopyVec, CopyVecEntry, DirstateEntry, DirstatePackError, DirstateParents, +DirstateParseError, DirstateVec, +}; + +/// Parents are stored in the dirstate as byte hashes. +const PARENT_SIZE: usize = 20; +/// Dirstate entries have a static part of 8 + 32 + 32 + 32 + 32 bits. +const MIN_ENTRY_SIZE: usize = 17; + +pub fn parse_dirstate( +contents: &[u8], +) -> Result<(DirstateParents, DirstateVec, CopyVec), DirstateParseError> { +if contents.len() < PARENT_SIZE * 2 { +return Err(DirstateParseError::TooLittleData); +} + +let mut dirstate_vec = vec![]; +let mut copies = vec![]; +let mut curr_pos = PARENT_SIZE * 2; +let parents = DirstateParents { +p1: [..PARENT_SIZE], +p2: [PARENT_SIZE..curr_pos], +}; + +while curr_pos < contents.len() { +if curr_pos + MIN_ENTRY_SIZE > contents.len() { +return Err(DirstateParseError::Overflow); +} +let entry_bytes = [curr_pos..]; + +let mut cursor = Cursor::new(entry_bytes); +let state = cursor.read_i8()?; +let mode = cursor.read_i32::()?; +let size = cursor.read_i32::()?; +let mtime = cursor.read_i32::()?; +let path_len = cursor.read_i32::()? as usize; + +if path_len > contents.len() - curr_pos { +return Err(DirstateParseError::Overflow); +} + +// Slice instead of allocating a Vec needed for `read_exact` +let path = _bytes[MIN_ENTRY_SIZE..MIN_ENTRY_SIZE + (path_len)]; + +let (path, copy) = match memchr::memchr(0, path) { +None => (path, None), +Some(i) => ([..i], Some([(i + 1)..])), +}; + +if let Some(copy_path) = copy { +copies.push(CopyVecEntry { path, copy_path }); +}; +dirstate_vec.push(( +path.to_owned(), +DirstateEntry { +state, +mode, +size, +mtime, +}, +)); +curr_pos = curr_pos + MIN_ENTRY_SIZE + (path_len); +} + +Ok((parents, dirstate_vec, copies)) +} + +pub fn pack_dirstate( +dirstate_vec: , +copymap: , Vec>, +parents: DirstateParents, +now: i32, +) -> Result<(Vec, DirstateVec), DirstatePackError> { +if parents.p1.len() != PARENT_SIZE || parents.p2.len() != PARENT_SIZE { +return Err(DirstatePackError::CorruptedParent); +} + +let expected_size: usize = dirstate_vec +.iter() +.map(|(ref filename, _)| { +let mut length = MIN_ENTRY_SIZE + filename.len(); +if let Some(ref copy) = copymap.get(filename) { +length += copy.len() + 1; +} +length +}) +.sum(); +let expected_size = expected_size + PARENT_SIZE * 2; + +let mut packed = Vec::with_capacity(expected_size); +let mut new_dirstate_vec = vec![]; + +packed.extend(parents.p1); +packed.extend(parents.p2); + +for (ref filename, entry) in dirstate_vec { +let mut new_filename: Vec = filename.to_owned(); +let mut new_mtime: i32 = entry.mtime; +if entry.state == 'n' as i8 && entry.mtime == now.into() { +// The file was last modified "simultaneously" with the current +// write to dirstate (i.e. within the same second for file- +// systems with a granularity of 1 sec). This commonly happens +// for at least a couple of files on
D6272: rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Alphare updated this revision to Diff 15142. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6272?vs=14841=15142 REVISION DETAIL https://phab.mercurial-scm.org/D6272 AFFECTED FILES rust/hg-cpython/src/ancestors.rs rust/hg-cpython/src/exceptions.rs rust/hg-cpython/src/filepatterns.rs rust/hg-cpython/src/lib.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -32,6 +32,7 @@ pub mod discovery; pub mod exceptions; pub mod dirstate; +pub mod filepatterns; py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| { m.add( @@ -45,6 +46,9 @@ m.add(py, "dagop", dagops::init_module(py, _name)?)?; m.add(py, "discovery", discovery::init_module(py, _name)?)?; m.add(py, "dirstate", dirstate::init_module(py, _name)?)?; +m.add(py, "filepatterns", filepatterns::init_module(py, _name)?)?; m.add(py, "GraphError", py.get_type::())?; +m.add(py, "PatternFileError", py.get_type::())?; +m.add(py, "PatternError", py.get_type::())?; Ok(()) }); diff --git a/rust/hg-cpython/src/ancestors.rs b/rust/hg-cpython/src/filepatterns.rs copy from rust/hg-cpython/src/ancestors.rs copy to rust/hg-cpython/src/filepatterns.rs --- a/rust/hg-cpython/src/ancestors.rs +++ b/rust/hg-cpython/src/filepatterns.rs @@ -1,220 +1,115 @@ -// ancestors.rs +// filepatterns.rs // -// Copyright 2018 Georges Racinet +// Copyright 2019, Georges Racinet , +// Raphaël Gomès // // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. -//! Bindings for the `hg::ancestors` module provided by the -//! `hg-core` crate. From Python, this will be seen as `rustext.ancestor` -//! and can be used as replacement for the the pure `ancestor` Python module. -//! -//! # Classes visible from Python: -//! - [`LazyAncestors`] is the Rust implementation of -//! `mercurial.ancestor.lazyancestors`. The only difference is that it is -//! instantiated with a C `parsers.index` instance instead of a parents -//! function. -//! -//! - [`MissingAncestors`] is the Rust implementation of -//! `mercurial.ancestor.incrementalmissingancestors`. +//! Bindings for the `hg::filepatterns` module provided by the +//! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns` +//! and can be used as replacement for the the pure `filepatterns` Python module. //! -//! API differences: -//!+ it is instantiated with a C `parsers.index` -//! instance instead of a parents function. -//!+ `MissingAncestors.bases` is a method returning a tuple instead of -//! a set-valued attribute. We could return a Python set easily if our -//! [PySet PR](https://github.com/dgrunwald/rust-cpython/pull/165) -//! is accepted. -//! -//! - [`AncestorsIterator`] is the Rust counterpart of the -//! `ancestor._lazyancestorsiter` Python generator. From Python, instances of -//! this should be mainly obtained by calling `iter()` on a [`LazyAncestors`] -//! instance. -//! -//! [`LazyAncestors`]: struct.LazyAncestors.html -//! [`MissingAncestors`]: struct.MissingAncestors.html -//! [`AncestorsIterator`]: struct.AncestorsIterator.html -use crate::conversion::{py_set, rev_pyiter_collect}; -use cindex::Index; use cpython::{ -ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, PyResult, -Python, PythonObject, ToPyObject, +exc, PyDict, PyErr, PyModule, PyResult, PyString, PyTuple, Python, +ToPyObject, }; -use exceptions::GraphError; -use hg::Revision; -use hg::{ -AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy, -MissingAncestors as CoreMissing, +use hg::{build_single_regex, read_pattern_file, PatternTuple}; +use exceptions::{ +PatternError, +PatternFileError, }; -use std::cell::RefCell; -use std::collections::HashSet; -py_class!(pub class AncestorsIterator |py| { -data inner: RefCell>>; - -def __next__() -> PyResult> { -match self.inner(py).borrow_mut().next() { -Some(Err(e)) => Err(GraphError::pynew(py, e)), -None => Ok(None), -Some(Ok(r)) => Ok(Some(r)), +/// Rust does not like functions with different return signatures. +/// The 3-tuple version is always returned by the hg-core function, +/// the (potential) conversion is handled at this level since it is not likely +/// to have any measurable impact on performance. +/// +/// The Python implementation passes a function reference for `warn` instead +/// of a boolean that is used to emit warnings while parsing. The Rust +/// implementation chooses to accumulate the warnings and propagate them to +/// Python upon completion. See the `readpatternfile` function in `match.py` +/// for more details. +fn read_pattern_file_wrapper( +py: Python, +file_path: String, +warn: bool, +source_info: bool, +) ->
D6271: rust-filepatterns: add a Rust implementation of pattern-related utils
Alphare updated this revision to Diff 15141. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6271?vs=14905=15141 REVISION DETAIL https://phab.mercurial-scm.org/D6271 AFFECTED FILES rust/Cargo.lock rust/hg-core/Cargo.toml rust/hg-core/src/ancestors.rs rust/hg-core/src/filepatterns.rs rust/hg-core/src/lib.rs CHANGE DETAILS diff --git a/rust/hg-core/src/lib.rs b/rust/hg-core/src/lib.rs --- a/rust/hg-core/src/lib.rs +++ b/rust/hg-core/src/lib.rs @@ -4,6 +4,9 @@ // GNU General Public License version 2 or any later version. extern crate byteorder; extern crate memchr; +#[macro_use] +extern crate lazy_static; +extern crate regex; mod ancestors; pub mod dagops; @@ -15,6 +18,11 @@ pack_dirstate, parse_dirstate, CopyVec, CopyVecEntry, DirstateEntry, DirstateParents, DirstateVec, }; +mod filepatterns; + +pub use filepatterns::{ +build_single_regex, read_pattern_file, PatternSyntax, PatternTuple, +}; /// Mercurial revision numbers /// @@ -42,6 +50,8 @@ fn parents(, Revision) -> Result<[Revision; 2], GraphError>; } +pub type LineNumber = usize; + #[derive(Clone, Debug, PartialEq)] pub enum GraphError { ParentOutOfRange(Revision), @@ -73,3 +83,20 @@ DirstateParseError::CorruptedEntry(e.to_string()) } } + +#[derive(Debug)] +pub enum PatternError { +UnsupportedSyntax(String), +} + +#[derive(Debug)] +pub enum PatternFileError { +IO(std::io::Error), +Pattern(PatternError, LineNumber), +} + +impl From for PatternFileError { +fn from(e: std::io::Error) -> Self { +PatternFileError::IO(e) +} +} diff --git a/rust/hg-core/src/filepatterns.rs b/rust/hg-core/src/filepatterns.rs new file mode 100644 --- /dev/null +++ b/rust/hg-core/src/filepatterns.rs @@ -0,0 +1,345 @@ +use crate::{LineNumber, PatternError, PatternFileError}; +use regex::Regex; +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; +use std::vec::Vec; + +lazy_static! { +static ref reescape: Vec> = { +let mut v: Vec> = (0..=255).map(|byte| vec![byte]).collect(); +let to_escape = b"()[]{}?*+-|^$\\.&~# \t\n\r\x0b\x0c"; +for byte in to_escape { +v[*byte as usize].insert(0, b'\\'); +} +v +}; +} + +/// These are matched in order +const GLOB_REPLACEMENTS: &[(&[u8], &[u8])] = +&[(b"*/", b"(?:.*/)?"), (b"*", b".*"), (b"", b"[^/]*")]; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum PatternSyntax { +Regexp, +/// Glob that matches at the front of the path +RootGlob, +/// Glob that matches at any suffix of the path (still anchored at slashes) +Glob, +Path, +RelPath, +RelGlob, +RelRegexp, +RootFiles, +} + +/// Transforms a glob pattern into a regex +fn glob_to_re(pat: &[u8]) -> Vec { +let mut input = pat; +let mut res: Vec = vec![]; +let mut group_depth = 0; + +while let Some((c, rest)) = input.split_first() { +input = rest; + +match c { +b'*' => { +for (source, repl) in GLOB_REPLACEMENTS { +if input.starts_with(source) { +input = [source.len()..]; +res.extend(*repl); +break; +} +} +} +b'?' => res.extend(b"."), +b'[' => { +match input.iter().skip(1).position(|b| *b == b']') { +None => res.extend(b"\\["), +Some(end) => { +// Account for the one we skipped +let end = end + 1; + +res.extend(b"["); + +for (i, b) in input[..end].iter().enumerate() { +if *b == b'!' && i == 0 { +res.extend(b"^") +} else if *b == b'^' && i == 0 { +res.extend(b"\\^") +} else if *b == b'\\' { +res.extend(b"") +} else { +res.push(*b) +} +} +res.extend(b"]"); +input = [end + 1..]; +} +} +} +b'{' => { +group_depth += 1; +res.extend(b"(?:") +} +b'}' if group_depth > 0 => { +group_depth -= 1; +res.extend(b")"); +} +b',' if group_depth > 0 => res.extend(b"|"), +b'\\' => { +let c = { +if let Some((c, rest)) = input.split_first() { +input = rest; +c +} else { +c +} +}; +
D6273: rust-filepatterns: call new Rust implementations from Python
Alphare updated this revision to Diff 15143. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6273?vs=14842=15143 REVISION DETAIL https://phab.mercurial-scm.org/D6273 AFFECTED FILES mercurial/match.py tests/common-pattern.py CHANGE DETAILS diff --git a/tests/common-pattern.py b/tests/common-pattern.py --- a/tests/common-pattern.py +++ b/tests/common-pattern.py @@ -115,6 +115,11 @@ # Various platform error strings, keyed on a common replacement string _errors = { br'$ENOENT$': ( +# IOError in Python does not have the same error message +# than in Rust, and automatic conversion is not possible +# because of module member privacy. +br'No such file or directory \(os error 2\)', + # strerror() br'No such file or directory', diff --git a/mercurial/match.py b/mercurial/match.py --- a/mercurial/match.py +++ b/mercurial/match.py @@ -24,6 +24,12 @@ stringutil, ) +try: +from . import rustext +rustext.__name__ # force actual import (see hgdemandimport) +except ImportError: +rustext = None + allpatternkinds = ('re', 'glob', 'path', 'relglob', 'relpath', 'relre', 'rootglob', 'listfile', 'listfile0', 'set', 'include', 'subinclude', @@ -1175,8 +1181,22 @@ return res def _regex(kind, pat, globsuffix): -'''Convert a (normalized) pattern of any kind into a regular expression. +'''Convert a (normalized) pattern of any kind into a +regular expression. globsuffix is appended to the regexp of globs.''' + +if rustext is not None: +try: +return rustext.filepatterns.build_single_regex( +kind, +pat, +globsuffix +) +except rustext.filepatterns.PatternError: +raise error.ProgrammingError( +'not a regex pattern: %s:%s' % (kind, pat) +) + if not pat: return '' if kind == 're': @@ -1418,9 +1438,24 @@ pattern# pattern of the current default type if sourceinfo is set, returns a list of tuples: -(pattern, lineno, originalline). This is useful to debug ignore patterns. +(pattern, lineno, originalline). +This is useful to debug ignore patterns. ''' +if rustext is not None: +result, warnings = rustext.filepatterns.read_pattern_file( +filepath, +bool(warn), +sourceinfo, +) + +for warning_params in warnings: +# Can't be easily emitted from Rust, because it would require +# a mechanism for both gettext and calling the `warn` function. +warn(_("%s: ignoring invalid syntax '%s'\n") % warning_params) + +return result + syntaxes = { 're': 'relre:', 'regexp': 'relre:', To: Alphare, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[Bug 6139] New: CVS import fails on CVS-log-like commit message
https://bz.mercurial-scm.org/show_bug.cgi?id=6139 Bug ID: 6139 Summary: CVS import fails on CVS-log-like commit message Product: Mercurial Version: 5.0 Hardware: PC OS: NetBSD Status: UNCONFIRMED Severity: bug Priority: wish Component: convert Assignee: bugzi...@mercurial-scm.org Reporter: n...@n0.is CC: duri...@gmail.com, mercurial-devel@mercurial-scm.org I have tested the hg convert command with 4.9.1 and 5.0 release on NetBSD's pkgsrc CVS repository. Invocation command with hg 5.0 release: hg convert /usr/pkgsrc pkgsrc Where /usr/pkgsrc is my CVS checkout of pkgsrc. [...] 468300 graphics/dcraw/Makefile ** unknown exception encountered, please report by visiting ** https://mercurial-scm.org/wiki/BugTracker ** Python 2.7.16 (default, May 11 2019, 14:23:25) [GCC 7.4.0] ** Mercurial Distributed SCM (version 5.0) ** Extensions loaded: rebase, convert, pager Traceback (most recent call last): File "/usr/pkg/bin/hg", line 43, in dispatch.run() File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 99, in run status = dispatch(req) File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 225, in dispatch ret = _runcatch(req) or 0 File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 376, in _runcatch return _callcatch(ui, _runcatchfunc) File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 384, in _callcatch return scmutil.callcatch(ui, func) File "/usr/pkg/lib/python2.7/site-packages/mercurial/scmutil.py", line 167, in callcatch return func() File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 367, in _runcatchfunc return _dispatch(req) File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 1021, in _dispatch cmdpats, cmdoptions) File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 756, in runcommand ret = _runcommand(ui, options, cmd, d) File "/usr/pkg/lib/python2.7/site-packages/hgext/pager.py", line 77, in pagecmd return orig(ui, options, cmd, cmdfunc) File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 1030, in _runcommand return cmdfunc() File "/usr/pkg/lib/python2.7/site-packages/mercurial/dispatch.py", line 1018, in d = lambda: util.checksignature(func)(ui, *args, **strcmdopt) File "/usr/pkg/lib/python2.7/site-packages/mercurial/util.py", line 1680, in check return func(*args, **kwargs) File "/usr/pkg/lib/python2.7/site-packages/hgext/convert/__init__.py", line 450, in convert return convcmd.convert(ui, src, dest, revmapfile, **opts) File "/usr/pkg/lib/python2.7/site-packages/hgext/convert/convcmd.py", line 616, in convert c.convert(sortmode) File "/usr/pkg/lib/python2.7/site-packages/hgext/convert/convcmd.py", line 503, in convert heads = self.source.getheads() File "/usr/pkg/lib/python2.7/site-packages/hgext/convert/cvs.py", line 224, in getheads self._parse() File "/usr/pkg/lib/python2.7/site-packages/hgext/convert/cvs.py", line 83, in _parse db = cvsps.createlog(self.ui, cache=cache) File "/usr/pkg/lib/python2.7/site-packages/hgext/convert/cvsps.py", line 336, in createlog assert match, _('revision must be followed by date line') AssertionError: revision must be followed by date line A bit of insight into why this happens: http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/graphics/dcraw/Makefile is "messed up" in anything which tries to parse CVS to display it (including the NetBSD bsdweb.cgi script). The timeline goes from 1.21 -> 1.268 -> 1.22. Furthermore what happened is that someone has committed a commit message that looks exactly like a CVS log entry. So in the cvs log output it will -look- like a commit of an out of order revision is nested but it's actually a just the message. -- 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
mercurial@42295: 6 new changesets
6 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/e79aeb518aa1 changeset: 42290:e79aeb518aa1 user:Martin von Zweigbergk date:Fri May 10 14:27:22 2019 -0700 summary: overlayworkingctx: don't include added-then-deleted files in memctx https://www.mercurial-scm.org/repo/hg/rev/a13b30555ffb changeset: 42291:a13b30555ffb user:Martin von Zweigbergk date:Fri May 10 13:41:42 2019 -0700 summary: context: reuse changectx._copies() in all but workingctx https://www.mercurial-scm.org/repo/hg/rev/491855ea9d62 changeset: 42292:491855ea9d62 user:Martin von Zweigbergk date:Fri May 10 21:35:30 2019 -0700 summary: context: move flags overrides from committablectx to workingctx https://www.mercurial-scm.org/repo/hg/rev/4fbfc893e6b9 changeset: 42293:4fbfc893e6b9 user:Martin von Zweigbergk date:Fri May 10 21:53:41 2019 -0700 summary: context: move walk() and match() overrides from committablectx to workingctx https://www.mercurial-scm.org/repo/hg/rev/c51b103220c7 changeset: 42294:c51b103220c7 user:Martin von Zweigbergk date:Fri May 10 22:18:11 2019 -0700 summary: tests: demonstrate that close-head command updates working copy https://www.mercurial-scm.org/repo/hg/rev/fdd4d668ceb5 changeset: 42295:fdd4d668ceb5 bookmark:@ tag: tip user:Martin von Zweigbergk date:Fri May 10 21:55:59 2019 -0700 summary: context: move contents of committablectx.markcommitted() to workingctx -- 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
D6380: copies: fix duplicatecopies() with overlay context
This revision was automatically updated to reflect the committed changes. Closed by commit rHGac1dc92dc516: copies: fix duplicatecopies() with overlay context (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6380?vs=15124=15140 REVISION DETAIL https://phab.mercurial-scm.org/D6380 AFFECTED FILES mercurial/context.py mercurial/copies.py tests/test-rebase-inmemory.t CHANGE DETAILS diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -795,12 +795,10 @@ $ hg co -q 0 $ echo a2 > a $ hg ci -qm 'modify a' -BROKEN: obviously... $ hg rebase -r . -d 1 --collapse rebasing 2:41c4ea50d4cf "modify a" (tip) merging b and a to b - abort: a@b977edf6f839: not found in manifest! - [255] + saved backup bundle to $TESTTMP/rebase-rename-collapse/.hg/strip-backup/41c4ea50d4cf-b90b7994-rebase.hg $ cd .. Test rebasing when the file we are merging in destination is empty diff --git a/mercurial/copies.py b/mercurial/copies.py --- a/mercurial/copies.py +++ b/mercurial/copies.py @@ -798,4 +798,5 @@ for dst, src in pathcopies(repo[fromrev], repo[rev]).iteritems(): if dst in exclude: continue -wctx[dst].markcopied(src) +if dst in wctx: +wctx[dst].markcopied(src) diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -1773,8 +1773,7 @@ def markcopied(self, src): """marks this file a copy of `src`""" -if self._repo.dirstate[self._path] in "nma": -self._repo.dirstate.copy(src, self._path) +self._repo.dirstate.copy(src, self._path) def clearunknown(self): """Removes conflicting items in the working directory so that To: martinvonz, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6379: tests: demonstrate crash when rebasing across copy with --collapse
This revision was automatically updated to reflect the committed changes. Closed by commit rHG89b5fb616c8a: tests: demonstrate crash when rebasing across copy with --collapse (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6379?vs=15123=15139 REVISION DETAIL https://phab.mercurial-scm.org/D6379 AFFECTED FILES tests/test-rebase-inmemory.t CHANGE DETAILS diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -784,6 +784,25 @@ R a $ cd .. +Rebase across a copy with --collapse + + $ hg init rebase-rename-collapse + $ cd rebase-rename-collapse + $ echo a > a + $ hg ci -Aqm 'add a' + $ hg mv a b + $ hg ci -m 'rename a to b' + $ hg co -q 0 + $ echo a2 > a + $ hg ci -qm 'modify a' +BROKEN: obviously... + $ hg rebase -r . -d 1 --collapse + rebasing 2:41c4ea50d4cf "modify a" (tip) + merging b and a to b + abort: a@b977edf6f839: not found in manifest! + [255] + $ cd .. + Test rebasing when the file we are merging in destination is empty $ hg init test To: martinvonz, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6386: help: add missing blank line, making "revlog-compression" show up
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb5d6120951e6: help: add missing blank line, making revlog-compression show up (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6386?vs=15130=15137 REVISION DETAIL https://phab.mercurial-scm.org/D6386 AFFECTED FILES mercurial/help/config.txt tests/test-help.t CHANGE DETAILS diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -1511,6 +1511,8 @@ "sparse-revlog" + "revlog-compression" + "profiling" --- diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -870,6 +870,7 @@ Repositories with this on-disk format require Mercurial version 4.7 Enabled by default. + ``revlog-compression`` Compression algorithm used by revlog. Supported value are `zlib` and `zstd`. The `zlib` engine is the historical default of Mercurial. `zstd` is a newer To: martinvonz, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6384: tests: separate out bookmarks tests from test-share.t
This revision was automatically updated to reflect the committed changes. Closed by commit rHGfb00b3d76995: tests: separate out bookmarks tests from test-share.t (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6384?vs=15128=15135 REVISION DETAIL https://phab.mercurial-scm.org/D6384 AFFECTED FILES tests/test-share-bookmarks.t tests/test-share.t CHANGE DETAILS diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -157,251 +157,16 @@ $ cd .. -test sharing bookmarks - - $ hg share -B repo1 repo3 - updating working directory - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd repo1 - $ hg bookmark bm1 - $ hg bookmarks - * bm1 2:c2e0ac586386 - $ cd ../repo2 - $ hg book bm2 - $ hg bookmarks - * bm2 3:0e6e70d1d5f1 - $ cd ../repo3 - $ hg bookmarks - bm1 2:c2e0ac586386 - $ hg book bm3 - $ hg bookmarks - bm1 2:c2e0ac586386 - * bm3 2:c2e0ac586386 - $ cd ../repo1 - $ hg bookmarks - * bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - -check whether HG_PENDING makes pending changes only in relatd -repositories visible to an external hook. - -In "hg share" case, another transaction can't run in other -repositories sharing same source repository, because starting -transaction requires locking store of source repository. - -Therefore, this test scenario ignores checking visibility of -.hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks. - - $ cat > $TESTTMP/checkbookmarks.sh < echo "@repo1" - > hg -R "$TESTTMP/repo1" bookmarks - > echo "@repo2" - > hg -R "$TESTTMP/repo2" bookmarks - > echo "@repo3" - > hg -R "$TESTTMP/repo3" bookmarks - > exit 1 # to avoid adding new bookmark for subsequent tests - > EOF - - $ cd ../repo1 - $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX - @repo1 - bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - * bmX 2:c2e0ac586386 - @repo2 - * bm2 3:0e6e70d1d5f1 - @repo3 - bm1 2:c2e0ac586386 - * bm3 2:c2e0ac586386 - bmX 2:c2e0ac586386 - transaction abort! - rollback completed - abort: pretxnclose hook exited with status 1 - [255] - $ hg book bm1 - -FYI, in contrast to above test, bmX is invisible in repo1 (= shared -src), because (1) HG_PENDING refers only repo3 and (2) -"bookmarks.pending" is written only into repo3. - - $ cd ../repo3 - $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX - @repo1 - * bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - @repo2 - * bm2 3:0e6e70d1d5f1 - @repo3 - bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - * bmX 2:c2e0ac586386 - transaction abort! - rollback completed - abort: pretxnclose hook exited with status 1 - [255] - $ hg book bm3 - - $ cd ../repo1 - -test that commits work - - $ echo 'shared bookmarks' > a - $ hg commit -m 'testing shared bookmarks' - $ hg bookmarks - * bm1 3:b87954705719 - bm3 2:c2e0ac586386 - $ cd ../repo3 - $ hg bookmarks - bm1 3:b87954705719 - * bm3 2:c2e0ac586386 - $ echo 'more shared bookmarks' > a - $ hg commit -m 'testing shared bookmarks' - created new head - $ hg bookmarks - bm1 3:b87954705719 - * bm3 4:62f4ded848e4 - $ cd ../repo1 - $ hg bookmarks - * bm1 3:b87954705719 - bm3 4:62f4ded848e4 - $ cd .. - non largefiles repos won't enable largefiles - $ hg share --config extensions.largefiles= repo3 sharedrepo + $ hg share --config extensions.largefiles= repo2 sharedrepo The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ [ -f sharedrepo/.hg/hgrc ] [1] -test pushing bookmarks works - - $ hg clone repo3 repo4 - updating to branch default - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd repo4 - $ hg boo bm4 - $ echo foo > b - $ hg commit -m 'foo in b' - $ hg boo - bm1 3:b87954705719 - bm3 4:62f4ded848e4 - * bm4 5:92793bfc8cad - $ hg push -B bm4 - pushing to $TESTTMP/repo3 - searching for
D6385: tests: fix share test to actually share the repo
This revision was automatically updated to reflect the committed changes. Closed by commit rHGe0a1dc7daebe: tests: fix share test to actually share the repo (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6385?vs=15129=15136 REVISION DETAIL https://phab.mercurial-scm.org/D6385 AFFECTED FILES tests/test-share-bookmarks.t CHANGE DETAILS diff --git a/tests/test-share-bookmarks.t b/tests/test-share-bookmarks.t --- a/tests/test-share-bookmarks.t +++ b/tests/test-share-bookmarks.t @@ -21,21 +21,6 @@ updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved -unshare it - - $ cd repo2 - $ hg unshare - -check that a change does not propagate - - $ echo b >> b - $ hg commit -m'change in unshared' - $ cd ../repo1 - $ hg id -r tip - c2e0ac586386 tip - - $ cd .. - test sharing bookmarks $ hg share -B repo1 repo3 @@ -48,7 +33,7 @@ $ cd ../repo2 $ hg book bm2 $ hg bookmarks - * bm2 3:0e6e70d1d5f1 + * bm2 2:c2e0ac586386 $ cd ../repo3 $ hg bookmarks bm1 2:c2e0ac586386 @@ -69,7 +54,7 @@ transaction requires locking store of source repository. Therefore, this test scenario ignores checking visibility of -.hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks. +.hg/bookmarks.pending in repo2, which shares repo1 without bookmarks. $ cat > $TESTTMP/checkbookmarks.sh < echo "@repo1" @@ -88,7 +73,7 @@ bm3 2:c2e0ac586386 * bmX 2:c2e0ac586386 @repo2 - * bm2 3:0e6e70d1d5f1 + * bm2 2:c2e0ac586386 @repo3 bm1 2:c2e0ac586386 * bm3 2:c2e0ac586386 @@ -109,7 +94,7 @@ * bm1 2:c2e0ac586386 bm3 2:c2e0ac586386 @repo2 - * bm2 3:0e6e70d1d5f1 + * bm2 2:c2e0ac586386 @repo3 bm1 2:c2e0ac586386 bm3 2:c2e0ac586386 To: martinvonz, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6381: exthelper: add some semi-useful trace logs
This revision was automatically updated to reflect the committed changes. Closed by commit rHG7d4ca1ad6537: exthelper: add some semi-useful trace logs (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6381?vs=15125=15138 REVISION DETAIL https://phab.mercurial-scm.org/D6381 AFFECTED FILES mercurial/exthelper.py CHANGE DETAILS diff --git a/mercurial/exthelper.py b/mercurial/exthelper.py --- a/mercurial/exthelper.py +++ b/mercurial/exthelper.py @@ -15,9 +15,12 @@ commands, error, extensions, +pycompat, registrar, ) +from hgdemandimport import tracing + class exthelper(object): """Helper for modular extension setup @@ -135,7 +138,8 @@ for cont, funcname, wrapper in self._functionwrappers: extensions.wrapfunction(cont, funcname, wrapper) for c in self._uicallables: -c(ui) +with tracing.log(b'finaluisetup: %s', pycompat.sysbytes(repr(c))): +c(ui) def finaluipopulate(self, ui): """Method to be used as the extension uipopulate @@ -175,7 +179,8 @@ entry[1].append(opt) for c in self._extcallables: -c(ui) +with tracing.log(b'finalextsetup: %s', pycompat.sysbytes(repr(c))): +c(ui) def finalreposetup(self, ui, repo): """Method to be used as the extension reposetup @@ -187,7 +192,8 @@ - Changes to repo.__class__, repo.dirstate.__class__ """ for c in self._repocallables: -c(ui, repo) +with tracing.log(b'finalreposetup: %s', pycompat.sysbytes(repr(c))): +c(ui, repo) def uisetup(self, call): """Decorated function will be executed during uisetup 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
D6383: bookmarks: use vfs.tryread() instead of reimplementing it
This revision was automatically updated to reflect the committed changes. Closed by commit rHG798b27e46971: bookmarks: use vfs.tryread() instead of reimplementing it (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6383?vs=15127=15134 REVISION DETAIL https://phab.mercurial-scm.org/D6383 AFFECTED FILES mercurial/bookmarks.py CHANGE DETAILS diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -297,28 +297,12 @@ itself as we commit. This function returns the name of that bookmark. It is stored in .hg/bookmarks.current """ -try: -file = repo.vfs('bookmarks.current') -except IOError as inst: -if inst.errno != errno.ENOENT: -raise -return None -try: -# No readline() in osutil.posixfile, reading everything is -# cheap. -# Note that it's possible for readlines() here to raise -# IOError, since we might be reading the active mark over -# static-http which only tries to load the file when we try -# to read from it. -mark = encoding.tolocal((file.readlines() or [''])[0]) -if mark == '' or mark not in marks: -mark = None -except IOError as inst: -if inst.errno != errno.ENOENT: -raise -return None -finally: -file.close() +# No readline() in osutil.posixfile, reading everything is +# cheap. +content = repo.vfs.tryread('bookmarks.current') +mark = encoding.tolocal((content.splitlines() or [''])[0]) +if mark == '' or mark not in marks: +mark = None return mark def activate(repo, mark): To: martinvonz, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6382: bookmarks: use context manager when writing files
This revision was automatically updated to reflect the committed changes. Closed by commit rHG042c27f35885: bookmarks: use context manager when writing files (authored by martinvonz, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D6382?vs=15126=15133 REVISION DETAIL https://phab.mercurial-scm.org/D6382 AFFECTED FILES mercurial/bookmarks.py CHANGE DETAILS diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -204,27 +204,18 @@ rbm._writeactive() with repo.wlock(): -file_ = repo.vfs('bookmarks', 'w', atomictemp=True, - checkambig=True) -try: -self._write(file_) -except: # re-raises -file_.discard() -raise -finally: -file_.close() +with repo.vfs('bookmarks', 'w', atomictemp=True, + checkambig=True) as f: +self._write(f) def _writeactive(self): if self._aclean: return with self._repo.wlock(): if self._active is not None: -f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True, - checkambig=True) -try: +with self._repo.vfs('bookmarks.current', 'w', atomictemp=True, + checkambig=True) as f: f.write(encoding.fromlocal(self._active)) -finally: -f.close() else: self._repo.vfs.tryunlink('bookmarks.current') self._aclean = True To: martinvonz, #hg-reviewers, pulkit Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D5299: phabricator: fallback reading arcanist config files
philpep added a comment. Thanks for reviewing @Kwan ! Actually I think parsing/merging arcconfig files will be quite hard to maintain because they are not fully documented and subject to changes. For my needs, just having hg being able to get phabricator.url and phabricator.callsign from .arcconfig in the repo root is enough. Then I just need to match this with hg auth config. I'll try to have a smaller patch not trying to read other files than .arcconfig and not reading the token. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D5299 To: philpep, #hg-reviewers, durin42 Cc: durin42, Kwan, mharbison72, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6273: rust-filepatterns: call new Rust implementations from Python
Alphare added a comment. In https://phab.mercurial-scm.org/D6273#92803, @durin42 wrote: > Are there any performance implications of this yet? We (read Octobus) are planning very soon to start benchmarking Rust vs non-Rust Mercurial, so I'll hopefully have an answer within a few weeks. Though If I had to take a guess, I'd say these patches as well as the few next ones will be detrimental to performance in the short-term. This is because of some limitations in the rust-cpython bindings (some of which are more difficult to fix than others), the inherent overhead of doing ffi, Python idoms awkward for Rust, etc.. The C code I'm re-implemented in some modules is very heavily optimized, but the current approach is to build enough critical mass to have the Rust bits of code interacting as little as possible with Python and then start optimizing/parallelizing. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6273 To: Alphare, #hg-reviewers, durin42 Cc: durin42, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6387: bookmarks: keep bookmarks in .hg/store if new config set
martinvonz created this revision. Herald added subscribers: mercurial-devel, mjpieters. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Bookmarks storage consists of two parts: (1) the set of bookmarks and their positions, and (2) the current bookmark. The former can get updated by exchange, while the latter cannot. However, they are both stored in directly .hg/ and protected by repo.wlock(). As a result, ugly workarounds were needed. This patch introduces a new config option to store the set of bookmarks and their positions in .hg/store/ but still storing the current bookmark directory in .hg/. The config option only takes effect at repo creation time. It results in a new requirement being set. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6387 AFFECTED FILES hgext/share.py mercurial/bookmarks.py mercurial/configitems.py mercurial/help/config.txt mercurial/localrepo.py mercurial/store.py tests/test-help.t tests/test-share-bookmarks.t CHANGE DETAILS diff --git a/tests/test-share-bookmarks.t b/tests/test-share-bookmarks.t --- a/tests/test-share-bookmarks.t +++ b/tests/test-share-bookmarks.t @@ -1,6 +1,13 @@ +#testcases vfs svfs + $ echo "[extensions]" >> $HGRCPATH $ echo "share = " >> $HGRCPATH +#if svfs + $ echo "[format]" >> $HGRCPATH + $ echo "bookmarks-in-store = yes " >> $HGRCPATH +#endif + prepare repo1 $ hg init repo1 @@ -33,17 +40,21 @@ $ cd ../repo2 $ hg book bm2 $ hg bookmarks + bm1 2:c2e0ac586386 (svfs !) * bm2 2:c2e0ac586386 $ cd ../repo3 $ hg bookmarks bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) $ hg book bm3 $ hg bookmarks bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) * bm3 2:c2e0ac586386 $ cd ../repo1 $ hg bookmarks * bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) bm3 2:c2e0ac586386 check whether HG_PENDING makes pending changes only in relatd @@ -70,14 +81,18 @@ $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX @repo1 bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) bm3 2:c2e0ac586386 * bmX 2:c2e0ac586386 @repo2 + bm1 2:c2e0ac586386 (svfs !) * bm2 2:c2e0ac586386 + bm3 2:c2e0ac586386 (svfs !) @repo3 bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) * bm3 2:c2e0ac586386 - bmX 2:c2e0ac586386 + bmX 2:c2e0ac586386 (vfs !) transaction abort! rollback completed abort: pretxnclose hook exited with status 1 @@ -92,19 +107,28 @@ $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX @repo1 * bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) bm3 2:c2e0ac586386 @repo2 + bm1 2:c2e0ac586386 (svfs !) * bm2 2:c2e0ac586386 + bm3 2:c2e0ac586386 (svfs !) @repo3 bm1 2:c2e0ac586386 + bm2 2:c2e0ac586386 (svfs !) bm3 2:c2e0ac586386 * bmX 2:c2e0ac586386 transaction abort! rollback completed abort: pretxnclose hook exited with status 1 [255] $ hg book bm3 +clean up bm2 since it's uninteresting (not shared in the vfs case and +same as bm3 in the svfs case) + $ cd ../repo2 + $ hg book -d bm2 + $ cd ../repo1 test that commits work diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -1513,6 +1513,8 @@ "revlog-compression" + "bookmarks-in-store" + "profiling" --- diff --git a/mercurial/store.py b/mercurial/store.py --- a/mercurial/store.py +++ b/mercurial/store.py @@ -337,7 +337,7 @@ mode = None return mode -_data = ('narrowspec data meta 00manifest.d 00manifest.i' +_data = ('bookmarks narrowspec data meta 00manifest.d 00manifest.i' ' 00changelog.d 00changelog.i phaseroots obsstore') def isrevlog(f, kind, st): @@ -612,7 +612,7 @@ raise def copylist(self): -d = ('narrowspec data meta dh fncache phaseroots obsstore' +d = ('bookmarks narrowspec data meta dh fncache phaseroots obsstore' ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i') return (['requires', '00changelog.i'] + ['store/' + f for f in d.split()])
D6388: exchange: don't take wlock if bookmarks are stored in .hg/store/
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY If bookmarks are stored in .hg/store/, there is no need for the wlock(). REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6388 AFFECTED FILES mercurial/exchange.py CHANGE DETAILS diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -539,10 +539,12 @@ # get lock as we might write phase data wlock = lock = None try: -# bundle2 push may receive a reply bundle touching bookmarks or other -# things requiring the wlock. Take it now to ensure proper ordering. +# bundle2 push may receive a reply bundle touching bookmarks +# requiring the wlock. Take it now to ensure proper ordering. maypushback = pushop.ui.configbool('experimental', 'bundle2.pushback') -if (not _forcebundle1(pushop)) and maypushback: +if ((not _forcebundle1(pushop)) and +maypushback and +not bookmod.bookmarksinstore(repo)): wlock = pushop.repo.wlock() lock = pushop.repo.lock() pushop.trmanager = transactionmanager(pushop.repo, @@ -1548,7 +1550,10 @@ raise error.Abort(msg) pullop.trmanager = transactionmanager(repo, 'pull', remote.url()) -with repo.wlock(), repo.lock(), pullop.trmanager: +wlock = util.nullcontextmanager() +if not bookmod.bookmarksinstore(repo): +wlock = repo.wlock() +with wlock, repo.lock(), pullop.trmanager: # Use the modern wire protocol, if available. if remote.capable('command-changesetdata'): exchangev2.pull(pullop) @@ -2395,7 +2400,8 @@ try: def gettransaction(): if not lockandtr[2]: -lockandtr[0] = repo.wlock() +if not bookmod.bookmarksinstore(repo): +lockandtr[0] = repo.wlock() lockandtr[1] = repo.lock() lockandtr[2] = repo.transaction(source) lockandtr[2].hookargs['source'] = source To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6386: help: add missing blank line, making "revlog-compression" show up
martinvonz 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/D6386 AFFECTED FILES mercurial/help/config.txt tests/test-help.t CHANGE DETAILS diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -1511,6 +1511,8 @@ "sparse-revlog" + "revlog-compression" + "profiling" --- diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -870,6 +870,7 @@ Repositories with this on-disk format require Mercurial version 4.7 Enabled by default. + ``revlog-compression`` Compression algorithm used by revlog. Supported value are `zlib` and `zstd`. The `zlib` engine is the historical default of Mercurial. `zstd` is a newer To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6384: tests: separate out bookmarks tests from test-share.t
martinvonz created this revision. Herald added subscribers: mercurial-devel, mjpieters. Herald added a reviewer: hg-reviewers. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6384 AFFECTED FILES tests/test-share-bookmarks.t tests/test-share.t CHANGE DETAILS diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -157,251 +157,16 @@ $ cd .. -test sharing bookmarks - - $ hg share -B repo1 repo3 - updating working directory - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd repo1 - $ hg bookmark bm1 - $ hg bookmarks - * bm1 2:c2e0ac586386 - $ cd ../repo2 - $ hg book bm2 - $ hg bookmarks - * bm2 3:0e6e70d1d5f1 - $ cd ../repo3 - $ hg bookmarks - bm1 2:c2e0ac586386 - $ hg book bm3 - $ hg bookmarks - bm1 2:c2e0ac586386 - * bm3 2:c2e0ac586386 - $ cd ../repo1 - $ hg bookmarks - * bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - -check whether HG_PENDING makes pending changes only in relatd -repositories visible to an external hook. - -In "hg share" case, another transaction can't run in other -repositories sharing same source repository, because starting -transaction requires locking store of source repository. - -Therefore, this test scenario ignores checking visibility of -.hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks. - - $ cat > $TESTTMP/checkbookmarks.sh < echo "@repo1" - > hg -R "$TESTTMP/repo1" bookmarks - > echo "@repo2" - > hg -R "$TESTTMP/repo2" bookmarks - > echo "@repo3" - > hg -R "$TESTTMP/repo3" bookmarks - > exit 1 # to avoid adding new bookmark for subsequent tests - > EOF - - $ cd ../repo1 - $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX - @repo1 - bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - * bmX 2:c2e0ac586386 - @repo2 - * bm2 3:0e6e70d1d5f1 - @repo3 - bm1 2:c2e0ac586386 - * bm3 2:c2e0ac586386 - bmX 2:c2e0ac586386 - transaction abort! - rollback completed - abort: pretxnclose hook exited with status 1 - [255] - $ hg book bm1 - -FYI, in contrast to above test, bmX is invisible in repo1 (= shared -src), because (1) HG_PENDING refers only repo3 and (2) -"bookmarks.pending" is written only into repo3. - - $ cd ../repo3 - $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX - @repo1 - * bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - @repo2 - * bm2 3:0e6e70d1d5f1 - @repo3 - bm1 2:c2e0ac586386 - bm3 2:c2e0ac586386 - * bmX 2:c2e0ac586386 - transaction abort! - rollback completed - abort: pretxnclose hook exited with status 1 - [255] - $ hg book bm3 - - $ cd ../repo1 - -test that commits work - - $ echo 'shared bookmarks' > a - $ hg commit -m 'testing shared bookmarks' - $ hg bookmarks - * bm1 3:b87954705719 - bm3 2:c2e0ac586386 - $ cd ../repo3 - $ hg bookmarks - bm1 3:b87954705719 - * bm3 2:c2e0ac586386 - $ echo 'more shared bookmarks' > a - $ hg commit -m 'testing shared bookmarks' - created new head - $ hg bookmarks - bm1 3:b87954705719 - * bm3 4:62f4ded848e4 - $ cd ../repo1 - $ hg bookmarks - * bm1 3:b87954705719 - bm3 4:62f4ded848e4 - $ cd .. - non largefiles repos won't enable largefiles - $ hg share --config extensions.largefiles= repo3 sharedrepo + $ hg share --config extensions.largefiles= repo2 sharedrepo The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ [ -f sharedrepo/.hg/hgrc ] [1] -test pushing bookmarks works - - $ hg clone repo3 repo4 - updating to branch default - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd repo4 - $ hg boo bm4 - $ echo foo > b - $ hg commit -m 'foo in b' - $ hg boo - bm1 3:b87954705719 - bm3 4:62f4ded848e4 - * bm4 5:92793bfc8cad - $ hg push -B bm4 - pushing to $TESTTMP/repo3 - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - exporting bookmark bm4 - $ cd
D6385: tests: fix share test to actually share the repo
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY "repo2" is clearly meant to be a share from "repo1" but without sharing bookmarks. However, `hg unshare` was called in the repo, so it had become completely unrelated and thus not testing what it was supposed to test. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6385 AFFECTED FILES tests/test-share-bookmarks.t CHANGE DETAILS diff --git a/tests/test-share-bookmarks.t b/tests/test-share-bookmarks.t --- a/tests/test-share-bookmarks.t +++ b/tests/test-share-bookmarks.t @@ -21,21 +21,6 @@ updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved -unshare it - - $ cd repo2 - $ hg unshare - -check that a change does not propagate - - $ echo b >> b - $ hg commit -m'change in unshared' - $ cd ../repo1 - $ hg id -r tip - c2e0ac586386 tip - - $ cd .. - test sharing bookmarks $ hg share -B repo1 repo3 @@ -48,7 +33,7 @@ $ cd ../repo2 $ hg book bm2 $ hg bookmarks - * bm2 3:0e6e70d1d5f1 + * bm2 2:c2e0ac586386 $ cd ../repo3 $ hg bookmarks bm1 2:c2e0ac586386 @@ -69,7 +54,7 @@ transaction requires locking store of source repository. Therefore, this test scenario ignores checking visibility of -.hg/bookmakrs.pending in repo2, which shares repo1 without bookmarks. +.hg/bookmarks.pending in repo2, which shares repo1 without bookmarks. $ cat > $TESTTMP/checkbookmarks.sh < echo "@repo1" @@ -88,7 +73,7 @@ bm3 2:c2e0ac586386 * bmX 2:c2e0ac586386 @repo2 - * bm2 3:0e6e70d1d5f1 + * bm2 2:c2e0ac586386 @repo3 bm1 2:c2e0ac586386 * bm3 2:c2e0ac586386 @@ -109,7 +94,7 @@ * bm1 2:c2e0ac586386 bm3 2:c2e0ac586386 @repo2 - * bm2 3:0e6e70d1d5f1 + * bm2 2:c2e0ac586386 @repo3 bm1 2:c2e0ac586386 bm3 2:c2e0ac586386 To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6383: bookmarks: use vfs.tryread() instead of reimplementing it
martinvonz 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/D6383 AFFECTED FILES mercurial/bookmarks.py CHANGE DETAILS diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -297,28 +297,12 @@ itself as we commit. This function returns the name of that bookmark. It is stored in .hg/bookmarks.current """ -try: -file = repo.vfs('bookmarks.current') -except IOError as inst: -if inst.errno != errno.ENOENT: -raise -return None -try: -# No readline() in osutil.posixfile, reading everything is -# cheap. -# Note that it's possible for readlines() here to raise -# IOError, since we might be reading the active mark over -# static-http which only tries to load the file when we try -# to read from it. -mark = encoding.tolocal((file.readlines() or [''])[0]) -if mark == '' or mark not in marks: -mark = None -except IOError as inst: -if inst.errno != errno.ENOENT: -raise -return None -finally: -file.close() +# No readline() in osutil.posixfile, reading everything is +# cheap. +content = repo.vfs.tryread('bookmarks.current') +mark = encoding.tolocal((content.splitlines() or [''])[0]) +if mark == '' or mark not in marks: +mark = None return mark def activate(repo, mark): To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D6382: bookmarks: use context manager when writing files
martinvonz 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/D6382 AFFECTED FILES mercurial/bookmarks.py CHANGE DETAILS diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -204,27 +204,18 @@ rbm._writeactive() with repo.wlock(): -file_ = repo.vfs('bookmarks', 'w', atomictemp=True, - checkambig=True) -try: -self._write(file_) -except: # re-raises -file_.discard() -raise -finally: -file_.close() +with repo.vfs('bookmarks', 'w', atomictemp=True, + checkambig=True) as f: +self._write(f) def _writeactive(self): if self._aclean: return with self._repo.wlock(): if self._active is not None: -f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True, - checkambig=True) -try: +with self._repo.vfs('bookmarks.current', 'w', atomictemp=True, + checkambig=True) as f: f.write(encoding.fromlocal(self._active)) -finally: -f.close() else: self._repo.vfs.tryunlink('bookmarks.current') self._aclean = True To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel