Use the fs accessor for readInvalidDerivation
Extend `FSAccessor::readFile` to allow not checking that the path is a valid one, and rewrite `readInvalidDerivation` using this extended `readFile`. Several places in the code use `readInvalidDerivation`, either because they need to read a derivation that has been written in the store but not registered yet, or more generally to prevent a deadlock because `readDerivation` tries to lock the state, so can't be called from a place where the lock is already held. However, `readInvalidDerivation` implicitely assumes that the store is a `LocalFSStore`, which isn't always the case. The concrete motivation for this is that it's required for `nix copy --from someBinaryCache` to work, which is tremendously useful for the tests.
This commit is contained in:
parent
f2f60bf5d6
commit
7080321618
|
@ -25,7 +25,14 @@ public:
|
||||||
|
|
||||||
virtual StringSet readDirectory(const Path & path) = 0;
|
virtual StringSet readDirectory(const Path & path) = 0;
|
||||||
|
|
||||||
virtual std::string readFile(const Path & path) = 0;
|
/**
|
||||||
|
* Read a file inside the store.
|
||||||
|
*
|
||||||
|
* If `requireValidPath` is set to `true` (the default), the path must be
|
||||||
|
* inside a valid store path, otherwise it just needs to be physically
|
||||||
|
* present (but not necessarily properly registered)
|
||||||
|
*/
|
||||||
|
virtual std::string readFile(const Path & path, bool requireValidPath = true) = 0;
|
||||||
|
|
||||||
virtual std::string readLink(const Path & path) = 0;
|
virtual std::string readLink(const Path & path) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,10 +19,10 @@ struct LocalStoreAccessor : public FSAccessor
|
||||||
|
|
||||||
LocalStoreAccessor(ref<LocalFSStore> store) : store(store) { }
|
LocalStoreAccessor(ref<LocalFSStore> store) : store(store) { }
|
||||||
|
|
||||||
Path toRealPath(const Path & path)
|
Path toRealPath(const Path & path, bool requireValidPath = true)
|
||||||
{
|
{
|
||||||
auto storePath = store->toStorePath(path).first;
|
auto storePath = store->toStorePath(path).first;
|
||||||
if (!store->isValidPath(storePath))
|
if (requireValidPath && !store->isValidPath(storePath))
|
||||||
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath));
|
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath));
|
||||||
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,9 @@ struct LocalStoreAccessor : public FSAccessor
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string readFile(const Path & path) override
|
std::string readFile(const Path & path, bool requireValidPath = true) override
|
||||||
{
|
{
|
||||||
return nix::readFile(toRealPath(path));
|
return nix::readFile(toRealPath(path, requireValidPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string readLink(const Path & path) override
|
std::string readLink(const Path & path) override
|
||||||
|
|
|
@ -203,7 +203,7 @@ struct NarAccessor : public FSAccessor
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string readFile(const Path & path) override
|
std::string readFile(const Path & path, bool requireValidPath = true) override
|
||||||
{
|
{
|
||||||
auto i = get(path);
|
auto i = get(path);
|
||||||
if (i.type != FSAccessor::Type::tRegular)
|
if (i.type != FSAccessor::Type::tRegular)
|
||||||
|
|
|
@ -43,13 +43,13 @@ void RemoteFSAccessor::addToCache(std::string_view hashPart, const std::string &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_)
|
std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_, bool requireValidPath)
|
||||||
{
|
{
|
||||||
auto path = canonPath(path_);
|
auto path = canonPath(path_);
|
||||||
|
|
||||||
auto [storePath, restPath] = store->toStorePath(path);
|
auto [storePath, restPath] = store->toStorePath(path);
|
||||||
|
|
||||||
if (!store->isValidPath(storePath))
|
if (requireValidPath && !store->isValidPath(storePath))
|
||||||
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath));
|
throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath));
|
||||||
|
|
||||||
auto i = nars.find(std::string(storePath.hashPart()));
|
auto i = nars.find(std::string(storePath.hashPart()));
|
||||||
|
@ -113,9 +113,9 @@ StringSet RemoteFSAccessor::readDirectory(const Path & path)
|
||||||
return res.first->readDirectory(res.second);
|
return res.first->readDirectory(res.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RemoteFSAccessor::readFile(const Path & path)
|
std::string RemoteFSAccessor::readFile(const Path & path, bool requireValidPath)
|
||||||
{
|
{
|
||||||
auto res = fetch(path);
|
auto res = fetch(path, requireValidPath);
|
||||||
return res.first->readFile(res.second);
|
return res.first->readFile(res.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ class RemoteFSAccessor : public FSAccessor
|
||||||
|
|
||||||
Path cacheDir;
|
Path cacheDir;
|
||||||
|
|
||||||
std::pair<ref<FSAccessor>, Path> fetch(const Path & path_);
|
std::pair<ref<FSAccessor>, Path> fetch(const Path & path_, bool requireValidPath = true);
|
||||||
|
|
||||||
friend class BinaryCacheStore;
|
friend class BinaryCacheStore;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ public:
|
||||||
|
|
||||||
StringSet readDirectory(const Path & path) override;
|
StringSet readDirectory(const Path & path) override;
|
||||||
|
|
||||||
std::string readFile(const Path & path) override;
|
std::string readFile(const Path & path, bool requireValidPath = true) override;
|
||||||
|
|
||||||
std::string readLink(const Path & path) override;
|
std::string readLink(const Path & path) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1018,26 +1018,23 @@ Derivation Store::derivationFromPath(const StorePath & drvPath)
|
||||||
return readDerivation(drvPath);
|
return readDerivation(drvPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Derivation readDerivationCommon(Store& store, const StorePath& drvPath, bool requireValidPath)
|
||||||
Derivation Store::readDerivation(const StorePath & drvPath)
|
|
||||||
{
|
{
|
||||||
auto accessor = getFSAccessor();
|
auto accessor = store.getFSAccessor();
|
||||||
try {
|
try {
|
||||||
return parseDerivation(*this,
|
return parseDerivation(store,
|
||||||
accessor->readFile(printStorePath(drvPath)),
|
accessor->readFile(store.printStorePath(drvPath), requireValidPath),
|
||||||
Derivation::nameFromPath(drvPath));
|
Derivation::nameFromPath(drvPath));
|
||||||
} catch (FormatError & e) {
|
} catch (FormatError & e) {
|
||||||
throw Error("error parsing derivation '%s': %s", printStorePath(drvPath), e.msg());
|
throw Error("error parsing derivation '%s': %s", store.printStorePath(drvPath), e.msg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Derivation Store::readDerivation(const StorePath & drvPath)
|
||||||
|
{ return readDerivationCommon(*this, drvPath, true); }
|
||||||
|
|
||||||
Derivation Store::readInvalidDerivation(const StorePath & drvPath)
|
Derivation Store::readInvalidDerivation(const StorePath & drvPath)
|
||||||
{
|
{ return readDerivationCommon(*this, drvPath, false); }
|
||||||
return parseDerivation(
|
|
||||||
*this,
|
|
||||||
readFile(Store::toRealPath(drvPath)),
|
|
||||||
Derivation::nameFromPath(drvPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue