libutil: make SourcePath::path private

use canonical() to get the disk path, to_string() to get the string form.

Change-Id: I95bb6df53356f30290b487d1cca0aa2fb37249ed
This commit is contained in:
eldritch horrors
2025-01-10 15:20:27 -08:00
committed by Jade Lovelace
parent 3acba7951a
commit f93af1db1f
14 changed files with 36 additions and 32 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ static void getAllExprs(Evaluator & state,
}
/* Load the expression on demand. */
auto vArg = state.mem.allocValue();
vArg->mkString(path2.path.abs());
vArg->mkString(path2.canonical().abs());
if (seen.size() == maxAttrs)
throw Error("too many Nix expressions in directory '%1%'", path);
attrs.alloc(attrName).mkApp(&state.builtins.get("import"), vArg);
+1 -1
View File
@@ -168,7 +168,7 @@ static int main_nix_instantiate(std::string programName, Strings argv)
if (findFile) {
for (auto & i : files) {
auto p = evaluator->paths.findFile(i);
std::cout << p.path.abs() << std::endl;
std::cout << p.canonical().abs() << std::endl;
}
return 0;
}
+1 -1
View File
@@ -15,7 +15,7 @@ Strings editorFor(const SourcePath & file, uint32_t line)
editor.find("vim") != std::string::npos ||
editor.find("kak") != std::string::npos))
args.push_back(fmt("+%d", line));
args.push_back(file.path.abs());
args.push_back(file.canonical().abs());
return args;
}
+1 -1
View File
@@ -676,7 +676,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
// Reload right after exiting the editor if path is not in store
// Store is immutable, so there could be no changes, so there's no need to reload
if (!evaluator.store->isInStore(path.resolveSymlinks().path.abs())) {
if (!evaluator.store->isInStore(path.resolveSymlinks().canonical().abs())) {
state.resetFileCache();
reloadFiles();
}
+1 -1
View File
@@ -178,7 +178,7 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
NixStringContext context;
auto path = state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation");
auto fn = path.path.abs();
auto fn = path.canonical().abs();
auto fail = [fn]() {
throw ParseError("cannot parse 'meta.position' attribute '%s'", fn);
+2 -2
View File
@@ -439,8 +439,8 @@ Value & AttrCursor::forceValue(EvalState & state)
cachedValue = {root->db->setString(getKey(), v.string.s, v.string.context),
string_t{v.string.s, {}}};
else if (v.type() == nPath) {
auto path = v.path().path;
cachedValue = {root->db->setString(getKey(), path.abs()), string_t{path.abs(), {}}};
auto path = v.path().canonical().abs();
cachedValue = {root->db->setString(getKey(), path), string_t{path, {}}};
}
else if (v.type() == nBool)
cachedValue = {root->db->setBool(getKey(), v.boolean), v.boolean};
+6 -6
View File
@@ -383,7 +383,7 @@ SourcePath EvalPaths::checkSourcePath(const SourcePath & path_)
{
if (!allowedPaths) return path_;
auto i = resolvedPaths.find(path_.path.abs());
auto i = resolvedPaths.find(path_.canonical().abs());
if (i != resolvedPaths.end())
return i->second;
@@ -393,7 +393,7 @@ SourcePath EvalPaths::checkSourcePath(const SourcePath & path_)
* attacker can't append ../../... to a path that would be in allowedPaths
* and thus leak symlink targets.
*/
Path abspath = canonPath(path_.path.abs());
Path abspath = canonPath(path_.canonical().abs());
if (abspath.starts_with(corepkgsPrefix)) return CanonPath(abspath);
@@ -416,8 +416,8 @@ SourcePath EvalPaths::checkSourcePath(const SourcePath & path_)
SourcePath path = CanonPath(canonPath(abspath, true));
for (auto & i : *allowedPaths) {
if (isDirOrInDir(path.path.abs(), i)) {
resolvedPaths.insert_or_assign(path_.path.abs(), path);
if (isDirOrInDir(path.canonical().abs(), i)) {
resolvedPaths.insert_or_assign(path_.canonical().abs(), path);
return path;
}
}
@@ -2339,7 +2339,7 @@ BackedStringView EvalState::coerceToString(
StorePath EvalPaths::copyPathToStore(NixStringContext & context, const SourcePath & path, RepairFlag repair)
{
if (nix::isDerivation(path.path.abs()))
if (nix::isDerivation(path.canonical().abs()))
errors.make<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow();
auto i = srcToStore.find(path);
@@ -2672,7 +2672,7 @@ SourcePath resolveExprPath(SourcePath path)
if (++followCount >= maxFollow)
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
if (path.lstat().type != InputAccessor::tSymlink) break;
path = {CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))};
path = {CanonPath(path.readLink(), path.canonical().parent().value_or(CanonPath::root))};
}
/* If `path' refers to a directory, append `/default.nix'. */
+1 -1
View File
@@ -605,7 +605,7 @@ template<> struct BuildAST<grammar::v1::path::interpolation> : BuildAST<grammar:
template<> struct BuildAST<grammar::v1::path::anchor> {
static void apply(const auto & in, StringState & s, State & ps) {
Path path(absPath(in.string(), ps.basePath.path.abs()));
Path path(absPath(in.string(), ps.basePath.canonical().abs()));
/* add back in the trailing '/' to the first segment */
if (in.string_view().ends_with('/') && in.size() > 1)
path += "/";
+10 -10
View File
@@ -131,7 +131,7 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, co
try {
StringMap rewrites = state.ctx.paths.realiseContext(context);
auto realPath = CanonPath(state.ctx.paths.toRealPath(rewriteStrings(path.path.abs(), rewrites), context));
auto realPath = CanonPath(state.ctx.paths.toRealPath(rewriteStrings(path.canonical().abs(), rewrites), context));
return flags.checkForPureEval
? state.ctx.paths.checkSourcePath(realPath)
@@ -176,7 +176,7 @@ static void mkOutputString(
static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * vScope, Value & v)
{
auto path = realisePath(state, pos, vPath);
auto path2 = path.path.abs();
auto path2 = path.canonical().abs();
// FIXME
auto isValidDerivationInStore = [&]() -> std::optional<StorePath> {
@@ -283,7 +283,7 @@ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Valu
std::string sym(state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.importNative"));
void *handle = dlopen(path.path.c_str(), RTLD_LAZY | RTLD_LOCAL);
void *handle = dlopen(path.canonical().c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!handle)
state.ctx.errors.make<EvalError>("could not open '%1%': %2%", path, dlerror()).debugThrow();
@@ -1173,7 +1173,7 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args,
).atPos(pos).debugThrow();
NixStringContext context;
auto path = state.ctx.paths.checkSourcePath(state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.storePath")).path;
auto path = state.ctx.paths.checkSourcePath(state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.storePath")).canonical();
/* 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. */
@@ -1241,7 +1241,7 @@ static void prim_dirOf(EvalState & state, const PosIdx pos, Value * * args, Valu
state.forceValue(*args[0], pos);
if (args[0]->type() == nPath) {
auto path = args[0]->path();
v.mkPath(path.path.isRoot() ? path : path.parent());
v.mkPath(path.canonical().isRoot() ? path : path.parent());
} else {
NixStringContext context;
auto path = state.coerceToString(pos, *args[0], context,
@@ -1263,9 +1263,9 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
path
).atPos(pos).debugThrow();
StorePathSet refs;
if (state.ctx.store->isInStore(path.path.abs())) {
if (state.ctx.store->isInStore(path.canonical().abs())) {
try {
refs = state.ctx.store->queryPathInfo(state.ctx.store->toStorePath(path.path.abs()).first)->references;
refs = state.ctx.store->queryPathInfo(state.ctx.store->toStorePath(path.canonical().abs()).first)->references;
} catch (Error &) { // FIXME: should be InvalidPathError
}
// Re-scan references to filter down to just the ones that actually occur in the file.
@@ -1513,7 +1513,7 @@ static void addPath(
path = evalSettings.pureEval && expectedHash
? path
: state.ctx.paths.checkSourcePath(CanonPath(path)).path.abs();
: state.ctx.paths.checkSourcePath(CanonPath(path)).canonical().abs();
PathFilter filter = filterFun ? ([&](const Path & path) {
auto st = lstat(path);
@@ -1569,7 +1569,7 @@ static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * arg
auto path = state.coerceToPath(pos, *args[1], context,
"while evaluating the second argument (the path to filter) passed to builtins.filterSource");
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource");
addPath(state, pos, path.baseName(), path.path.abs(), args[0], FileIngestionMethod::Recursive, std::nullopt, v, context);
addPath(state, pos, path.baseName(), path.canonical().abs(), args[0], FileIngestionMethod::Recursive, std::nullopt, v, context);
}
static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value & v)
@@ -1608,7 +1608,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
if (name.empty())
name = path->baseName();
addPath(state, pos, name, path->path.abs(), filterFun, method, expectedHash, v, context);
addPath(state, pos, name, path->canonical().abs(), filterFun, method, expectedHash, v, context);
}
+1 -1
View File
@@ -100,7 +100,7 @@ void Value::mkStringMove(const char * s, const NixStringContext & context)
void Value::mkPath(const SourcePath & path)
{
mkPath(gcCopyStringIfNeeded(path.path.abs()));
*this = Value(NewValueAs::path, path);
}
}
+1 -1
View File
@@ -347,7 +347,7 @@ public:
/// dynamic (GC) allocation to do so.
Value(path_t, SourcePath const & path)
: internalType(tPath)
, _path(gcCopyStringIfNeeded(path.path.abs()))
, _path(gcCopyStringIfNeeded(path.canonical().abs()))
, _path_pad(0)
{ }
+2 -2
View File
@@ -18,8 +18,8 @@ StorePath fetchToStore(
return
settings.readOnlyMode
? store.computeStorePathForPath(name, path.path.abs(), method, HashType::SHA256, filter2).first
: store.addToStore(name, path.path.abs(), method, HashType::SHA256, filter2, repair);
? store.computeStorePathForPath(name, path.canonical().abs(), method, HashType::SHA256, filter2).first
: store.addToStore(name, path.canonical().abs(), method, HashType::SHA256, filter2, repair);
}
+4
View File
@@ -42,8 +42,10 @@ enum class SymlinkResolution {
*/
struct SourcePath
{
private:
CanonPath path;
public:
SourcePath(CanonPath path)
: path(std::move(path))
{ }
@@ -103,6 +105,8 @@ struct SourcePath
PathFilter & filter = defaultPathFilter) const
{ sink << nix::dumpPath(path.abs(), filter); }
const CanonPath & canonical() const { return path; }
std::string to_string() const
{ return path.abs(); }
+4 -4
View File
@@ -34,12 +34,12 @@ TEST(Arguments, lookupFileArg) {
auto state = std::make_shared<Evaluator>(searchPath, store, store);
SourcePath const foundUnitData = lookupFileArg(*state, "<example>");
EXPECT_EQ(foundUnitData.path, canonDataPath);
EXPECT_EQ(foundUnitData.canonical(), canonDataPath);
// lookupFileArg should not resolve <search paths> if anything else is before or after it.
SourcePath const yepEvenSpaces = lookupFileArg(*state, " <example>");
EXPECT_EQ(yepEvenSpaces.path, CanonPath::fromCwd(" <example>"));
EXPECT_EQ(lookupFileArg(*state, "<example>/nixos").path, CanonPath::fromCwd("<example>/nixos"));
EXPECT_EQ(yepEvenSpaces.canonical(), CanonPath::fromCwd(" <example>"));
EXPECT_EQ(lookupFileArg(*state, "<example>/nixos").canonical(), CanonPath::fromCwd("<example>/nixos"));
try {
lookupFileArg(*state, INVALID_CHANNEL);
@@ -49,7 +49,7 @@ TEST(Arguments, lookupFileArg) {
}
SourcePath const normalFile = lookupFileArg(*state, unitDataPath);
EXPECT_EQ(normalFile.path, canonDataPath);
EXPECT_EQ(normalFile.canonical(), canonDataPath);
}
}