Skip to content

Commit 6129aee

Browse files
committed
refactor(nix/why-depends): use scanForReferencesDeep for --precise mode
Replaces manual tree-walking and reference scanning with the new scanForReferencesDeep function.
1 parent 5e22027 commit 6129aee

File tree

1 file changed

+38
-45
lines changed

1 file changed

+38
-45
lines changed

src/nix/why-depends.cc

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "nix/cmd/command.hh"
22
#include "nix/store/store-api.hh"
3+
#include "nix/store/path-references.hh"
34
#include "nix/util/source-accessor.hh"
45
#include "nix/main/shared.hh"
56

@@ -191,7 +192,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
191192
/* Sort the references by distance to `dependency` to
192193
ensure that the shortest path is printed first. */
193194
std::multimap<size_t, Node *> refs;
194-
StringSet hashes;
195+
StorePathSet refPaths;
195196

196197
for (auto & ref : node.refs) {
197198
if (ref == node.path && packagePath != dependencyPath)
@@ -200,7 +201,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
200201
if (node2.dist == inf)
201202
continue;
202203
refs.emplace(node2.dist, &node2);
203-
hashes.insert(std::string(node2.path.hashPart()));
204+
refPaths.insert(node2.path);
204205
}
205206

206207
/* For each reference, find the files and symlinks that
@@ -209,58 +210,50 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
209210

210211
auto accessor = store->requireStoreObjectAccessor(node.path);
211212

212-
auto visitPath = [&](this auto && recur, const CanonPath & p) -> void {
213-
auto st = accessor->maybeLstat(p);
214-
assert(st);
215-
216-
auto p2 = p.isRoot() ? p.abs() : p.rel();
217-
218-
auto getColour = [&](const std::string & hash) {
219-
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
220-
};
221-
222-
if (st->type == SourceAccessor::Type::tDirectory) {
223-
auto names = accessor->readDirectory(p);
224-
for (auto & [name, type] : names)
225-
recur(p / name);
226-
}
227-
228-
else if (st->type == SourceAccessor::Type::tRegular) {
229-
auto contents = accessor->readFile(p);
213+
auto getColour = [&](const std::string & hash) {
214+
return hash == dependencyPathHash ? ANSI_GREEN : ANSI_BLUE;
215+
};
230216

231-
for (auto & hash : hashes) {
232-
auto pos = contents.find(hash);
233-
if (pos != std::string::npos) {
234-
size_t margin = 32;
235-
auto pos2 = pos >= margin ? pos - margin : 0;
236-
hits[hash].emplace_back(
237-
fmt("%s: …%s…",
217+
if (precise) {
218+
// Use scanForReferencesDeep to find files containing references
219+
scanForReferencesDeep(*accessor, CanonPath::root, refPaths, [&](FileRefScanResult result) {
220+
auto p2 = result.filePath.isRoot() ? result.filePath.abs() : result.filePath.rel();
221+
auto st = accessor->lstat(result.filePath);
222+
223+
if (st.type == SourceAccessor::Type::tRegular) {
224+
auto contents = accessor->readFile(result.filePath);
225+
226+
// For each reference found in this file, extract context
227+
for (auto & foundRef : result.foundRefs) {
228+
std::string hash(foundRef.hashPart());
229+
auto pos = contents.find(hash);
230+
if (pos != std::string::npos) {
231+
size_t margin = 32;
232+
auto pos2 = pos >= margin ? pos - margin : 0;
233+
hits[hash].emplace_back(fmt(
234+
"%s: …%s…",
238235
p2,
239236
hilite(
240237
filterPrintable(std::string(contents, pos2, pos - pos2 + hash.size() + margin)),
241238
pos - pos2,
242239
StorePath::HashLen,
243240
getColour(hash))));
241+
}
242+
}
243+
} else if (st.type == SourceAccessor::Type::tSymlink) {
244+
auto target = accessor->readLink(result.filePath);
245+
246+
// For each reference found in this symlink, show it
247+
for (auto & foundRef : result.foundRefs) {
248+
std::string hash(foundRef.hashPart());
249+
auto pos = target.find(hash);
250+
if (pos != std::string::npos)
251+
hits[hash].emplace_back(
252+
fmt("%s -> %s", p2, hilite(target, pos, StorePath::HashLen, getColour(hash))));
244253
}
245254
}
246-
}
247-
248-
else if (st->type == SourceAccessor::Type::tSymlink) {
249-
auto target = accessor->readLink(p);
250-
251-
for (auto & hash : hashes) {
252-
auto pos = target.find(hash);
253-
if (pos != std::string::npos)
254-
hits[hash].emplace_back(
255-
fmt("%s -> %s", p2, hilite(target, pos, StorePath::HashLen, getColour(hash))));
256-
}
257-
}
258-
};
259-
260-
// FIXME: should use scanForReferences().
261-
262-
if (precise)
263-
visitPath(CanonPath::root);
255+
});
256+
}
264257

265258
for (auto & ref : refs) {
266259
std::string hash(ref.second->path.hashPart());

0 commit comments

Comments
 (0)