libstore: asyncify FSAccessor, listNar
Change-Id: I804ac18c4b6b80699247bb885493056799bf3d0c
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
#include <kj/async.h>
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -33,9 +35,9 @@ public:
|
||||
|
||||
virtual ~FSAccessor() { }
|
||||
|
||||
virtual Stat stat(const Path & path) = 0;
|
||||
virtual kj::Promise<Result<Stat>> stat(const Path & path) = 0;
|
||||
|
||||
virtual StringSet readDirectory(const Path & path) = 0;
|
||||
virtual kj::Promise<Result<StringSet>> readDirectory(const Path & path) = 0;
|
||||
|
||||
/**
|
||||
* Read a file inside the store.
|
||||
@@ -44,9 +46,10 @@ public:
|
||||
* 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 kj::Promise<Result<std::string>>
|
||||
readFile(const Path & path, bool requireValidPath = true) = 0;
|
||||
|
||||
virtual std::string readLink(const Path & path) = 0;
|
||||
virtual kj::Promise<Result<std::string>> readLink(const Path & path) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -14,38 +14,42 @@ struct LocalStoreAccessor : public FSAccessor
|
||||
|
||||
LocalStoreAccessor(ref<LocalFSStore> store) : store(store) { }
|
||||
|
||||
Path toRealPath(const Path & path, bool requireValidPath = true)
|
||||
{
|
||||
kj::Promise<Result<Path>> toRealPath(const Path & path, bool requireValidPath = true)
|
||||
try {
|
||||
auto storePath = store->toStorePath(path).first;
|
||||
if (requireValidPath && !store->isValidPath(storePath))
|
||||
throw InvalidPath("path '%1%' does not exist in the store", store->printStorePath(storePath));
|
||||
return store->getRealStoreDir() + std::string(path, store->config().storeDir.size());
|
||||
co_return store->getRealStoreDir() + std::string(path, store->config().storeDir.size());
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
FSAccessor::Stat stat(const Path & path) override
|
||||
{
|
||||
auto realPath = toRealPath(path);
|
||||
kj::Promise<Result<FSAccessor::Stat>> stat(const Path & path) override
|
||||
try {
|
||||
auto realPath = TRY_AWAIT(toRealPath(path));
|
||||
|
||||
struct stat st;
|
||||
if (lstat(realPath.c_str(), &st)) {
|
||||
if (errno == ENOENT || errno == ENOTDIR) return {Type::tMissing, 0, false};
|
||||
if (errno == ENOENT || errno == ENOTDIR) co_return {Type::tMissing, 0, false};
|
||||
throw SysError("getting status of '%1%'", path);
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
|
||||
throw Error("file '%1%' has unsupported type", path);
|
||||
|
||||
return {
|
||||
co_return {
|
||||
S_ISREG(st.st_mode) ? Type::tRegular :
|
||||
S_ISLNK(st.st_mode) ? Type::tSymlink :
|
||||
Type::tDirectory,
|
||||
S_ISREG(st.st_mode) ? (uint64_t) st.st_size : 0,
|
||||
S_ISREG(st.st_mode) && st.st_mode & S_IXUSR};
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
StringSet readDirectory(const Path & path) override
|
||||
{
|
||||
auto realPath = toRealPath(path);
|
||||
kj::Promise<Result<StringSet>> readDirectory(const Path & path) override
|
||||
try {
|
||||
auto realPath = TRY_AWAIT(toRealPath(path));
|
||||
|
||||
auto entries = nix::readDirectory(realPath);
|
||||
|
||||
@@ -53,17 +57,24 @@ struct LocalStoreAccessor : public FSAccessor
|
||||
for (auto & entry : entries)
|
||||
res.insert(entry.name);
|
||||
|
||||
return res;
|
||||
co_return res;
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::string readFile(const Path & path, bool requireValidPath = true) override
|
||||
{
|
||||
return nix::readFile(toRealPath(path, requireValidPath));
|
||||
kj::Promise<Result<std::string>>
|
||||
readFile(const Path & path, bool requireValidPath = true) override
|
||||
try {
|
||||
co_return nix::readFile(TRY_AWAIT(toRealPath(path, requireValidPath)));
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::string readLink(const Path & path) override
|
||||
{
|
||||
return nix::readLink(toRealPath(path));
|
||||
kj::Promise<Result<std::string>> readLink(const Path & path) override
|
||||
try {
|
||||
co_return nix::readLink(TRY_AWAIT(toRealPath(path)));
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lix/libstore/nar-accessor.hh"
|
||||
#include "lix/libutil/archive.hh"
|
||||
#include "lix/libutil/async.hh"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -87,11 +88,11 @@ struct NarAccessor : public FSAccessor
|
||||
return *result;
|
||||
}
|
||||
|
||||
Stat stat(const Path & path) override
|
||||
{
|
||||
kj::Promise<Result<Stat>> stat(const Path & path) override
|
||||
try {
|
||||
auto i = find(path);
|
||||
if (i == nullptr)
|
||||
return {FSAccessor::Type::tMissing, 0, false};
|
||||
co_return {FSAccessor::Type::tMissing, 0, false};
|
||||
auto handlers = overloaded{
|
||||
[](const nar_index::File & f) {
|
||||
return Stat{tRegular, f.size, f.executable, f.offset};
|
||||
@@ -99,11 +100,13 @@ struct NarAccessor : public FSAccessor
|
||||
[](const nar_index::Symlink &) { return Stat{tSymlink}; },
|
||||
[](const nar_index::Directory &) { return Stat{tDirectory}; },
|
||||
};
|
||||
return std::visit(handlers, *i);
|
||||
co_return std::visit(handlers, *i);
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
StringSet readDirectory(const Path & path) override
|
||||
{
|
||||
kj::Promise<Result<StringSet>> readDirectory(const Path & path) override
|
||||
try {
|
||||
auto & i = get(path);
|
||||
auto dir = std::get_if<nar_index::Directory>(&i);
|
||||
|
||||
@@ -114,29 +117,36 @@ struct NarAccessor : public FSAccessor
|
||||
for (auto & child : dir->contents)
|
||||
res.insert(child.first);
|
||||
|
||||
return res;
|
||||
co_return res;
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::string readFile(const Path & path, bool requireValidPath = true) override
|
||||
{
|
||||
kj::Promise<Result<std::string>>
|
||||
readFile(const Path & path, bool requireValidPath = true) override
|
||||
try {
|
||||
auto & i = get(path);
|
||||
auto file = std::get_if<nar_index::File>(&i);
|
||||
if (!file)
|
||||
throw Error("path '%1%' inside NAR file is not a regular file", path);
|
||||
|
||||
if (getNarBytes) return getNarBytes(file->offset, file->size);
|
||||
if (getNarBytes) co_return getNarBytes(file->offset, file->size);
|
||||
|
||||
assert(nar);
|
||||
return std::string(*nar, file->offset, file->size);
|
||||
co_return std::string(*nar, file->offset, file->size);
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::string readLink(const Path & path) override
|
||||
{
|
||||
kj::Promise<Result<std::string>> readLink(const Path & path) override
|
||||
try {
|
||||
auto & i = get(path);
|
||||
auto link = std::get_if<nar_index::Symlink>(&i);
|
||||
if (!link)
|
||||
throw Error("path '%1%' inside NAR file is not a symlink", path);
|
||||
return link->target;
|
||||
co_return link->target;
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -157,9 +167,9 @@ ref<FSAccessor> makeLazyNarAccessor(const std::string & listing,
|
||||
}
|
||||
|
||||
using nlohmann::json;
|
||||
json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||
{
|
||||
auto st = accessor->stat(path);
|
||||
kj::Promise<Result<json>> listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||
try {
|
||||
auto st = TRY_AWAIT(accessor->stat(path));
|
||||
|
||||
json obj = json::object();
|
||||
|
||||
@@ -177,9 +187,9 @@ json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||
{
|
||||
obj["entries"] = json::object();
|
||||
json &res2 = obj["entries"];
|
||||
for (auto & name : accessor->readDirectory(path)) {
|
||||
for (auto & name : TRY_AWAIT(accessor->readDirectory(path))) {
|
||||
if (recurse) {
|
||||
res2[name] = listNar(accessor, path + "/" + name, true);
|
||||
res2[name] = TRY_AWAIT(listNar(accessor, path + "/" + name, true));
|
||||
} else
|
||||
res2[name] = json::object();
|
||||
}
|
||||
@@ -187,13 +197,15 @@ json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||
break;
|
||||
case FSAccessor::Type::tSymlink:
|
||||
obj["type"] = "symlink";
|
||||
obj["target"] = accessor->readLink(path);
|
||||
obj["target"] = TRY_AWAIT(accessor->readLink(path));
|
||||
break;
|
||||
case FSAccessor::Type::tMissing:
|
||||
default:
|
||||
throw Error("path '%s' does not exist in NAR", path);
|
||||
}
|
||||
return obj;
|
||||
co_return obj;
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
static nlohmann::json listNar(const nar_index::Entry & e, Path path)
|
||||
|
||||
@@ -37,7 +37,8 @@ ref<FSAccessor> makeLazyNarAccessor(
|
||||
* Write a JSON representation of the contents of a NAR (except file
|
||||
* contents).
|
||||
*/
|
||||
nlohmann::json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse);
|
||||
kj::Promise<Result<nlohmann::json>>
|
||||
listNar(ref<FSAccessor> accessor, const Path & path, bool recurse);
|
||||
nlohmann::json listNar(const nar_index::Entry & nar);
|
||||
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ Path RemoteFSAccessor::makeCacheFile(std::string_view hashPart, const std::strin
|
||||
return fmt("%s/%s.%s", cacheDir, hashPart, ext);
|
||||
}
|
||||
|
||||
ref<FSAccessor> RemoteFSAccessor::addToCache(std::string_view hashPart, std::string && nar)
|
||||
{
|
||||
kj::Promise<Result<ref<FSAccessor>>>
|
||||
RemoteFSAccessor::addToCache(std::string_view hashPart, std::string && nar)
|
||||
try {
|
||||
if (cacheDir != "") {
|
||||
try {
|
||||
/* FIXME: do this asynchronously. */
|
||||
@@ -38,18 +39,21 @@ ref<FSAccessor> RemoteFSAccessor::addToCache(std::string_view hashPart, std::str
|
||||
|
||||
if (cacheDir != "") {
|
||||
try {
|
||||
nlohmann::json j = listNar(narAccessor, "", true);
|
||||
nlohmann::json j = TRY_AWAIT(listNar(narAccessor, "", true));
|
||||
writeFile(makeCacheFile(hashPart, "ls"), j.dump());
|
||||
} catch (...) {
|
||||
ignoreExceptionExceptInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
return narAccessor;
|
||||
co_return narAccessor;
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_, bool requireValidPath)
|
||||
{
|
||||
kj::Promise<Result<std::pair<ref<FSAccessor>, Path>>>
|
||||
RemoteFSAccessor::fetch(const Path & path_, bool requireValidPath)
|
||||
try {
|
||||
auto path = canonPath(path_);
|
||||
|
||||
auto [storePath, restPath] = store->toStorePath(path);
|
||||
@@ -58,7 +62,7 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_, boo
|
||||
throw InvalidPath("path '%1%' does not exist in remote store", store->printStorePath(storePath));
|
||||
|
||||
auto i = nars.find(std::string(storePath.hashPart()));
|
||||
if (i != nars.end()) return {i->second, restPath};
|
||||
if (i != nars.end()) co_return {i->second, restPath};
|
||||
|
||||
std::string listing;
|
||||
Path cacheFile;
|
||||
@@ -85,44 +89,55 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_, boo
|
||||
});
|
||||
|
||||
nars.emplace(storePath.hashPart(), narAccessor);
|
||||
return {narAccessor, restPath};
|
||||
co_return {narAccessor, restPath};
|
||||
|
||||
} catch (SysError &) { }
|
||||
|
||||
try {
|
||||
auto narAccessor = makeNarAccessor(nix::readFile(cacheFile));
|
||||
nars.emplace(storePath.hashPart(), narAccessor);
|
||||
return {narAccessor, restPath};
|
||||
co_return {narAccessor, restPath};
|
||||
} catch (SysError &) { }
|
||||
}
|
||||
|
||||
StringSink sink;
|
||||
store->narFromPath(storePath)->drainInto(sink);
|
||||
return {addToCache(storePath.hashPart(), std::move(sink.s)), restPath};
|
||||
co_return {TRY_AWAIT(addToCache(storePath.hashPart(), std::move(sink.s))), restPath};
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
FSAccessor::Stat RemoteFSAccessor::stat(const Path & path)
|
||||
{
|
||||
auto res = fetch(path);
|
||||
return res.first->stat(res.second);
|
||||
kj::Promise<Result<FSAccessor::Stat>> RemoteFSAccessor::stat(const Path & path)
|
||||
try {
|
||||
auto res = TRY_AWAIT(fetch(path));
|
||||
co_return TRY_AWAIT(res.first->stat(res.second));
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
StringSet RemoteFSAccessor::readDirectory(const Path & path)
|
||||
{
|
||||
auto res = fetch(path);
|
||||
return res.first->readDirectory(res.second);
|
||||
kj::Promise<Result<StringSet>> RemoteFSAccessor::readDirectory(const Path & path)
|
||||
try {
|
||||
auto res = TRY_AWAIT(fetch(path));
|
||||
co_return TRY_AWAIT(res.first->readDirectory(res.second));
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::string RemoteFSAccessor::readFile(const Path & path, bool requireValidPath)
|
||||
{
|
||||
auto res = fetch(path, requireValidPath);
|
||||
return res.first->readFile(res.second);
|
||||
kj::Promise<Result<std::string>>
|
||||
RemoteFSAccessor::readFile(const Path & path, bool requireValidPath)
|
||||
try {
|
||||
auto res = TRY_AWAIT(fetch(path, requireValidPath));
|
||||
co_return TRY_AWAIT(res.first->readFile(res.second));
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
std::string RemoteFSAccessor::readLink(const Path & path)
|
||||
{
|
||||
auto res = fetch(path);
|
||||
return res.first->readLink(res.second);
|
||||
kj::Promise<Result<std::string>> RemoteFSAccessor::readLink(const Path & path)
|
||||
try {
|
||||
auto res = TRY_AWAIT(fetch(path));
|
||||
co_return TRY_AWAIT(res.first->readLink(res.second));
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,26 +15,28 @@ class RemoteFSAccessor : public FSAccessor
|
||||
|
||||
Path cacheDir;
|
||||
|
||||
std::pair<ref<FSAccessor>, Path> fetch(const Path & path_, bool requireValidPath = true);
|
||||
kj::Promise<Result<std::pair<ref<FSAccessor>, Path>>>
|
||||
fetch(const Path & path_, bool requireValidPath = true);
|
||||
|
||||
friend class BinaryCacheStore;
|
||||
|
||||
Path makeCacheFile(std::string_view hashPart, const std::string & ext);
|
||||
|
||||
ref<FSAccessor> addToCache(std::string_view hashPart, std::string && nar);
|
||||
kj::Promise<Result<ref<FSAccessor>>> addToCache(std::string_view hashPart, std::string && nar);
|
||||
|
||||
public:
|
||||
|
||||
RemoteFSAccessor(ref<Store> store,
|
||||
const /* FIXME: use std::optional */ Path & cacheDir = "");
|
||||
|
||||
Stat stat(const Path & path) override;
|
||||
kj::Promise<Result<Stat>> stat(const Path & path) override;
|
||||
|
||||
StringSet readDirectory(const Path & path) override;
|
||||
kj::Promise<Result<StringSet>> readDirectory(const Path & path) override;
|
||||
|
||||
std::string readFile(const Path & path, bool requireValidPath = true) override;
|
||||
kj::Promise<Result<std::string>>
|
||||
readFile(const Path & path, bool requireValidPath = true) override;
|
||||
|
||||
std::string readLink(const Path & path) override;
|
||||
kj::Promise<Result<std::string>> readLink(const Path & path) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1392,9 +1392,11 @@ readDerivationCommon(Store& store, const StorePath& drvPath, bool requireValidPa
|
||||
try {
|
||||
auto accessor = store.getFSAccessor();
|
||||
try {
|
||||
co_return parseDerivation(store,
|
||||
accessor->readFile(store.printStorePath(drvPath), requireValidPath),
|
||||
Derivation::nameFromPath(drvPath));
|
||||
co_return parseDerivation(
|
||||
store,
|
||||
TRY_AWAIT(accessor->readFile(store.printStorePath(drvPath), requireValidPath)),
|
||||
Derivation::nameFromPath(drvPath)
|
||||
);
|
||||
} catch (FormatError & e) {
|
||||
throw Error("error parsing derivation '%s': %s", store.printStorePath(drvPath), e.msg());
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,13 +11,13 @@ struct MixCat : virtual Args
|
||||
|
||||
void cat(ref<FSAccessor> accessor)
|
||||
{
|
||||
auto st = accessor->stat(path);
|
||||
auto st = aio().blockOn(accessor->stat(path));
|
||||
if (st.type == FSAccessor::Type::tMissing)
|
||||
throw Error("path '%1%' does not exist", path);
|
||||
if (st.type != FSAccessor::Type::tRegular)
|
||||
throw Error("path '%1%' is not a regular file", path);
|
||||
|
||||
auto file = accessor->readFile(path);
|
||||
auto file = aio().blockOn(accessor->readFile(path));
|
||||
|
||||
logger->pause();
|
||||
writeFull(STDOUT_FILENO, file);
|
||||
|
||||
+6
-6
@@ -45,7 +45,7 @@ struct MixLs : virtual Args, MixJSON
|
||||
|
||||
auto showFile = [&](const Path & curPath, const std::string & relPath) {
|
||||
if (verbose) {
|
||||
auto st = accessor->stat(curPath);
|
||||
auto st = aio().blockOn(accessor->stat(curPath));
|
||||
std::string tp =
|
||||
st.type == FSAccessor::Type::tRegular ?
|
||||
(st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") :
|
||||
@@ -53,14 +53,14 @@ struct MixLs : virtual Args, MixJSON
|
||||
"dr-xr-xr-x";
|
||||
auto line = fmt("%s %20d %s", tp, st.fileSize, relPath);
|
||||
if (st.type == FSAccessor::Type::tSymlink)
|
||||
line += " -> " + accessor->readLink(curPath);
|
||||
line += " -> " + aio().blockOn(accessor->readLink(curPath));
|
||||
logger->cout(line);
|
||||
if (recursive && st.type == FSAccessor::Type::tDirectory)
|
||||
doPath(st, curPath, relPath, false);
|
||||
} else {
|
||||
logger->cout(relPath);
|
||||
if (recursive) {
|
||||
auto st = accessor->stat(curPath);
|
||||
auto st = aio().blockOn(accessor->stat(curPath));
|
||||
if (st.type == FSAccessor::Type::tDirectory)
|
||||
doPath(st, curPath, relPath, false);
|
||||
}
|
||||
@@ -71,14 +71,14 @@ struct MixLs : virtual Args, MixJSON
|
||||
const std::string & relPath, bool showDirectory)
|
||||
{
|
||||
if (st.type == FSAccessor::Type::tDirectory && !showDirectory) {
|
||||
auto names = accessor->readDirectory(curPath);
|
||||
auto names = aio().blockOn(accessor->readDirectory(curPath));
|
||||
for (auto & name : names)
|
||||
showFile(curPath + "/" + name, relPath + "/" + name);
|
||||
} else
|
||||
showFile(curPath, relPath);
|
||||
};
|
||||
|
||||
auto st = accessor->stat(path);
|
||||
auto st = aio().blockOn(accessor->stat(path));
|
||||
if (st.type == FSAccessor::Type::tMissing)
|
||||
throw Error("path '%1%' does not exist", path);
|
||||
doPath(st, path,
|
||||
@@ -93,7 +93,7 @@ struct MixLs : virtual Args, MixJSON
|
||||
if (json) {
|
||||
if (showDirectory)
|
||||
throw UsageError("'--directory' is useless with '--json'");
|
||||
logger->cout("%s", listNar(accessor, path, recursive));
|
||||
logger->cout("%s", aio().blockOn(listNar(accessor, path, recursive)));
|
||||
} else
|
||||
listText(accessor);
|
||||
}
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
||||
pathAdditions.push_back(store->printStorePath(path) + "/bin");
|
||||
|
||||
auto propPath = store->printStorePath(path) + "/nix-support/propagated-user-env-packages";
|
||||
if (accessor->stat(propPath).type == FSAccessor::tRegular) {
|
||||
if (aio().blockOn(accessor->stat(propPath)).type == FSAccessor::tRegular) {
|
||||
for (auto & p : tokenizeString<Paths>(readFile(propPath)))
|
||||
todo.push(store->parseStorePath(p));
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||
std::function<void(const Path &)> visitPath;
|
||||
|
||||
visitPath = [&](const Path & p) {
|
||||
auto st = accessor->stat(p);
|
||||
auto st = aio().blockOn(accessor->stat(p));
|
||||
|
||||
auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1);
|
||||
|
||||
@@ -222,13 +222,13 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||
};
|
||||
|
||||
if (st.type == FSAccessor::Type::tDirectory) {
|
||||
auto names = accessor->readDirectory(p);
|
||||
auto names = aio().blockOn(accessor->readDirectory(p));
|
||||
for (auto & name : names)
|
||||
visitPath(p + "/" + name);
|
||||
}
|
||||
|
||||
else if (st.type == FSAccessor::Type::tRegular) {
|
||||
auto contents = accessor->readFile(p);
|
||||
auto contents = aio().blockOn(accessor->readFile(p));
|
||||
|
||||
for (auto & hash : hashes) {
|
||||
auto pos = contents.find(hash);
|
||||
@@ -246,7 +246,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||
}
|
||||
|
||||
else if (st.type == FSAccessor::Type::tSymlink) {
|
||||
auto target = accessor->readLink(p);
|
||||
auto target = aio().blockOn(accessor->readLink(p));
|
||||
|
||||
for (auto & hash : hashes) {
|
||||
auto pos = target.find(hash);
|
||||
|
||||
Reference in New Issue
Block a user