Patchwork D6273: rust-filepatterns: call new Rust implementations from Python

login
register
mail settings
Submitter phabricator
Date April 18, 2019, 12:11 p.m.
Message ID <differential-rev-PHID-DREV-mbnhqc4zvc3pbdub3qfr-req@phab.mercurial-scm.org>
Download mbox | patch
Permalink /patch/39742/
State Superseded
Headers show

Comments

phabricator - April 18, 2019, 12:11 p.m.
Alphare created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This change adds the import to the `rust-cpython` bindings and uses
  them when appropriate.
  
  A wrapper function has been defined in the case of `_regex` to
  keep this patch simple.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6273

AFFECTED FILES
  mercurial/match.py
  tests/common-pattern.py

CHANGE DETAILS




To: Alphare, #hg-reviewers
Cc: mercurial-devel
phabricator - May 15, 2019, 6:13 p.m.
durin42 accepted this revision.
durin42 added a comment.
This revision is now accepted and ready to land.


  Are there any performance implications of this yet?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6273

To: Alphare, #hg-reviewers, durin42
Cc: durin42, mercurial-devel
phabricator - May 16, 2019, 8:33 a.m.
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

Patch

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',
@@ -1178,8 +1184,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':
@@ -1421,9 +1441,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:',