From 7047298629f07500acb1541d2c8b3d3398041fde Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Thu, 13 Aug 2026 16:50:57 -0400 Subject: [PATCH] A file's mtime is unique, so cargo's freshness record is stable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cargo records a path dependency's freshness as the newest mtime in the package and the name of the file that carried it. Dating files by their last commit gives every file a commit touched the same timestamp, so which one is newest falls to directory order — which differs between clones. The gate rebuilt iroh, iroh-dns, iroh-relay and iroh-peer on every run, reporting PrecalculatedComponentsChanged { old: "1784575660.000000000s (Cargo.toml)", new: "1784575660.000000000s (CHANGELOG.md)" } the same instant, a different file. Each file now takes a sub-second offset derived from its path, so one file is newest and every clone agrees which. The stamping policy joins the build-directory cache key: artifacts are kept or discarded on the strength of the mtimes they were judged against, so a change to how those are assigned invalidates them. --- .github/workflows/ci.yml | 5 +++-- scripts/restore-mtimes.py | 12 +++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 050f3ac..3856d19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,10 +101,11 @@ jobs: .deps/iroh/target # Everything that invalidates artifacts wholesale is in the key: # the toolchain, the profiles, the resolved dependency versions, - # and the gate's cargo invocations. A key that misses still + # the gate's cargo invocations, and the mtime policy the restored + # artifacts were judged fresh against. A key that misses still # restores the newest entry under the prefix, so cargo rebuilds # what changed instead of everything. - key: build-dirs-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml', 'Cargo.lock', '.deps/iroh/Cargo.toml', '.deps/iroh/Cargo.lock', 'justfile', '.github/justfile', '.github/workflows/ci.yml') }} + key: build-dirs-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml', 'Cargo.lock', '.deps/iroh/Cargo.toml', '.deps/iroh/Cargo.lock', 'justfile', '.github/justfile', '.github/workflows/ci.yml', 'scripts/restore-mtimes.py') }} restore-keys: build-dirs- - name: Run the gate diff --git a/scripts/restore-mtimes.py b/scripts/restore-mtimes.py index 09a29a1..089947a 100755 --- a/scripts/restore-mtimes.py +++ b/scripts/restore-mtimes.py @@ -12,12 +12,21 @@ file would hide the modification from cargo and produce a build that does not match the source. +Each file also gets a sub-second offset derived from its path. Cargo records +a path dependency's freshness as the newest mtime in the package *and the name +of the file that carried it*, and a commit that touched several files would +otherwise give them one identical timestamp — leaving the newest file to be +decided by directory order, which differs between clones. The package then +looks changed on a machine that walked its directory differently, and every +crate above it rebuilds. + Usage: restore-mtimes.py [REPO ...] """ import os import subprocess import sys +import zlib def git(repo, *args): @@ -64,8 +73,9 @@ def restore(repo): continue pending.discard(line) path = os.path.join(repo, line) + stamp = timestamp * 10**9 + zlib.crc32(line.encode()) % 10**9 try: - os.utime(path, (timestamp, timestamp)) + os.utime(path, ns=(stamp, stamp)) stamped += 1 except OSError: pass