-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Low level <drvPath>^<outputName> installable syntax to match existing <highLevelInstallable>^<outputNames> syntax
#4543
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
Changes from 20 commits
8499f32
1ef88da
e5c42bb
0966532
9c6be01
6951b26
5c1f2e0
fda2224
41e755b
6b61d77
b18720e
49ad315
b585548
6cafe30
f3262bc
8735f55
279ecf7
0e4ec98
12461e2
13f2a6f
26534f1
1879c7c
dc075dc
c7cce3e
d8c1c24
c886b18
dabb03b
32ae715
5273cf4
f61d575
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -395,44 +395,56 @@ static StorePath getDeriver( | |
| struct InstallableStorePath : Installable | ||
| { | ||
| ref<Store> store; | ||
| StorePath storePath; | ||
| DerivedPath req; | ||
|
Ericson2314 marked this conversation as resolved.
|
||
|
|
||
| InstallableStorePath(ref<Store> store, StorePath && storePath) | ||
| : store(store), storePath(std::move(storePath)) { } | ||
| : store(store), | ||
| req(storePath.isDerivation() | ||
| ? (DerivedPath) DerivedPath::Built { | ||
| .drvPath = std::move(storePath), | ||
| .outputs = {}, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note it previously read the derivation and returned all its output names explicitly here, but that didn't work e.g. when the drv file itself needs to be downloaded and so we cannot yet read it. |
||
| } | ||
| : (DerivedPath) DerivedPath::Opaque { | ||
| .path = std::move(storePath), | ||
| }) | ||
| { } | ||
|
|
||
| InstallableStorePath(ref<Store> store, DerivedPath && req) | ||
| : store(store), req(std::move(req)) | ||
| { } | ||
|
|
||
| std::string what() const override { return store->printStorePath(storePath); } | ||
| std::string what() const override | ||
| { | ||
| return req.to_string(*store); | ||
| } | ||
|
|
||
| DerivedPaths toDerivedPaths() override | ||
| { | ||
| if (storePath.isDerivation()) { | ||
| auto drv = store->readDerivation(storePath); | ||
| return { | ||
| DerivedPath::Built { | ||
| .drvPath = storePath, | ||
| .outputs = drv.outputNames(), | ||
| } | ||
| }; | ||
| } else { | ||
| return { | ||
| DerivedPath::Opaque { | ||
| .path = storePath, | ||
| } | ||
| }; | ||
| } | ||
| return { req }; | ||
| } | ||
|
|
||
| StorePathSet toDrvPaths(ref<Store> store) override | ||
| { | ||
| if (storePath.isDerivation()) { | ||
| return {storePath}; | ||
| } else { | ||
| return {getDeriver(store, *this, storePath)}; | ||
| } | ||
| return std::visit(overloaded { | ||
| [&](const DerivedPath::Built & bfd) -> StorePathSet { | ||
| return { bfd.drvPath }; | ||
| }, | ||
| [&](const DerivedPath::Opaque & bo) -> StorePathSet { | ||
| return { getDeriver(store, *this, bo.path) }; | ||
| }, | ||
| }, req.raw()); | ||
| } | ||
|
|
||
| std::optional<StorePath> getStorePath() override | ||
| { | ||
| return storePath; | ||
| return std::visit(overloaded { | ||
| [&](const DerivedPath::Built & bfd) { | ||
| return bfd.drvPath; | ||
| }, | ||
| [&](const DerivedPath::Opaque & bo) { | ||
| return bo.path; | ||
| }, | ||
| }, req.raw()); | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -798,7 +810,22 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables( | |
| for (auto & s : ss) { | ||
| std::exception_ptr ex; | ||
|
|
||
| if (s.find('/') != std::string::npos) { | ||
| auto found = s.rfind('^'); | ||
| if (found != std::string::npos) { | ||
| try { | ||
| result.push_back(std::make_shared<InstallableStorePath>( | ||
| store, | ||
| DerivedPath::Built::parse(*store, s.substr(0, found), s.substr(found + 1)))); | ||
| continue; | ||
| } catch (BadStorePath &) { | ||
| } catch (...) { | ||
| if (!ex) | ||
| ex = std::current_exception(); | ||
| } | ||
| } | ||
|
|
||
| found = s.find('/'); | ||
| if (found != std::string::npos) { | ||
| try { | ||
| result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s))); | ||
| continue; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -93,24 +93,25 @@ DerivedPath::Opaque DerivedPath::Opaque::parse(const Store & store, std::string_ | |||||
| return {store.parseStorePath(s)}; | ||||||
| } | ||||||
|
|
||||||
| DerivedPath::Built DerivedPath::Built::parse(const Store & store, std::string_view s) | ||||||
| DerivedPath::Built DerivedPath::Built::parse(const Store & store, std::string_view drvS, std::string_view outputsS) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
and then use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See #6815 which I made so this deduplication can happen. Note that part of the complication is
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A simpler patch is not available because we still need to parse with with both
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #6815 now works! But I'll still keep it separately because that is much bigger than this. |
||||||
| { | ||||||
| size_t n = s.find("!"); | ||||||
| assert(n != s.npos); | ||||||
| auto drvPath = store.parseStorePath(s.substr(0, n)); | ||||||
| auto outputsS = s.substr(n + 1); | ||||||
| auto drvPath = store.parseStorePath(drvS); | ||||||
| std::set<std::string> outputs; | ||||||
| if (outputsS != "*") | ||||||
| if (outputsS != "*") { | ||||||
| outputs = tokenizeString<std::set<std::string>>(outputsS, ","); | ||||||
| if (outputs.empty()) | ||||||
| throw Error( | ||||||
| "Explicit list of wanted outputs '%s' must not be empty. Consider using '*' as a wildcard meaning all outputs if no output in particular is wanted.", outputsS); | ||||||
| } | ||||||
| return {drvPath, outputs}; | ||||||
| } | ||||||
|
|
||||||
| DerivedPath DerivedPath::parse(const Store & store, std::string_view s) | ||||||
| { | ||||||
| size_t n = s.find("!"); | ||||||
| size_t n = s.rfind("!"); | ||||||
|
Ericson2314 marked this conversation as resolved.
Outdated
|
||||||
| return n == s.npos | ||||||
| ? (DerivedPath) DerivedPath::Opaque::parse(store, s) | ||||||
| : (DerivedPath) DerivedPath::Built::parse(store, s); | ||||||
| : (DerivedPath) DerivedPath::Built::parse(store, s.substr(0, n), s.substr(n + 1)); | ||||||
| } | ||||||
|
|
||||||
| RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| source common.sh | ||
|
Ericson2314 marked this conversation as resolved.
Outdated
|
||
|
|
||
| set -o pipefail | ||
|
|
||
| drv=$(nix eval -f multiple-outputs.nix --raw a.drvPath) | ||
| if nix build "$drv^not-an-output" --no-link --json; then | ||
| fail "'not-an-output' should fail to build" | ||
| fi | ||
|
|
||
| if nix build "$drv^" --no-link --json; then | ||
| fail "'empty outputs list' should fail to build" | ||
| fi | ||
|
|
||
| if nix build "$drv^*nope" --no-link --json; then | ||
| fail "'* must be entire string' should fail to build" | ||
| fi | ||
|
|
||
| nix build "$drv^first" --no-link --json | jq --exit-status ' | ||
| (.[0] | | ||
| (.drvPath | match(".*multiple-outputs-a.drv")) and | ||
| (.outputs | | ||
| (keys | length == 1) and | ||
| (.first | match(".*multiple-outputs-a-first")) and | ||
| (has("second") | not))) | ||
| ' | ||
|
|
||
| nix build "$drv^first,second" --no-link --json | jq --exit-status ' | ||
| (.[0] | | ||
| (.drvPath | match(".*multiple-outputs-a.drv")) and | ||
| (.outputs | | ||
| (keys | length == 2) and | ||
| (.first | match(".*multiple-outputs-a-first")) and | ||
| (.second | match(".*multiple-outputs-a-second")))) | ||
| ' | ||
|
|
||
| nix build "$drv^*" --no-link --json | jq --exit-status ' | ||
| (.[0] | | ||
| (.drvPath | match(".*multiple-outputs-a.drv")) and | ||
| (.outputs | | ||
| (keys | length == 2) and | ||
| (.first | match(".*multiple-outputs-a-first")) and | ||
| (.second | match(".*multiple-outputs-a-second")))) | ||
| ' | ||
Uh oh!
There was an error while loading. Please reload this page.