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:
parent
de35e2d3b4
commit
a71f209330
31 changed files with 503 additions and 187 deletions
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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]]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ static void fetchTree(
|
|||
|
||||
emitTreeAttrs(
|
||||
state,
|
||||
{state.registerAccessor(accessor), "/"},
|
||||
{state.registerAccessor(accessor), CanonPath::root},
|
||||
input2,
|
||||
v,
|
||||
params.emptyRevFallback,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue