mirror of
https://github.com/NixOS/nix
synced 2025-06-25 19:01:16 +02:00
Remove FSAccessor::Type::tMissing
Instead stat() now returns std::nullopt to denote that the file doesn't exist.
This commit is contained in:
parent
e3febfcd53
commit
b2ac6fc040
10 changed files with 77 additions and 74 deletions
|
@ -208,7 +208,7 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
||||||
|
|
||||||
std::string buildIdDir = "/lib/debug/.build-id";
|
std::string buildIdDir = "/lib/debug/.build-id";
|
||||||
|
|
||||||
if (narAccessor->stat(buildIdDir).type == FSAccessor::tDirectory) {
|
if (auto st = narAccessor->stat(buildIdDir); st && st->type == FSAccessor::tDirectory) {
|
||||||
|
|
||||||
ThreadPool threadPool(25);
|
ThreadPool threadPool(25);
|
||||||
|
|
||||||
|
@ -234,14 +234,14 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
||||||
for (auto & s1 : narAccessor->readDirectory(buildIdDir)) {
|
for (auto & s1 : narAccessor->readDirectory(buildIdDir)) {
|
||||||
auto dir = buildIdDir + "/" + s1;
|
auto dir = buildIdDir + "/" + s1;
|
||||||
|
|
||||||
if (narAccessor->stat(dir).type != FSAccessor::tDirectory
|
if (auto st = narAccessor->stat(dir); !st || st->type != FSAccessor::tDirectory
|
||||||
|| !std::regex_match(s1, regex1))
|
|| !std::regex_match(s1, regex1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (auto & s2 : narAccessor->readDirectory(dir)) {
|
for (auto & s2 : narAccessor->readDirectory(dir)) {
|
||||||
auto debugPath = dir + "/" + s2;
|
auto debugPath = dir + "/" + s2;
|
||||||
|
|
||||||
if (narAccessor->stat(debugPath).type != FSAccessor::tRegular
|
if (auto st = narAccessor->stat(debugPath); !st || st->type != FSAccessor::tRegular
|
||||||
|| !std::regex_match(s2, regex2))
|
|| !std::regex_match(s2, regex2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,28 +14,29 @@ namespace nix {
|
||||||
class FSAccessor
|
class FSAccessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type { tMissing, tRegular, tSymlink, tDirectory };
|
enum Type { tRegular, tSymlink, tDirectory };
|
||||||
|
|
||||||
struct Stat
|
struct Stat
|
||||||
{
|
{
|
||||||
Type type = tMissing;
|
Type type;
|
||||||
/**
|
/**
|
||||||
* regular files only
|
* For regular files only: the size of the file.
|
||||||
*/
|
*/
|
||||||
uint64_t fileSize = 0;
|
uint64_t fileSize = 0;
|
||||||
/**
|
/**
|
||||||
* regular files only
|
* For regular files only: whether this is an executable.
|
||||||
*/
|
*/
|
||||||
bool isExecutable = false; // regular files only
|
bool isExecutable = false;
|
||||||
/**
|
/**
|
||||||
* regular files only
|
* For regular files only: the position of the contents of this
|
||||||
|
* file in the NAR.
|
||||||
*/
|
*/
|
||||||
uint64_t narOffset = 0; // regular files only
|
uint64_t narOffset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~FSAccessor() { }
|
virtual ~FSAccessor() { }
|
||||||
|
|
||||||
virtual Stat stat(const Path & path) = 0;
|
virtual std::optional<Stat> stat(const Path & path) = 0;
|
||||||
|
|
||||||
virtual StringSet readDirectory(const Path & path) = 0;
|
virtual StringSet readDirectory(const Path & path) = 0;
|
||||||
|
|
||||||
|
|
|
@ -27,25 +27,25 @@ struct LocalStoreAccessor : public FSAccessor
|
||||||
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
FSAccessor::Stat stat(const Path & path) override
|
std::optional<FSAccessor::Stat> stat(const Path & path) override
|
||||||
{
|
{
|
||||||
auto realPath = toRealPath(path);
|
auto realPath = toRealPath(path);
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(realPath.c_str(), &st)) {
|
if (lstat(realPath.c_str(), &st)) {
|
||||||
if (errno == ENOENT || errno == ENOTDIR) return {Type::tMissing, 0, false};
|
if (errno == ENOENT || errno == ENOTDIR) return std::nullopt;
|
||||||
throw SysError("getting status of '%1%'", path);
|
throw SysError("getting status of '%1%'", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
|
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
|
||||||
throw Error("file '%1%' has unsupported type", path);
|
throw Error("file '%1%' has unsupported type", path);
|
||||||
|
|
||||||
return {
|
return {{
|
||||||
S_ISREG(st.st_mode) ? Type::tRegular :
|
S_ISREG(st.st_mode) ? Type::tRegular :
|
||||||
S_ISLNK(st.st_mode) ? Type::tSymlink :
|
S_ISLNK(st.st_mode) ? Type::tSymlink :
|
||||||
Type::tDirectory,
|
Type::tDirectory,
|
||||||
S_ISREG(st.st_mode) ? (uint64_t) st.st_size : 0,
|
S_ISREG(st.st_mode) ? (uint64_t) st.st_size : 0,
|
||||||
S_ISREG(st.st_mode) && st.st_mode & S_IXUSR};
|
S_ISREG(st.st_mode) && st.st_mode & S_IXUSR}};
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSet readDirectory(const Path & path) override
|
StringSet readDirectory(const Path & path) override
|
||||||
|
|
|
@ -11,13 +11,7 @@ namespace nix {
|
||||||
|
|
||||||
struct NarMember
|
struct NarMember
|
||||||
{
|
{
|
||||||
FSAccessor::Type type = FSAccessor::Type::tMissing;
|
FSAccessor::Stat stat;
|
||||||
|
|
||||||
bool isExecutable = false;
|
|
||||||
|
|
||||||
/* If this is a regular file, position of the contents of this
|
|
||||||
file in the NAR. */
|
|
||||||
uint64_t start = 0, size = 0;
|
|
||||||
|
|
||||||
std::string target;
|
std::string target;
|
||||||
|
|
||||||
|
@ -57,7 +51,7 @@ struct NarAccessor : public FSAccessor
|
||||||
acc.root = std::move(member);
|
acc.root = std::move(member);
|
||||||
parents.push(&acc.root);
|
parents.push(&acc.root);
|
||||||
} else {
|
} else {
|
||||||
if (parents.top()->type != FSAccessor::Type::tDirectory)
|
if (parents.top()->stat.type != FSAccessor::Type::tDirectory)
|
||||||
throw Error("NAR file missing parent directory of path '%s'", path);
|
throw Error("NAR file missing parent directory of path '%s'", path);
|
||||||
auto result = parents.top()->children.emplace(baseNameOf(path), std::move(member));
|
auto result = parents.top()->children.emplace(baseNameOf(path), std::move(member));
|
||||||
parents.push(&result.first->second);
|
parents.push(&result.first->second);
|
||||||
|
@ -79,14 +73,15 @@ struct NarAccessor : public FSAccessor
|
||||||
|
|
||||||
void isExecutable() override
|
void isExecutable() override
|
||||||
{
|
{
|
||||||
parents.top()->isExecutable = true;
|
parents.top()->stat.isExecutable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void preallocateContents(uint64_t size) override
|
void preallocateContents(uint64_t size) override
|
||||||
{
|
{
|
||||||
assert(size <= std::numeric_limits<uint64_t>::max());
|
assert(size <= std::numeric_limits<uint64_t>::max());
|
||||||
parents.top()->size = (uint64_t) size;
|
auto & st = parents.top()->stat;
|
||||||
parents.top()->start = pos;
|
st.fileSize = (uint64_t) size;
|
||||||
|
st.narOffset = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void receiveContents(std::string_view data) override
|
void receiveContents(std::string_view data) override
|
||||||
|
@ -95,7 +90,9 @@ struct NarAccessor : public FSAccessor
|
||||||
void createSymlink(const Path & path, const std::string & target) override
|
void createSymlink(const Path & path, const std::string & target) override
|
||||||
{
|
{
|
||||||
createMember(path,
|
createMember(path,
|
||||||
NarMember{FSAccessor::Type::tSymlink, false, 0, 0, target});
|
NarMember{
|
||||||
|
.stat = {.type = FSAccessor::Type::tSymlink},
|
||||||
|
.target = target});
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t read(char * data, size_t len) override
|
size_t read(char * data, size_t len) override
|
||||||
|
@ -130,18 +127,20 @@ struct NarAccessor : public FSAccessor
|
||||||
std::string type = v["type"];
|
std::string type = v["type"];
|
||||||
|
|
||||||
if (type == "directory") {
|
if (type == "directory") {
|
||||||
member.type = FSAccessor::Type::tDirectory;
|
member.stat = {.type = FSAccessor::Type::tDirectory};
|
||||||
for (auto i = v["entries"].begin(); i != v["entries"].end(); ++i) {
|
for (auto i = v["entries"].begin(); i != v["entries"].end(); ++i) {
|
||||||
std::string name = i.key();
|
std::string name = i.key();
|
||||||
recurse(member.children[name], i.value());
|
recurse(member.children[name], i.value());
|
||||||
}
|
}
|
||||||
} else if (type == "regular") {
|
} else if (type == "regular") {
|
||||||
member.type = FSAccessor::Type::tRegular;
|
member.stat = {
|
||||||
member.size = v["size"];
|
.type = FSAccessor::Type::tRegular,
|
||||||
member.isExecutable = v.value("executable", false);
|
.fileSize = v["size"],
|
||||||
member.start = v["narOffset"];
|
.isExecutable = v.value("executable", false),
|
||||||
|
.narOffset = v["narOffset"]
|
||||||
|
};
|
||||||
} else if (type == "symlink") {
|
} else if (type == "symlink") {
|
||||||
member.type = FSAccessor::Type::tSymlink;
|
member.stat = {.type = FSAccessor::Type::tSymlink};
|
||||||
member.target = v.value("target", "");
|
member.target = v.value("target", "");
|
||||||
} else return;
|
} else return;
|
||||||
};
|
};
|
||||||
|
@ -158,7 +157,7 @@ struct NarAccessor : public FSAccessor
|
||||||
for (auto it = path.begin(); it != end; ) {
|
for (auto it = path.begin(); it != end; ) {
|
||||||
// because it != end, the remaining component is non-empty so we need
|
// because it != end, the remaining component is non-empty so we need
|
||||||
// a directory
|
// a directory
|
||||||
if (current->type != FSAccessor::Type::tDirectory) return nullptr;
|
if (current->stat.type != FSAccessor::Type::tDirectory) return nullptr;
|
||||||
|
|
||||||
// skip slash (canonPath above ensures that this is always a slash)
|
// skip slash (canonPath above ensures that this is always a slash)
|
||||||
assert(*it == '/');
|
assert(*it == '/');
|
||||||
|
@ -183,19 +182,19 @@ struct NarAccessor : public FSAccessor
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stat stat(const Path & path) override
|
std::optional<Stat> stat(const Path & path) override
|
||||||
{
|
{
|
||||||
auto i = find(path);
|
auto i = find(path);
|
||||||
if (i == nullptr)
|
if (i == nullptr)
|
||||||
return {FSAccessor::Type::tMissing, 0, false};
|
return std::nullopt;
|
||||||
return {i->type, i->size, i->isExecutable, i->start};
|
return i->stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSet readDirectory(const Path & path) override
|
StringSet readDirectory(const Path & path) override
|
||||||
{
|
{
|
||||||
auto i = get(path);
|
auto i = get(path);
|
||||||
|
|
||||||
if (i.type != FSAccessor::Type::tDirectory)
|
if (i.stat.type != FSAccessor::Type::tDirectory)
|
||||||
throw Error("path '%1%' inside NAR file is not a directory", path);
|
throw Error("path '%1%' inside NAR file is not a directory", path);
|
||||||
|
|
||||||
StringSet res;
|
StringSet res;
|
||||||
|
@ -208,19 +207,19 @@ struct NarAccessor : public FSAccessor
|
||||||
std::string readFile(const Path & path, bool requireValidPath = true) 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.stat.type != FSAccessor::Type::tRegular)
|
||||||
throw Error("path '%1%' inside NAR file is not a regular file", path);
|
throw Error("path '%1%' inside NAR file is not a regular file", path);
|
||||||
|
|
||||||
if (getNarBytes) return getNarBytes(i.start, i.size);
|
if (getNarBytes) return getNarBytes(i.stat.narOffset, i.stat.fileSize);
|
||||||
|
|
||||||
assert(nar);
|
assert(nar);
|
||||||
return std::string(*nar, i.start, i.size);
|
return std::string(*nar, i.stat.narOffset, i.stat.fileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string readLink(const Path & path) override
|
std::string readLink(const Path & path) override
|
||||||
{
|
{
|
||||||
auto i = get(path);
|
auto i = get(path);
|
||||||
if (i.type != FSAccessor::Type::tSymlink)
|
if (i.stat.type != FSAccessor::Type::tSymlink)
|
||||||
throw Error("path '%1%' inside NAR file is not a symlink", path);
|
throw Error("path '%1%' inside NAR file is not a symlink", path);
|
||||||
return i.target;
|
return i.target;
|
||||||
}
|
}
|
||||||
|
@ -246,17 +245,19 @@ using nlohmann::json;
|
||||||
json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||||
{
|
{
|
||||||
auto st = accessor->stat(path);
|
auto st = accessor->stat(path);
|
||||||
|
if (!st)
|
||||||
|
throw Error("path '%s' does not exist in NAR", path);
|
||||||
|
|
||||||
json obj = json::object();
|
json obj = json::object();
|
||||||
|
|
||||||
switch (st.type) {
|
switch (st->type) {
|
||||||
case FSAccessor::Type::tRegular:
|
case FSAccessor::Type::tRegular:
|
||||||
obj["type"] = "regular";
|
obj["type"] = "regular";
|
||||||
obj["size"] = st.fileSize;
|
obj["size"] = st->fileSize;
|
||||||
if (st.isExecutable)
|
if (st->isExecutable)
|
||||||
obj["executable"] = true;
|
obj["executable"] = true;
|
||||||
if (st.narOffset)
|
if (st->narOffset)
|
||||||
obj["narOffset"] = st.narOffset;
|
obj["narOffset"] = st->narOffset;
|
||||||
break;
|
break;
|
||||||
case FSAccessor::Type::tDirectory:
|
case FSAccessor::Type::tDirectory:
|
||||||
obj["type"] = "directory";
|
obj["type"] = "directory";
|
||||||
|
@ -275,9 +276,6 @@ json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||||
obj["type"] = "symlink";
|
obj["type"] = "symlink";
|
||||||
obj["target"] = accessor->readLink(path);
|
obj["target"] = accessor->readLink(path);
|
||||||
break;
|
break;
|
||||||
case FSAccessor::Type::tMissing:
|
|
||||||
default:
|
|
||||||
throw Error("path '%s' does not exist in NAR", path);
|
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_, boo
|
||||||
return {addToCache(storePath.hashPart(), std::move(sink.s)), restPath};
|
return {addToCache(storePath.hashPart(), std::move(sink.s)), restPath};
|
||||||
}
|
}
|
||||||
|
|
||||||
FSAccessor::Stat RemoteFSAccessor::stat(const Path & path)
|
std::optional<FSAccessor::Stat> RemoteFSAccessor::stat(const Path & path)
|
||||||
{
|
{
|
||||||
auto res = fetch(path);
|
auto res = fetch(path);
|
||||||
return res.first->stat(res.second);
|
return res.first->stat(res.second);
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
RemoteFSAccessor(ref<Store> store,
|
RemoteFSAccessor(ref<Store> store,
|
||||||
const /* FIXME: use std::optional */ Path & cacheDir = "");
|
const /* FIXME: use std::optional */ Path & cacheDir = "");
|
||||||
|
|
||||||
Stat stat(const Path & path) override;
|
std::optional<Stat> stat(const Path & path) override;
|
||||||
|
|
||||||
StringSet readDirectory(const Path & path) override;
|
StringSet readDirectory(const Path & path) override;
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,12 @@ struct MixCat : virtual Args
|
||||||
|
|
||||||
void cat(ref<FSAccessor> accessor)
|
void cat(ref<FSAccessor> accessor)
|
||||||
{
|
{
|
||||||
auto st = accessor->stat(path);
|
if (auto st = accessor->stat(path)) {
|
||||||
if (st.type == FSAccessor::Type::tMissing)
|
if (st->type != FSAccessor::Type::tRegular)
|
||||||
|
throw Error("path '%1%' is not a regular file", path);
|
||||||
|
writeFull(STDOUT_FILENO, accessor->readFile(path));
|
||||||
|
} else
|
||||||
throw Error("path '%1%' does not exist", path);
|
throw Error("path '%1%' does not exist", path);
|
||||||
if (st.type != FSAccessor::Type::tRegular)
|
|
||||||
throw Error("path '%1%' is not a regular file", path);
|
|
||||||
|
|
||||||
writeFull(STDOUT_FILENO, accessor->readFile(path));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,23 +46,25 @@ struct MixLs : virtual Args, MixJSON
|
||||||
auto showFile = [&](const Path & curPath, const std::string & relPath) {
|
auto showFile = [&](const Path & curPath, const std::string & relPath) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
auto st = accessor->stat(curPath);
|
auto st = accessor->stat(curPath);
|
||||||
|
assert(st);
|
||||||
std::string tp =
|
std::string tp =
|
||||||
st.type == FSAccessor::Type::tRegular ?
|
st->type == FSAccessor::Type::tRegular ?
|
||||||
(st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") :
|
(st->isExecutable ? "-r-xr-xr-x" : "-r--r--r--") :
|
||||||
st.type == FSAccessor::Type::tSymlink ? "lrwxrwxrwx" :
|
st->type == FSAccessor::Type::tSymlink ? "lrwxrwxrwx" :
|
||||||
"dr-xr-xr-x";
|
"dr-xr-xr-x";
|
||||||
auto line = fmt("%s %20d %s", tp, st.fileSize, relPath);
|
auto line = fmt("%s %20d %s", tp, st->fileSize, relPath);
|
||||||
if (st.type == FSAccessor::Type::tSymlink)
|
if (st->type == FSAccessor::Type::tSymlink)
|
||||||
line += " -> " + accessor->readLink(curPath);
|
line += " -> " + accessor->readLink(curPath);
|
||||||
logger->cout(line);
|
logger->cout(line);
|
||||||
if (recursive && st.type == FSAccessor::Type::tDirectory)
|
if (recursive && st->type == FSAccessor::Type::tDirectory)
|
||||||
doPath(st, curPath, relPath, false);
|
doPath(*st, curPath, relPath, false);
|
||||||
} else {
|
} else {
|
||||||
logger->cout(relPath);
|
logger->cout(relPath);
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
auto st = accessor->stat(curPath);
|
auto st = accessor->stat(curPath);
|
||||||
if (st.type == FSAccessor::Type::tDirectory)
|
assert(st);
|
||||||
doPath(st, curPath, relPath, false);
|
if (st->type == FSAccessor::Type::tDirectory)
|
||||||
|
doPath(*st, curPath, relPath, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -79,10 +81,10 @@ struct MixLs : virtual Args, MixJSON
|
||||||
};
|
};
|
||||||
|
|
||||||
auto st = accessor->stat(path);
|
auto st = accessor->stat(path);
|
||||||
if (st.type == FSAccessor::Type::tMissing)
|
if (!st)
|
||||||
throw Error("path '%1%' does not exist", path);
|
throw Error("path '%1%' does not exist", path);
|
||||||
doPath(st, path,
|
doPath(*st, path,
|
||||||
st.type == FSAccessor::Type::tDirectory ? "." : std::string(baseNameOf(path)),
|
st->type == FSAccessor::Type::tDirectory ? "." : std::string(baseNameOf(path)),
|
||||||
showDirectory);
|
showDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
|
||||||
unixPath.push_front(store->printStorePath(path) + "/bin");
|
unixPath.push_front(store->printStorePath(path) + "/bin");
|
||||||
|
|
||||||
auto propPath = store->printStorePath(path) + "/nix-support/propagated-user-env-packages";
|
auto propPath = store->printStorePath(path) + "/nix-support/propagated-user-env-packages";
|
||||||
if (accessor->stat(propPath).type == FSAccessor::tRegular) {
|
if (auto st = accessor->stat(propPath); st && st->type == FSAccessor::tRegular) {
|
||||||
for (auto & p : tokenizeString<Paths>(readFile(propPath)))
|
for (auto & p : tokenizeString<Paths>(readFile(propPath)))
|
||||||
todo.push(store->parseStorePath(p));
|
todo.push(store->parseStorePath(p));
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
|
|
||||||
visitPath = [&](const Path & p) {
|
visitPath = [&](const Path & p) {
|
||||||
auto st = accessor->stat(p);
|
auto st = accessor->stat(p);
|
||||||
|
assert(st);
|
||||||
|
|
||||||
auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1);
|
auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1);
|
||||||
|
|
||||||
|
@ -221,13 +222,13 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
|
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (st.type == FSAccessor::Type::tDirectory) {
|
if (st->type == FSAccessor::Type::tDirectory) {
|
||||||
auto names = accessor->readDirectory(p);
|
auto names = accessor->readDirectory(p);
|
||||||
for (auto & name : names)
|
for (auto & name : names)
|
||||||
visitPath(p + "/" + name);
|
visitPath(p + "/" + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (st.type == FSAccessor::Type::tRegular) {
|
else if (st->type == FSAccessor::Type::tRegular) {
|
||||||
auto contents = accessor->readFile(p);
|
auto contents = accessor->readFile(p);
|
||||||
|
|
||||||
for (auto & hash : hashes) {
|
for (auto & hash : hashes) {
|
||||||
|
@ -245,7 +246,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (st.type == FSAccessor::Type::tSymlink) {
|
else if (st->type == FSAccessor::Type::tSymlink) {
|
||||||
auto target = accessor->readLink(p);
|
auto target = accessor->readLink(p);
|
||||||
|
|
||||||
for (auto & hash : hashes) {
|
for (auto & hash : hashes) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue