why-depends: extract visitPath function

First step towards moving this code into libstore to re-use it
elsewhere.

Change-Id: I1daccd984f759b235c4c187d5c7783cb5a35f0b9
This commit is contained in:
Maximilian Bosch
2025-07-07 11:44:17 +00:00
parent 4bc0bdc20b
commit 7b84545ce1
+80 -48
View File
@@ -28,6 +28,74 @@ static std::string filterPrintable(const std::string & s)
return res;
}
static std::map<std::string, Strings> visitPath(
const Path & p,
Store & store,
AsyncIoRoot & aio,
const Path & pathS,
std::string_view & dependencyPathHash,
const std::set<std::string> & hashes,
const StorePath & from,
const StorePath & to
)
{
/* For each reference, find the files and symlinks that
contain the reference. */
std::map<std::string, Strings> hits;
auto accessor = store.getFSAccessor();
auto st = aio.blockOn(accessor->stat(p));
auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1);
auto getColour = [&](const std::string & hash) {
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
};
if (st.type == FSAccessor::Type::tDirectory) {
auto names = aio.blockOn(accessor->readDirectory(p));
for (auto & name : names) {
auto found =
visitPath(p + "/" + name, store, aio, pathS, dependencyPathHash, hashes, from, to);
hits.merge(found);
}
} else if (st.type == FSAccessor::Type::tRegular) {
auto contents = aio.blockOn(accessor->readFile(p));
for (auto & hash : hashes) {
auto pos = contents.find(hash);
if (pos != std::string::npos) {
size_t margin = 32;
auto pos2 = pos >= margin ? pos - margin : 0;
hits[hash].emplace_back(
fmt("%s: …%s…",
p2,
hilite(
filterPrintable(
std::string(contents, pos2, pos - pos2 + hash.size() + margin)
),
pos - pos2,
StorePath::HashLen,
getColour(hash)
))
);
}
}
} else if (st.type == FSAccessor::Type::tSymlink) {
auto target = aio.blockOn(accessor->readLink(p));
for (auto & hash : hashes) {
auto pos = target.find(hash);
if (pos != std::string::npos) {
hits[hash].emplace_back(
fmt("%s -> %s", p2, hilite(target, pos, StorePath::HashLen, getColour(hash)))
);
}
}
}
return hits;
};
struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
{
std::string _package, _dependency;
@@ -212,56 +280,20 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
contain the reference. */
std::map<std::string, Strings> hits;
std::function<void(const Path &)> visitPath;
visitPath = [&](const Path & p) {
auto st = aio().blockOn(accessor->stat(p));
auto p2 = p == pathS ? "/" : std::string(p, pathS.size() + 1);
auto getColour = [&](const std::string & hash) {
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
};
if (st.type == FSAccessor::Type::tDirectory) {
auto names = aio().blockOn(accessor->readDirectory(p));
for (auto & name : names)
visitPath(p + "/" + name);
}
else if (st.type == FSAccessor::Type::tRegular) {
auto contents = aio().blockOn(accessor->readFile(p));
for (auto & hash : hashes) {
auto pos = contents.find(hash);
if (pos != std::string::npos) {
size_t margin = 32;
auto pos2 = pos >= margin ? pos - margin : 0;
hits[hash].emplace_back(fmt("%s: …%s…",
p2,
hilite(filterPrintable(
std::string(contents, pos2, pos - pos2 + hash.size() + margin)),
pos - pos2, StorePath::HashLen,
getColour(hash))));
}
}
}
else if (st.type == FSAccessor::Type::tSymlink) {
auto target = aio().blockOn(accessor->readLink(p));
for (auto & hash : hashes) {
auto pos = target.find(hash);
if (pos != std::string::npos)
hits[hash].emplace_back(fmt("%s -> %s", p2,
hilite(target, pos, StorePath::HashLen, getColour(hash))));
}
}
};
// FIXME: should use scanForReferences().
if (precise) visitPath(pathS);
if (precise) {
hits = visitPath(
pathS,
*store,
aio(),
pathS,
dependencyPathHash,
hashes,
packagePath,
dependencyPath
);
}
for (auto & ref : refs) {
std::string hash(ref.second->path.hashPart());