tvl-depot/third_party/nix/src/libstore/remote-fs-accessor.cc
Vincent Ambo 1cf11317ca refactor(tvix/libutil): Mark single-argument constructors explicit
This is the clang-tidy lint 'google-explicit-constructor'.

There's a whole bunch of breakage that was introduced by this, and we
had to opt out a few types of this (esp. the string formatting crap).

In some cases minor other changes have been done to keep the code
working, instead of converting between types (e.g. an explicit
comparison operator implementation for nix::Pid).

Change-Id: I12e1ca51a6bc2c882dba81a2526b9729d26988e7
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1832
Tested-by: BuildkiteCI
Reviewed-by: kanepyork <rikingcoding@gmail.com>
Reviewed-by: glittershark <grfn@gws.fyi>
2020-08-23 11:58:44 +00:00

133 lines
3.5 KiB
C++

#include "libstore/remote-fs-accessor.hh"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "libstore/nar-accessor.hh"
#include "libutil/json.hh"
namespace nix {
RemoteFSAccessor::RemoteFSAccessor(const ref<Store>& store,
const Path& cacheDir)
: store(store), cacheDir(cacheDir) {
if (!cacheDir.empty()) {
createDirs(cacheDir);
}
}
Path RemoteFSAccessor::makeCacheFile(const Path& storePath,
const std::string& ext) {
assert(!cacheDir.empty());
return fmt("%s/%s.%s", cacheDir, storePathToHash(storePath), ext);
}
void RemoteFSAccessor::addToCache(const Path& storePath, const std::string& nar,
const ref<FSAccessor>& narAccessor) {
nars.emplace(storePath, narAccessor);
if (!cacheDir.empty()) {
try {
std::ostringstream str;
JSONPlaceholder jsonRoot(str);
listNar(jsonRoot, narAccessor, "", true);
writeFile(makeCacheFile(storePath, "ls"), str.str());
/* FIXME: do this asynchronously. */
writeFile(makeCacheFile(storePath, "nar"), nar);
} catch (...) {
ignoreException();
}
}
}
std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path& path_) {
auto path = canonPath(path_);
auto storePath = store->toStorePath(path);
std::string restPath = std::string(path, storePath.size());
if (!store->isValidPath(storePath)) {
throw InvalidPath(format("path '%1%' is not a valid store path") %
storePath);
}
auto i = nars.find(storePath);
if (i != nars.end()) {
return {i->second, restPath};
}
StringSink sink;
std::string listing;
Path cacheFile;
if (!cacheDir.empty() &&
pathExists(cacheFile = makeCacheFile(storePath, "nar"))) {
try {
listing = nix::readFile(makeCacheFile(storePath, "ls"));
auto narAccessor = makeLazyNarAccessor(
listing, [cacheFile](uint64_t offset, uint64_t length) {
AutoCloseFD fd(open(cacheFile.c_str(), O_RDONLY | O_CLOEXEC));
if (!fd) {
throw SysError("opening NAR cache file '%s'", cacheFile);
}
if (lseek(fd.get(), offset, SEEK_SET) !=
static_cast<off_t>(offset)) {
throw SysError("seeking in '%s'", cacheFile);
}
std::string buf(length, 0);
readFull(fd.get(), reinterpret_cast<unsigned char*>(buf.data()),
length);
return buf;
});
nars.emplace(storePath, narAccessor);
return {narAccessor, restPath};
} catch (SysError&) {
}
try {
*sink.s = nix::readFile(cacheFile);
auto narAccessor = makeNarAccessor(sink.s);
nars.emplace(storePath, narAccessor);
return {narAccessor, restPath};
} catch (SysError&) {
}
}
store->narFromPath(storePath, sink);
auto narAccessor = makeNarAccessor(sink.s);
addToCache(storePath, *sink.s, narAccessor);
return {narAccessor, restPath};
}
FSAccessor::Stat RemoteFSAccessor::stat(const Path& path) {
auto res = fetch(path);
return res.first->stat(res.second);
}
StringSet RemoteFSAccessor::readDirectory(const Path& path) {
auto res = fetch(path);
return res.first->readDirectory(res.second);
}
std::string RemoteFSAccessor::readFile(const Path& path) {
auto res = fetch(path);
return res.first->readFile(res.second);
}
std::string RemoteFSAccessor::readLink(const Path& path) {
auto res = fetch(path);
return res.first->readLink(res.second);
}
} // namespace nix