# Copyright 2024 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. """Helpers that use wildcards to match one or more directories.""" def match_dir_internal(include, exclude = [], allow_empty = True, _fail_callback = fail): """The actual implementation of match_dir with more testability. DO NOT USE THIS DIRECTLY!!! Use `match_dir()`! Args: include: A list of wildcard patterns to match against. exclude: A list of wildcard patterns to exclude. allow_empty: Whether or not to permit returning `None`. _fail_callback: Callback to call when an error is encountered. Returns: Path to a single directory that matches the specified constraints. """ matches = glob_dirs( include, exclude, allow_empty = allow_empty, ) if not allow_empty and not matches: return _fail_callback( ("glob pattern {} didn't match anything, but allow_empty is set " + "to False").format(include), ) if len(matches) > 1: return _fail_callback( ("glob pattern {} matches multiple directories when only one " + "was requested: {}").format(include, matches), ) return matches[0] if matches else None def match_dir(include, exclude = [], allow_empty = True): """Identifies a single directory using a wildcard pattern. This helper follows the same semantics as Bazel's native glob() function, but only matches a single directory. If more than one match is found, this will fail. Args: include: A list of wildcard patterns to match against. exclude: A list of wildcard patterns to exclude. allow_empty: Whether or not to permit returning `None`. Returns: Path to a single directory that matches the specified constraints, or `None` if no match is found and `allow_empty` is `True`. """ return match_dir_internal( include, exclude = exclude, allow_empty = allow_empty, ) def glob_dirs(include, exclude = [], allow_empty = True): """Matches the provided glob pattern to identify a list of directories. This helper follows the same semantics as Bazel's native glob() function, but only matches directories. Args: include: A list of wildcard patterns to match against. exclude: A list of wildcard patterns to exclude. allow_empty: Whether or not to permit an empty list of matches. Returns: List of directory paths that match the specified constraints. """ without_dirs = native.glob( include, exclude, exclude_directories = 1, allow_empty = True, ) with_dirs = native.glob( include, exclude, exclude_directories = 0, allow_empty = allow_empty, ) results = {p: None for p in with_dirs} for p in without_dirs: results.pop(p) return list(results.keys())