Skip to content
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 optional location expansion for the nixopts attribute #132

Merged
merged 16 commits into from
Nov 17, 2020
Merged

Conversation

aherrmann
Copy link
Member

@aherrmann aherrmann commented Jul 17, 2020

This factors out the addition of location expansion for the nixopts attribute from #128.

This adds an additional attribute expand_location to nixpkgs_package. When set to True location expansion will be performed on the value of the nixopts attribute. This performs location expansion on the value of the nixopts attribute to nixpkgs_packge. I.e. any occurrence of $(location LABEL) will be expanded to the path to the file referenced by LABEL. This feature is motivated by #128 where we need to predict the file path of a dependency from within a macro invoking repository rules.

This also adds a test-case for location expansion.

@support-dpulls
Copy link

support-dpulls commented Jul 20, 2020

Hey there! Walid from Dpulls here.
We recently noticed a bug that happens when the Dpulls status check is set as required (link of the issue: dpulls/backlog#10) blocking some PRs from being merged. This PR seems to be concerned by this issue.
We suggest you to temporarily uncheck Dpulls from your branch protection rule until we fix the issue. We will let you know once it is done.
Thanks.
cc @aherrmann

@mboes
Copy link
Member

mboes commented Jul 28, 2020

@aherrmann why not do this always? i.e. not gate the location expansion by a flag?

@aherrmann
Copy link
Member Author

@aherrmann why not do this always? i.e. not gate the location expansion by a flag?

The motivation was to not make this a breaking change. Prior uses of nixopts could be using $, e.g. "${foo}/bar", which would now be illegal and should instead be "$${foo}/bar".

@mboes
Copy link
Member

mboes commented Jul 29, 2020

I'd go for making this a breaking change. We're otherwise stuck with a more complicated API that breaks precedent with the way location expansion in other rules work (where i've never seen this be gated by a flag). We could introduce expand_location for now and emit a warning if we see $ in nixopts, thus offering a deprecation period to users. But that hardly seems worth it, since this is small corner case that will affect very few users if any.

Alternatively, maybe it's possible to steal less syntax? Allow ${foo}/bar but also $(location ...). It appears that in Bazel Make variable expansion, $ needs to be escaped only because they allow shorthands. But we only need $(location ...). In fact it's possible that the parsing code might end up simpler: look for a $(location , then a ) somewhere later. Anything in between is deemed to be a label (which we can optionally further sanity check). Essentially, we'd be implementing only the equivalent of ctx.expand_location(), not ctx.expand_make_variables().

Nit: I'd put the expand_location() thing in its own source file. It's a complex enough function that is completely generic and that others may want to use by copying the source file.

@aherrmann
Copy link
Member Author

I'd go for making this a breaking change. We're otherwise stuck with a more complicated API that breaks precedent with the way location expansion in other rules work (where i've never seen this be gated by a flag). We could introduce expand_location for now and emit a warning if we see $ in nixopts, thus offering a deprecation period to users. But that hardly seems worth it, since this is small corner case that will affect very few users if any.

Fair enough, I'll remove the gating.

It appears that in Bazel Make variable expansion, $ needs to be escaped only because they allow shorthands. But we only need $(location ...). In fact it's possible that the parsing code might end up simpler: look for a $(location , then a ) somewhere later. Anything in between is deemed to be a label (which we can optionally further sanity check).

That's what the initial implementation did, however based on feedback I moved it to be consistent with Bazel's behavior.

aherrmann added a commit that referenced this pull request Jul 29, 2020
aherrmann added a commit that referenced this pull request Jul 29, 2020
@aherrmann
Copy link
Member Author

I've removed the gating and factored out the location expansion into its own module.

aherrmann added a commit that referenced this pull request Nov 6, 2020
aherrmann added a commit that referenced this pull request Nov 6, 2020
Copy link
Contributor

@Profpatsch Profpatsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The feature makes sense to me, but the tests and implementation are a bit involved and rather hard to understand (I couldn’t fit everything into my head during review without spending undue amounts of time on it). More separation into smaller tests/subroutines would help.

expr_args.extend(repository_ctx.attr.nixopts)
if repository_ctx.attr.expand_location:
expr_args.extend([
_expand_location(repository_ctx, opt, nix_file_deps, "nixopts")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use attr keys for easier reading

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 57 to 76
# Test nixopts location expansion
sh_test(
name = "location-expansion-test",
srcs = ["location_expansion.sh"],
args = [
"$(POSIX_DIFF)",
"$(rootpath //:nixpkgs.json)",
"$(rootpath //:nixpkgs.nix)",
"$(rootpath //tests:relative_imports/nixpkgs.nix)",
"$(rootpath @nixpkgs_location_expansion_test//:out/nixpkgs.json)",
"$(rootpath @nixpkgs_location_expansion_test//:out/nixpkgs.nix)",
"$(rootpath @nixpkgs_location_expansion_test//:out/relative_imports.nix)",
],
data = [
"//:nixpkgs.json",
"//:nixpkgs.nix",
"//tests:relative_imports/nixpkgs.nix",
"@nixpkgs_location_expansion_test//:out/nixpkgs.json",
"@nixpkgs_location_expansion_test//:out/nixpkgs.nix",
"@nixpkgs_location_expansion_test//:out/relative_imports.nix",
],
toolchains = ["@rules_sh//sh/posix:make_variables"],
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is extremely convoluted, it has so many moving parts that it’s hard to understand what it does or why. Needs either a more detailed description of what is done and why, or be split up into more tests that each do a lot less.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, the location expansion stuff is just a string replacement, and the algo could be tested as a unit-test entirely; which would mean the integration test needs to test less.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the factored out pure parsing and label resolution functions it is now possible to define unit tests for these, which I've done. I've simplified this integration test to only test that the mapping to paths works correctly for a file in the main repository and for one in an external repository.

Comment on lines 94 to 95
# Step through occurrences of `$`. This is bounded by the length of the string.
for _ in range(len(string)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is a bit too unwieldy for my taste.

I would have said we should split it up into generators, but skylark does not have them. However, the location strings should be short enough for it not to matter.

So e.g. have one function which returns all “$ to end” strings for $ that are not escaped, one function tries to parse the location syntax, and then one function which replaces the location syntax with its actual content.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've factored out the parsing and label resolution into separate pure functions. With this change it becomes possible to test them in unit tests. I've also changed the parsing logic a bit to make it clearer.

aherrmann added a commit that referenced this pull request Nov 11, 2020
Addressing review comment
#132 (comment)
aherrmann added a commit that referenced this pull request Nov 11, 2020
Addressing review comment
#132 (comment)

Implement parsing of location expansion commands and label resolution as
pure functions that do not depend on the repository context. This allows
to test these functions in unit tests.
aherrmann added a commit that referenced this pull request Nov 11, 2020
aherrmann added a commit that referenced this pull request Nov 11, 2020
It now only tests the correct mapping of paths in the local workspace
and in an external workspace. The parsing of more complicated location
strings is tested in the unit tests.

Addressing review comment
#132 (comment)
@aherrmann aherrmann requested a review from Profpatsch November 11, 2020 15:02
Copy link
Contributor

@Profpatsch Profpatsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great now! I’m confident that it does what we want and is well-tested.

@Profpatsch Profpatsch added the merge-queue merge on green CI label Nov 17, 2020
Addressing review comment
#132 (comment)
Addressing review comment
#132 (comment)

Implement parsing of location expansion commands and label resolution as
pure functions that do not depend on the repository context. This allows
to test these functions in unit tests.
It now only tests the correct mapping of paths in the local workspace
and in an external workspace. The parsing of more complicated location
strings is tested in the unit tests.

Addressing review comment
#132 (comment)
@mergify mergify bot merged commit 3043609 into master Nov 17, 2020
@mergify mergify bot deleted the location branch November 17, 2020 14:54
@mergify mergify bot removed the merge-queue merge on green CI label Nov 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants