-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
nix-store: implement --query --unsubstitutable #7526
Conversation
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
Are you interested in this relative issue? |
You could use this PR to accomplish your goal by simply processing your derivations through In general, my recent experience writing a Nix-centric CI has kind of changed my perspective somewhat, and I'm starting to feel like we should take a more "git-like" approach to our cli, rather than replacing the older, more verbose commands outright, we should stabalize them as much as possible and use them as the "plumbing" to the higher level commands. |
Because there isn't really a nice standalone solution for this atm, I went ahead and extracted the logic as a standalone tool for now until this is accepted: |
I think functionality like this should be added to the new CLI rather than the legacy CLI. It seems to me that what we really want here is a CLI interface to Also "uncached" is a vague term. What does it mean for a path to be uncached? Maybe "unsubstitutable" is better. |
I can add it to Even so, Also, my first implementation did just use
Yeah I was thinking that myself, for now I just used the terminology that has been used elsewhere in the community so far, but I was also thinking of using unsubstitutable instead just last night, only thing is that it's quite long, although I guess with a short flag it would still be fine. |
@edolstra, I implemented the same logic for However there are a few downsides to the Importantly, I only want to run evaluation once, and only once, for a given CI run, so passing flake refs around isn't desirable as they may induce additional evaluation. Instead we query information on the derivations directly. This just doesn't work well with With the Specifically these are the quircks I've encountered with the
For these reasons I propose we keep both implementations until both are more in-line, and as mentioned in my previous comment, we may want to consider a more "plumbing" and "porceline" approach for flakes 2.0, to keep drift between the old and new commands from becoming a big issue. I like the low-level control the legacy commands give me when I need that. Say in a complex CI system that focuses on doing as little work as possible, but I like the higher level commands for ease of use when working on my own system. I think there is an argument to be made for keeping both around and taking implementations from the lower-level commands and reusing them for their flake counterparts. |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/what-would-you-like-to-see-improved-in-nix-cli-experience/24012/58 |
src/nix/path-info.cc
Outdated
clone["substitute"] = !infos.empty(); | ||
|
||
auto jsonList(jsonList_.lock()); | ||
jsonList->emplace_back(clone); |
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.
in order to really emplace it at the back without unneeded copies i suggest this:
jsonList->emplace_back(clone); | |
jsonList->emplace_back(std::move(clone)); |
src/nix/path-info.cc
Outdated
} | ||
|
||
std::function<void(nlohmann::json::basic_json::value_type)> checkSubs; | ||
checkSubs = [&](const nlohmann::json::basic_json::value_type & value) { |
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.
same suggestion with the nested lambda expression here. all the type info is relatively noisy and can be reduced.
src/nix/path-info.cc
Outdated
auto clone = value; | ||
std::string storePathS = value["path"]; | ||
auto info = store->queryPathInfo(store->followLinksToStorePath(storePathS)); | ||
auto storePath = info->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.
it seems like some const ... &
could help the reader understand what really needs to be a (mutable) copy and what not, as well as reduce some redundant copying.
src/nix/path-info.cc
Outdated
Sync<std::set<std::string>> results_; | ||
|
||
std::function<void(StorePath)> printPath; | ||
printPath = [&](const StorePath & storePath) { |
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.
Here, the parameter type from the std::function
and the actual assignment differ by having and not having const ... &
qualifiers. i suggest using the same nested lambda expression approach here, too.
src/nix/path-info.cc
Outdated
} | ||
|
||
std::cout << std::endl; | ||
auto results(results_.lock()); | ||
results->emplace(storePathS); |
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.
using std::move
will help avoiding a needless copy.
src/nix/path-info.cc
Outdated
auto results(results_.lock()); | ||
for (auto & str : *results) { | ||
std::cout << std::endl << str; | ||
} |
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.
std::endl
means to emit a new line character and flush the terminal. But this code suggests that you mean to separate all strings by newlines and then flush only once at the end, so i suggest this:
auto results(results_.lock()); | |
for (auto & str : *results) { | |
std::cout << std::endl << str; | |
} | |
for (const auto & str : *results_.lock()) { | |
std::cout << '\n' << str; | |
} | |
std::cout << std::endl; |
Thanks for the review, I'm moving to draft for now as the implementation needs work. After some initial benchmarks, the threadpool didn't actually help anything and is about the same as using a single thread, even when setting the threadpool limit to something super high like 1000. |
I will go ahead and continue my effort here, address the review comments, and possibly simplify the implementation by just removing the threadpool unless/until we find a solution to the performance issues. That should probably be handled in a separate PR though anyway. |
6d692d5
to
65e57dd
Compare
Resolves NixOS#3946 by providing an efficient means of querying cache status of the passed paths. For every path passed, it will be returned on standard output only if it is not available in any of the configured substituters.
|
||
StorePathSet storePaths; | ||
for (auto const & str : opArgs) { | ||
storePaths.emplace(store->followLinksToStorePath(str)); |
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.
The indentation here and below is wrong (should be 4 characters per level).
} | ||
|
||
for ( auto & path : storePaths) { | ||
if (substitutablePaths.find(path) == substitutablePaths.end()) |
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.
if (substitutablePaths.find(path) == substitutablePaths.end()) | |
if (!substitutablePaths.count(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.
This does not short-circuit
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.
In what way? On an std::map
it should be equally efficient.
But since we're fine with C++20 now, you can also use substitutablePaths.contains(path)
.
adding to make the cross-link easier to find: #7587 |
closing in favour of the aforementioned PR |
Miss click |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2023-01-20-nix-team-meeting-minutes-25/25432/1 |
Resolves #3946 by providing an efficient means of querying cache status of the passed paths.
For every path passed, it will be returned back on standard output only if it is not available in any of the configured substituters.
A threadpool is used to make this as quick as possible.Included in the documentation is a sample command showing how users can now trivially capture any and all uncached build & runtime dependencies of a given derivation. This information is highly useful in CI environments, for example.
Only caveat is that we might hit the OS arg limit until #7437 is fixed.
TODO
nix-store
queryChecklist for maintainers
Maintainers: tick if completed or explain if not relevant
tests/**.sh
src/*/tests
tests/nixos/*