Skip to content

Commit

Permalink
Adapt rlocation
Browse files Browse the repository at this point in the history
  • Loading branch information
fmeum committed Nov 8, 2022
1 parent ea62b96 commit 7b15eec
Show file tree
Hide file tree
Showing 4 changed files with 331 additions and 59 deletions.
56 changes: 56 additions & 0 deletions src/test/py/bazel/bzlmod/bazel_module_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,5 +695,61 @@ def testRunfilesRepoMappingManifest(self):
self.Path('bazel-bin/external/bar~2.0/bar.runfiles_manifest')) as f:
self.assertIn("_repo_mapping ", f.read())

def testBashRunfilesLibraryRepoMapping(self):
self.main_registry.setModuleBasePath('projects')
projects_dir = self.main_registry.projects

self.main_registry.createLocalPathModule('data', '1.0', 'data')
projects_dir.joinpath('data').mkdir(exist_ok=True)
scratchFile(projects_dir.joinpath('data', 'WORKSPACE'))
scratchFile(projects_dir.joinpath('data', 'foo.txt'), ['hello'])
scratchFile(projects_dir.joinpath('data', 'BUILD'),
['exports_files(["foo.txt"])'])

self.main_registry.createLocalPathModule('test', '1.0', 'test',
{'data': '1.0'})
projects_dir.joinpath('test').mkdir(exist_ok=True)
scratchFile(projects_dir.joinpath('test', 'WORKSPACE'))
scratchFile(projects_dir.joinpath('test', 'BUILD'), [
'sh_test(',
' name = "test",'
' srcs = ["test.sh"],',
' data = ["@data//:foo.txt"],',
' args = ["$(rlocationpath @data//:foo.txt)"],',
' deps = ["@bazel_tools//tools/bash/runfiles"],',
')'
])
test_script = projects_dir.joinpath('test', 'test.sh')
scratchFile(test_script, """#!/usr/bin/env bash
# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
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 v2 ---
[[ -f "$(rlocation $1)" ]] || exit 1
[[ -f "$(rlocation data/foo.txt)" ]] || exit 2
""".splitlines())
os.chmod(test_script, 0o755)

self.ScratchFile('MODULE.bazel', ['bazel_dep(name="test",version="1.0")'])
self.ScratchFile('WORKSPACE')

# Run sandboxed on Linux and macOS.
exit_code, stderr, stdout = self.RunBazel(
['test', '@test//:test', '--test_output=errors',
'--test_env=RUNFILES_LIB_DEBUG=1'], allow_failure=True)
self.AssertExitCode(exit_code, 0, stderr, stdout)
# Run unsandboxed on all platforms.
exit_code, stderr, stdout = self.RunBazel(
['run', '@test//:test'], allow_failure=True,
env_add={"RUNFILES_LIB_DEBUG": "1"})
self.AssertExitCode(exit_code, 0, stderr, stdout)


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion src/test/shell/bazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ sh_test(
":test-deps",
"@bazel_tools//tools/bash/runfiles",
],
tags = ["requires-network"],
shard_count = 3,
tags = ["requires-network"],
)

sh_test(
Expand Down
156 changes: 98 additions & 58 deletions tools/bash/runfiles/runfiles.bash
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ msys*|mingw*|cygwin*)
esac

# 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"
Expand All @@ -111,72 +115,40 @@ function rlocation() {
"drive name"
fi
return 1
else
if [[ -e "${RUNFILES_DIR:-/dev/null}/$1" ]]; then
fi

if [[ -f "$RUNFILES_REPO_MAPPING" ]]; then
local -r target_repo_apparent_name=$(echo "$1" | cut -d / -f 1)
local -r remainder=$(echo "$1" | cut -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): found under RUNFILES_DIR ($RUNFILES_DIR), return"
echo >&2 "INFO[runfiles.bash]: rlocation($1): looking up canonical name for ($target_repo_apparent_name) from ($source_repo) in ($RUNFILES_REPO_MAPPING)"
fi
echo "${RUNFILES_DIR}/$1"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
local -r target_repo=$(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): looking in RUNFILES_MANIFEST_FILE ($RUNFILES_MANIFEST_FILE)"
echo >&2 "INFO[runfiles.bash]: rlocation($1): canonical name of target repo is ($target_repo)"
fi
local -r result=$(grep -m1 "^$1 " "${RUNFILES_MANIFEST_FILE}" | cut -d ' ' -f 2-)
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"
prefix_result=$(grep -m1 "^$prefix " "${RUNFILES_MANIFEST_FILE}" | cut -d ' ' -f 2-)
[[ -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.
break
done
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): not found in manifest"
fi
echo ""
if [[ -n "$target_repo" ]]; then
local -r rlocation_path="$target_repo/$remainder"
else
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"
fi
local -r rlocation_path="$1"
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
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

Expand Down Expand Up @@ -241,7 +213,6 @@ function runfiles_current_repository() {
if [[ -z "$rlocation_path" ]]; then
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: runfiles_current_repository($idx): ($normalized_caller_path) is not the target of an entry in the runfiles manifest ($RUNFILES_MANIFEST_FILE)"
cat "$RUNFILES_MANIFEST_FILE" >&2
fi
return 1
else
Expand Down Expand Up @@ -306,3 +277,72 @@ function runfiles_current_repository() {
fi
}
export -f runfiles_current_repository

function runfiles_rlocation_checked() {
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
local -r result=$(grep -m1 "^$1 " "${RUNFILES_MANIFEST_FILE}" | cut -d ' ' -f 2-)
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"
prefix_result=$(grep -m1 "^$prefix " "${RUNFILES_MANIFEST_FILE}" | cut -d ' ' -f 2-)
[[ -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.
break
done
if [[ "${RUNFILES_LIB_DEBUG:-}" == 1 ]]; then
echo >&2 "INFO[runfiles.bash]: rlocation($1): not found in manifest"
fi
echo ""
else
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"
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 RUNFILES_REPO_MAPPING=$(runfiles_rlocation_checked _repo_mapping 2> /dev/null)
Loading

0 comments on commit 7b15eec

Please sign in to comment.