xref: /illumos-gate/usr/src/tools/onbld/Scm/Ignore.py (revision eb9a1df2aeb866bf1de4494433b6d7e5fa07b3ae)
1#
2# Permission is hereby granted, free of charge, to any person obtaining a copy
3# of this software and associated documentation files (the "Software"), to deal
4# in the Software without restriction, including without limitation the rights
5# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6# copies of the Software, and to permit persons to whom the Software is
7# furnished to do so, subject to the following conditions:
8#
9# The above copyright notice and this permission notice shall be included in
10# all copies or substantial portions of the Software.
11#
12# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18# THE SOFTWARE
19#
20# Copyright (c) 2014, Joyent, Inc.
21#
22
23'''
24Process our ignore/exception_list file format.
25
26The format is broadly similar, if not identical, to .gitignore and .hgignore
27files.
28'''
29
30import re
31import fnmatch
32
33RE_SYNTAX = re.compile(r'^syntax:\s*(.*)\s*$')
34
35#
36# It is important that this module not rely on Mercurial
37#
38
39def _read_ignore_file(ignorefile):
40    '''Read an ignore file and return an array of regular expressions
41    to match ignored paths.'''
42
43    syntax = 'regex'
44    ignore_list = []
45    lc = 0
46
47    with open(ignorefile, 'r') as f:
48        for l in f:
49            lc += 1
50            # Remove comments and blank lines
51            l = l.split('#', 2)[0].strip()
52            if l == '':
53                continue
54            # Process "syntax:" lines
55            m = RE_SYNTAX.match(l)
56            if m:
57                syntax = m.group(1)
58                continue
59            # All other lines are considered patterns
60            if (syntax == 'glob'):
61                ignore_list.append(re.compile('.*' + fnmatch.translate(l)))
62            elif (syntax == 'regex'):
63                ignore_list.append(re.compile(l))
64            else:
65                raise Exception('%s:%d: syntax "%s" is not supported' %
66                    (ignorefile, lc, syntax))
67
68    return ignore_list
69
70def ignore(root, ignorefiles):
71    # If we aren't provided any ignore files, we'll never ignore
72    # any paths:
73    if (len(ignorefiles) < 1):
74        return lambda x: False
75
76    ignore_list = []
77    for ignorefile in ignorefiles:
78        ignore_list.extend(_read_ignore_file(ignorefile))
79
80    # If the ignore files contained no patterns, we'll never ignore
81    # any paths:
82    if (len(ignore_list) < 1):
83        return lambda x: False
84
85    def _ignore_func(path):
86        for regex in ignore_list:
87            if (regex.match(path)):
88                return True
89        return False
90
91    return _ignore_func
92