1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-30 06:01:00 +01:00

Add CanonPath wrapper to represent canonicalized paths

This commit is contained in:
Eelco Dolstra 2022-05-16 23:27:04 +02:00
parent de35e2d3b4
commit a71f209330
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
31 changed files with 503 additions and 187 deletions

View file

@ -425,7 +425,7 @@ Value & AttrCursor::forceValue()
else if (v.type() == nPath) {
// FIXME: take accessor into account?
auto path = v.path().path;
cachedValue = {root->db->setString(getKey(), path), string_t{path, {}}};
cachedValue = {root->db->setString(getKey(), path.abs()), string_t{path.abs(), {}}};
}
else if (v.type() == nBool)
cachedValue = {root->db->setBool(getKey(), v.boolean), v.boolean};

View file

@ -461,9 +461,9 @@ EvalState::EvalState(
, sPrefix(symbols.create("prefix"))
, repair(NoRepair)
, emptyBindings(0)
, rootFS(makeFSInputAccessor("",
, rootFS(makeFSInputAccessor(CanonPath::root,
evalSettings.restrictEval || evalSettings.pureEval
? std::optional<PathSet>(PathSet())
? std::optional<std::set<CanonPath>>(std::set<CanonPath>())
: std::nullopt))
, corepkgsFS(makeMemoryInputAccessor())
, store(store)
@ -515,7 +515,7 @@ EvalState::EvalState(
createBaseEnv();
corepkgsFS->addFile(
"/fetchurl.nix",
CanonPath("fetchurl.nix"),
#include "fetchurl.nix.gen.hh"
);
}
@ -528,15 +528,15 @@ EvalState::~EvalState()
void EvalState::allowPath(const Path & path)
{
rootFS->allowPath(path);
rootFS->allowPath(CanonPath(path)); // FIXME
}
void EvalState::allowPath(const StorePath & storePath)
{
rootFS->allowPath(store->toRealPath(storePath));
rootFS->allowPath(CanonPath(store->toRealPath(storePath))); // FIXME
}
void EvalState::allowAndSetStorePathString(const StorePath &storePath, Value & v)
void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v)
{
allowPath(storePath);
@ -612,12 +612,12 @@ void EvalState::checkURI(const std::string & uri)
/* If the URI is a path, then check it against allowedPaths as
well. */
if (hasPrefix(uri, "/")) {
rootFS->checkAllowed(uri);
rootFS->checkAllowed(CanonPath(uri));
return;
}
if (hasPrefix(uri, "file://")) {
rootFS->checkAllowed(uri.substr(7));
rootFS->checkAllowed(CanonPath(uri.substr(7)));
return;
}
@ -758,7 +758,7 @@ void EvalState::throwEvalError(const PosIdx pos, const Suggestions & suggestions
});
}
void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2) const
void EvalState::throwEvalError(const PosIdx pos, const char * s, std::string_view s2) const
{
throw EvalError(ErrorInfo {
.msg = hintfmt(s, s2),
@ -890,7 +890,7 @@ void Value::mkStringMove(const char * s, const PathSet & context)
void Value::mkPath(const SourcePath & path)
{
mkPath(&path.accessor, makeImmutableString(path.path));
mkPath(&path.accessor, makeImmutableString(path.path.abs()));
}
@ -1827,7 +1827,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
else if (firstType == nPath) {
if (!context.empty())
state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path");
v.mkPath({.accessor = *accessor, .path = canonPath(str())});
v.mkPath({.accessor = *accessor, .path = CanonPath(str())});
} else
v.mkStringMove(c_str(), context);
}
@ -2027,7 +2027,7 @@ BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet
auto path = v.path();
return copyToStore
? store->printStorePath(copyPathToStore(context, path))
: path.path;
: BackedStringView((Path) path.path.abs());
}
if (v.type() == nAttrs) {
@ -2071,7 +2071,7 @@ BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet
StorePath EvalState::copyPathToStore(PathSet & context, const SourcePath & path)
{
if (nix::isDerivation(path.path))
if (nix::isDerivation(path.path.abs()))
throw EvalError("file names are not allowed to end in '%s'", drvExtension);
auto i = srcToStore.find(path);
@ -2103,7 +2103,10 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & contex
if (v.type() == nString) {
copyContext(v, context);
return {*rootFS, v.string.s};
auto path = v.str();
if (path == "" || path[0] != '/')
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
return {*rootFS, CanonPath(path)};
}
if (v.type() == nPath)

View file

@ -160,7 +160,7 @@ public:
SearchPath getSearchPath() { return searchPath; }
SourcePath rootPath(Path path);
SourcePath rootPath(const Path & path);
InputAccessor & registerAccessor(ref<InputAccessor> accessor);
@ -256,7 +256,7 @@ public:
void throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s,
const std::string & s2) const;
[[gnu::noinline, gnu::noreturn]]
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2) const;
void throwEvalError(const PosIdx pos, const char * s, std::string_view s2) const;
[[gnu::noinline, gnu::noreturn]]
void throwEvalError(const char * s, const std::string & s2, const std::string & s3) const;
[[gnu::noinline, gnu::noreturn]]

View file

@ -206,8 +206,8 @@ static Flake readFlake(
InputAccessor & accessor,
const InputPath & lockRootPath)
{
auto flakeDir = canonPath("/" + resolvedRef.subdir);
SourcePath flakePath{accessor, canonPath(flakeDir + "/flake.nix")};
CanonPath flakeDir(resolvedRef.subdir);
SourcePath flakePath{accessor, flakeDir + CanonPath("flake.nix")};
if (!flakePath.pathExists())
throw Error("source tree referenced by '%s' does not contain a file named '%s'", resolvedRef, flakePath.path);
@ -232,7 +232,7 @@ static Flake readFlake(
auto sInputs = state.symbols.create("inputs");
if (auto inputs = vInfo.attrs->get(sInputs))
flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir, lockRootPath);
flake.inputs = parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir.abs(), lockRootPath);
auto sOutputs = state.symbols.create("outputs");
@ -337,7 +337,7 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup
static LockFile readLockFile(const Flake & flake)
{
auto lockFilePath = flake.path.parent().append("/flake.lock");
auto lockFilePath = flake.path.parent() + "flake.lock";
return lockFilePath.pathExists()
? LockFile(lockFilePath.readFile(), fmt("%s", lockFilePath))
: LockFile();
@ -721,7 +721,7 @@ void callFlake(EvalState & state,
emitTreeAttrs(
state,
{lockedFlake.flake.path.accessor, "/"},
{lockedFlake.flake.path.accessor, CanonPath::root},
lockedFlake.flake.lockedRef.input,
*vRootSrc,
false,

View file

@ -188,7 +188,7 @@ struct ExprPath : Expr
ExprPath(SourcePath && _path)
: path(_path)
{
v.mkPath(&path.accessor, path.path.c_str());
v.mkPath(&path.accessor, path.path.abs().data());
}
COMMON_METHODS
Value * maybeThunk(EvalState & state, Env & env);

View file

@ -508,10 +508,12 @@ string_parts_interpolated
path_start
: PATH {
SourcePath path { data->basePath.accessor, absPath({$1.p, $1.l}, data->basePath.path) };
SourcePath path { data->basePath.accessor, CanonPath({$1.p, $1.l}, data->basePath.path) };
#if 0
/* add back in the trailing '/' to the first segment */
if ($1.p[$1.l-1] == '/' && $1.l > 1)
path.path += "/";
#endif
$$ = new ExprPath(std::move(path));
}
| HPATH {
@ -699,7 +701,7 @@ SourcePath resolveExprPath(const SourcePath & path)
#endif
// FIXME
auto path2 = path.append("/default.nix");
auto path2 = path + "default.nix";
return path2.pathExists() ? path2 : path;
}
@ -716,7 +718,7 @@ Expr * EvalState::parseExprFromFile(const SourcePath & path, StaticEnv & staticE
// readFile hopefully have left some extra space for terminators
buffer.append("\0\0", 2);
// FIXME: pass SourcePaths
return parse(buffer.data(), buffer.size(), foFile, path.path, path.parent(), staticEnv);
return parse(buffer.data(), buffer.size(), foFile, path.path.abs(), path.parent(), staticEnv);
}
@ -779,13 +781,13 @@ SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view p
suffix = path.size() == s ? "" : concatStrings("/", path.substr(s));
}
if (auto path = resolveSearchPathElem(i)) {
auto res = path->append("/" + suffix);
auto res = *path + CanonPath(suffix);
if (res.pathExists()) return res;
}
}
if (hasPrefix(path, "nix/"))
return {*corepkgsFS, (std::string) path.substr(3)};
return {*corepkgsFS, CanonPath(path.substr(3))};
throw ThrownError({
.msg = hintfmt(evalSettings.pureEval
@ -808,8 +810,8 @@ std::optional<SourcePath> EvalState::resolveSearchPathElem(const SearchPathElem
try {
auto storePath = fetchers::downloadTarball(
store, resolveUri(elem.second), "source", false).first.storePath;
auto & accessor = registerAccessor(makeFSInputAccessor(store->toRealPath(storePath)));
res.emplace(SourcePath {accessor, "/"});
auto & accessor = registerAccessor(makeFSInputAccessor(CanonPath(store->toRealPath(storePath))));
res.emplace(SourcePath {accessor, CanonPath::root});
} catch (FileTransferError & e) {
logWarning({
.msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)

View file

@ -3,9 +3,9 @@
namespace nix {
SourcePath EvalState::rootPath(Path path)
SourcePath EvalState::rootPath(const Path & path)
{
return {*rootFS, std::move(path)};
return {*rootFS, CanonPath(path)};
}
InputAccessor & EvalState::registerAccessor(ref<InputAccessor> accessor)

View file

@ -1335,12 +1335,13 @@ static RegisterPrimOp primop_placeholder({
*************************************************************/
/* Convert the argument to a path. !!! obsolete? */
/* Convert the argument to a path and then to a string (confusing,
eh?). !!! obsolete? */
static void prim_toPath(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
PathSet context;
auto path = state.coerceToPath(pos, *args[0], context);
v.mkString(canonPath(path.path), context);
v.mkString(path.path.abs(), context);
}
static RegisterPrimOp primop_toPath({
@ -1375,17 +1376,17 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args,
/* Resolve symlinks in path, unless path itself is a symlink
directly in the store. The latter condition is necessary so
e.g. nix-push does the right thing. */
if (!state.store->isStorePath(path)) path = canonPath(path, true);
if (!state.store->isInStore(path))
if (!state.store->isStorePath(path.abs())) path = path.resolveSymlinks();
if (!state.store->isInStore(path.abs()))
throw EvalError({
.msg = hintfmt("path '%1%' is not in the Nix store", path),
.errPos = state.positions[pos]
});
auto path2 = state.store->toStorePath(path).first;
auto path2 = state.store->toStorePath(path.abs()).first;
if (!settings.readOnlyMode)
state.store->ensurePath(path2);
context.insert(state.store->printStorePath(path2));
v.mkString(path, context);
v.mkString(path.abs(), context);
}
static RegisterPrimOp primop_storePath({
@ -1492,8 +1493,8 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
// FIXME: only do queryPathInfo if path.accessor is the store accessor
auto refs =
state.store->isInStore(path.path) ?
state.store->queryPathInfo(state.store->toStorePath(path.path).first)->references :
state.store->isInStore(path.path.abs()) ?
state.store->queryPathInfo(state.store->toStorePath(path.path.abs()).first)->references :
StorePathSet{};
auto context = state.store->printStorePathSet(refs);
v.mkString(s, context);
@ -1949,14 +1950,14 @@ static void addPath(
#endif
PathFilter filter = filterFun ? ([&](const Path & p) {
SourcePath path2{path.accessor, canonPath(p)};
SourcePath path2{path.accessor, CanonPath(p)};
auto st = path2.lstat();
/* Call the filter function. The first argument is the path,
the second is a string indicating the type of the file. */
Value arg1;
arg1.mkString(path2.path);
arg1.mkString(path2.path.abs());
Value arg2;
// assert that type is not "unknown"

View file

@ -195,7 +195,7 @@ static void fetchTree(
emitTreeAttrs(
state,
{state.registerAccessor(accessor), "/"},
{state.registerAccessor(accessor), CanonPath::root},
input2,
v,
params.emptyRevFallback,

View file

@ -104,7 +104,7 @@ namespace nix {
return false;
} else {
auto path = arg.path();
if (path.path != p) {
if (path.path != CanonPath(p)) {
*result_listener << "Expected a path that equals \"" << p << "\" but got: " << path.path;
return false;
}

View file

@ -415,7 +415,13 @@ public:
SourcePath path() const
{
assert(internalType == tPath);
return SourcePath { .accessor = *_path.accessor, .path = _path.path };
return SourcePath { .accessor = *_path.accessor, .path = CanonPath(CanonPath::unchecked_t(), _path.path) };
}
std::string_view str() const
{
assert(internalType == tString);
return std::string_view(string.s);
}
};