From 6f40a3e7e47160261f427420741b66f95a17de4a Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 11 Nov 2025 14:10:57 -0500 Subject: [PATCH 1/2] test(package): generated file not have deterministic timestamp We only set deterministic timestamp for actual file we copy cover during `cargo package`ing. Generated files should actually follow. --- tests/testsuite/package.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 6ed4ba3c5b0..7b665db5fb9 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -3162,12 +3162,27 @@ fn reproducible_output() { let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); let decoder = GzDecoder::new(f); let mut archive = Archive::new(decoder); + + // Hardcoded value be removed once alexcrichton/tar-rs#420 is merged and released. + // See also rust-lang/cargo#16237 + const DETERMINISTIC_TIMESTAMP: u64 = 1153704088; for ent in archive.entries().unwrap() { let ent = ent.unwrap(); println!("checking {:?}", ent.path()); let header = ent.header(); assert_eq!(header.mode().unwrap(), 0o644); assert!(header.mtime().unwrap() != 0); + // Generated files do not have deterministic timestamp (yet). + let path = ent.path().unwrap(); + let file_name = path.file_name().unwrap().to_str().unwrap(); + if ["Cargo.toml", "Cargo.lock", ".cargo_vcs_info.json"] + .into_iter() + .any(|f| f == file_name) + { + assert!(header.mtime().unwrap() != DETERMINISTIC_TIMESTAMP); + } else { + assert!(header.mtime().unwrap() == DETERMINISTIC_TIMESTAMP); + } assert_eq!(header.username().unwrap().unwrap(), ""); assert_eq!(header.groupname().unwrap().unwrap(), ""); } From 9e9ac16175c2b69ff844e02a62d45be768e5c0a8 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 11 Nov 2025 14:13:29 -0500 Subject: [PATCH 2/2] fix(package): all tar entries timestamp be the same With this commit, all tar entries' timestamp is the same, all set to DETERMINISTIC_TIMESTAMP in tar-rs. This fixes the first half of rust-lang/cargo#16237 that `cargo package` should tar everything in the same timestamp. --- src/cargo/ops/cargo_package/mod.rs | 8 ++++++-- tests/testsuite/package.rs | 13 +------------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index 73bb0f7570c..0321b5601ad 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -917,8 +917,12 @@ fn tar( header.set_entry_type(EntryType::file()); header.set_mode(0o644); header.set_size(contents.len() as u64); - // use something nonzero to avoid rust-lang/cargo#9512 - header.set_mtime(1); + // We need to have the same DETERMINISTIC_TIMESTAMP for generated files + // https://github.com/alexcrichton/tar-rs/blob/d0261f1f6cc959ba0758e7236b3fd81e90dd1dc6/src/header.rs#L18-L24 + // Unfortunately tar-rs doesn't expose that so we harcode the timestamp here. + // Hardcoded value be removed once alexcrichton/tar-rs#420 is merged and released. + // See also rust-lang/cargo#16237 + header.set_mtime(1153704088); header.set_cksum(); ar.append_data(&mut header, &ar_path, contents.as_bytes()) .with_context(|| format!("could not archive source file `{}`", rel_str))?; diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 7b665db5fb9..3a12d8cf904 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -3171,18 +3171,7 @@ fn reproducible_output() { println!("checking {:?}", ent.path()); let header = ent.header(); assert_eq!(header.mode().unwrap(), 0o644); - assert!(header.mtime().unwrap() != 0); - // Generated files do not have deterministic timestamp (yet). - let path = ent.path().unwrap(); - let file_name = path.file_name().unwrap().to_str().unwrap(); - if ["Cargo.toml", "Cargo.lock", ".cargo_vcs_info.json"] - .into_iter() - .any(|f| f == file_name) - { - assert!(header.mtime().unwrap() != DETERMINISTIC_TIMESTAMP); - } else { - assert!(header.mtime().unwrap() == DETERMINISTIC_TIMESTAMP); - } + assert!(header.mtime().unwrap() == DETERMINISTIC_TIMESTAMP); assert_eq!(header.username().unwrap().unwrap(), ""); assert_eq!(header.groupname().unwrap().unwrap(), ""); }