Resolve relative manifest targets like the runfiles directory does (#69)

The target of a runfiles manifest entry is an absolute path, except for
unresolved symlinks (`ctx.actions.declare_symlink`), whose target Bazel
copies into the manifest verbatim:
[`SourceManifestAction#writeFile`](https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/analysis/SourceManifestAction.java)
writes `metadata.getUnresolvedSymlinkTarget()`, which may be relative.
In a runfiles directory, sandboxes and
`SymlinkTreeHelper#createRunfilesSymlinks` create such an entry
textually ("Unresolved symlinks are created textually"), so the file
system resolves it relative to the directory containing the symlink.

A manifest-based lookup returned that raw target instead, i.e. a path
relative to the current working directory. `rlocation` thus either
failed or, worse, returned an unrelated file that happened to exist
relative to the working directory.

This change makes it so that a relative target resolves as an rlocation
path relative to the directory of its entry and looks that up in the
manifest again, which is what resolving the symlink in a materialized
runfiles directory amounts to. Targets that escape the runfiles root
cannot be resolved this way and are reported as missing, as are cycles,
which are broken after 32 levels.

The test runs the same lookups against both backends:
`write_relative_symlink_target_layout` emits the same set of unresolved
symlinks as a manifest and as a materialized runfiles directory, and
`assert_relative_symlink_target_lookups` asserts that each resolves to
the same file. Before this change, the directory-backed half passes and
the manifest-backed one fails on its first assertion. The only case in
which the two cannot agree is a relative target that leaves the runfiles
tree, which the file system resolves against the directory's parent; the
manifest offers no way to reach it, so it is reported as missing.
2 files changed
tree: 5f60217283727780bf98151b4dedd3ed58ae1c30
  1. .bazelci/
  2. .bcr/
  3. .github/
  4. docs/
  5. shell/
  6. tests/
  7. .bazelignore
  8. .bazelrc
  9. .bazelversion
  10. .gitignore
  11. CONTRIBUTING.md
  12. LICENSE
  13. MODULE.bazel
  14. README.md
  15. WORKSPACE
README.md

rules_shell

This repository contains the Bazel ruleset for shell scripts.