1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-15 23:12:44 +01:00

Store::getFSAccessor: Do not include the store dir

Rather than "mounting" the store inside an empty virtual filesystem,
just return the store as a virtual filesystem. This is more modular.

(FWIW, it also supports two long term hopes of mind:

1. More capability-based Nix language mode. I dream of a "super pure
   eval" where you can only use relative path literals (See #8738), and
   any `fetchTree`-fetched stuff + the store are all disjoint (none is
   mounted in another) file systems.

2. Windows, where the store dir may include drive letters, etc., and is
   thus unsuitable to be the prefix of any `CanonPath`s.

)

Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
This commit is contained in:
John Ericson 2025-02-19 18:46:37 -05:00
parent 2455bda91b
commit eb643d034f
18 changed files with 146 additions and 50 deletions

View file

@ -524,7 +524,7 @@ bool Worker::pathContentsGood(const StorePath & path)
res = false;
else {
auto current = hashPath(
{store.getFSAccessor(), CanonPath(store.printStorePath(path))},
{store.getFSAccessor(), CanonPath(path.to_string())},
FileIngestionMethod::NixArchive, info->narHash.algo).first;
Hash nullHash(HashAlgorithm::SHA256);
res = info->narHash == nullHash || info->narHash == current;

View file

@ -83,7 +83,9 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store
{ callback(nullptr); }
virtual ref<SourceAccessor> getFSAccessor(bool requireValidPath) override
{ unsupported("getFSAccessor"); }
{
return makeEmptySourceAccessor();
}
};
static RegisterStoreImplementation<DummyStore, DummyStoreConfig> regDummyStore;

View file

@ -33,30 +33,35 @@ struct LocalStoreAccessor : PosixSourceAccessor
bool requireValidPath;
LocalStoreAccessor(ref<LocalFSStore> store, bool requireValidPath)
: store(store)
: PosixSourceAccessor(std::filesystem::path{store->realStoreDir.get()})
, store(store)
, requireValidPath(requireValidPath)
{ }
CanonPath toRealPath(const CanonPath & path)
{
auto [storePath, rest] = store->toStorePath(path.abs());
}
void requireStoreObject(const CanonPath & path)
{
auto [storePath, rest] = store->toStorePath(store->storeDir + path.abs());
if (requireValidPath && !store->isValidPath(storePath))
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath));
return CanonPath(store->getRealStoreDir()) / storePath.to_string() / CanonPath(rest);
}
std::optional<Stat> maybeLstat(const CanonPath & path) override
{
/* Handle the case where `path` is (a parent of) the store. */
if (isDirOrInDir(store->storeDir, path.abs()))
/* Also allow `path` to point to the entire store, which is
needed for resolving symlinks. */
if (path.isRoot())
return Stat{ .type = tDirectory };
return PosixSourceAccessor::maybeLstat(toRealPath(path));
requireStoreObject(path);
return PosixSourceAccessor::maybeLstat(path);
}
DirEntries readDirectory(const CanonPath & path) override
{
return PosixSourceAccessor::readDirectory(toRealPath(path));
requireStoreObject(path);
return PosixSourceAccessor::readDirectory(path);
}
void readFile(
@ -64,12 +69,14 @@ struct LocalStoreAccessor : PosixSourceAccessor
Sink & sink,
std::function<void(uint64_t)> sizeCallback) override
{
return PosixSourceAccessor::readFile(toRealPath(path), sink, sizeCallback);
requireStoreObject(path);
return PosixSourceAccessor::readFile(path, sink, sizeCallback);
}
std::string readLink(const CanonPath & path) override
{
return PosixSourceAccessor::readLink(toRealPath(path));
requireStoreObject(path);
return PosixSourceAccessor::readLink(path);
}
};

View file

@ -1102,7 +1102,7 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
auto & specified = *info.ca;
auto actualHash = ({
auto accessor = getFSAccessor(false);
CanonPath path { printStorePath(info.path) };
CanonPath path { info.path.to_string() };
Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++
auto fim = specified.method.getFileIngestionMethod();
switch (fim) {

View file

@ -51,7 +51,7 @@ ref<SourceAccessor> RemoteFSAccessor::addToCache(std::string_view hashPart, std:
std::pair<ref<SourceAccessor>, CanonPath> RemoteFSAccessor::fetch(const CanonPath & path)
{
auto [storePath, restPath_] = store->toStorePath(path.abs());
auto [storePath, restPath_] = store->toStorePath(store->storeDir + path.abs());
auto restPath = CanonPath(restPath_);
if (requireValidPath && !store->isValidPath(storePath))

View file

@ -1233,7 +1233,7 @@ static Derivation readDerivationCommon(Store & store, const StorePath & drvPath,
auto accessor = store.getFSAccessor(requireValidPath);
try {
return parseDerivation(store,
accessor->readFile(CanonPath(store.printStorePath(drvPath))),
accessor->readFile(CanonPath(drvPath.to_string())),
Derivation::nameFromPath(drvPath));
} catch (FormatError & e) {
throw Error("error parsing derivation '%s': %s", store.printStorePath(drvPath), e.msg());