changeset 25215:4040e06e9b99

match: add 'include:' syntax This allows the matcher to understand 'include:path/to/file' style rules. The files support the standard hgignore syntax and any rules read from the file are included in the matcher without regard to the files location in the repository (i.e. if the included file is in somedir/otherdir, all of it's rules will still apply to the entire repository).
author Durham Goode <durham@fb.com>
date Sat, 16 May 2015 15:56:52 -0700
parents 08703b10c3ae
children dc562165044a
files mercurial/match.py tests/test-hgignore.t
diffstat 2 files changed, 39 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/match.py	Mon May 18 16:27:56 2015 -0700
+++ b/mercurial/match.py	Sat May 16 15:56:52 2015 -0700
@@ -75,6 +75,7 @@
         'relpath:<path>' - a path relative to cwd
         '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
         '<something>' - a pattern of the specified default type
         """
 
@@ -228,6 +229,19 @@
                                                     auditor):
                     kindpats.append((k, p, pat))
                 continue
+            elif kind == 'include':
+                try:
+                    includepats = readpatternfile(pat, self._warn)
+                    for k, p, source in self._normalize(includepats, default,
+                                                        root, cwd, auditor):
+                        kindpats.append((k, p, source or pat))
+                except util.Abort, inst:
+                    raise util.Abort('%s: %s' % (pat, inst[0]))
+                except IOError, inst:
+                    if self._warn:
+                        self._warn(_("skipping unreadable pattern file "
+                                     "'%s': %s\n") % (pat, inst.strerror))
+                continue
             # else: re or relre - which cannot be normalized
             kindpats.append((kind, pat, ''))
         return kindpats
@@ -335,7 +349,7 @@
     if ':' in pattern:
         kind, pat = pattern.split(':', 1)
         if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
-                    'listfile', 'listfile0', 'set'):
+                    'listfile', 'listfile0', 'set', 'include'):
             return kind, pat
     return default, pattern
 
@@ -515,7 +529,8 @@
     '''parse a pattern file, returning a list of
     patterns. These patterns should be given to compile()
     to be validated and converted into a match function.'''
-    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
+    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
+                'include': 'include'}
     syntax = 'relre:'
     patterns = []
 
--- a/tests/test-hgignore.t	Mon May 18 16:27:56 2015 -0700
+++ b/tests/test-hgignore.t	Sat May 16 15:56:52 2015 -0700
@@ -167,3 +167,25 @@
   ? a.c
   ? a.o
   ? syntax
+
+Check using 'include:' in ignore file
+
+  $ hg purge --all --config extensions.purge=
+  $ touch foo.included
+
+  $ echo ".*.included" > otherignore
+  $ hg status -I "include:otherignore"
+  ? foo.included
+
+  $ echo "include:otherignore" >> .hgignore
+  $ hg status
+  A dir/b.o
+  ? .hgignore
+  ? otherignore
+
+Check recursive uses of 'include:'
+
+  $ echo "include:nestedignore" >> otherignore
+  $ echo "glob:*ignore" > nestedignore
+  $ hg status
+  A dir/b.o