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