-
-
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
Improve support for subflakes #10089
base: master
Are you sure you want to change the base?
Conversation
🎉 All dependencies have been resolved ! |
Discussed during the Nix maintainers meeting on 2024-03-04.
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-03-04-nix-team-meeting-minute-130/40830/1 |
…re path This is needed for the path:// input scheme (until it returns a FSInputAccessor to the original path, but that's blocked by NixOS#10089) and the Mercurial input scheme.
…re path This is needed for the path:// input scheme (until it returns a FSInputAccessor to the original path, but that's blocked by NixOS#10089) and the Mercurial input scheme.
47ccb1d
to
690281f
Compare
Subflakes are flakes in the same tree, accessed in flake inputs via relative paths (e.g. `inputs.foo.url = "path:./subdir"`). Previously these didn't work very well because they would be separately copied to the store, which is inefficient and makes references to parent directories tricky or impossible. Furthermore, they had their own NAR hash in the lock file, which is superfluous since the parent is already locked. Now subflakes are accessed via the accessor of the calling flake. This avoids the unnecessary copy and makes it possible for subflakes to depend on flakes in a parent directory (so long as they're in the same tree). Lock file nodes for relative flake inputs now have a new `parent` field: { "locked": { "path": "./subdir", "type": "path" }, "original": { "path": "./subdir", "type": "path" }, "parent": [ "foo", "bar" ] } which denotes that `./subdir` is to be interpreted relative to the directory of the `bar` input of the `foo` input of the root flake. Extracted from the lazy-trees branch.
`parentNode.sourceInfo.outPath` does not include the subdir of the parent flake, while `parentNode.outPath` does. So we need to use the latter.
Relative path flakes ("subflakes") are basically fundamentally broken, since they produce lock file entries like "locked": { "lastModified": 1, "narHash": "sha256-/2tW9SKjQbRLzfcJs5SHijli6l3+iPr1235zylGynK8=", "path": "./flakeC", "type": "path" }, that don't specify what "./flakeC" is relative to. They *sometimes* worked by accident because the `narHash` field allowed `fetchToStore()` to get the store path of the subflake *if* it happened to exist in the local store or in a substituter. Subflakes are properly fixed in NixOS#10089 (which adds a "parent" field to the lock file). Rather than come up with some crazy hack to make them work in the interim, let's just disable the only test that depends on the broken behaviour for now.
…Jobs.tests.functional_user
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-11-27-nix-team-meeting-minutes-198/56691/1 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-12-18-nix-team-meeting-minutes-204/57602/1 |
Does this also mean that subflakes will auto-update? In other words, |
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.
Reviewed together in meeting
- Release note: Generalizing the flake format can break tools that consume
flake.nix
files. For instancetoJSON (import ./flake.nix).inputs
will not work as expected anymore for flakes that use path values.
InputPath -> InputChain?
* Only for relative path flakes, i.e. 'path:./foo', returns the | ||
* relative path, i.e. './foo'. | ||
*/ | ||
std::optional<std::string> isRelative() const; |
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 should be in the expr / flake layer.
Open issue?
the directory containing that `flake.nix`. However, the resolved | ||
path must be in the same tree. For instance, a `flake.nix` in the | ||
root of a tree can use `path:./foo` to access the flake in | ||
subdirectory `foo`, but `path:../bar` is illegal. |
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.
Worth mentioning that foo
can refer to its ../bar
@@ -84,7 +84,8 @@ FlakeRef parseFlakeRef( | |||
const std::string & url, | |||
const std::optional<Path> & baseDir = {}, | |||
bool allowMissing = false, | |||
bool isFlake = true); | |||
bool isFlake = true, | |||
bool allowRelative = false); |
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.
bool allowRelative = false); | |
bool preserveRelativePaths = false); |
@@ -386,13 +408,29 @@ LockedFlake lockFlake( | |||
|
|||
debug("old lock file: %s", oldLockFile); | |||
|
|||
std::map<InputPath, FlakeInput> overrides; | |||
struct Override |
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.
struct Override | |
struct OverrideValue |
/* Respect the "flakeness" of the input even if we | ||
override it. */ | ||
if (hasOverride) | ||
input.isFlake = input2.isFlake; |
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.
Off-topic: perhaps flake-ness should be "type-checked"
(existing code, moved)
} | ||
|
||
fetchers::Attrs attrs; | ||
attrs.insert_or_assign("type", "path"); | ||
attrs.insert_or_assign("path", path); | ||
|
||
return std::make_pair(FlakeRef(fetchers::Input::fromAttrs(fetchSettings, std::move(attrs)), ""), fragment); | ||
return fromParsedURL(fetchSettings, { | ||
.url = 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 is a bit wrong.
We could either
- remove this and always reconstruct URLs for display, or
- the field name should be something like
displayText
.
@@ -38,11 +38,19 @@ struct LockedNode : Node | |||
FlakeRef lockedRef, originalRef; | |||
bool isFlake = true; | |||
|
|||
/* The node relative to which relative source paths | |||
(e.g. 'path:../foo') are interpreted. */ | |||
std::optional<InputPath> parentPath; |
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::optional<InputPath> parentPath; | |
std::optional<InputPath> parentInputChain; |
as mentioned in the review header comment
path must be in the same tree. For instance, a `flake.nix` in the | ||
root of a tree can use `path:./foo` to access the flake in | ||
subdirectory `foo`, but `path:../bar` is illegal. | ||
|
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.
Path inputs can be specified with path values in `flake.nix`. Path values are a syntax for `path` inputs, and they are converted by | |
1. resolving them into relative paths, relative to the base directory of `flake.nix` | |
2. escaping URL characters (refer to IETF RFC?) | |
3. prepending `path:` | |
Note that the allowed syntax for path values in flake `inputs` may be more restrictive than general Nix, so you may need to use `path:` if your path contains certain special characters. See [Path literals](@docroot@/language/syntax#path-literal) | |
# Test circular relative path flakes. FIXME: doesn't work at the moment. | ||
if false; then |
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 it an ok-ish error or a crash?
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-12-23-nix-team-meeting-minutes-205/57783/1 |
Motivation
Subflakes are flakes in the same tree, accessed in flake inputs via relative paths (e.g.
inputs.foo.url = "path:./subdir"
). Previously these didn't work very well because they would be separately copied to the store, which is inefficient and makes references to parent directories tricky or impossible. Furthermore, they had their own NAR hash in the lock file, which is superfluous since the parent is already locked. In fact, if subflakes worked at all, it was by accident.Now subflakes are accessed via the accessor of the calling flake. This avoids the unnecessary copy and makes it possible for subflakes to depend on flakes in a parent directory (so long as they're in the same tree).
Lock file nodes for relative flake inputs now have a new
parent
field:which denotes that
./subdir
is to be interpreted relative to the directory of thebar
input of thefoo
input of the root flake.Extracted from the lazy-trees branch.
Depends on #10088.
Context
Priorities and Process
Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.