-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Minimal implementation of a drv outputs copy #4225
Conversation
3220131
to
2c9f509
Compare
I've updated the PR to make the @edolstra the |
45799bb
to
6aa848f
Compare
I would defer it, as the migration is not so complex that I'm worried about doing it later, but the reverse migration is lossy. |
StringSink sink; | ||
dumpString(s, sink); | ||
auto source = StringSource { *sink.s }; |
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 looks like a bugfix we should PR sooner?
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.
We could yes. Though I don't think this method was used anywhere before this PR so probably not an emergency
src/libstore/drv-output-info.hh
Outdated
{ return static_cast<RawDrvInput>(*this); } | ||
}; | ||
|
||
std::list<std::string> stringify_refs(const std::set<DrvInput> & refs); |
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.
unused
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.
Thanks, removed in a2803d6
src/libstore/local-store.cc
Outdated
// XXX: This ignores the references of the output because we can | ||
// recompute them later from the drv and the references of the associated | ||
// store path, but doing so is both inefficient and fragile. |
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 doesn't apply to this version, right?
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.
Indeed it doesn't. Removed in 58ea93c
I think I would feel most comfortable if the first minimal version didn't store mappings for unresolved derivations to paths, because doing that while making sure we don't have accidental mapping collisions is very hard. |
I fail to see which collision you think of here. It's possible that the drv would resolve to something else (and possibly transitively produce a different output path) if you were to rebuild it, but it's not fundamentally different from having the resolved derivation producing a different output path. |
The only where the collected build-time-only deps could be built again different.
Sure, but if we just start with resolved derivation mappings, we are sure to be correct: rather than stuff being dubiously cached, it will just fail to be cached if some resolved derivation along the way is different. Because that is is a "definitely correct" starting point, I think it's where I'd like to begin. Another idea i was thinking was leaving the current DerivationOutputs as-is, and having a new table for CA derv mappings. Queries can union the two tables together, and this means we can continue having the foreign key and simple cleanup for input-addressed derivations, and we separate the "normative" CA mappings from the purely-for-caching IA ones. Thoughts? |
3be2780
to
c29bfd7
Compare
dc9e34a
to
8dfbbe3
Compare
8dfbbe3
to
910fe3e
Compare
910fe3e
to
faf5d7a
Compare
So picking up where I left off with #4225 (comment) I think the most minimal thing to do is:
Yes, we don't want users to have to actually do this tedious stuff in practice, but I think there are good building blocks to have in the end too, and by starting with that, we avoid anything with multiple competing designs. |
What do you mean exactly by “atomic”? The way I understand it is “without bothering with the dependencies”, but that's already what this PR does.
That's an interesting point. I overloaded nix-copy for that because
But there's arguments to be made in the other directions, so…
I feel like it would make things noticeably more complex. Even if just for the tests, it's quite nice to be able to expect
As a matter of fact I've been discussing with Eelco yesterday and we reached the same conclusion (though we might not need to do any union as it's totally fine for the two tables to overlap). The nice side of this is that it makes it easier to iterate on the ca-specific schema without touching the rest |
I've had a chat with @edolstra yesterday, which led to a few suggestions for this:
|
7a0ba80
to
1acb0cb
Compare
Glad we're all on the same page for multiple tables!
Right, but my big schick is that that it's sketchy to have mappings of unresolved derivations without dependencies.
Well the main thing is if we don't have dependencies and restrict ourselves to resolved derivations, we would have a hard time overloading it. (I also think it is good to allow just copying outputs, derivations, and mappings independent, but this is less important; I'm not disagreeing that copping the data and mappings is a good default once we can support it.)
It does make testing harder, because it's such a cumberson low-level interface. I think that's just the (IMO worth it) price of making a minimal thing with as uncontroversial design as we can. Basically taking a step back, because I'm very keen on keeping the full provenance of resolved derivation mappings around, I think it's just going to be more work before we get to good usable interfaces. But I'm OK with that. |
…sed ones Fix an overlook of NixOS#4056
This requires adding `nix` to its own closure which is a bit unfortunate, but as it is optional (the test will be disabled if `OUTER_NIX` is unset) it shouldn't be too much of an issue. (Ideally this should go in another derivation so that we can build Nix and run the test independently, but as the tests are running in the same derivation as the build it's a bit complicated to do so).
For each “known” derivation output, store: - its output id - its output path This comes with a set of needed changes: - New `drv-output-info` module declaring the types needed for describing these mappings - New `Store::registerDrvOutput` method registering all the needed informations about a derivation output (also replaces `LocalStore::linkDeriverToPath`) - new `Store::queryDrvOutputInfo` method to retrieve the informations for a derivations This introcudes some redundancy on the remote-store side between `wopQueryDerivationOutputMap` and `wopQueryDrvOutputInfo`. However we might need to keep both (regardless of backwards compat) because we sometimes need to get some infos for all the outputs of a derivation (where `wopQueryDerivationOutputMap` is handy), but all the stores can't implement it − because listing all the outputs of a derivation isn't really possible for binary caches where the server doesn't allow to list a directory.
Copying a derivation output is equivalent to copy the output path, except that it will also link the output to the path (with `linkDeriverToPath` on the remote store)
Commands that accept store paths or installables as input can now take a derivation path with outputs. Like when the input is a nix expr, the derivation will be realised if needed.
Generalises `StorePathsCommand` to allow manipulating `Buildables` rather than just store paths.
Mostly dummy atm as it just computes the closure of the output path, but might be extended later
Add a new table for tracking the derivation output mappings. We used to hijack the `DerivationOutputs` table for that, but (despite its name), it isn't a really good fit: - Its entries depend on the drv being a valid path, making it play badly with garbage collection and preventing us to copy a drv output without copying the whole drv closure too; - It dosen't guaranty that the output path exists; By using a different table, we can experiment with a different schema better suited for tracking the output mappings of CA derivations. (incidentally, this also fixes NixOS#4138)
That way we can `nix copy --from` a store that doesn't have the derivation but just its outputs
That way we don't need to resolve it again to know its output paths. In particular, this means that we don't need to keep its whole build-time closure
`buildPaths` can be called even for stores where it's not defined in case it's bound to be a no-op. The “no-op detection” mechanism was only detecting the case wher `buildPaths` was called on a set of (non-drv) paths that were already present on the store. This commit extends this mechanism to also detect the case where `buildPaths` is called on a set of derivation outputs which are already built on the store.
1acb0cb
to
dcb8957
Compare
Depends on #4227 #4282 #4284
This PR tries to provide the simplest possible way of copying drv outputs.
In particular it doesn't try to tackle the issue of copying the drv output closure at all, all it does is allow to do
nix copy /nix/store/...-foo.drv!out
which will copy the corresponding outpath and register the out path mapping for...-foo.drv!out
.For coherence (and also because it's at least as simple to do things that way),
nix copy nixpgs#foo
has the same semantics, meaning that it will both copy the output path(s) and register the derivation output(s).