Adding src_exclude_filter to exclude files - makes common operations like 'all but X' easier

This commit is contained in:
Ben Vanik 2012-09-11 22:54:01 -07:00
parent 5b84fa35e6
commit a2d7c0def1
5 changed files with 51 additions and 7 deletions

View File

@ -398,9 +398,12 @@ class RuleContext(object):
OSError: A source path was not found or could not be accessed.
RuntimeError: Internal runtime error (rule executed out of order/etc)
"""
src_filter_list = None
include_filter_list = []
if apply_src_filter and self.rule.src_filter:
src_filter_list = self.rule.src_filter.split('|')
include_filter_list = self.rule.src_filter.split('|')
exclude_filter_list = []
if apply_src_filter and self.rule.src_exclude_filter:
exclude_filter_list = self.rule.src_exclude_filter.split('|')
base_path = os.path.dirname(self.rule.parent_module.path)
input_paths = []
@ -420,16 +423,20 @@ class RuleContext(object):
else:
# File or folder path
src_path = os.path.join(base_path, src)
mode = os.stat(src_path).st_mode
if stat.S_ISDIR(mode):
if not os.path.exists(src_path):
raise OSError('Source path "%s" not found' % (src_path))
elif os.path.isdir(src_path):
src_items = os.listdir(src_path)
else:
src_items = [src_path]
# Apply the src_filter, if any
if src_filter_list:
if len(include_filter_list) or len(exclude_filter_list):
for file_path in src_items:
if any(fnmatch.fnmatch(file_path, f) for f in src_filter_list):
if any(fnmatch.fnmatch(file_path, f) for f in exclude_filter_list):
continue
if (not len(include_filter_list) or
any(fnmatch.fnmatch(file_path, f) for f in include_filter_list)):
input_paths.append(file_path)
else:
input_paths.extend(src_items)

View File

@ -331,6 +331,22 @@ class RuleContextTest(FixtureTestCase):
set([os.path.basename(f) for f in rule_outputs]),
set(['a.txt', 'b.txt', 'c.txt', 'd.txt', 'e.txt']))
rule = project.resolve_rule(':exclude_txt_filter')
d = build_ctx._execute_rule(rule)
self.assertTrue(d.is_done())
rule_outputs = build_ctx.get_rule_outputs(rule)
self.assertEqual(
set([os.path.basename(f) for f in rule_outputs]),
set(['dir_2', 'a.txt-a', 'b.txt-b', 'c.txt-c', 'g.not-txt', 'BUILD']))
rule = project.resolve_rule(':include_exclude_filter')
d = build_ctx._execute_rule(rule)
self.assertTrue(d.is_done())
rule_outputs = build_ctx.get_rule_outputs(rule)
self.assertEqual(
set([os.path.basename(f) for f in rule_outputs]),
set(['a.txt-a', 'b.txt-b']))
rule = project.resolve_rule(':multi_exts')
build_ctx._execute_rule(rule)

View File

@ -40,7 +40,7 @@ class Rule(object):
_whitespace_re = re.compile('\s', re.M)
def __init__(self, name, srcs=None, deps=None, src_filter=None,
rule_name=None, *args, **kwargs):
src_exclude_filter=None, rule_name=None, *args, **kwargs):
"""Initializes a rule.
Args:
@ -50,6 +50,9 @@ class Rule(object):
deps: A list of depdendency strings or a single dependency string.
src_filter: An inclusionary file name filter for all non-rule paths. If
defined only srcs that match this filter will be included.
src_exclude_filter: An exclusionary file name filter for all non-rule
paths. If defined only srcs that do not match this filter will be
included.
rule_name: Name of the rule in BUILD files, making it easier to debug.
Raises:
@ -97,6 +100,9 @@ class Rule(object):
self.src_filter = None
if src_filter and len(src_filter):
self.src_filter = src_filter
self.src_exclude_filter = None
if src_exclude_filter and len(src_exclude_filter):
self.src_exclude_filter = src_exclude_filter
def __repr__(self):
return '%s(%s)' % (self.rule_name, self.path)

View File

@ -188,6 +188,14 @@ class RuleTest(unittest2.TestCase):
rule = Rule('a', src_filter='*.js')
self.assertEqual(rule.src_filter, '*.js')
def testRuleExclusionFilter(self):
rule = Rule('a')
self.assertIsNone(rule.src_exclude_filter)
rule = Rule('a', src_filter='')
self.assertIsNone(rule.src_exclude_filter)
rule = Rule('a', src_exclude_filter='*.js')
self.assertEqual(rule.src_exclude_filter, '*.js')
class RuleNamespaceTest(FixtureTestCase):
"""Behavioral tests of the Rule type."""

View File

@ -26,6 +26,13 @@ file_set('local_txt_filter',
file_set('recursive_txt_filter',
srcs=glob('**/*'),
src_filter='*.txt')
file_set('exclude_txt_filter',
srcs=glob('*'),
src_exclude_filter='*.txt')
file_set('include_exclude_filter',
srcs=glob('*'),
src_filter='*.txt-a|*.txt-b',
src_exclude_filter='*.txt')
file_set('file_input',
srcs='a.txt')