Patchwork [7,of,7] match: replace icasefsmatch() function by flag to regular match()

login
register
mail settings
Submitter via Mercurial-devel
Date May 22, 2017, 6:16 a.m.
Message ID <ed78062d1d886bf26565.1495433767@martinvonz.svl.corp.google.com>
Download mbox | patch
Permalink /patch/20821/
State Accepted
Headers show

Comments

via Mercurial-devel - May 22, 2017, 6:16 a.m.
# HG changeset patch
# User Martin von Zweigbergk <martinvonz@google.com>
# Date 1495171259 25200
#      Thu May 18 22:20:59 2017 -0700
# Node ID ed78062d1d886bf26565a9deaeb193ba0dadc3ab
# Parent  9e10877c30246447a99745c70f3303ee11c33fac
match: replace icasefsmatch() function by flag to regular match()

match() will soon gain more logic and we don't want to duplicate that
in icasefsmatch(), so merge the two functions instead and use a flag
to get case-insensitive behavior.
Yuya Nishihara - May 22, 2017, 2:40 p.m.
On Sun, 21 May 2017 23:16:07 -0700, Martin von Zweigbergk via Mercurial-devel wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1495171259 25200
> #      Thu May 18 22:20:59 2017 -0700
> # Node ID ed78062d1d886bf26565a9deaeb193ba0dadc3ab
> # Parent  9e10877c30246447a99745c70f3303ee11c33fac
> match: replace icasefsmatch() function by flag to regular match()
> 
> match() will soon gain more logic and we don't want to duplicate that
> in icasefsmatch(), so merge the two functions instead and use a flag
> to get case-insensitive behavior.
> 
> diff --git a/mercurial/context.py b/mercurial/context.py
> --- a/mercurial/context.py
> +++ b/mercurial/context.py
> @@ -1593,13 +1593,11 @@
>  
>          # Only a case insensitive filesystem needs magic to translate user input
>          # to actual case in the filesystem.
> -        matcherfunc = matchmod.match
> -        if not util.fscasesensitive(r.root):
> -            matcherfunc = matchmod.icasefsmatch
> -        return matcherfunc(r.root, r.getcwd(), pats,
> -                           include, exclude, default,
> -                           auditor=r.auditor, ctx=self,
> -                           listsubrepos=listsubrepos, badfn=badfn)
> +        icasefs = not util.fscasesensitive(r.root)
> +        return matchmod.match(r.root, r.getcwd(), pats, include, exclude,
> +                              default, auditor=r.auditor, ctx=self,
> +                              listsubrepos=listsubrepos, badfn=badfn,
> +                              icasefs=icasefs)
>  
>      def _filtersuspectsymlink(self, files):
>          if not files or self._repo.dirstate._checklink:
> diff --git a/mercurial/match.py b/mercurial/match.py
> --- a/mercurial/match.py
> +++ b/mercurial/match.py
> @@ -86,7 +86,7 @@
>  
>  def match(root, cwd, patterns, include=None, exclude=None, default='glob',
>            exact=False, auditor=None, ctx=None, listsubrepos=False, warn=None,
> -          badfn=None):
> +          badfn=None, icasefs=False):
>      """build an object to match a set of file patterns
>  
>      arguments:
> @@ -99,6 +99,8 @@
>      exact - patterns are actually filenames (include/exclude still apply)
>      warn - optional function used for printing warnings
>      badfn - optional bad() callback for this matcher instead of the default
> +    icasefs - make a matcher for wdir on case insensitive filesystems, which
> +        normalizes the given patterns to the case in the filesystem
>  
>      a pattern is one of:
>      'glob:<glob>' - a glob relative to cwd
> @@ -116,39 +118,31 @@
>                            the same directory
>      '<something>' - a pattern of the specified default type
>      """
> -    return matcher(root, cwd, _donormalize, patterns, include=include,
> +    normalize = _donormalize
> +    if icasefs:
> +        dirstate = ctx.repo().dirstate
> +        dsnormalize = dirstate.normalize
> +
> +        def normalize(patterns, default, root, cwd, auditor, warn):
> +            kp = _donormalize(patterns, default, root, cwd, auditor, warn)
> +            kindpats = []
> +            for kind, pats, source in kp:
> +                if kind not in ('re', 'relre'):  # regex can't be normalized
> +                    p = pats
> +                    pats = dsnormalize(pats)
> +
> +                    # Preserve the original to handle a case only rename.
> +                    if p != pats and p in dirstate:
> +                        kindpats.append((kind, p, source))
> +
> +                kindpats.append((kind, pats, source))
> +            return kindpats
> +
> +    return matcher(root, cwd, normalize, patterns, include=include,

Maybe we should reject bad combination such as icasefs + exact?
via Mercurial-devel - May 22, 2017, 3:44 p.m.
On Mon, May 22, 2017 at 7:40 AM, Yuya Nishihara <yuya@tcha.org> wrote:
> On Sun, 21 May 2017 23:16:07 -0700, Martin von Zweigbergk via Mercurial-devel wrote:
>> # HG changeset patch
>> # User Martin von Zweigbergk <martinvonz@google.com>
>> # Date 1495171259 25200
>> #      Thu May 18 22:20:59 2017 -0700
>> # Node ID ed78062d1d886bf26565a9deaeb193ba0dadc3ab
>> # Parent  9e10877c30246447a99745c70f3303ee11c33fac
>> match: replace icasefsmatch() function by flag to regular match()
>>
>> match() will soon gain more logic and we don't want to duplicate that
>> in icasefsmatch(), so merge the two functions instead and use a flag
>> to get case-insensitive behavior.
>>
>> diff --git a/mercurial/context.py b/mercurial/context.py
>> --- a/mercurial/context.py
>> +++ b/mercurial/context.py
>> @@ -1593,13 +1593,11 @@
>>
>>          # Only a case insensitive filesystem needs magic to translate user input
>>          # to actual case in the filesystem.
>> -        matcherfunc = matchmod.match
>> -        if not util.fscasesensitive(r.root):
>> -            matcherfunc = matchmod.icasefsmatch
>> -        return matcherfunc(r.root, r.getcwd(), pats,
>> -                           include, exclude, default,
>> -                           auditor=r.auditor, ctx=self,
>> -                           listsubrepos=listsubrepos, badfn=badfn)
>> +        icasefs = not util.fscasesensitive(r.root)
>> +        return matchmod.match(r.root, r.getcwd(), pats, include, exclude,
>> +                              default, auditor=r.auditor, ctx=self,
>> +                              listsubrepos=listsubrepos, badfn=badfn,
>> +                              icasefs=icasefs)
>>
>>      def _filtersuspectsymlink(self, files):
>>          if not files or self._repo.dirstate._checklink:
>> diff --git a/mercurial/match.py b/mercurial/match.py
>> --- a/mercurial/match.py
>> +++ b/mercurial/match.py
>> @@ -86,7 +86,7 @@
>>
>>  def match(root, cwd, patterns, include=None, exclude=None, default='glob',
>>            exact=False, auditor=None, ctx=None, listsubrepos=False, warn=None,
>> -          badfn=None):
>> +          badfn=None, icasefs=False):
>>      """build an object to match a set of file patterns
>>
>>      arguments:
>> @@ -99,6 +99,8 @@
>>      exact - patterns are actually filenames (include/exclude still apply)
>>      warn - optional function used for printing warnings
>>      badfn - optional bad() callback for this matcher instead of the default
>> +    icasefs - make a matcher for wdir on case insensitive filesystems, which
>> +        normalizes the given patterns to the case in the filesystem
>>
>>      a pattern is one of:
>>      'glob:<glob>' - a glob relative to cwd
>> @@ -116,39 +118,31 @@
>>                            the same directory
>>      '<something>' - a pattern of the specified default type
>>      """
>> -    return matcher(root, cwd, _donormalize, patterns, include=include,
>> +    normalize = _donormalize
>> +    if icasefs:
>> +        dirstate = ctx.repo().dirstate
>> +        dsnormalize = dirstate.normalize
>> +
>> +        def normalize(patterns, default, root, cwd, auditor, warn):
>> +            kp = _donormalize(patterns, default, root, cwd, auditor, warn)
>> +            kindpats = []
>> +            for kind, pats, source in kp:
>> +                if kind not in ('re', 'relre'):  # regex can't be normalized
>> +                    p = pats
>> +                    pats = dsnormalize(pats)
>> +
>> +                    # Preserve the original to handle a case only rename.
>> +                    if p != pats and p in dirstate:
>> +                        kindpats.append((kind, p, source))
>> +
>> +                kindpats.append((kind, pats, source))
>> +            return kindpats
>> +
>> +    return matcher(root, cwd, normalize, patterns, include=include,
>
> Maybe we should reject bad combination such as icasefs + exact?

Good idea. I'll send a patch (either separately or as part of the
remainder of the series).

Patch

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1593,13 +1593,11 @@ 
 
         # Only a case insensitive filesystem needs magic to translate user input
         # to actual case in the filesystem.
-        matcherfunc = matchmod.match
-        if not util.fscasesensitive(r.root):
-            matcherfunc = matchmod.icasefsmatch
-        return matcherfunc(r.root, r.getcwd(), pats,
-                           include, exclude, default,
-                           auditor=r.auditor, ctx=self,
-                           listsubrepos=listsubrepos, badfn=badfn)
+        icasefs = not util.fscasesensitive(r.root)
+        return matchmod.match(r.root, r.getcwd(), pats, include, exclude,
+                              default, auditor=r.auditor, ctx=self,
+                              listsubrepos=listsubrepos, badfn=badfn,
+                              icasefs=icasefs)
 
     def _filtersuspectsymlink(self, files):
         if not files or self._repo.dirstate._checklink:
diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -86,7 +86,7 @@ 
 
 def match(root, cwd, patterns, include=None, exclude=None, default='glob',
           exact=False, auditor=None, ctx=None, listsubrepos=False, warn=None,
-          badfn=None):
+          badfn=None, icasefs=False):
     """build an object to match a set of file patterns
 
     arguments:
@@ -99,6 +99,8 @@ 
     exact - patterns are actually filenames (include/exclude still apply)
     warn - optional function used for printing warnings
     badfn - optional bad() callback for this matcher instead of the default
+    icasefs - make a matcher for wdir on case insensitive filesystems, which
+        normalizes the given patterns to the case in the filesystem
 
     a pattern is one of:
     'glob:<glob>' - a glob relative to cwd
@@ -116,39 +118,31 @@ 
                           the same directory
     '<something>' - a pattern of the specified default type
     """
-    return matcher(root, cwd, _donormalize, patterns, include=include,
+    normalize = _donormalize
+    if icasefs:
+        dirstate = ctx.repo().dirstate
+        dsnormalize = dirstate.normalize
+
+        def normalize(patterns, default, root, cwd, auditor, warn):
+            kp = _donormalize(patterns, default, root, cwd, auditor, warn)
+            kindpats = []
+            for kind, pats, source in kp:
+                if kind not in ('re', 'relre'):  # regex can't be normalized
+                    p = pats
+                    pats = dsnormalize(pats)
+
+                    # Preserve the original to handle a case only rename.
+                    if p != pats and p in dirstate:
+                        kindpats.append((kind, p, source))
+
+                kindpats.append((kind, pats, source))
+            return kindpats
+
+    return matcher(root, cwd, normalize, patterns, include=include,
                    exclude=exclude, default=default, exact=exact,
                    auditor=auditor, ctx=ctx, listsubrepos=listsubrepos,
                    warn=warn, badfn=badfn)
 
-def icasefsmatch(root, cwd, patterns, include=None, exclude=None,
-                 default='glob', auditor=None, ctx=None,
-                 listsubrepos=False, badfn=None):
-    """A matcher for wdir on case insensitive filesystems, which normalizes the
-    given patterns to the case in the filesystem.
-    """
-    dirstate = ctx.repo().dirstate
-    dsnormalize = dirstate.normalize
-
-    def normalize(patterns, default, root, cwd, auditor, warn):
-        kp = _donormalize(patterns, default, root, cwd, auditor, warn)
-        kindpats = []
-        for kind, pats, source in kp:
-            if kind not in ('re', 'relre'):  # regex can't be normalized
-                p = pats
-                pats = dsnormalize(pats)
-
-                # Preserve the original to handle a case only rename.
-                if p != pats and p in dirstate:
-                    kindpats.append((kind, p, source))
-
-            kindpats.append((kind, pats, source))
-        return kindpats
-
-    return matcher(root, cwd, normalize, patterns=patterns, include=include,
-                   exclude=exclude, default=default, auditor=auditor, ctx=ctx,
-                   listsubrepos=listsubrepos, badfn=badfn)
-
 def exact(root, cwd, files, badfn=None):
     return match(root, cwd, files, exact=True, badfn=badfn)