-
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
Add factory for creating paths relative to well-known roots #15805
Conversation
This change adds a factory for creating `PathFragments` relative to pre-defined (named) roots (e.g., relative to `%workspace%`). The syntax is choosen to match existing ad-hoc solutions for `%workspace%`, or `%builtins%` in other places (so that we can ideally migrate them in a follow-up). We'll use this for parsing paths from the command-line (e.g., `--credential_helper=%workspace%/foo`). Progress on https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md
@tjgq PTAL |
* (e.g., {@code %workspace%/foo} becomes {@code </path/to/workspace>/foo}). | ||
*/ | ||
public final class CommandLinePathFactory { | ||
private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("^(%([a-z_]+)%/)?([^%].*)$"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the last *
a +
so that an empty path is rejected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*
is actually correct. We reject the empty path because of the required [^%]
before. Changing it to +
would wrongly reject single-char paths (which are fine)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, you're right :)
if (root == null) { | ||
throw new IllegalArgumentException(String.format(Locale.US, "Unknown root %s", rootName)); | ||
} | ||
return root.getRelative(path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, what's the result of
new CommandLinePathFactory(ImmutableMap.of("workspace", "/path/to/workspace")).create("%workspace%/../bar");
Should we make it a requirement that the path must resolve to a descendant of the root (or possible even disallow .
and ..
segments entirely)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed it to reject upwards references. PathFragment.create()
will take care of normalizing it.
} | ||
|
||
@Test | ||
public void UnknownRoot() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method name should start with lowercase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
of course...
assertThat(factory.create("/absolute/path/2")) | ||
.isEqualTo(PathFragment.create("/absolute/path/2")); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test to verify that the empty path is rejected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
/** Tests for {@link CommandLinePathFactory}. */ | ||
@RunWith(JUnit4.class) | ||
public class CommandLinePathFactoryTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this class also going to be used in the PATH lookup case? (i.e., --credential_helper=somehelper
)? If so, we should have tests here for paths that don't start with a slash, or without slashes at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, let me clarify:
- If we're going to use this class for PATH lookup (e.g.
--credential_helper=foo
), we should have a test for them. - Since we agreed in the proposal to disallow non-absolute paths with slashes (e.g.
--credential_helper=foo/bar
) unless they're relative to a%root%
, we should reject them (and have a test to verify that we do).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added PATH
lookup (I was originally planning to do it somewhere else, but we may as well do it in this factory)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I'm not so sure PATH lookup belongs here. (What I had in mind was to simply store the non-absolute path, and resolve it later.)
I expect this code will run once at options parsing time, which means the result will be cached during the lifetime of the Bazel server process. Hence, if you add or remove a binary from one of the PATH directories that could affect the resolution of a particular helper, it won't take effect until you restart the server, which might be surprising to users.
WDYT? Should we defer PATH resolution until the helper is invoked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think what I said above only applies to startup options. If we can make --credential_helper
a non-startup option, then I think it's fine to do the resolution here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of not making it the same option kind as --remote_{cache,executor}
, which I think is build
. It feels weird to make the credential helper a startup option when those aren't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect build
is not enough (e.g. repository fetching is necessary for the query
command to work) but I'm struggling to imagine a reason for it to be available at startup. Let's go with the current version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack. I think query
actually implies build
for historical reasons.
PTAL |
|
||
/** Tests for {@link CommandLinePathFactory}. */ | ||
@RunWith(JUnit4.class) | ||
public class CommandLinePathFactoryTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I'm not so sure PATH lookup belongs here. (What I had in mind was to simply store the non-absolute path, and resolve it later.)
I expect this code will run once at options parsing time, which means the result will be cached during the lifetime of the Bazel server process. Hence, if you add or remove a binary from one of the PATH directories that could affect the resolution of a particular helper, it won't take effect until you restart the server, which might be surprising to users.
WDYT? Should we defer PATH resolution until the helper is invoked?
|
||
String rootName = matcher.group(2); | ||
PathFragment path = PathFragment.create(matcher.group(3)); | ||
if (path.containsUplevelReferences()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just use PathFragment.isNormalized
here? I can't imagine a good reason to include a .
component either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should. IIUC, PathFragment.isNormalized
would mean that you need to pass /
instead of \
on Windows, which feels like an unnecessary restriction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack, I thought it only checked for .
and ..
.
|
||
String rootName = matcher.group(2); | ||
PathFragment path = PathFragment.create(matcher.group(3)); | ||
if (path.containsUplevelReferences()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack, I thought it only checked for .
and ..
.
|
||
/** Tests for {@link CommandLinePathFactory}. */ | ||
@RunWith(JUnit4.class) | ||
public class CommandLinePathFactoryTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect build
is not enough (e.g. repository fetching is necessary for the query
command to work) but I'm struggling to imagine a reason for it to be available at startup. Let's go with the current version.
@bazel-io flag |
@bazel-io fork 5.3.0 |
Hey @Yannic, we are trying to cherry-pick these changes to release-5.3.0. But pre-submit checks are failing due to missing dependencies. So, could you please help us in cherry picking these changes to release-5.3.0? |
Taking a look @ckolli5 |
This change adds a factory for creating `PathFragments` relative to pre-defined (named) roots (e.g., relative to `%workspace%`). The syntax is choosen to match existing ad-hoc solutions for `%workspace%`, or `%builtins%` in other places (so that we can ideally migrate them in a follow-up). We'll use this for parsing paths from the command-line (e.g., `--credential_helper=%workspace%/foo`). Progress on https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md Closes bazelbuild#15805. PiperOrigin-RevId: 460950483 Change-Id: Ie263fb6d6c2ea938a850a72793d551135df6862e
This change adds a factory for creating `PathFragments` relative to pre-defined (named) roots (e.g., relative to `%workspace%`). The syntax is choosen to match existing ad-hoc solutions for `%workspace%`, or `%builtins%` in other places (so that we can ideally migrate them in a follow-up). We'll use this for parsing paths from the command-line (e.g., `--credential_helper=%workspace%/foo`). Progress on https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md Closes bazelbuild#15805. PiperOrigin-RevId: 460950483 Change-Id: Ie263fb6d6c2ea938a850a72793d551135df6862e
This change adds a factory for creating `PathFragments` relative to pre-defined (named) roots (e.g., relative to `%workspace%`). The syntax is choosen to match existing ad-hoc solutions for `%workspace%`, or `%builtins%` in other places (so that we can ideally migrate them in a follow-up). We'll use this for parsing paths from the command-line (e.g., `--credential_helper=%workspace%/foo`). Progress on https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md Closes bazelbuild#15805. PiperOrigin-RevId: 460950483 Change-Id: Ie263fb6d6c2ea938a850a72793d551135df6862e
This change adds a factory for creating
PathFragments
relative topre-defined (named) roots (e.g., relative to
%workspace%
).The syntax is choosen to match existing ad-hoc solutions for
%workspace%
,or
%builtins%
in other places (so that we can ideally migrate them ina follow-up).
We'll use this for parsing paths from the command-line (e.g.,
--credential_helper=%workspace%/foo
).Progress on https://github.com/bazelbuild/proposals/blob/main/designs/2022-06-07-bazel-credential-helpers.md