blob: ad48dc1ef98d5050a24949971263c9f79c706106 [file] [log] [blame]
# Copyright 2024 The Bazel Authors. All rights reserved.
#
# 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
#
# http://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.
"""Skylib module containing path operations on directories."""
load("//lib:paths.bzl", "paths")
_NOT_FOUND = """{directory} does not contain an entry named {name}.
Instead, it contains the following entries:
{children}
"""
_WRONG_TYPE = "Expected {dir}/{name} to have type {want}, but got {got}"
# These correspond to an "enum".
FILE = "file"
DIRECTORY = "directory"
def _check_path_relative(path):
if paths.is_absolute(path):
fail("Path must be relative. Got {path}".format(path = path))
def _get_direct_child(directory, name, require_type = None):
"""Gets the direct child of a directory.
Args:
directory: (DirectoryInfo) The directory to look within.
name: (string) The name of the directory/file to look for.
require_type: (Optional[DIRECTORY|FILE]) If provided, must return
either a the corresponding type.
Returns:
(File|DirectoryInfo) The content contained within.
"""
entry = directory.entries.get(name, None)
if entry == None:
fail(_NOT_FOUND.format(
directory = directory.human_readable,
name = repr(name),
children = "\n".join(directory.entries.keys()),
))
if require_type == DIRECTORY and type(entry) == "File":
fail(_WRONG_TYPE.format(
dir = directory.human_readable,
name = name,
want = "Directory",
got = "File",
))
if require_type == FILE and type(entry) != "File":
fail(_WRONG_TYPE.format(
dir = directory.human_readable,
name = name,
want = "File",
got = "Directory",
))
return entry
def get_path(directory, path, require_type = None):
"""Gets a subdirectory or file contained within a directory.
Example: `get_path(directory, "a/b", require_type=FILE)`
-> the file corresponding to `directory.path + "/a/b"`
Args:
directory: (DirectoryInfo) The directory to look within.
path: (string) The path of the directory to look for within it.
require_type: (Optional[DIRECTORY|FILE]) If provided, must return
either a the corresponding type.
Returns:
(File|DirectoryInfo) The directory contained within.
"""
_check_path_relative(path)
chunks = path.split("/")
for dirname in chunks[:-1]:
directory = _get_direct_child(directory, dirname, require_type = DIRECTORY)
return _get_direct_child(
directory,
chunks[-1],
require_type = require_type,
)