[PATCH 3 of 4] match: enable 'relinclude:' syntax

Martin von Zweigbergk martinvonz at google.com
Thu May 21 13:20:37 CDT 2015


On Thu, May 21, 2015 at 11:11 AM Martin von Zweigbergk <
martinvonz at google.com> wrote:

> On Wed, May 20, 2015 at 3:01 PM Durham Goode <durham at fb.com> wrote:
>
>> # HG changeset patch
>> # User Durham Goode <durham at fb.com>
>> # Date 1431818705 25200
>> #      Sat May 16 16:25:05 2015 -0700
>> # Node ID 3bbfdda372e8e4204a5440009bfbc9e81f2a93e9
>> # Parent  28ac58249dbc906622e368357daadd4814f9c71c
>> match: enable 'relinclude:' syntax
>>
>> This adds a new rule syntax that allows the user to include a pattern
>> file, but
>> only have those patterns match against files underneath the subdirectory
>> of the
>> pattern file.
>>
>> This is useful when you have nested projects in a repository and the inner
>> projects wants to set up ignore rules that won't affect other projects in
>> the
>> repository. It is also useful in high commit rate repositories for
>> removing the
>> root .hgignore as a point of contention.
>>
>> diff --git a/mercurial/match.py b/mercurial/match.py
>> --- a/mercurial/match.py
>> +++ b/mercurial/match.py
>> @@ -5,7 +5,7 @@
>>  # This software may be used and distributed according to the terms of the
>>  # GNU General Public License version 2 or any later version.
>>
>> -import re
>> +import os, re
>>  import util, pathutil
>>  from i18n import _
>>
>> @@ -42,6 +42,25 @@ def _expandsets(kindpats, ctx, listsubre
>>          other.append((kind, pat, source))
>>      return fset, other
>>
>> +def _expandsubinclude(kindpats, root):
>> +    '''Returns the list of subinclude matchers and the kindpats without
>> the
>> +    subincludes in it.'''
>> +    relmatchers = []
>> +    other = []
>> +
>> +    for kind, pat, source in kindpats:
>> +        if kind == 'subinclude':
>> +            sourceroot = os.path.dirname(source)
>> +            path = os.path.join(sourceroot, pat)
>> +            newroot = os.path.dirname(path)
>> +            relmatcher = match(newroot, '', [], ['include:%s' % path])
>>
>
What will the "bad" message say? Will it be relative to newroot? Is it easy
to add a test for that too?


> +            prefix = os.path.relpath(newroot, root) + '/'
>> +            relmatchers.append((prefix, relmatcher))
>> +        else:
>> +            other.append((kind, pat, source))
>> +
>> +    return relmatchers, other
>> +
>>  def _kindpatsalwaysmatch(kindpats):
>>      """"Checks whether the kindspats match everything, as e.g.
>>      'relpath:.' does.
>> @@ -76,6 +95,8 @@ class match(object):
>>          'relre:<regexp>' - a regexp that needn't match the start of a
>> name
>>          'set:<fileset>' - a fileset expression
>>          'include:<path>' - a file of patterns to read and include
>> +        'subinclude:<path>' - a file of patterns to match against files
>> under
>> +                              the same directory
>>          '<something>' - a pattern of the specified default type
>>          """
>>
>> @@ -349,7 +370,7 @@ def _patsplit(pattern, default):
>>      if ':' in pattern:
>>          kind, pat = pattern.split(':', 1)
>>          if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
>> -                    'listfile', 'listfile0', 'set', 'include'):
>> +                    'listfile', 'listfile0', 'set', 'include',
>> 'subinclude'):
>>              return kind, pat
>>      return default, pattern
>>
>> @@ -455,6 +476,15 @@ def _buildmatch(ctx, kindpats, globsuffi
>>      globsuffix is appended to the regexp of globs.'''
>>      matchfuncs = []
>>
>> +    subincludes, kindpats = _expandsubinclude(kindpats, root)
>> +    if subincludes:
>> +        def matchsubinclude(f):
>> +            for prefix, mf in subincludes:
>> +                if f.startswith(prefix) and mf(f[len(prefix):]):
>> +                    return True
>> +            return False
>> +        matchfuncs.append(matchsubinclude)
>> +
>>      fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
>>      if fset:
>>          matchfuncs.append(fset.__contains__)
>> @@ -551,7 +581,7 @@ def readpatternfile(filepath, warn):
>>      pattern        # pattern of the current default type'''
>>
>>      syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
>> -                'include': 'include'}
>> +                'include': 'include', 'subinclude': 'subinclude'}
>>      syntax = 'relre:'
>>      patterns = []
>>
>> diff --git a/tests/test-hgignore.t b/tests/test-hgignore.t
>> --- a/tests/test-hgignore.t
>> +++ b/tests/test-hgignore.t
>> @@ -190,7 +190,45 @@ Check recursive uses of 'include:'
>>    $ hg status
>>    A dir/b.o
>>
>> +  $ cp otherignore goodignore
>>    $ echo "include:badignore" >> otherignore
>>    $ hg status
>>    skipping unreadable pattern file 'badignore': No such file or directory
>>    A dir/b.o
>> +
>> +  $ mv goodignore otherignore
>> +
>> +Check including subincludes
>>
>
> Should we also have a test with "subinclude:foo" (i.e. in the current
> directory)?
>
>
>> +
>> +  $ hg revert -q --all
>> +  $ hg purge --all --config extensions.purge=
>> +  $ echo ".hgignore" > .hgignore
>> +  $ mkdir dir1 dir2
>> +  $ touch dir1/file1 dir1/file2 dir2/file1 dir2/file2
>> +  $ echo "subinclude:dir2/.hgignore" >> .hgignore
>> +  $ echo "glob:file*2" > dir2/.hgignore
>> +  $ hg status
>> +  ? dir1/file1
>> +  ? dir1/file2
>> +  ? dir2/file1
>> +
>> +Check including subincludes with regexs
>> +
>> +  $ echo "subinclude:dir1/.hgignore" >> .hgignore
>> +  $ echo "regexp:f.le1" > dir1/.hgignore
>> +
>> +  $ hg status
>> +  ? dir1/file2
>> +  ? dir2/file1
>> +
>> +Check multiple levels of sub-ignores
>> +
>> +  $ mkdir dir1/subdir
>> +  $ touch dir1/subdir/subfile1 dir1/subdir/subfile3 dir1/subdir/subfile4
>> +  $ echo "subinclude:subdir/.hgignore" >> dir1/.hgignore
>> +  $ echo "glob:subfil*3" >> dir1/subdir/.hgignore
>> +
>> +  $ hg status
>> +  ? dir1/file2
>> +  ? dir1/subdir/subfile4
>> +  ? dir2/file1
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at selenic.com
>> http://selenic.com/mailman/listinfo/mercurial-devel
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20150521/ec8a1be8/attachment.html>


More information about the Mercurial-devel mailing list