fix(hardlink): content freshness moved switches, it was not withdrawn
CI / shellcheck + selftests (pull_request) Successful in 1m17s
CI / shellcheck + selftests (pull_request) Successful in 1m17s
`unshare_mutable_paths`' comment recorded that upstream had stopped rewriting `dep-<target>` in place, on a measurement taken against 1.100.0-nightly. It had not. Two unrelated cargo changes landed within four days of each other and between them moved the switch that turns the behaviour on and the path it writes to: - cargo PR #17382 (2026-08-22) demoted `-Z checksum-freshness` to a gate and gave `build.fingerprint` the choice, defaulting to `mtime`. Setting only the gate is accepted and does nothing, which is exactly the result that was read as a withdrawal. - build-dir layout v2 (cargo PR #17354, stable 1.100.0 on 2026-11-12, nightly default since 1.99) moved the file from `.fingerprint/<unit>/dep-*` to `build/<pkg>/<hash>/fingerprint/dep-*`. Measured 2026-08-26 on 1.100.0-nightly (e8cb624d5): same toolchain, same clone procedure, one env var apart — with the gate alone a `cp -al` clone mutates only the build/ and *.d families; add `CARGO_BUILD_FINGERPRINT=content` and the source's dep-info file is mutated through the shared inode again. The hazard is intact. So the suite now exports both switches, and its strongest scenario runs again on current nightlies — verified passing against both layouts. Its control note learned the v2 path too: it looked for the v1 path only, and so printed "does NOT rewrite ... in place" three lines beneath a listing that showed the rewrite. Every claim these comments make is now dated and cited, because the defect being fixed is a comment that cited one measurement and silently stopped reproducing. Layout v2 also drags the artifacts under `build/`, which collapses this function's real-copy set from 21.3% of a target dir to 99.998%. That is a live cost, not a correctness problem, and it is filed as gitdan-actions#14 rather than fixed here. Part of daniel/gitdan#62.
This commit is contained in:
+65
-19
@@ -329,21 +329,18 @@ _unshare_files() {
|
||||
# the source) the following files in the SOURCE were mutated through the
|
||||
# shared inode:
|
||||
#
|
||||
# <profile>/.fingerprint/<unit>/dep-<target> (only under
|
||||
# CARGO_UNSTABLE_CHECKSUM_FRESHNESS,
|
||||
# where this file carries the
|
||||
# per-source blake3 checksums.
|
||||
# NOT reproduced on
|
||||
# 1.100.0-nightly (2026-08-25),
|
||||
# measured by this repo's own CI
|
||||
# — upstream appears to have
|
||||
# stopped writing it in place.
|
||||
# Kept in the unshared set
|
||||
# anyway: it costs 22 MB of a
|
||||
# 6.9 GB tree, and the failure
|
||||
# it guards is a wrong answer,
|
||||
# not a slow one.)
|
||||
# <profile>/build/<pkg>/output, root-output (Cargo build-script metadata)
|
||||
# <profile>/.fingerprint/<unit>/dep-<target> (build-dir layout v1) — or,
|
||||
# <profile>/build/<pkg>/<hash>/fingerprint/dep-<target>
|
||||
# (build-dir layout v2; see the
|
||||
# dated note below for which
|
||||
# Cargo writes which). Only
|
||||
# when Cargo resolves freshness
|
||||
# by CONTENT, where this file
|
||||
# carries the per-source blake3
|
||||
# checksums.
|
||||
# <profile>/build/<pkg>/output, root-output (Cargo build-script metadata;
|
||||
# `<pkg>/<hash>/run/root-output`
|
||||
# under layout v2)
|
||||
# <profile>/build/<pkg>/out/** (whatever the build script
|
||||
# writes into OUT_DIR — build
|
||||
# scripts overwhelmingly use a
|
||||
@@ -359,10 +356,59 @@ _unshare_files() {
|
||||
# sources, reports `Fresh`, and reuses a binary built from the PRE-merge code.
|
||||
# That is silent stale-artifact reuse — a wrong answer, not a slow one.
|
||||
#
|
||||
# So: hardlink the artifacts (the GB), real-copy the metadata (the MB).
|
||||
# Measured on a 6.9 GB Bevy workspace target dir, the unshared set is
|
||||
# .fingerprint 22 MB + build/ 237 MB + a handful of dep-info files — about
|
||||
# 3.7% of the tree, against 100% for a plain `cp -a`.
|
||||
# WHAT UPSTREAM CHANGED, AND WHAT IT DID NOT (measured 2026-08-26, daniel/gitdan#62).
|
||||
#
|
||||
# An earlier revision of this comment recorded that the dep-info write was
|
||||
# "NOT reproduced on 1.100.0-nightly (2026-08-25) — upstream appears to have
|
||||
# stopped writing it in place". That reading was wrong, and the way it was
|
||||
# wrong is the reason this paragraph is dated. Two unrelated upstream changes
|
||||
# landed within days of each other, and between them they moved both the
|
||||
# switch that turns the behaviour on and the path it writes to:
|
||||
#
|
||||
# 1. The ON-SWITCH MOVED. cargo PR #17382 `feat(config): Add build.fingerprint`
|
||||
# (merged 2026-08-22) demoted `-Z checksum-freshness` to a gate: it now
|
||||
# only UNLOCKS the feature, and `build.fingerprint` SELECTS it, defaulting
|
||||
# to `"mtime"`. So `CARGO_UNSTABLE_CHECKSUM_FRESHNESS=true` on its own is
|
||||
# accepted and does nothing, which is exactly the "flag accepted, mtime
|
||||
# anyway" result that was mistaken for a withdrawal. Content freshness
|
||||
# needs BOTH, and with both it is entirely intact:
|
||||
#
|
||||
# CARGO_UNSTABLE_CHECKSUM_FRESHNESS=true CARGO_BUILD_FINGERPRINT=content
|
||||
#
|
||||
# Measured on cargo 1.100.0-nightly (e8cb624d5 2026-08-22): with the gate
|
||||
# alone a `cp -al` clone mutates only the build/ and *.d families; add
|
||||
# `CARGO_BUILD_FINGERPRINT=content` and the source's dep-info file is
|
||||
# mutated through the shared inode again. Same toolchain, same clone, one
|
||||
# env var apart. The hazard was never removed — it was switched off.
|
||||
#
|
||||
# 2. THE PATH MOVED. Build-dir layout v2 (`-Z build-dir-new-layout`, cargo
|
||||
# 1.91) became the nightly default in cargo 1.99 (PR #17258) and was
|
||||
# stabilised by PR #17354, merged 2026-08-18, shipping in cargo 1.100.0
|
||||
# stable on 2026-11-12. Under v2 there is no `<profile>/.fingerprint` and
|
||||
# no `<profile>/deps` at all: everything is regrouped per build unit under
|
||||
# `<profile>/build/<pkg>/<hash>/{fingerprint,out,run}/`, artifacts
|
||||
# included. Bracketed locally: cargo 1.97.1 and 1.98.0-nightly write v1,
|
||||
# 1.100.0-nightly writes v2.
|
||||
#
|
||||
# The `-name .fingerprint` clause below therefore matches nothing under a v2
|
||||
# Cargo, and the dep-info file is covered only because the `-name build` clause
|
||||
# happens to swallow its new home. That is belt-and-braces by accident, not by
|
||||
# design — and the same accident makes this function real-copy essentially the
|
||||
# whole tree, because the artifacts moved under `build/` too. Measured on one
|
||||
# scratch crate (serde + serde_json + regex), same sources both ways:
|
||||
#
|
||||
# cargo 1.97.1 (layout v1) 27.0 MB unshared of 126.7 MB — 21.3%
|
||||
# 1.100.0-nightly (layout v2) 105.9 MB unshared of 105.9 MB — 99.998%
|
||||
#
|
||||
# So the guard still holds and the saving does not. Deliberately NOT fixed
|
||||
# here: adjusting the selection is a change to what gets hardlinked on every
|
||||
# consumer, which wants its own change and its own review, and the deadline is
|
||||
# cargo 1.100.0 stable on 2026-11-12. Tracked as gitdan-actions#14.
|
||||
#
|
||||
# The historical v1 figure this block used to quote stands as measured: on a
|
||||
# 6.9 GB Bevy workspace target dir the unshared set was .fingerprint 22 MB +
|
||||
# build/ 237 MB + a handful of dep-info files — about 3.7% of the tree, against
|
||||
# 100% for a plain `cp -a`. It describes layout v1 only.
|
||||
#
|
||||
# `incremental/` is deliberately left shared: rustc writes each incremental
|
||||
# session to a fresh `s-*-working` directory and finalises it with a rename,
|
||||
|
||||
Reference in New Issue
Block a user