From 10caceef96242833c3028c19e874b9fbab2d1060 Mon Sep 17 00:00:00 2001 From: Sepehr Ganji Date: Mon, 17 Nov 2025 20:17:34 -0700 Subject: [PATCH 1/2] test(package): demonstrate target dir not excluded from backups Add a test that documents the current behavior where `cargo package` creates the target/package directory without excluding it from backups. The CACHEDIR.TAG file does not currently exist in the target directory, causing backup tools to include these temporary build artifacts. This test currently passes by asserting the buggy behavior (CACHEDIR.TAG does not exist). The next commit will fix the issue and update the test to verify correct behavior. --- tests/testsuite/package.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 4b149928d05..b9f5c65d8e0 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -7807,3 +7807,33 @@ fn publish_to_alt_registry_warns() { "#]]) .run(); } + +#[cargo_test] +fn package_dir_not_excluded_from_backups() { + // This test documents the current behavior where target directory is NOT excluded from backups. + // After the fix, this test will be updated to verify that CACHEDIR.TAG exists. + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("package --allow-dirty") + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository + | + = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Currently, CACHEDIR.TAG does NOT exist in target directory + let cachedir_tag = p.root().join("target/CACHEDIR.TAG"); + assert!( + !cachedir_tag.exists(), + "CACHEDIR.TAG should not exist (documenting current buggy behavior)" + ); +} From d77851d7e5d02c79520eb11bf3500cc72e9fcd0f Mon Sep 17 00:00:00 2001 From: Sepehr Ganji Date: Mon, 17 Nov 2025 20:18:02 -0700 Subject: [PATCH 2/2] fix(package): exclude target dir from backups Ensure that the target directory is excluded from backups when running `cargo package` by creating a CACHEDIR.TAG file. According to the CACHEDIR.TAG specification, a tag file in a parent directory excludes all subdirectories, so tagging the target directory protects the entire tree including the package/ subdirectory and all build artifacts. This prevents temporary packaging artifacts from being included in Time Machine and other backup systems that respect CACHEDIR.TAG. The fix applies to both build_dir (which typically equals target_dir) during package creation, and to target_dir when uplifting artifacts in workspaces where they differ. Updates the test from the previous commit to verify that target/CACHEDIR.TAG now exists after running `cargo package`. Fixes #16238 --- src/cargo/ops/cargo_package/mod.rs | 5 ++++- tests/testsuite/package.rs | 9 ++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cargo/ops/cargo_package/mod.rs b/src/cargo/ops/cargo_package/mod.rs index 92282751f81..1c096816b55 100644 --- a/src/cargo/ops/cargo_package/mod.rs +++ b/src/cargo/ops/cargo_package/mod.rs @@ -161,7 +161,9 @@ fn create_package( } let filename = pkg.package_id().tarball_name(); - let dir = ws.build_dir().join("package"); + let build_dir = ws.build_dir(); + paths::create_dir_all_excluded_from_backups_atomic(build_dir.as_path_unlocked())?; + let dir = build_dir.join("package"); let mut dst = { let tmp = format!(".{}", filename); dir.open_rw_exclusive_create(&tmp, gctx, "package scratch space")? @@ -225,6 +227,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult