mirror of
https://github.com/NixOS/nix
synced 2025-07-19 23:09:37 +02:00
Merge pull request #10089 from edolstra/relative-flakes
Improve support for relative path inputs
This commit is contained in:
commit
043df13f72
14 changed files with 358 additions and 114 deletions
|
@ -166,6 +166,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;
|
||||
|
|
|
@ -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().
|
||||
*/
|
||||
|
@ -104,6 +99,12 @@ public:
|
|||
bool isConsideredLocked(
|
||||
const Settings & settings) const;
|
||||
|
||||
/**
|
||||
* Only for relative path flakes, i.e. 'path:./foo', returns the
|
||||
* relative path, i.e. './foo'.
|
||||
*/
|
||||
std::optional<std::string> isRelative() const;
|
||||
|
||||
/**
|
||||
* Return whether this is a "final" input, meaning that fetching
|
||||
* it will not add, remove or change any attributes. (See
|
||||
|
@ -269,6 +270,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);
|
||||
|
|
|
@ -91,10 +91,10 @@ struct PathInputScheme : InputScheme
|
|||
std::string_view contents,
|
||||
std::optional<std::string> commitMsg) const override
|
||||
{
|
||||
writeFile((CanonPath(getAbsPath(input)) / path).abs(), contents);
|
||||
writeFile(getAbsPath(input) / path.rel(), 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 (isAbsolute(path))
|
||||
|
@ -108,12 +108,12 @@ struct PathInputScheme : InputScheme
|
|||
return (bool) input.getNarHash();
|
||||
}
|
||||
|
||||
CanonPath getAbsPath(const Input & input) const
|
||||
std::filesystem::path getAbsPath(const Input & input) const
|
||||
{
|
||||
auto path = getStrAttr(input.attrs, "path");
|
||||
|
||||
if (path[0] == '/')
|
||||
return CanonPath(path);
|
||||
if (isAbsolute(path))
|
||||
return canonPath(path);
|
||||
|
||||
throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
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.string());
|
||||
|
||||
if (storePath)
|
||||
store->addTempRoot(*storePath);
|
||||
|
@ -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.string(), sink, defaultPathFilter);
|
||||
});
|
||||
storePath = store->addToStoreFromDump(*src, "source");
|
||||
}
|
||||
|
@ -176,7 +159,7 @@ struct PathInputScheme : InputScheme
|
|||
store object and the subpath. */
|
||||
auto path = getAbsPath(input);
|
||||
try {
|
||||
auto [storePath, subPath] = store->toStorePath(path.abs());
|
||||
auto [storePath, subPath] = store->toStorePath(path.string());
|
||||
auto info = store->queryPathInfo(storePath);
|
||||
return fmt("path:%s:%s", info->narHash.to_string(HashFormat::Base16, false), subPath);
|
||||
} catch (Error &) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue