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

Improve support for relative path inputs #10089

Merged
merged 25 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b2be6fe
Improve support for subflakes
edolstra Apr 23, 2024
49f592d
call-flake.nix: Fix relative path resolution
edolstra May 17, 2024
3180671
Allow the 'url' flake input attribute to be a path literal
edolstra May 17, 2024
21fc07c
Merge remote-tracking branch 'origin/master' into relative-flakes
edolstra Sep 16, 2024
09d7197
shellcheck
edolstra Sep 16, 2024
71d4bb8
parentPath -> parentInputPath
edolstra Sep 16, 2024
91e7d49
Merge remote-tracking branch 'origin/master' into relative-flakes
edolstra Sep 23, 2024
f206325
tests/functional/flakes/relative-paths.sh: Fix build failure in hydra…
edolstra Sep 25, 2024
0b00bf7
Merge remote-tracking branch 'origin/master' into relative-flakes
edolstra Nov 22, 2024
00b99b8
Remove FIXME
edolstra Nov 22, 2024
985b2f9
Remove FIXME
edolstra Nov 27, 2024
8534c42
Merge remote-tracking branch 'origin/master' into relative-flakes
edolstra Dec 18, 2024
9223d64
Remove dead code
edolstra Dec 23, 2024
75cda2d
Document path values in inputs
edolstra Jan 7, 2025
e8c7dd9
Rename allowRelative -> preserveRelativePaths
edolstra Jan 7, 2025
0792152
Rename Override -> OverrideTarget
edolstra Jan 7, 2025
ef2739b
Example of referencing parent directories
edolstra Jan 7, 2025
d329b26
Fix manual
edolstra Jan 7, 2025
cd0127f
Merge remote-tracking branch 'origin/master' into relative-flakes
edolstra Jan 13, 2025
6cc5b48
Add release note
edolstra Jan 14, 2025
550fe88
Merge remote-tracking branch 'origin/master' into relative-flakes
edolstra Jan 16, 2025
521667e
Fix follow-paths test
edolstra Jan 16, 2025
5d03ef9
PathInputSchema::getAbsPath(): Return std::filesystem::path
edolstra Jan 16, 2025
8b1fb92
flakes.md: Fix indentation that broke the list
edolstra Jan 16, 2025
db46d40
Update release note
edolstra Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/libexpr/call-flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,17 @@ let
(key: node:
let

parentNode = allNodes.${getInputByPath lockFile.root node.parent};

sourceInfo =
if overrides ? ${key}
then
overrides.${key}.sourceInfo
else if node.locked.type == "path" && builtins.substring 0 1 node.locked.path != "/"
then
parentNode.sourceInfo // {
outPath = parentNode.outPath + ("/" + node.locked.path);
}
else
# FIXME: remove obsolete node.info.
# Note: lock file entries are always final.
Expand Down
6 changes: 6 additions & 0 deletions src/libfetchers/fetchers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ bool Input::isFinal() const
return maybeGetBoolAttr(attrs, "__final").value_or(false);
}

std::optional<std::string> Input::isRelative() const
{
assert(scheme);
return scheme->isRelative(*this);
}

Attrs Input::toAttrs() const
{
return attrs;
Expand Down
14 changes: 9 additions & 5 deletions src/libfetchers/fetchers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ struct Input
std::shared_ptr<InputScheme> scheme; // note: can be null
Attrs attrs;

/**
* path of the parent of this input, used for relative path resolution
*/
std::optional<Path> parent;

/**
* Cached result of getFingerprint().
*/
Expand Down Expand Up @@ -95,6 +90,12 @@ public:
*/
bool isLocked() const;

/**
* Only for relative path flakes, i.e. 'path:./foo', returns the
* relative path, i.e. './foo'.
*/
std::optional<std::string> isRelative() const;
Copy link
Member

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?


/**
* Return whether this is a "final" input, meaning that fetching
* it will not add, remove or change any attributes. (See
Expand Down Expand Up @@ -260,6 +261,9 @@ struct InputScheme

virtual bool isLocked(const Input & input) const
{ return false; }

virtual std::optional<std::string> isRelative(const Input & input) const
{ return std::nullopt; }
};

void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
Expand Down
27 changes: 5 additions & 22 deletions src/libfetchers/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct PathInputScheme : InputScheme
writeFile((CanonPath(getAbsPath(input)) / path).abs(), contents);
}

std::optional<std::string> isRelative(const Input & input) const
std::optional<std::string> isRelative(const Input & input) const override
{
auto path = getStrAttr(input.attrs, "path");
if (hasPrefix(path, "/"))
Expand All @@ -121,31 +121,14 @@ struct PathInputScheme : InputScheme
std::pair<ref<SourceAccessor>, Input> getAccessor(ref<Store> store, const Input & _input) const override
{
Input input(_input);
std::string absPath;
auto path = getStrAttr(input.attrs, "path");

if (path[0] != '/') {
if (!input.parent)
throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());
auto absPath = getAbsPath(input);
edolstra marked this conversation as resolved.
Show resolved Hide resolved

auto parent = canonPath(*input.parent);

// the path isn't relative, prefix it
absPath = nix::absPath(path, parent);

// for security, ensure that if the parent is a store path, it's inside it
if (store->isInStore(parent)) {
auto storePath = store->printStorePath(store->toStorePath(parent).first);
if (!isDirOrInDir(absPath, storePath))
throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath);
}
} else
absPath = path;

Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s'", absPath));
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s' to the store", absPath));

// FIXME: check whether access to 'path' is allowed.
auto storePath = store->maybeParseStorePath(absPath);
auto storePath = store->maybeParseStorePath(absPath.abs());

if (storePath)
store->addTempRoot(*storePath);
Expand All @@ -154,7 +137,7 @@ struct PathInputScheme : InputScheme
if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) {
// FIXME: try to substitute storePath.
auto src = sinkToSource([&](Sink & sink) {
mtime = dumpPathAndGetMtime(absPath, sink, defaultPathFilter);
mtime = dumpPathAndGetMtime(absPath.abs(), sink, defaultPathFilter);
});
storePath = store->addToStoreFromDump(*src, "source");
}
Expand Down
Loading
Loading