pax_global_header 0000666 0000000 0000000 00000000064 14746742163 0014530 g ustar 00root root 0000000 0000000 52 comment=8120a5186fd67f6248245ba28f2f76c899a83c07
rules_shell-0.4.0/ 0000775 0000000 0000000 00000000000 14746742163 0014052 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/.bazelci/ 0000775 0000000 0000000 00000000000 14746742163 0015541 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/.bazelci/presubmit.yml 0000664 0000000 0000000 00000001667 14746742163 0020310 0 ustar 00root root 0000000 0000000 ---
buildifier: latest
matrix:
platform:
- ubuntu2004
- macos
- windows
bazel:
- 6.5.0
- 7.4.0
tasks:
test_module_bzlmod:
name: "Test module (Bzlmod)"
working_directory: "tests/bcr"
bazel: ${{ bazel }}
platform: ${{ platform }}
build_flags:
- "--enable_bzlmod"
build_targets:
- "//..."
test_flags:
- "--enable_bzlmod"
test_targets:
- "//..."
test_module_workspace:
name: "Test module (WORKSPACE)"
working_directory: "tests/bcr"
bazel: ${{ bazel }}
platform: ${{ platform }}
build_flags:
- "--enable_bzlmod"
build_targets:
- "//..."
test_flags:
- "--enable_bzlmod"
test_targets:
- "//..."
test_module_head:
name: "Test module (Bazel@HEAD, Bzlmod)"
working_directory: "tests/bcr"
bazel: last_green
platform: ${{ platform }}
build_targets:
- "//..."
test_targets:
- "//..."
rules_shell-0.4.0/.bazelignore 0000664 0000000 0000000 00000000012 14746742163 0016345 0 ustar 00root root 0000000 0000000 tests/bcr
rules_shell-0.4.0/.bazelversion 0000664 0000000 0000000 00000000006 14746742163 0016552 0 ustar 00root root 0000000 0000000 7.4.0
rules_shell-0.4.0/.bcr/ 0000775 0000000 0000000 00000000000 14746742163 0014676 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/.bcr/config.yml 0000664 0000000 0000000 00000000316 14746742163 0016666 0 ustar 00root root 0000000 0000000 # See https://github.com/bazel-contrib/publish-to-bcr#a-note-on-release-automation
# for guidance about whether to uncomment this section:
#
fixedReleaser:
login: meteorcloudy
email: pcloudy@google.com
rules_shell-0.4.0/.bcr/metadata.template.json 0000664 0000000 0000000 00000000735 14746742163 0021170 0 ustar 00root root 0000000 0000000 {
"homepage": "https://github.com/bazelbuild/rules_shell",
"maintainers": [
{
"email": "pcloudy@google.com",
"github": "meteorcloudy",
"name": "Yun Peng"
},
{
"email": "fabian@meumertzhe.im",
"github": "fmeum",
"name": "Fabian Meumertzheim"
}
],
"repository": [
"github:bazelbuild/rules_shell"
],
"versions": [],
"yanked_versions": {}
}
rules_shell-0.4.0/.bcr/presubmit.yml 0000664 0000000 0000000 00000000504 14746742163 0017432 0 ustar 00root root 0000000 0000000 bcr_test_module:
module_path: tests/bcr
matrix:
platform:
- centos7
- debian10
- ubuntu2004
- macos
- windows
bazel: [6.x, 7.x]
tasks:
run_test_module:
name: Run test module
platform: ${{ platform }}
bazel: ${{ bazel }}
test_targets:
- "//..."
rules_shell-0.4.0/.bcr/source.template.json 0000664 0000000 0000000 00000000260 14746742163 0020701 0 ustar 00root root 0000000 0000000 {
"integrity": "**leave this alone**",
"strip_prefix": "{REPO}-{VERSION}",
"url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.tar.gz"
}
rules_shell-0.4.0/.github/ 0000775 0000000 0000000 00000000000 14746742163 0015412 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14746742163 0017447 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/.github/workflows/release.yml 0000664 0000000 0000000 00000000665 14746742163 0021621 0 ustar 00root root 0000000 0000000 # Cut a release whenever a new tag is pushed to the repo.
# You should use an annotated tag, like `git tag -a v1.2.3`
# and put the release notes into the commit message for the tag.
name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
jobs:
release:
uses: bazel-contrib/.github/.github/workflows/release_ruleset.yaml@v6
with:
prerelease: false
release_files: rules_shell-*.tar.gz
rules_shell-0.4.0/.github/workflows/release_prep.sh 0000775 0000000 0000000 00000002674 14746742163 0022465 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
# Set by GH actions, see
# https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
TAG=${GITHUB_REF_NAME}
# The prefix is chosen to match what GitHub generates for source archives
# This guarantees that users can easily switch from a released artifact to a source archive
# with minimal differences in their code (e.g. strip_prefix remains the same)
PREFIX="rules_shell-${TAG:1}"
ARCHIVE="rules_shell-$TAG.tar.gz"
# NB: configuration for 'git archive' is in /.gitattributes
git archive --format=tar --prefix="${PREFIX}/" "${TAG}" | gzip > "$ARCHIVE"
SHA=$(shasum -a 256 "$ARCHIVE" | awk '{print $1}')
cat << EOF
## Using Bzlmod with Bazel 6 or greater
1. (Bazel 6 only) Enable with \`common --enable_bzlmod\` in \`.bazelrc\`.
2. Add to your \`MODULE.bazel\` file:
\`\`\`starlark
bazel_dep(name = "rules_shell", version = "${TAG:1}")
\`\`\`
## Using WORKSPACE
Paste this snippet into your \`WORKSPACE.bazel\` file:
\`\`\`starlark
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_shell",
sha256 = "${SHA}",
strip_prefix = "${PREFIX}",
url = "https://github.com/bazelbuild/rules_shell/releases/download/${TAG}/${ARCHIVE}",
)
load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains")
rules_shell_dependencies()
rules_shell_toolchains()
\`\`\`
EOF
rules_shell-0.4.0/.gitignore 0000664 0000000 0000000 00000000032 14746742163 0016035 0 ustar 00root root 0000000 0000000 bazel-*
MODULE.bazel.lock
rules_shell-0.4.0/CONTRIBUTING.md 0000664 0000000 0000000 00000002152 14746742163 0016303 0 ustar 00root root 0000000 0000000 # How to contribute
We'd love to accept your patches and contributions to this project.
## Before you begin
### Sign our Contributor License Agreement
Contributions to this project must be accompanied by a
[Contributor License Agreement](https://cla.developers.google.com/about) (CLA).
You (or your employer) retain the copyright to your contribution; this simply
gives us permission to use and redistribute your contributions as part of the
project.
If you or your current employer have already signed the Google CLA (even if it
was for a different project), you probably don't need to do it again.
Visit to see your current agreements or to
sign a new one.
### Review our community guidelines
This project follows
[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
## Contribution process
### Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
rules_shell-0.4.0/LICENSE 0000664 0000000 0000000 00000026136 14746742163 0015067 0 ustar 00root root 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
rules_shell-0.4.0/MODULE.bazel 0000664 0000000 0000000 00000000625 14746742163 0016061 0 ustar 00root root 0000000 0000000 module(
name = "rules_shell",
version = "0.0.0",
)
bazel_dep(name = "bazel_features", version = "1.18.0")
bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "platforms", version = "0.0.10")
sh_configure = use_extension("//shell/private/extensions:sh_configure.bzl", "sh_configure")
use_repo(sh_configure, "local_config_shell")
register_toolchains("@local_config_shell//:all")
rules_shell-0.4.0/README.md 0000664 0000000 0000000 00000000115 14746742163 0015326 0 ustar 00root root 0000000 0000000 # rules_shell
This repository contains the Bazel ruleset for shell scripts.
rules_shell-0.4.0/WORKSPACE 0000664 0000000 0000000 00000000256 14746742163 0015336 0 ustar 00root root 0000000 0000000 workspace(name = "rules_shell")
load("//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains")
rules_shell_dependencies()
rules_shell_toolchains()
rules_shell-0.4.0/shell/ 0000775 0000000 0000000 00000000000 14746742163 0015161 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/BUILD 0000664 0000000 0000000 00000001425 14746742163 0015745 0 ustar 00root root 0000000 0000000 # A runtime toolchain for shell scripts.
#
# Use `sh_toolchain` to register a toolchain for this type.
#
# Every toolchain registered for this type has the following attributes:
# - `path`: The path to the shell interpreter for the target platform.
#
# Other attribute may be present but are considered implementation details of
# Bazel's sh_* rules.
#
# Toolchains registered for this type should have target constraints.
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
toolchain_type(
name = "toolchain_type",
visibility = ["//visibility:public"],
)
bzl_library(
name = "rules_bzl",
srcs = [
"sh_binary.bzl",
"sh_library.bzl",
"sh_test.bzl",
],
visibility = ["//visibility:public"],
deps = ["//shell/private:private_bzl"],
)
rules_shell-0.4.0/shell/private/ 0000775 0000000 0000000 00000000000 14746742163 0016633 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/private/BUILD 0000664 0000000 0000000 00000000402 14746742163 0017411 0 ustar 00root root 0000000 0000000 load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
bzl_library(
name = "private_bzl",
srcs = [
"sh_binary.bzl",
"sh_executable.bzl",
"sh_library.bzl",
"sh_test.bzl",
],
visibility = ["//shell:__pkg__"],
)
rules_shell-0.4.0/shell/private/extensions/ 0000775 0000000 0000000 00000000000 14746742163 0021032 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/private/extensions/BUILD 0000664 0000000 0000000 00000000000 14746742163 0021602 0 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/private/extensions/sh_configure.bzl 0000664 0000000 0000000 00000002057 14746742163 0024222 0 ustar 00root root 0000000 0000000 # Copyright 2018 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.
"""The sh_configure module extension."""
load("@bazel_features//:features.bzl", "bazel_features")
load("//shell/private/repositories:sh_config.bzl", "sh_config")
def _sh_configure_impl(module_ctx):
sh_config(name = "local_config_shell")
if bazel_features.external_deps.extension_metadata_has_reproducible:
return module_ctx.extension_metadata(reproducible = True)
return None
sh_configure = module_extension(implementation = _sh_configure_impl)
rules_shell-0.4.0/shell/private/repositories/ 0000775 0000000 0000000 00000000000 14746742163 0021362 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/private/repositories/BUILD 0000664 0000000 0000000 00000000000 14746742163 0022132 0 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/private/repositories/sh_config.bzl 0000664 0000000 0000000 00000010461 14746742163 0024034 0 ustar 00root root 0000000 0000000 # Copyright 2018 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.
"""Configure sh_toolchains based on the local machine."""
visibility(["//shell", "//shell/private/extensions"])
_DEFAULT_SHELL_PATHS = {
"windows": "c:/msys64/usr/bin/bash.exe",
"linux": "/bin/bash",
"osx": "/bin/bash",
"freebsd": "/usr/local/bin/bash",
"openbsd": "/usr/local/bin/bash",
}
_UNIX_SH_TOOLCHAIN_TEMPLATE = """
sh_toolchain(
name = "{os}_sh",
path = {sh_path},
)
"""
_WINDOWS_SH_TOOLCHAIN_TEMPLATE = """
sh_toolchain(
name = "{os}_sh",
path = {sh_path},
launcher = "@bazel_tools//tools/launcher",
launcher_maker = "@bazel_tools//tools/launcher:launcher_maker",
)
"""
_TOOLCHAIN_TEMPLATE = """
toolchain(
name = "{os}_sh_toolchain",
toolchain = ":{os}_sh",
toolchain_type = "@rules_shell//shell:toolchain_type",
target_compatible_with = [
"@platforms//os:{os}",
],
)
"""
def _sh_config_impl(repository_ctx):
"""sh_config rule implementation.
Creates sh_toolchains for commonly supported target platforms.
For the target platform matching the local machine, it detects the path of
the shell interpreter instead of using the default path.
Args:
repository_ctx: the repository rule context object
"""
toolchains = []
for os, default_shell_path in _DEFAULT_SHELL_PATHS.items():
is_host = repository_ctx.os.name.startswith(os)
if is_host:
# This toolchain was first added before optional toolchains were
# available, so instead of not registering a toolchain if we
# couldn't find the shell, we register a toolchain with an empty
# path.
sh_path = _detect_local_shell_path(repository_ctx) or ""
else:
sh_path = default_shell_path
sh_toolchain_template = _WINDOWS_SH_TOOLCHAIN_TEMPLATE if os == "windows" else _UNIX_SH_TOOLCHAIN_TEMPLATE
toolchains.append(sh_toolchain_template.format(
os = os,
sh_path = repr(sh_path),
))
toolchains.append(_TOOLCHAIN_TEMPLATE.format(
os = os,
))
repository_ctx.file("BUILD", """
load("@rules_shell//shell/toolchains:sh_toolchain.bzl", "sh_toolchain")
""" + "\n".join(toolchains))
sh_config = repository_rule(
environ = [
"BAZEL_SH",
"WINDIR",
"PATH",
],
configure = True,
implementation = _sh_config_impl,
)
def _detect_local_shell_path(repository_ctx):
if repository_ctx.os.name.startswith("windows"):
return _detect_local_shell_path_windows(repository_ctx)
else:
return _detect_local_shell_path_unix(repository_ctx)
def _detect_local_shell_path_windows(repository_ctx):
sh_path = repository_ctx.os.environ.get("BAZEL_SH")
if sh_path:
return sh_path.replace("\\", "/")
sh_path_obj = repository_ctx.which("bash.exe")
if sh_path_obj:
# repository_ctx.which returns a path object, convert that to
# string so we can call string.startswith on it.
sh_path = str(sh_path_obj)
# When the Windows Subsystem for Linux is installed there's a
# bash.exe under %WINDIR%\system32\bash.exe that launches Ubuntu
# Bash which cannot run native Windows programs so it's not what
# we want.
windir = repository_ctx.os.environ.get("WINDIR")
if not windir or not sh_path.startswith(windir):
return sh_path.replace("\\", "/")
return None
def _detect_local_shell_path_unix(repository_ctx):
sh_path = repository_ctx.os.environ.get("BAZEL_SH")
if sh_path:
return sh_path
sh_path_obj = repository_ctx.which("bash")
if sh_path_obj:
return str(sh_path_obj)
sh_path_obj = repository_ctx.which("sh")
if sh_path_obj:
return str(sh_path_obj)
return None
rules_shell-0.4.0/shell/private/root_symlinks.bzl 0000664 0000000 0000000 00000003567 14746742163 0022273 0 ustar 00root root 0000000 0000000 # 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.
"""Helper rule to preserve the legacy runfiles path for the runfiles lib."""
# Requires the private skip_conflict_checking parameter on ctx.runfiles, which
# is only available as of Bazel 7.4.0. We only use it when the native shell
# rules are not available.
ROOT_SYMLINKS_SUPPORTED = not hasattr(native, "sh_binary")
def _single_file_or_fail(target):
files = target[DefaultInfo].files.to_list()
if len(files) != 1:
fail("Expected exactly one file in {}, got {}".format(target.label, files))
return files[0]
def _root_symlinks_impl(ctx):
runfiles = ctx.runfiles(
root_symlinks = {
path: _single_file_or_fail(target)
for target, path in ctx.attr.root_symlinks.items()
},
# Adding root symlinks from Starlark usually enables conflict checking,
# but that would break backwards compatibility as it affects all
# runfiles, not just the symlinks.
skip_conflict_checking = True,
)
return [
DefaultInfo(
files = depset(),
runfiles = runfiles,
),
]
root_symlinks = rule(
implementation = _root_symlinks_impl,
attrs = {
"root_symlinks": attr.label_keyed_string_dict(
allow_files = True,
mandatory = True,
),
},
)
rules_shell-0.4.0/shell/private/sh_binary.bzl 0000664 0000000 0000000 00000001434 14746742163 0021324 0 ustar 00root root 0000000 0000000 # 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.
"""sh_binary rule definition."""
load(":sh_executable.bzl", "make_sh_executable_rule")
# For doc generation only.
visibility("public")
sh_binary = make_sh_executable_rule(executable = True)
rules_shell-0.4.0/shell/private/sh_executable.bzl 0000664 0000000 0000000 00000016630 14746742163 0022165 0 ustar 00root root 0000000 0000000 # 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.
"""Common code for sh_binary and sh_test rules."""
visibility(["//shell"])
_SH_TOOLCHAIN_TYPE = Label("//shell:toolchain_type")
def _sh_executable_impl(ctx):
if len(ctx.files.srcs) != 1:
fail("you must specify exactly one file in 'srcs'", attr = "srcs")
symlink = ctx.actions.declare_file(ctx.label.name)
src = ctx.files.srcs[0]
ctx.actions.symlink(
output = symlink,
target_file = src,
is_executable = True,
progress_message = "Symlinking %{label}",
)
direct_files = [src, symlink]
# TODO: Consider extracting this logic into a function provided by
# sh_toolchain to allow users to inject launcher creation logic for
# non-Windows platforms.
if ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]):
main_executable = _launcher_for_windows(ctx, symlink, src)
direct_files.append(main_executable)
else:
main_executable = symlink
files = depset(direct = direct_files)
runfiles = ctx.runfiles(transitive_files = files, collect_default = True)
default_info = DefaultInfo(
executable = main_executable,
files = files,
runfiles = runfiles,
)
instrumented_files_info = coverage_common.instrumented_files_info(
ctx,
source_attributes = ["srcs"],
dependency_attributes = ["deps", "data"],
)
run_environment_info = RunEnvironmentInfo(
environment = {
key: ctx.expand_make_variables(
"env",
ctx.expand_location(value, ctx.attr.data, short_paths = True),
{},
)
for key, value in ctx.attr.env.items()
},
inherited_environment = ctx.attr.env_inherit,
)
return [
default_info,
instrumented_files_info,
run_environment_info,
]
_WINDOWS_EXECUTABLE_EXTENSIONS = [
"exe",
"cmd",
"bat",
]
def _is_windows_executable(file):
return file.extension in _WINDOWS_EXECUTABLE_EXTENSIONS
def _create_windows_exe_launcher(ctx, sh_toolchain, primary_output):
if not sh_toolchain.launcher or not sh_toolchain.launcher_maker:
fail("Windows sh_toolchain requires both 'launcher' and 'launcher_maker' to be set")
bash_launcher = ctx.actions.declare_file(ctx.label.name + ".exe")
launch_info = ctx.actions.args().use_param_file("%s", use_always = True).set_param_file_format("multiline")
launch_info.add("binary_type=Bash")
launch_info.add(ctx.workspace_name, format = "workspace_name=%s")
launch_info.add("1" if ctx.configuration.runfiles_enabled() else "0", format = "symlink_runfiles_enabled=%s")
launch_info.add(sh_toolchain.path, format = "bash_bin_path=%s")
bash_file_short_path = primary_output.short_path
if bash_file_short_path.startswith("../"):
bash_file_rlocationpath = bash_file_short_path[3:]
else:
bash_file_rlocationpath = ctx.workspace_name + "/" + bash_file_short_path
launch_info.add(bash_file_rlocationpath, format = "bash_file_rlocationpath=%s")
launcher_artifact = sh_toolchain.launcher
ctx.actions.run(
executable = sh_toolchain.launcher_maker,
inputs = [launcher_artifact],
outputs = [bash_launcher],
arguments = [launcher_artifact.path, launch_info, bash_launcher.path],
use_default_shell_env = True,
toolchain = _SH_TOOLCHAIN_TYPE,
)
return bash_launcher
def _launcher_for_windows(ctx, primary_output, main_file):
if _is_windows_executable(main_file):
if main_file.extension == primary_output.extension:
return primary_output
else:
fail("Source file is a Windows executable file, target name extension should match source file extension")
# bazel_tools should always registers a toolchain for Windows, but it may have an empty path.
sh_toolchain = ctx.toolchains[_SH_TOOLCHAIN_TYPE]
if not sh_toolchain or not sh_toolchain.path:
# Let fail print the toolchain type with an apparent repo name.
fail(
"""No suitable shell toolchain found:
* if you are running Bazel on Windows, set the BAZEL_SH environment variable to the path of bash.exe
* if you are running Bazel on a non-Windows platform but are targeting Windows, register an sh_toolchain for the""",
_SH_TOOLCHAIN_TYPE,
"toolchain type",
)
return _create_windows_exe_launcher(ctx, sh_toolchain, primary_output)
def make_sh_executable_rule(extra_attrs = {}, **kwargs):
return rule(
_sh_executable_impl,
doc = """
The sh_binary rule is used to declare executable shell scripts.
(sh_binary is a misnomer: its outputs aren't necessarily binaries.) This rule ensures
that all dependencies are built, and appear in the runfiles area at execution time.
We recommend that you name your sh_binary() rules after the name of the script minus
the extension (e.g. .sh); the rule name and the file name must be distinct.
sh_binary respects shebangs, so any available interpreter may be used (eg.
#!/bin/zsh)
Example
For a simple shell script with no dependencies and some data files:
sh_binary(
name = "foo",
srcs = ["foo.sh"],
data = glob(["datafiles/*.txt"]),
)
""",
attrs = {
"srcs": attr.label_list(
allow_files = True,
doc = """
The list of input files.
This attribute should be used to list shell script source files that belong to
this library. Scripts can load other scripts using the shell's source
or . command.
""",
),
"data": attr.label_list(
allow_files = True,
flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
),
"deps": attr.label_list(
allow_rules = ["sh_library"],
doc = """
The list of "library" targets to be aggregated into this target.
See general comments about deps
at Typical attributes defined by
most build rules.
This attribute should be used to list other sh_library rules that provide
interpreted program source code depended on by the code in srcs. The files
provided by these rules will be present among the runfiles of this target.
""",
),
"env": attr.string_dict(),
"env_inherit": attr.string_list(),
"_windows_constraint": attr.label(
default = "@platforms//os:windows",
),
} | extra_attrs,
toolchains = [
config_common.toolchain_type(_SH_TOOLCHAIN_TYPE, mandatory = False),
],
**kwargs
)
rules_shell-0.4.0/shell/private/sh_library.bzl 0000664 0000000 0000000 00000007607 14746742163 0021514 0 ustar 00root root 0000000 0000000 # 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.
"""sh_library rule definition."""
# For doc generation only.
visibility("public")
def _sh_library_impl(ctx):
transitive_files = []
for target in ctx.attr.srcs:
transitive_files.append(target[DefaultInfo].files)
for target in ctx.attr.deps:
transitive_files.append(target[DefaultInfo].files)
for target in ctx.attr.data:
transitive_files.append(target[DefaultInfo].files)
files = depset(transitive = transitive_files)
runfiles = ctx.runfiles(transitive_files = files, collect_default = True)
instrumented_files_info = coverage_common.instrumented_files_info(
ctx,
source_attributes = ["srcs"],
dependency_attributes = ["deps", "data"],
)
return [
DefaultInfo(
files = files,
runfiles = runfiles,
),
instrumented_files_info,
]
sh_library = rule(
_sh_library_impl,
doc = """
The main use for this rule is to aggregate together a logical
"library" consisting of related scripts—programs in an
interpreted language that does not require compilation or linking,
such as the Bourne shell—and any data those programs need at
run-time. Such "libraries" can then be used from
the data attribute of one or
more sh_binary rules.
You can use the filegroup rule to aggregate data
files.
In interpreted programming languages, there's not always a clear
distinction between "code" and "data": after all, the program is
just "data" from the interpreter's point of view. For this reason
this rule has three attributes which are all essentially equivalent:
srcs, deps and data.
The current implementation does not distinguish between the elements of these lists.
All three attributes accept rules, source files and generated files.
It is however good practice to use the attributes for their usual purpose (as with other rules).
Examples
sh_library(
name = "foo",
data = [
":foo_service_script", # an sh_binary with srcs
":deploy_foo", # another sh_binary with srcs
],
)
""",
attrs = {
"srcs": attr.label_list(
allow_files = True,
doc = """
The list of input files.
This attribute should be used to list shell script source files that belong to
this library. Scripts can load other scripts using the shell's source
or . command.
""",
),
"data": attr.label_list(
allow_files = True,
flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
),
"deps": attr.label_list(
allow_rules = ["sh_library"],
doc = """
The list of "library" targets to be aggregated into this target.
See general comments about deps
at Typical attributes defined by
most build rules.
This attribute should be used to list other sh_library rules that provide
interpreted program source code depended on by the code in srcs. The files
provided by these rules will be present among the runfiles of this target.
""",
),
},
)
rules_shell-0.4.0/shell/private/sh_test.bzl 0000664 0000000 0000000 00000002542 14746742163 0021020 0 ustar 00root root 0000000 0000000 # 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.
"""sh_test rule definition."""
load(":sh_executable.bzl", "make_sh_executable_rule")
# For doc generation only.
visibility("public")
sh_test = make_sh_executable_rule(
test = True,
fragments = ["coverage"],
extra_attrs = {
"_lcov_merger": attr.label(
cfg = "exec",
default = configuration_field(fragment = "coverage", name = "output_generator"),
executable = True,
),
# Add the script as an attribute in order for sh_test to output code coverage results for
# code covered by CC binaries invocations.
"_collect_cc_coverage": attr.label(
cfg = "exec",
default = "@bazel_tools//tools/test:collect_cc_coverage",
executable = True,
),
},
)
rules_shell-0.4.0/shell/repositories.bzl 0000664 0000000 0000000 00000003205 14746742163 0020421 0 ustar 00root root 0000000 0000000 # 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.
"""WORKSPACE dependency macros for the shell rules."""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("//shell/private/repositories:sh_config.bzl", "sh_config")
visibility("public")
# buildifier: disable=unnamed-macro
def rules_shell_dependencies():
"""Instantiates repositories required by rules_shell."""
maybe(
http_archive,
name = "bazel_skylib",
sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz",
],
)
# buildifier: disable=unnamed-macro
def rules_shell_toolchains():
"""Register sh_toolchains for the host and common other platforms."""
sh_config(name = "local_config_shell")
native.register_toolchains("@local_config_shell//:all")
rules_shell-0.4.0/shell/runfiles/ 0000775 0000000 0000000 00000000000 14746742163 0017010 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/runfiles/BUILD 0000664 0000000 0000000 00000001132 14746742163 0017567 0 ustar 00root root 0000000 0000000 load("//shell:sh_library.bzl", "sh_library")
load("//shell/private:root_symlinks.bzl", "ROOT_SYMLINKS_SUPPORTED", "root_symlinks")
alias(
name = "runfiles",
actual = ":runfiles_impl" if ROOT_SYMLINKS_SUPPORTED else "@bazel_tools//tools/bash/runfiles",
visibility = ["//visibility:public"],
)
sh_library(
name = "runfiles_impl",
data = [":runfiles_at_legacy_location"],
tags = ["manual"],
)
root_symlinks(
name = "runfiles_at_legacy_location",
root_symlinks = {
"runfiles.bash": "bazel_tools/tools/bash/runfiles/runfiles.bash",
},
tags = ["manual"],
)
rules_shell-0.4.0/shell/runfiles/runfiles.bash 0000664 0000000 0000000 00000052204 14746742163 0021501 0 ustar 00root root 0000000 0000000 # Copyright 2018 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.
# Runfiles lookup library for Bazel-built Bash binaries and tests, version 3.
#
# VERSION HISTORY:
# - version 3: Fixes a bug in the init code on macOS and makes the library aware
# of Bzlmod repository mappings.
# Features:
# - With Bzlmod enabled, rlocation now takes the repository mapping of the
# Bazel repository containing the calling script into account when
# looking up runfiles. The new, optional second argument to rlocation can
# be used to specify the canonical name of the Bazel repository to use
# instead of this default. The new runfiles_current_repository function
# can be used to obtain the canonical name of the N-th caller's Bazel
# repository.
# Fixed:
# - Sourcing a shell script that contains the init code from a shell script
# that itself contains the init code no longer fails on macOS.
# Compatibility:
# - The init script and the runfiles library are backwards and forwards
# compatible with version 2.
# - version 2: Shorter init code.
# Features:
# - "set -euo pipefail" only at end of init code.
# "set -e" breaks the source || source || ... scheme on
# macOS, because it terminates if path1 does not exist.
# - Not exporting any environment variables in init code.
# This is now done in runfiles.bash itself.
# Compatibility:
# - The v1 init code can load the v2 library, i.e. if you have older source
# code (still using v1 init) then you can build it with newer Bazel (which
# contains the v2 library).
# - The reverse is not true: the v2 init code CANNOT load the v1 library,
# i.e. if your project (or any of its external dependencies) use v2 init
# code, then you need a newer Bazel version (which contains the v2
# library).
# - version 1: Original Bash runfiles library.
#
# ENVIRONMENT:
# - If RUNFILES_LIB_DEBUG=1 is set, the script will print diagnostic messages to
# stderr.
#
# USAGE:
# 1. Depend on this runfiles library from your build rule:
#
# sh_binary(
# name = "my_binary",
# ...
# deps = ["@bazel_tools//tools/bash/runfiles"],
# )
#
# 2. Source the runfiles library.
#
# The runfiles library itself defines rlocation which you would need to look
# up the library's runtime location, thus we have a chicken-and-egg problem.
# Insert the following code snippet to the top of your main script:
#
# # --- begin runfiles.bash initialization v3 ---
# # Copy-pasted from the Bazel Bash runfiles library v3.
# set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
# # shellcheck disable=SC1090
# source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
# source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
# source "$0.runfiles/$f" 2>/dev/null || \
# source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
# source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
# { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# # --- end runfiles.bash initialization v3 ---
#
#
# 3. Use rlocation to look up runfile paths.
#
# cat "$(rlocation my_workspace/path/to/my/data.txt)"
#
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
case "$(uname -s | tr [:upper:] [:lower:])" in
msys*|mingw*|cygwin*)
# matches an absolute Windows path
export _RLOCATION_ISABS_PATTERN="^[a-zA-Z]:[/\\]"
# Windows paths are case insensitive and Bazel and MSYS2 capitalize differently, so we can't
# assume that all paths are in the same native case.
export _RLOCATION_GREP_CASE_INSENSITIVE_ARGS=-i
;;
*)
# matches an absolute Unix path
export _RLOCATION_ISABS_PATTERN="^/[^/].*"
export _RLOCATION_GREP_CASE_INSENSITIVE_ARGS=
;;
esac
# Does not exit with a non-zero exit code if no match is found and performs a case-insensitive
# search on Windows.
function __runfiles_maybe_grep() {
grep $_RLOCATION_GREP_CASE_INSENSITIVE_ARGS "$@" || test $? = 1;
}
export -f __runfiles_maybe_grep
# Prints to stdout the runtime location of a data-dependency.
# The optional second argument can be used to specify the canonical name of the
# repository whose repository mapping should be used to resolve the repository
# part of the provided path. If not specified, the repository of the caller is
# used.
function rlocation() {
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): start"
fi
if [[ "$1" =~ $_RLOCATION_ISABS_PATTERN ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): absolute path, return"
fi
# If the path is absolute, print it as-is.
echo "$1"
return 0
elif [[ "$1" == ../* || "$1" == */.. || "$1" == ./* || "$1" == */./* || "$1" == "*/." || "$1" == *//* ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "ERROR[runfiles.bash]: rlocation($1): path is not normalized"
fi
return 1
elif [[ "$1" == \\* ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "ERROR[runfiles.bash]: rlocation($1): absolute path without" \
"drive name"
fi
return 1
fi
if [[ -f "$RUNFILES_REPO_MAPPING" ]]; then
local -r target_repo_apparent_name=$(echo "$1" | cut -d / -f 1)
# Use -s to get an empty remainder if the argument does not contain a slash.
# The repo mapping should not be applied to single segment paths, which may
# be root symlinks.
local -r remainder=$(echo "$1" | cut -s -d / -f 2-)
if [[ -n "$remainder" ]]; then
if [[ -z "${2+x}" ]]; then
local -r source_repo=$(runfiles_current_repository 2)
else
local -r source_repo=$2
fi
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): looking up canonical name for ($target_repo_apparent_name) from ($source_repo) in ($RUNFILES_REPO_MAPPING)"
fi
local -r target_repo=$(__runfiles_maybe_grep -m1 "^$source_repo,$target_repo_apparent_name," "$RUNFILES_REPO_MAPPING" | cut -d , -f 3)
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): canonical name of target repo is ($target_repo)"
fi
if [[ -n "$target_repo" ]]; then
local -r rlocation_path="$target_repo/$remainder"
else
local -r rlocation_path="$1"
fi
else
local -r rlocation_path="$1"
fi
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): not using repository mapping ($RUNFILES_REPO_MAPPING) since it does not exist"
fi
local -r rlocation_path="$1"
fi
runfiles_rlocation_checked "$rlocation_path"
}
export -f rlocation
# Exports the environment variables that subprocesses need in order to use
# runfiles.
# If a subprocess is a Bazel-built binary rule that also uses the runfiles
# libraries under @bazel_tools//tools//runfiles, then that binary needs
# these envvars in order to initialize its own runfiles library.
function runfiles_export_envvars() {
if [[ ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" \
&& ! -d "${RUNFILES_DIR:-/dev/null}" ]]; then
return 1
fi
if [[ ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$RUNFILES_DIR/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$RUNFILES_DIR/MANIFEST"
elif [[ -f "${RUNFILES_DIR}_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="${RUNFILES_DIR}_manifest"
else
export RUNFILES_MANIFEST_FILE=
fi
elif [[ ! -d "${RUNFILES_DIR:-/dev/null}" ]]; then
if [[ "$RUNFILES_MANIFEST_FILE" == */MANIFEST \
&& -d "${RUNFILES_MANIFEST_FILE%/MANIFEST}" ]]; then
export RUNFILES_DIR="${RUNFILES_MANIFEST_FILE%/MANIFEST}"
export JAVA_RUNFILES="$RUNFILES_DIR"
elif [[ "$RUNFILES_MANIFEST_FILE" == *_manifest \
&& -d "${RUNFILES_MANIFEST_FILE%_manifest}" ]]; then
export RUNFILES_DIR="${RUNFILES_MANIFEST_FILE%_manifest}"
export JAVA_RUNFILES="$RUNFILES_DIR"
else
export RUNFILES_DIR=
fi
fi
}
export -f runfiles_export_envvars
# Returns the canonical name of the Bazel repository containing the script that
# calls this function.
# The optional argument N, which defaults to 1, can be used to return the
# canonical name of the N-th caller instead.
#
# Note: This function only works correctly with Bzlmod enabled. Without Bzlmod,
# its return value is ignored if passed to rlocation.
function runfiles_current_repository() {
local -r idx=${1:-1}
local -r raw_caller_path="${BASH_SOURCE[$idx]}"
# Make the caller path absolute if needed to handle the case where the script is run directly
# from bazel-bin, with working directory a subdirectory of bazel-bin.
if [[ "$raw_caller_path" =~ $_RLOCATION_ISABS_PATTERN ]]; then
local -r caller_path="$raw_caller_path"
else
local -r caller_path="$(cd $(dirname "$raw_caller_path"); pwd)/$(basename "$raw_caller_path")"
fi
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): caller's path is ($caller_path)"
fi
local rlocation_path=
# If the runfiles manifest exists, search for an entry with target the caller's path.
if [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
# Escape $caller_path for use in the grep regex below. Also replace \ with / since the manifest
# uses / as the path separator even on Windows.
local -r normalized_caller_path="$(echo "$caller_path" | sed 's|\\\\*|/|g')"
local -r escaped_caller_path="$(echo "$normalized_caller_path" | sed 's/[.[\*^$]/\\&/g')"
rlocation_path=$(__runfiles_maybe_grep -m1 "^[^ ]* ${escaped_caller_path}$" "${RUNFILES_MANIFEST_FILE}" | cut -d ' ' -f 1)
if [[ -z "$rlocation_path" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "ERROR[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) is not the target of an entry in the runfiles manifest ($RUNFILES_MANIFEST_FILE)"
fi
# The binary may also be run directly from bazel-bin or bazel-out.
local -r repository=$(echo "$normalized_caller_path" | __runfiles_maybe_grep -E -o '(^|/)(bazel-out/[^/]+/bin|bazel-bin)/external/[^/]+/' | tail -1 | awk -F/ '{print $(NF-1)}')
if [[ -n "$repository" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) lies in repository ($repository) (parsed exec path)"
fi
echo "$repository"
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) lies in the main repository (parsed exec path)"
fi
echo ""
fi
return 1
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) is the target of ($rlocation_path) in the runfiles manifest"
fi
fi
fi
# If the runfiles directory exists, check if the caller's path is of the form
# $RUNFILES_DIR/rlocation_path and if so, set $rlocation_path.
if [[ -z "$rlocation_path" && -d "${RUNFILES_DIR:-/dev/null}" ]]; then
normalized_caller_path="$(echo "$caller_path" | sed 's|\\\\*|/|g')"
normalized_dir="$(echo "${RUNFILES_DIR%[\/]}" | sed 's|\\\\*|/|g')"
if [[ -n "${_RLOCATION_GREP_CASE_INSENSITIVE_ARGS}" ]]; then
# When comparing file paths insensitively, also normalize the case of the prefixes.
normalized_caller_path=$(echo "$normalized_caller_path" | tr '[:upper:]' '[:lower:]')
normalized_dir=$(echo "$normalized_dir" | tr '[:upper:]' '[:lower:]')
fi
if [[ "$normalized_caller_path" == "$normalized_dir"/* ]]; then
rlocation_path=${normalized_caller_path:${#normalized_dir}}
rlocation_path=${rlocation_path:1}
fi
if [[ -z "$rlocation_path" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) does not lie under the runfiles directory ($normalized_dir)"
fi
# The only shell script that is not executed from the runfiles directory (if it is populated)
# is the sh_binary entrypoint. Parse its path under the execroot, using the last match to
# allow for nested execroots (e.g. in Bazel integration tests). The binary may also be run
# directly from bazel-bin.
local -r repository=$(echo "$normalized_caller_path" | __runfiles_maybe_grep -E -o '(^|/)(bazel-out/[^/]+/bin|bazel-bin)/external/[^/]+/' | tail -1 | awk -F/ '{print $(NF-1)}')
if [[ -n "$repository" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) lies in repository ($repository) (parsed exec path)"
fi
echo "$repository"
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) lies in the main repository (parsed exec path)"
fi
echo ""
fi
return 0
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($caller_path) has path ($rlocation_path) relative to the runfiles directory ($RUNFILES_DIR)"
fi
fi
fi
if [[ -z "$rlocation_path" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "ERROR[runfiles.bash]: runfiles_current_repository($idx): cannot determine repository for ($caller_path) since neither the runfiles directory (${RUNFILES_DIR:-}) nor the runfiles manifest (${RUNFILES_MANIFEST_FILE:-}) exist"
fi
return 1
fi
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($caller_path) corresponds to rlocation path ($rlocation_path)"
fi
# Normalize the rlocation path to be of the form repo/pkg/file.
rlocation_path=${rlocation_path#_main/external/}
rlocation_path=${rlocation_path#_main/../}
local -r repository=$(echo "$rlocation_path" | cut -d / -f 1)
if [[ "$repository" == _main ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($rlocation_path) lies in the main repository"
fi
echo ""
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($rlocation_path) lies in repository ($repository)"
fi
echo "$repository"
fi
}
export -f runfiles_current_repository
function runfiles_rlocation_checked() {
# FIXME: If the runfiles lookup fails, the exit code of this function is 0 if
# and only if the runfiles manifest exists. In particular, the exit code
# behavior is not consistent across platforms.
if [[ -e "${RUNFILES_DIR:-/dev/null}/$1" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): found under RUNFILES_DIR ($RUNFILES_DIR), return"
fi
echo "${RUNFILES_DIR}/$1"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): looking in RUNFILES_MANIFEST_FILE ($RUNFILES_MANIFEST_FILE)"
fi
# If the rlocation path contains a space or newline, it needs to be prefixed
# with a space and spaces, newlines, and backslashes have to be escaped as
# \s, \n, and \b.
if [[ "$1" == *" "* || "$1" == *$'\n'* ]]; then
local search_prefix=" $(echo -n "$1" | sed 's/\\/\\b/g; s/ /\\s/g')"
search_prefix="${search_prefix//$'\n'/\\n}"
local escaped=true
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): using escaped search prefix ($search_prefix)"
fi
else
local search_prefix="$1"
local escaped=false
fi
# The extra space below is added because cut counts from 1.
local trim_length=$(echo -n "$search_prefix " | wc -c | tr -d ' ')
# Escape the search prefix for use in the grep regex below *after*
# determining the trim length.
local result=$(__runfiles_maybe_grep -m1 "^$(echo -n "$search_prefix" | sed 's/[.[\*^$]/\\&/g') " "${RUNFILES_MANIFEST_FILE}" | cut -b "${trim_length}-")
if [[ -z "$result" ]]; then
# If path references a runfile that lies under a directory that itself
# is a runfile, then only the directory is listed in the manifest. Look
# up all prefixes of path in the manifest and append the relative path
# from the prefix if there is a match.
local prefix="$1"
local prefix_result=
local new_prefix=
while true; do
new_prefix="${prefix%/*}"
[[ "$new_prefix" == "$prefix" ]] && break
prefix="$new_prefix"
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): looking for prefix ($prefix)"
fi
if [[ "$prefix" == *" "* || "$prefix" == *$'\n'* ]]; then
search_prefix=" $(echo -n "$prefix" | sed 's/\\/\\b/g; s/ /\\s/g')"
search_prefix="${search_prefix//$'\n'/\\n}"
escaped=true
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): using escaped search prefix ($search_prefix)"
fi
else
search_prefix="$prefix"
escaped=false
fi
# The extra space below is added because cut counts from 1.
trim_length=$(echo -n "$search_prefix " | wc -c)
prefix_result=$(__runfiles_maybe_grep -m1 "$(echo -n "$search_prefix" | sed 's/[.[\*^$]/\\&/g') " "${RUNFILES_MANIFEST_FILE}" | cut -b ${trim_length}-)
if [[ "$escaped" = true ]]; then
prefix_result="${prefix_result//\\n/$'\n'}"
prefix_result="${prefix_result//\\b/\\}"
fi
[[ -z "$prefix_result" ]] && continue
local -r candidate="${prefix_result}${1#"${prefix}"}"
if [[ -e "$candidate" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): found in manifest as ($candidate) via prefix ($prefix)"
fi
echo "$candidate"
return 0
fi
# At this point, the manifest lookup of prefix has been successful,
# but the file at the relative path given by the suffix does not
# exist. We do not continue the lookup with a shorter prefix for two
# reasons:
# 1. Manifests generated by Bazel never contain a path that is a
# prefix of another path.
# 2. Runfiles libraries for other languages do not check for file
# existence and would have returned the non-existent path. It seems
# better to return no path rather than a potentially different,
# non-empty path.
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): found in manifest as ($candidate) via prefix ($prefix), but file does not exist"
fi
break
done
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): not found in manifest"
fi
echo ""
else
if [[ "$escaped" = true ]]; then
result="${result//\\n/$'\n'}"
result="${result//\\b/\\}"
fi
if [[ -e "$result" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): found in manifest as ($result)"
fi
echo "$result"
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): found in manifest as ($result), but file does not exist"
fi
echo ""
fi
fi
else
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "ERROR[runfiles.bash]: cannot look up runfile \"$1\" " \
"(RUNFILES_DIR=\"${RUNFILES_DIR:-}\"," \
"RUNFILES_MANIFEST_FILE=\"${RUNFILES_MANIFEST_FILE:-}\")"
fi
return 1
fi
}
export -f runfiles_rlocation_checked
export RUNFILES_REPO_MAPPING=$(runfiles_rlocation_checked _repo_mapping 2> /dev/null)
rules_shell-0.4.0/shell/sh_binary.bzl 0000664 0000000 0000000 00000001411 14746742163 0017645 0 ustar 00root root 0000000 0000000 # 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.
"""sh_binary rule definition."""
load("//shell/private:sh_binary.bzl", _sh_binary = "sh_binary")
visibility("public")
sh_binary = getattr(native, "sh_binary", _sh_binary)
rules_shell-0.4.0/shell/sh_library.bzl 0000664 0000000 0000000 00000001420 14746742163 0020025 0 ustar 00root root 0000000 0000000 # 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.
"""sh_library rule definition."""
load("//shell/private:sh_library.bzl", _sh_library = "sh_library")
visibility("public")
sh_library = getattr(native, "sh_library", _sh_library)
rules_shell-0.4.0/shell/sh_test.bzl 0000664 0000000 0000000 00000001373 14746742163 0017347 0 ustar 00root root 0000000 0000000 # 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.
"""sh_test rule definition."""
load("//shell/private:sh_test.bzl", _sh_test = "sh_test")
visibility("public")
sh_test = getattr(native, "sh_test", _sh_test)
rules_shell-0.4.0/shell/toolchains/ 0000775 0000000 0000000 00000000000 14746742163 0017324 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/toolchains/BUILD 0000664 0000000 0000000 00000000000 14746742163 0020074 0 ustar 00root root 0000000 0000000 rules_shell-0.4.0/shell/toolchains/sh_toolchain.bzl 0000664 0000000 0000000 00000003357 14746742163 0022517 0 ustar 00root root 0000000 0000000 # Copyright 2018 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.
"""Define a toolchain rule for the shell."""
visibility("public")
def _sh_toolchain_impl(ctx):
"""sh_toolchain rule implementation."""
return [
platform_common.ToolchainInfo(
path = ctx.attr.path,
launcher = ctx.executable.launcher,
launcher_maker = ctx.executable.launcher_maker,
),
]
sh_toolchain = rule(
doc = "A runtime toolchain for shell targets.",
attrs = {
"path": attr.string(
doc = "Absolute path to the shell interpreter.",
mandatory = True,
),
"launcher": attr.label(
doc = "The generic launcher binary to use to run sh_binary/sh_test targets (only used when targeting Windows).",
cfg = "target",
allow_single_file = True,
executable = True,
),
"launcher_maker": attr.label(
doc = "The tool to use to create a target-specific launcher from the generic launcher binary (only used when targeting Windows).",
cfg = "exec",
allow_single_file = True,
executable = True,
),
},
implementation = _sh_toolchain_impl,
)
rules_shell-0.4.0/tests/ 0000775 0000000 0000000 00000000000 14746742163 0015214 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/tests/bcr/ 0000775 0000000 0000000 00000000000 14746742163 0015762 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/tests/bcr/BUILD 0000664 0000000 0000000 00000001041 14746742163 0016540 0 ustar 00root root 0000000 0000000 load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
load("@rules_shell//shell:sh_library.bzl", "sh_library")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
sh_library(
name = "lib",
srcs = ["lib.sh"],
data = ["greeting.txt"],
deps = ["@rules_shell//shell/runfiles"],
)
sh_binary(
name = "bin",
srcs = ["bin.sh"],
deps = [
":lib",
"@rules_shell//shell/runfiles",
],
)
sh_test(
name = "test",
srcs = ["test.sh"],
data = [":bin"],
deps = ["@rules_shell//shell/runfiles"],
)
rules_shell-0.4.0/tests/bcr/MODULE.bazel 0000664 0000000 0000000 00000000220 14746742163 0017760 0 ustar 00root root 0000000 0000000 module(name = "rules_shell_tests")
bazel_dep(name = "rules_shell")
local_path_override(
module_name = "rules_shell",
path = "../..",
)
rules_shell-0.4.0/tests/bcr/WORKSPACE 0000664 0000000 0000000 00000000403 14746742163 0017240 0 ustar 00root root 0000000 0000000 workspace(name = "rules_shell_tests")
local_repository(
name = "rules_shell",
path = "../..",
)
load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains")
rules_shell_dependencies()
rules_shell_toolchains()
rules_shell-0.4.0/tests/bcr/WORKSPACE.bzlmod 0000664 0000000 0000000 00000000000 14746742163 0020517 0 ustar 00root root 0000000 0000000 rules_shell-0.4.0/tests/bcr/bin.sh 0000775 0000000 0000000 00000002544 14746742163 0017076 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# 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.
# --- begin runfiles.bash initialization v3 ---
# Copy-pasted from the Bazel Bash runfiles library v3.
set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
# shellcheck disable=SC1090
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v3 ---
source "$(rlocation "rules_shell_tests/lib.sh")"
get_greeting
rules_shell-0.4.0/tests/bcr/greeting.txt 0000664 0000000 0000000 00000000027 14746742163 0020326 0 ustar 00root root 0000000 0000000 hello from rules_shell
rules_shell-0.4.0/tests/bcr/lib.sh 0000775 0000000 0000000 00000002634 14746742163 0017074 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# 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.
# --- begin runfiles.bash initialization v3 ---
# Copy-pasted from the Bazel Bash runfiles library v3.
set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
# shellcheck disable=SC1090
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v3 ---
function get_greeting() {
greeting_path=$(rlocation "rules_shell_tests/greeting.txt")
cat "${greeting_path}"
}
rules_shell-0.4.0/tests/bcr/test.sh 0000775 0000000 0000000 00000003161 14746742163 0017301 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# 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.
# --- begin runfiles.bash initialization v3 ---
# Copy-pasted from the Bazel Bash runfiles library v3.
set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
# shellcheck disable=SC1090
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v3 ---
bin_path="$(rlocation "rules_shell_tests/bin.sh")"
if [[ ! -x "${bin_path}" ]]; then
echo "Expected '${bin_path}' to be an executable"
exit 1
fi
runfiles_export_envvars
greeting=$("${bin_path}")
if [[ "${greeting}" != "hello from rules_shell" ]]; then
echo "Expected 'hello from rules_shell', got '${greeting}'"
exit 1
fi
rules_shell-0.4.0/tests/runfiles/ 0000775 0000000 0000000 00000000000 14746742163 0017043 5 ustar 00root root 0000000 0000000 rules_shell-0.4.0/tests/runfiles/BUILD 0000664 0000000 0000000 00000000223 14746742163 0017622 0 ustar 00root root 0000000 0000000 load("//shell:sh_test.bzl", "sh_test")
sh_test(
name = "runfiles_test",
srcs = ["runfiles_test.bash"],
deps = ["//shell/runfiles"],
)
rules_shell-0.4.0/tests/runfiles/runfiles_test.bash 0000775 0000000 0000000 00000046545 14746742163 0022611 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Copyright 2018 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.
set -euo pipefail
function _log_base() {
prefix=$1
shift
echo >&2 "${prefix}[$(basename "${BASH_SOURCE[0]}"):${BASH_LINENO[1]} ($(date "+%H:%M:%S %z"))] $*"
}
function fail() {
_log_base "FAILED" "$@"
exit 1
}
function log_fail() {
# non-fatal version of fail()
_log_base "FAILED" $*
}
function log_info() {
_log_base "INFO" $*
}
which uname >&/dev/null || fail "cannot locate GNU coreutils"
case "$(uname -s | tr [:upper:] [:lower:])" in
msys*|mingw*|cygwin*)
function is_windows() { true; }
;;
*)
function is_windows() { false; }
;;
esac
function find_runfiles_lib() {
# Unset existing definitions of the functions we want to test.
if type rlocation >&/dev/null; then
unset rlocation
unset runfiles_export_envvars
fi
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
echo "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-
else
echo >&2 "ERROR: cannot find //shell/runfiles:runfiles.bash"
exit 1
fi
}
function test_rlocation_call_requires_no_envvars() {
export RUNFILES_DIR=mock/runfiles
export RUNFILES_MANIFEST_FILE=
export RUNFILES_MANIFEST_ONLY=
source "$runfiles_lib_path" || fail
}
function test_rlocation_argument_validation() {
export RUNFILES_DIR=
export RUNFILES_MANIFEST_FILE=
export RUNFILES_MANIFEST_ONLY=
source "$runfiles_lib_path"
# Test invalid inputs to make sure rlocation catches these.
if rlocation "../foo" >&/dev/null; then
fail
fi
if rlocation "foo/.." >&/dev/null; then
fail
fi
if rlocation "foo/../bar" >&/dev/null; then
fail
fi
if rlocation "./foo" >&/dev/null; then
fail
fi
if rlocation "foo/." >&/dev/null; then
fail
fi
if rlocation "foo/./bar" >&/dev/null; then
fail
fi
if rlocation "//foo" >&/dev/null; then
fail
fi
if rlocation "foo//" >&/dev/null; then
fail
fi
if rlocation "foo//bar" >&/dev/null; then
fail
fi
if rlocation "\\foo" >&/dev/null; then
fail
fi
}
function test_rlocation_abs_path() {
export RUNFILES_DIR=
export RUNFILES_MANIFEST_FILE=
export RUNFILES_MANIFEST_ONLY=
source "$runfiles_lib_path"
if is_windows; then
[[ "$(rlocation "c:/Foo" || echo failed)" == "c:/Foo" ]] || fail
[[ "$(rlocation "c:\\Foo" || echo failed)" == "c:\\Foo" ]] || fail
else
[[ "$(rlocation "/Foo" || echo failed)" == "/Foo" ]] || fail
fi
}
function test_init_manifest_based_runfiles() {
local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
cat > $tmpdir/foo.runfiles_manifest << EOF
a/b $tmpdir/c/d
e/f $tmpdir/g h
y $tmpdir/y
c/dir $tmpdir/dir
unresolved $tmpdir/unresolved
h/\si $tmpdir/ j k
h/\s\bi $tmpdir/ j k b
h/\n\bi $tmpdir/ \bnj k \na
dir\swith\sspaces $tmpdir/dir with spaces
space\snewline\nbackslash\b_dir $tmpdir/space newline\nbackslash\ba
EOF
mkdir "${tmpdir}/c"
mkdir "${tmpdir}/y"
mkdir -p "${tmpdir}/dir/deeply/nested"
touch "${tmpdir}/c/d" "${tmpdir}/g h"
touch "${tmpdir}/dir/file"
ln -s /does/not/exist "${tmpdir}/dir/unresolved"
touch "${tmpdir}/dir/deeply/nested/file"
touch "${tmpdir}/dir/deeply/nested/file with spaces"
ln -s /does/not/exist "${tmpdir}/unresolved"
touch "${tmpdir}/ j k"
touch "${tmpdir}/ j k b"
mkdir -p "${tmpdir}/dir with spaces/nested"
touch "${tmpdir}/dir with spaces/nested/file"
if ! is_windows; then
touch "${tmpdir}/ \nj k "$'\n'a
mkdir -p "${tmpdir}/space newline"$'\n'"backslash\a"
touch "${tmpdir}/space newline"$'\n'"backslash\a/f i\le"
fi
export RUNFILES_DIR=
export RUNFILES_MANIFEST_FILE=$tmpdir/foo.runfiles_manifest
source "$runfiles_lib_path"
[[ -z "$(rlocation a || echo failed)" ]] || fail
[[ -z "$(rlocation c/d || echo failed)" ]] || fail
[[ "$(rlocation a/b || echo failed)" == "$tmpdir/c/d" ]] || fail
[[ "$(rlocation e/f || echo failed)" == "$tmpdir/g h" ]] || fail
[[ "$(rlocation y || echo failed)" == "$tmpdir/y" ]] || fail
[[ -z "$(rlocation c || echo failed)" ]] || fail
[[ -z "$(rlocation c/di || echo failed)" ]] || fail
[[ "$(rlocation c/dir || echo failed)" == "$tmpdir/dir" ]] || fail
[[ "$(rlocation c/dir/file || echo failed)" == "$tmpdir/dir/file" ]] || fail
[[ -z "$(rlocation c/dir/unresolved || echo failed)" ]] || fail
[[ "$(rlocation c/dir/deeply/nested/file || echo failed)" == "$tmpdir/dir/deeply/nested/file" ]] || fail
[[ "$(rlocation "c/dir/deeply/nested/file with spaces" || echo failed)" == "$tmpdir/dir/deeply/nested/file with spaces" ]] || fail
[[ -z "$(rlocation unresolved || echo failed)" ]] || fail
[[ "$(rlocation "h/ i" || echo failed)" == "$tmpdir/ j k" ]] || fail
[[ "$(rlocation "h/ \i" || echo failed)" == "$tmpdir/ j k b" ]] || fail
[[ "$(rlocation "dir with spaces" || echo failed)" == "$tmpdir/dir with spaces" ]] || fail
[[ "$(rlocation "dir with spaces/nested/file" || echo failed)" == "$tmpdir/dir with spaces/nested/file" ]] || fail
if ! is_windows; then
[[ "$(rlocation $'h/\n\\i' || echo failed)" == "$tmpdir/ \nj k "$'\n'a ]] || fail
[[ "$(rlocation "space newline"$'\n'"backslash\_dir/f i\le" || echo failed)" == "${tmpdir}/space newline"$'\n'"backslash\a/f i\le" ]] || fail
fi
rm -r "$tmpdir/c/d" "$tmpdir/g h" "$tmpdir/y" "$tmpdir/dir" "$tmpdir/unresolved" "$tmpdir/ j k" "$tmpdir/dir with spaces"
if ! is_windows; then
rm -r "$tmpdir/ \nj k "$'\n'a "${tmpdir}/space newline"$'\n'"backslash\a"
[[ -z "$(rlocation $'h/\n\\i' || echo failed)" ]] || fail
[[ -z "$(rlocation "space newline"$'\n'"backslash\_dir/f i\le" || echo failed)" ]] || fail
fi
[[ -z "$(rlocation a/b || echo failed)" ]] || fail
[[ -z "$(rlocation e/f || echo failed)" ]] || fail
[[ -z "$(rlocation y || echo failed)" ]] || fail
[[ -z "$(rlocation c/dir || echo failed)" ]] || fail
[[ -z "$(rlocation c/dir/file || echo failed)" ]] || fail
[[ -z "$(rlocation c/dir/deeply/nested/file || echo failed)" ]] || fail
[[ -z "$(rlocation "h/ i" || echo failed)" ]] || fail
[[ -z "$(rlocation "dir with spaces" || echo failed)" ]] || fail
[[ -z "$(rlocation "dir with spaces/nested/file" || echo failed)" ]] || fail
}
function test_manifest_based_envvars() {
local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
echo "a b" > $tmpdir/foo.runfiles_manifest
export RUNFILES_DIR=
export RUNFILES_MANIFEST_FILE=$tmpdir/foo.runfiles_manifest
mkdir -p $tmpdir/foo.runfiles
source "$runfiles_lib_path"
runfiles_export_envvars
[[ "${RUNFILES_DIR:-}" == "$tmpdir/foo.runfiles" ]] || fail
[[ "${RUNFILES_MANIFEST_FILE:-}" == "$tmpdir/foo.runfiles_manifest" ]] || fail
}
function test_init_directory_based_runfiles() {
local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
export RUNFILES_DIR=${tmpdir}/mock/runfiles
export RUNFILES_MANIFEST_FILE=
source "$runfiles_lib_path"
mkdir -p "$RUNFILES_DIR/a"
touch "$RUNFILES_DIR/a/b" "$RUNFILES_DIR/c d"
[[ "$(rlocation a || echo failed)" == "$RUNFILES_DIR/a" ]] || fail
[[ "$(rlocation c/d || echo failed)" == failed ]] || fail
[[ "$(rlocation a/b || echo failed)" == "$RUNFILES_DIR/a/b" ]] || fail
[[ "$(rlocation "c d" || echo failed)" == "$RUNFILES_DIR/c d" ]] || fail
[[ "$(rlocation "c" || echo failed)" == failed ]] || fail
rm -r "$RUNFILES_DIR/a" "$RUNFILES_DIR/c d"
[[ "$(rlocation a || echo failed)" == failed ]] || fail
[[ "$(rlocation a/b || echo failed)" == failed ]] || fail
[[ "$(rlocation "c d" || echo failed)" == failed ]] || fail
}
function test_directory_based_runfiles_with_repo_mapping_from_main() {
local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
export RUNFILES_DIR=${tmpdir}/mock/runfiles
mkdir -p "$RUNFILES_DIR"
cat > "$RUNFILES_DIR/_repo_mapping" < "$RUNFILES_DIR/_repo_mapping" < "$tmpdir/foo.repo_mapping" < "$RUNFILES_MANIFEST_FILE" << EOF
_repo_mapping $tmpdir/foo.repo_mapping
config.json $tmpdir/config.json
protobuf+3.19.2/foo/runfile $tmpdir/protobuf+3.19.2/foo/runfile
_main/bar/runfile $tmpdir/_main/bar/runfile
protobuf+3.19.2/bar/dir $tmpdir/protobuf+3.19.2/bar/dir
EOF
source "$runfiles_lib_path"
mkdir -p "$tmpdir/_main/bar"
touch "$tmpdir/_main/bar/runfile"
mkdir -p "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted"
touch "$tmpdir/protobuf+3.19.2/bar/dir/file"
touch "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"
mkdir -p "$tmpdir/protobuf+3.19.2/foo"
touch "$tmpdir/protobuf+3.19.2/foo/runfile"
touch "$tmpdir/config.json"
[[ "$(rlocation "my_module/bar/runfile" "" || echo failed)" == "$tmpdir/_main/bar/runfile" ]] || fail
[[ "$(rlocation "my_workspace/bar/runfile" "" || echo failed)" == "$tmpdir/_main/bar/runfile" ]] || fail
[[ "$(rlocation "my_protobuf/foo/runfile" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/foo/runfile" ]] || fail
[[ "$(rlocation "my_protobuf/bar/dir" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir" ]] || fail
[[ "$(rlocation "my_protobuf/bar/dir/file" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/file" ]] || fail
[[ "$(rlocation "my_protobuf/bar/dir/de eply/nes ted/fi+le" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le" ]] || fail
[[ -z "$(rlocation "protobuf/foo/runfile" "" || echo failed)" ]] || fail
[[ -z "$(rlocation "protobuf/bar/dir/dir/de eply/nes ted/fi+le" "" || echo failed)" ]] || fail
[[ "$(rlocation "_main/bar/runfile" "" || echo failed)" == "$tmpdir/_main/bar/runfile" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/foo/runfile" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/foo/runfile" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/bar/dir" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/bar/dir/file" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/file" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le" "" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le" ]] || fail
[[ "$(rlocation "config.json" "" || echo failed)" == "$tmpdir/config.json" ]] || fail
}
function test_manifest_based_runfiles_with_repo_mapping_from_other_repo() {
local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
cat > "$tmpdir/foo.repo_mapping" < "$RUNFILES_MANIFEST_FILE" << EOF
_repo_mapping $tmpdir/foo.repo_mapping
config.json $tmpdir/config.json
protobuf+3.19.2/foo/runfile $tmpdir/protobuf+3.19.2/foo/runfile
_main/bar/runfile $tmpdir/_main/bar/runfile
protobuf+3.19.2/bar/dir $tmpdir/protobuf+3.19.2/bar/dir
EOF
source "$runfiles_lib_path"
mkdir -p "$tmpdir/_main/bar"
touch "$tmpdir/_main/bar/runfile"
mkdir -p "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted"
touch "$tmpdir/protobuf+3.19.2/bar/dir/file"
touch "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"
mkdir -p "$tmpdir/protobuf+3.19.2/foo"
touch "$tmpdir/protobuf+3.19.2/foo/runfile"
touch "$tmpdir/config.json"
[[ "$(rlocation "protobuf/foo/runfile" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/foo/runfile" ]] || fail
[[ "$(rlocation "protobuf/bar/dir" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir" ]] || fail
[[ "$(rlocation "protobuf/bar/dir/file" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/file" ]] || fail
[[ "$(rlocation "protobuf/bar/dir/de eply/nes ted/fi+le" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le" ]] || fail
[[ -z "$(rlocation "my_module/bar/runfile" "protobuf+3.19.2" || echo failed)" ]] || fail
[[ -z "$(rlocation "my_protobuf/bar/dir/de eply/nes ted/fi+le" "protobuf+3.19.2" || echo failed)" ]] || fail
[[ "$(rlocation "_main/bar/runfile" "protobuf+3.19.2" || echo failed)" == "$tmpdir/_main/bar/runfile" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/foo/runfile" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/foo/runfile" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/bar/dir" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/bar/dir/file" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/file" ]] || fail
[[ "$(rlocation "protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le" "protobuf+3.19.2" || echo failed)" == "$tmpdir/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le" ]] || fail
[[ "$(rlocation "config.json" "protobuf+3.19.2" || echo failed)" == "$tmpdir/config.json" ]] || fail
}
function test_directory_based_envvars() {
export RUNFILES_DIR=mock/runfiles
export RUNFILES_MANIFEST_FILE=
source "$runfiles_lib_path"
runfiles_export_envvars
[[ "${RUNFILES_DIR:-}" == "mock/runfiles" ]] || fail
[[ -z "${RUNFILES_MANIFEST_FILE:-}" ]] || fail
}
function main() {
local -r manifest_file="${RUNFILES_MANIFEST_FILE:-}"
local -r dir="${RUNFILES_DIR:-}"
local -r runfiles_lib_path=$(find_runfiles_lib)
local -r tests=$(declare -F | grep " -f test" | awk '{print $3}')
local failure=0
for t in $tests; do
export RUNFILES_MANIFEST_FILE="$manifest_file"
export RUNFILES_DIR="$dir"
if ! ($t); then
failure=1
fi
done
return $failure
}
main