mirror of
https://github.com/NixOS/nix.git
synced 2025-11-08 19:46:02 +01:00
refactor(nix/why-depends): use scanForReferencesDeep for --precise mode
Replaces manual tree-walking and reference scanning with the new scanForReferencesDeep function.
This commit is contained in:
parent
5e220271e2
commit
6129aee988
1 changed files with 36 additions and 43 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
#include "nix/cmd/command.hh"
|
#include "nix/cmd/command.hh"
|
||||||
#include "nix/store/store-api.hh"
|
#include "nix/store/store-api.hh"
|
||||||
|
#include "nix/store/path-references.hh"
|
||||||
#include "nix/util/source-accessor.hh"
|
#include "nix/util/source-accessor.hh"
|
||||||
#include "nix/main/shared.hh"
|
#include "nix/main/shared.hh"
|
||||||
|
|
||||||
|
|
@ -191,7 +192,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
/* Sort the references by distance to `dependency` to
|
/* Sort the references by distance to `dependency` to
|
||||||
ensure that the shortest path is printed first. */
|
ensure that the shortest path is printed first. */
|
||||||
std::multimap<size_t, Node *> refs;
|
std::multimap<size_t, Node *> refs;
|
||||||
StringSet hashes;
|
StorePathSet refPaths;
|
||||||
|
|
||||||
for (auto & ref : node.refs) {
|
for (auto & ref : node.refs) {
|
||||||
if (ref == node.path && packagePath != dependencyPath)
|
if (ref == node.path && packagePath != dependencyPath)
|
||||||
|
|
@ -200,7 +201,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
if (node2.dist == inf)
|
if (node2.dist == inf)
|
||||||
continue;
|
continue;
|
||||||
refs.emplace(node2.dist, &node2);
|
refs.emplace(node2.dist, &node2);
|
||||||
hashes.insert(std::string(node2.path.hashPart()));
|
refPaths.insert(node2.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For each reference, find the files and symlinks that
|
/* For each reference, find the files and symlinks that
|
||||||
|
|
@ -209,32 +210,28 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
|
|
||||||
auto accessor = store->requireStoreObjectAccessor(node.path);
|
auto accessor = store->requireStoreObjectAccessor(node.path);
|
||||||
|
|
||||||
auto visitPath = [&](this auto && recur, const CanonPath & p) -> void {
|
|
||||||
auto st = accessor->maybeLstat(p);
|
|
||||||
assert(st);
|
|
||||||
|
|
||||||
auto p2 = p.isRoot() ? p.abs() : p.rel();
|
|
||||||
|
|
||||||
auto getColour = [&](const std::string & hash) {
|
auto getColour = [&](const std::string & hash) {
|
||||||
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
|
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (st->type == SourceAccessor::Type::tDirectory) {
|
if (precise) {
|
||||||
auto names = accessor->readDirectory(p);
|
// Use scanForReferencesDeep to find files containing references
|
||||||
for (auto & [name, type] : names)
|
scanForReferencesDeep(*accessor, CanonPath::root, refPaths, [&](FileRefScanResult result) {
|
||||||
recur(p / name);
|
auto p2 = result.filePath.isRoot() ? result.filePath.abs() : result.filePath.rel();
|
||||||
}
|
auto st = accessor->lstat(result.filePath);
|
||||||
|
|
||||||
else if (st->type == SourceAccessor::Type::tRegular) {
|
if (st.type == SourceAccessor::Type::tRegular) {
|
||||||
auto contents = accessor->readFile(p);
|
auto contents = accessor->readFile(result.filePath);
|
||||||
|
|
||||||
for (auto & hash : hashes) {
|
// For each reference found in this file, extract context
|
||||||
|
for (auto & foundRef : result.foundRefs) {
|
||||||
|
std::string hash(foundRef.hashPart());
|
||||||
auto pos = contents.find(hash);
|
auto pos = contents.find(hash);
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
size_t margin = 32;
|
size_t margin = 32;
|
||||||
auto pos2 = pos >= margin ? pos - margin : 0;
|
auto pos2 = pos >= margin ? pos - margin : 0;
|
||||||
hits[hash].emplace_back(
|
hits[hash].emplace_back(fmt(
|
||||||
fmt("%s: …%s…",
|
"%s: …%s…",
|
||||||
p2,
|
p2,
|
||||||
hilite(
|
hilite(
|
||||||
filterPrintable(std::string(contents, pos2, pos - pos2 + hash.size() + margin)),
|
filterPrintable(std::string(contents, pos2, pos - pos2 + hash.size() + margin)),
|
||||||
|
|
@ -243,24 +240,20 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
getColour(hash))));
|
getColour(hash))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (st.type == SourceAccessor::Type::tSymlink) {
|
||||||
|
auto target = accessor->readLink(result.filePath);
|
||||||
|
|
||||||
else if (st->type == SourceAccessor::Type::tSymlink) {
|
// For each reference found in this symlink, show it
|
||||||
auto target = accessor->readLink(p);
|
for (auto & foundRef : result.foundRefs) {
|
||||||
|
std::string hash(foundRef.hashPart());
|
||||||
for (auto & hash : hashes) {
|
|
||||||
auto pos = target.find(hash);
|
auto pos = target.find(hash);
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
hits[hash].emplace_back(
|
hits[hash].emplace_back(
|
||||||
fmt("%s -> %s", p2, hilite(target, pos, StorePath::HashLen, getColour(hash))));
|
fmt("%s -> %s", p2, hilite(target, pos, StorePath::HashLen, getColour(hash))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
}
|
||||||
// FIXME: should use scanForReferences().
|
|
||||||
|
|
||||||
if (precise)
|
|
||||||
visitPath(CanonPath::root);
|
|
||||||
|
|
||||||
for (auto & ref : refs) {
|
for (auto & ref : refs) {
|
||||||
std::string hash(ref.second->path.hashPart());
|
std::string hash(ref.second->path.hashPart());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue