xref: /aosp_15_r20/external/pigweed/pw_build/glob_dirs.bzl (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker#
3*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker# the License at
6*61c4878aSAndroid Build Coastguard Worker#
7*61c4878aSAndroid Build Coastguard Worker#     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker#
9*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker# the License.
14*61c4878aSAndroid Build Coastguard Worker"""Helpers that use wildcards to match one or more directories."""
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Workerdef match_dir_internal(include, exclude = [], allow_empty = True, _fail_callback = fail):
17*61c4878aSAndroid Build Coastguard Worker    """The actual implementation of match_dir with more testability.
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker    DO NOT USE THIS DIRECTLY!!! Use `match_dir()`!
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard Worker    Args:
22*61c4878aSAndroid Build Coastguard Worker      include: A list of wildcard patterns to match against.
23*61c4878aSAndroid Build Coastguard Worker      exclude: A list of wildcard patterns to exclude.
24*61c4878aSAndroid Build Coastguard Worker      allow_empty: Whether or not to permit returning `None`.
25*61c4878aSAndroid Build Coastguard Worker      _fail_callback: Callback to call when an error is encountered.
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker    Returns:
28*61c4878aSAndroid Build Coastguard Worker      Path to a single directory that matches the specified constraints.
29*61c4878aSAndroid Build Coastguard Worker    """
30*61c4878aSAndroid Build Coastguard Worker    matches = glob_dirs(
31*61c4878aSAndroid Build Coastguard Worker        include,
32*61c4878aSAndroid Build Coastguard Worker        exclude,
33*61c4878aSAndroid Build Coastguard Worker        allow_empty = allow_empty,
34*61c4878aSAndroid Build Coastguard Worker    )
35*61c4878aSAndroid Build Coastguard Worker    if not allow_empty and not matches:
36*61c4878aSAndroid Build Coastguard Worker        return _fail_callback(
37*61c4878aSAndroid Build Coastguard Worker            ("glob pattern {} didn't match anything, but allow_empty is set " +
38*61c4878aSAndroid Build Coastguard Worker             "to False").format(include),
39*61c4878aSAndroid Build Coastguard Worker        )
40*61c4878aSAndroid Build Coastguard Worker    if len(matches) > 1:
41*61c4878aSAndroid Build Coastguard Worker        return _fail_callback(
42*61c4878aSAndroid Build Coastguard Worker            ("glob pattern {} matches multiple directories when only one " +
43*61c4878aSAndroid Build Coastguard Worker             "was requested: {}").format(include, matches),
44*61c4878aSAndroid Build Coastguard Worker        )
45*61c4878aSAndroid Build Coastguard Worker    return matches[0] if matches else None
46*61c4878aSAndroid Build Coastguard Worker
47*61c4878aSAndroid Build Coastguard Workerdef match_dir(include, exclude = [], allow_empty = True):
48*61c4878aSAndroid Build Coastguard Worker    """Identifies a single directory using a wildcard pattern.
49*61c4878aSAndroid Build Coastguard Worker
50*61c4878aSAndroid Build Coastguard Worker    This helper follows the same semantics as Bazel's native glob() function,
51*61c4878aSAndroid Build Coastguard Worker    but only matches a single directory. If more than one match is found, this
52*61c4878aSAndroid Build Coastguard Worker    will fail.
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard Worker    Args:
55*61c4878aSAndroid Build Coastguard Worker      include: A list of wildcard patterns to match against.
56*61c4878aSAndroid Build Coastguard Worker      exclude: A list of wildcard patterns to exclude.
57*61c4878aSAndroid Build Coastguard Worker      allow_empty: Whether or not to permit returning `None`.
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker    Returns:
60*61c4878aSAndroid Build Coastguard Worker      Path to a single directory that matches the specified constraints, or
61*61c4878aSAndroid Build Coastguard Worker      `None` if no match is found and `allow_empty` is `True`.
62*61c4878aSAndroid Build Coastguard Worker    """
63*61c4878aSAndroid Build Coastguard Worker    return match_dir_internal(
64*61c4878aSAndroid Build Coastguard Worker        include,
65*61c4878aSAndroid Build Coastguard Worker        exclude = exclude,
66*61c4878aSAndroid Build Coastguard Worker        allow_empty = allow_empty,
67*61c4878aSAndroid Build Coastguard Worker    )
68*61c4878aSAndroid Build Coastguard Worker
69*61c4878aSAndroid Build Coastguard Workerdef glob_dirs(include, exclude = [], allow_empty = True):
70*61c4878aSAndroid Build Coastguard Worker    """Matches the provided glob pattern to identify a list of directories.
71*61c4878aSAndroid Build Coastguard Worker
72*61c4878aSAndroid Build Coastguard Worker    This helper follows the same semantics as Bazel's native glob() function,
73*61c4878aSAndroid Build Coastguard Worker    but only matches directories.
74*61c4878aSAndroid Build Coastguard Worker
75*61c4878aSAndroid Build Coastguard Worker    Args:
76*61c4878aSAndroid Build Coastguard Worker      include: A list of wildcard patterns to match against.
77*61c4878aSAndroid Build Coastguard Worker      exclude: A list of wildcard patterns to exclude.
78*61c4878aSAndroid Build Coastguard Worker      allow_empty: Whether or not to permit an empty list of matches.
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker    Returns:
81*61c4878aSAndroid Build Coastguard Worker      List of directory paths that match the specified constraints.
82*61c4878aSAndroid Build Coastguard Worker    """
83*61c4878aSAndroid Build Coastguard Worker    without_dirs = native.glob(
84*61c4878aSAndroid Build Coastguard Worker        include,
85*61c4878aSAndroid Build Coastguard Worker        exclude,
86*61c4878aSAndroid Build Coastguard Worker        exclude_directories = 1,
87*61c4878aSAndroid Build Coastguard Worker        allow_empty = True,
88*61c4878aSAndroid Build Coastguard Worker    )
89*61c4878aSAndroid Build Coastguard Worker    with_dirs = native.glob(
90*61c4878aSAndroid Build Coastguard Worker        include,
91*61c4878aSAndroid Build Coastguard Worker        exclude,
92*61c4878aSAndroid Build Coastguard Worker        exclude_directories = 0,
93*61c4878aSAndroid Build Coastguard Worker        allow_empty = allow_empty,
94*61c4878aSAndroid Build Coastguard Worker    )
95*61c4878aSAndroid Build Coastguard Worker    results = {p: None for p in with_dirs}
96*61c4878aSAndroid Build Coastguard Worker    for p in without_dirs:
97*61c4878aSAndroid Build Coastguard Worker        results.pop(p)
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker    return list(results.keys())
100