-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FR: allow ctx.which to watch for PATH/ program changes #24864
Comments
What do you think of the alternative of watching the binary that is returned? That's something you can already do today and it sounds more reliable to me (lower false negative and positive rate). |
i.e, given A repo rule can do that today, so it's a small, but welcome, quality-of-life improvement IMHO. However, it doesn't address the case that user code can't implement today: if PATH changes in such a way that which()'s value would be different. i.e. these cases:
|
Thanks for the additional explanation. I agree that having this on def _watch_which_impl(ctx):
# TODO: Support Windows.
path = ctx.getenv("PATH").split(":")
tool_path = None
for p in path:
candidate = ctx.path(p).get_child(ctx.attr.tool)
# Rerun if the file is created or deleted.
# This also reruns if the existing file changes, but
# this repo rule is cheap enough to evaluate.
ctx.watch(candidate)
# TODO: Check for executable bit on Unix.
if candidate.exists:
tool_path = p
break
ctx.file("BUILD")
ctx.file("path.bzl", "TOOL_PATH = {}".format(repr(tool_path)))
watch_which = repository_rule(
implementation = _watch_which_impl,
attrs = {
"tool": attr.string(mandatory = True),
},
) Would that be a suitable polyfill for you? Edit: It looks like this doesn't watch the |
Ohh, that's clever :) Yeah, that will probably work well enough. I'm trying to think of differences if an input is executed in one repo vs another, but can't think of anything. If the env was different in one repo vs another? Not sure how that would happen with PATH, though. I don't think there are flags/settings/things that would affect the env one repo sees but not other repos? For posterity, the Bazel implementation of Line 2005 in 08c6d42
Looking at the Java code, I don't think an identical implementation is possible in Starlark:
Other differences look easy to handle: colon/semicolon path separator, adding Maybe it'd make more sense to just call ctx.which() for the actual computed value, but still do the path parsing to capture the edge case of an earlier non-existent PATH entry coming into existence. |
Just for posterity: I was thinking through how to use the repo-per-tool for my case, and, yeah, I'm pretty sure its doable, but can become tedious to do. The tediousness comes from because, in my case, the tool is user-specified. e.g., in MODULE, a user might put:
Which means, ultimately, I need e.g. More generally, as a pattern, this can probably work for any case. The main limitation is how tedious it would be to implement. Fundamentally, what it does is split a repo rule in two: one half computes a value, the other half uses the value. So, as long as a repo can serialize its state to a file for the second repo to pick up from, it can be made to work. |
Description of the feature request:
In short: Add a
watch=True
arg toctx.which()
. This makes it parsePATH
and watch for$program
to exist/change in a directory before where it first found$program
. Unless that condition is met, the which() result is not invalidated. The pesudo-code for this would be something like:Background:
The
ctx.which()
function is used to find a program by looking for it in the locations specified by thePATH
environment variable. Thus, changing PATH could change the result of which(), depending on how path changed and where a program was found.Today, changes to the PATH environment variable won't invalidate any lookups using which(). This makes some sense because it's pretty context specific as to whether it matters or not. However, this is problematic for cases which do care if the result would have changed. My go-to example is when configuring a language toolchain using the local system (non-ideal, but IMHO, quite reasonable when users intentionally want to use a custom toolchain for whatever reason).
While a repository rule can call
getenv("PATH")
to watch the path environment variable, this ends up being too noisy -- tools like git may modify PATH when running hooks (bazelbuild/rules_python#2551 (comment)) in such a way that wouldn't invalidate most which() calls.Which category does this issue belong to?
External Dependency
What underlying problem are you trying to solve with this feature?
Making a repository rule correctly watch for changes to its inputs while not invalidating when unnecessary.
Which operating system are you running Bazel on?
Linux
What is the output of
bazel info release
?8.0.0
If
bazel info release
returnsdevelopment version
or(@non-git)
, tell us how you built Bazel.No response
What's the output of
git remote get-url origin; git rev-parse HEAD
?No response
Have you found anything relevant by searching the web?
Searched all, didn't find a mention of this.
Any other information, logs, or outputs that you want to share?
This feature request originates from discussion in bazelbuild/rules_python#2551
The text was updated successfully, but these errors were encountered: