Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://bford.info/cachedir/> 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,
Expand Down Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Loading