Skip to content

Commit 00847b8

Browse files
committed
fix(tool-store): upstream key 走传递闭包,与注释声称的一致
注释写的是「recursive (Merkle)」,实现只遍历了直接边 —— 注释**多声称了一个它没有 的性质**,这比没有注释更糟。 两个选择:改注释、或让代码兑现。选后者,因为传递闭包确实更对:对索引包来说直接边 够用(冻结的版本改不了自己的依赖),但 **path 依赖可以** —— 往下两层改一处,工具的 直接依赖列表纹丝不动,于是 store 里留下一个陈旧的二进制。那是**静默的错误产物**, 本项目为这一族问题付过不止一次学费,而闭包遍历几乎不要钱。
1 parent 143c612 commit 00847b8

2 files changed

Lines changed: 33 additions & 9 deletions

File tree

src/build/prepare.cppm

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4038,11 +4038,30 @@ prepare_build(bool print_fingerprint,
40384038
key.profile = "release";
40394039
key.features = closure;
40404040
std::ranges::sort(key.features);
4041-
for (auto const& edge : dependencyEdges) {
4042-
if (edge.consumerPackageIndex != depIdx) continue;
4043-
auto const& up = packages[edge.dependencyPackageIndex];
4044-
key.upstreamKeys.push_back(std::format("{}@{}",
4045-
up.manifest.package.name, up.manifest.package.version));
4041+
// The tool package's TRANSITIVE dependency closure, not just
4042+
// its direct edges. Direct-only would be enough for index
4043+
// packages (a frozen version cannot change its own deps),
4044+
// but a path dependency can: bump something two levels down
4045+
// and the tool's direct list is unchanged, so a stale binary
4046+
// stays in the store. That is a silently wrong artifact —
4047+
// the failure mode this project has paid for more than once
4048+
// — and the closure walk costs nothing.
4049+
{
4050+
std::set<std::size_t> seen{depIdx};
4051+
std::vector<std::size_t> queue{depIdx};
4052+
while (!queue.empty()) {
4053+
auto cur = queue.back();
4054+
queue.pop_back();
4055+
for (auto const& edge : dependencyEdges) {
4056+
if (edge.consumerPackageIndex != cur) continue;
4057+
auto up = edge.dependencyPackageIndex;
4058+
if (!seen.insert(up).second) continue;
4059+
queue.push_back(up);
4060+
key.upstreamKeys.push_back(std::format("{}@{}",
4061+
packages[up].manifest.package.name,
4062+
packages[up].manifest.package.version));
4063+
}
4064+
}
40464065
}
40474066
std::ranges::sort(key.upstreamKeys);
40484067

src/build/tool_store.cppm

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,15 @@ struct Key {
8484
std::string compilerIdentity; // the HOST toolchain that will build it
8585
std::string profile;
8686
std::vector<std::string> features; // resolved closure, sorted
87-
// The cache key of each direct dependency of the TOOL package, recursively
88-
// (Merkle). Without it, bumping one of protobuf's own dependencies would
89-
// leave a stale protoc in the store — a silently wrong artifact, which is
90-
// the failure mode this project has paid for more than once.
87+
// The tool package's TRANSITIVE dependency closure, as sorted
88+
// `<name>@<version>` entries. Without it, bumping something the tool
89+
// depends on leaves a stale binary in the store — a silently wrong
90+
// artifact, the failure mode this project has paid for more than once.
91+
//
92+
// Transitive rather than direct-only: for an index package a frozen
93+
// version cannot change its own dependencies, so direct edges would do —
94+
// but a PATH dependency can, and then a change two levels down leaves the
95+
// tool's direct list untouched.
9196
std::vector<std::string> upstreamKeys;
9297
};
9398

0 commit comments

Comments
 (0)