From 4e66f0631849041125703389c4c8dcc9f034614d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 3 Jul 2026 14:00:08 +0000
Subject: [PATCH 1/3] Initial plan
From bc66d76ac389d513acb52596376f4a7b6a05aef1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 3 Jul 2026 14:12:18 +0000
Subject: [PATCH 2/3] Add CACHEDIR.TAG to pack cache directory
---
README.md | 2 +-
src/pack.rs | 32 ++++++++++++++++++++++++++++++++
tests/integration_test.rs | 13 +++++++++++++
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9522ed0..fafc3aa 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ You can cache downloaded packages to speed up subsequent pack operations by usin
pixi-pack --use-cache ~/.pixi-pack/cache
```
-This will store all downloaded packages in the specified directory and reuse them in future pack operations. The cache follows the same structure as conda channels, organizing packages by platform subdirectories (e.g., linux-64, win-64, etc.).
+This will store all downloaded packages in the specified directory and reuse them in future pack operations. The cache follows the same structure as conda channels, organizing packages by platform subdirectories (e.g., linux-64, win-64, etc.). A `CACHEDIR.TAG` file is written to the cache directory so that backup and archiving tools can skip it (see the [cache directory tag specification](https://bford.info/cachedir/)).
Using a cache is particularly useful when:
diff --git a/src/pack.rs b/src/pack.rs
index ca881e3..77df651 100644
--- a/src/pack.rs
+++ b/src/pack.rs
@@ -49,6 +49,32 @@ use anyhow::anyhow;
static DEFAULT_REQWEST_TIMEOUT_SEC: Duration = Duration::from_secs(5 * 60);
+/// Contents of the `CACHEDIR.TAG` file written to the cache directory.
+///
+/// See for the specification. The signature on
+/// the first line marks the directory as a cache so that backup and archiving
+/// tools can skip it.
+const CACHEDIR_TAG_CONTENT: &str = "Signature: 8a477f597d28d172789f06886806bc55\n\
+# This file is a cache directory tag created by pixi-pack.\n\
+# For information about cache directory tags see https://bford.info/cachedir/\n";
+
+/// Write a `CACHEDIR.TAG` file to the given cache directory if it does not
+/// already exist, marking it as a cache directory.
+async fn write_cachedir_tag(cache_dir: &Path) -> Result<()> {
+ create_dir_all(cache_dir)
+ .await
+ .map_err(|e| anyhow!("could not create cache directory: {}", e))?;
+
+ let tag_path = cache_dir.join("CACHEDIR.TAG");
+ if tag_path.exists() {
+ return Ok(());
+ }
+
+ fs::write(&tag_path, CACHEDIR_TAG_CONTENT)
+ .await
+ .map_err(|e| anyhow!("could not write CACHEDIR.TAG file: {}", e))
+}
+
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum OutputMode {
Archive,
@@ -112,6 +138,12 @@ pub async fn pack(options: PackOptions) -> Result<()> {
let client = reqwest_client_from_options(&options)
.map_err(|e| anyhow!("could not create reqwest client from auth storage: {e}"))?;
+ // Mark the cache directory (if any) with a CACHEDIR.TAG file so that backup
+ // and archiving tools can skip it.
+ if let Some(cache_dir) = options.cache_dir.as_deref() {
+ write_cachedir_tag(cache_dir).await?;
+ }
+
let env = lockfile.environment(&options.environment).ok_or(anyhow!(
"environment not found in lockfile: {}",
options.environment
diff --git a/tests/integration_test.rs b/tests/integration_test.rs
index 52409f4..a801d47 100644
--- a/tests/integration_test.rs
+++ b/tests/integration_test.rs
@@ -797,6 +797,19 @@ async fn test_package_caching(
// Both output files should exist and be valid
assert!(options.pack_options.output_file.exists());
assert!(output_file2.exists());
+
+ // A CACHEDIR.TAG file should have been created in the cache directory,
+ // marking it as a cache directory for backup and archiving tools.
+ let cachedir_tag = cache_dir.join("CACHEDIR.TAG");
+ assert!(
+ cachedir_tag.is_file(),
+ "CACHEDIR.TAG should be created in the cache directory"
+ );
+ let tag_contents = fs::read_to_string(&cachedir_tag).unwrap();
+ assert!(
+ tag_contents.starts_with("Signature: 8a477f597d28d172789f06886806bc55"),
+ "CACHEDIR.TAG should start with the standard cache directory tag signature"
+ );
}
#[rstest]
From a69d4cf869c9d934f54e4528fea6ad10acd81e08 Mon Sep 17 00:00:00 2001
From: Daniel Elsner
Date: Fri, 3 Jul 2026 16:57:32 +0200
Subject: [PATCH 3/3] Apply suggestion from @delsner
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index fafc3aa..9522ed0 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ You can cache downloaded packages to speed up subsequent pack operations by usin
pixi-pack --use-cache ~/.pixi-pack/cache
```
-This will store all downloaded packages in the specified directory and reuse them in future pack operations. The cache follows the same structure as conda channels, organizing packages by platform subdirectories (e.g., linux-64, win-64, etc.). A `CACHEDIR.TAG` file is written to the cache directory so that backup and archiving tools can skip it (see the [cache directory tag specification](https://bford.info/cachedir/)).
+This will store all downloaded packages in the specified directory and reuse them in future pack operations. The cache follows the same structure as conda channels, organizing packages by platform subdirectories (e.g., linux-64, win-64, etc.).
Using a cache is particularly useful when: