blob: 4a1abcf998da4286d7f4c4a095287007964c3324 [file] [log] [blame] [edit]
# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
load("//bazel/build_defs/filter_files:glob.bzl", "glob_matches")
visibility("public")
_NO_MATCH_FMT = """The following entries failed to match anything. If this is \
expected, consider setting allow_entry to True in the filter_files invocation.
{globs}
Example file: "{f}"
"""
_BAD_STRIP_FMT = 'Unable to strip prefix - the path "{path}" does not start \
with "{strip_prefix}"'
def _filter_files_impl(ctx):
strip_prefix = ctx.attr.strip_prefix
include = [tuple(glob.split("/")) for glob in ctx.attr.include]
exclude = [tuple(glob.split("/")) for glob in ctx.attr.exclude]
matched = {k: False for k in include}
filtered = []
for src in ctx.attr.srcs:
for f in src[DefaultInfo].files.to_list():
path = f.short_path
if not path.startswith(strip_prefix):
fail(_BAD_STRIP_FMT.format(
path = path,
strip_prefix = strip_prefix,
))
path = path[len(strip_prefix):].lstrip("/").split("/")
for glob in include:
if glob_matches(path, glob):
if not any([glob_matches(path, g) for g in exclude]):
filtered.append(f)
matched[glob] = True
break
missing_matches = [k for k, v in matched.items() if not v]
if missing_matches and not ctx.attr.allow_empty:
fail(_NO_MATCH_FMT.format(
globs = ["/".join(glob) for glob in missing_matches],
f = "/".join(path),
))
return DefaultInfo(files = depset(filtered))
filter_files = rule(
implementation = _filter_files_impl,
attrs = dict(
srcs = attr.label_list(mandatory = True),
strip_prefix = attr.string(mandatory = True),
include = attr.string_list(mandatory = True),
exclude = attr.string_list(default = []),
allow_empty = attr.bool(default = False),
),
)