Skip to content

Exclude the target directory from backups using CACHEDIR.TAG #8378

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 2, 2020
Merged
Prev Previous commit
Next Next commit
Make target directory creation and backup exclusion atomic
  • Loading branch information
jstasiak committed Jun 19, 2020
commit 2793d7bf62aae0212c0c31430069445966aa2c26
35 changes: 33 additions & 2 deletions src/cargo/core/compiler/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ use crate::core::compiler::CompileTarget;
use crate::core::Workspace;
use crate::util::paths;
use crate::util::{CargoResult, FileLock};
use std::fs;
use std::path::{Path, PathBuf};
use tempfile::Builder as TempFileBuilder;

/// Contains the paths of all target output locations.
///
Expand Down Expand Up @@ -146,13 +148,42 @@ impl Layout {
if let Some(target) = target {
root.push(target.short_name());
}
// We need root to exist before we do the tempdir/rename dance inside it.
if !root.as_path_unlocked().exists() {
root.create_dir()?;
}
let dest = root.join(dest);
// If the root directory doesn't already exist go ahead and create it
// here. Use this opportunity to exclude it from backups as well if the
// system supports it since this is a freshly created folder.
//
// We do this in two steps (first create a temporary directory and exlucde
// it from backups, then rename it to the desired name. If we created the
// directory directly where it should be and then excluded it from backups
// we would risk a situation where cargo is interrupted right after the directory
// creation but before the exclusion the the directory would remain non-excluded from
// backups because we only perform exclusion right after we created the directory
// ourselves.
if !dest.as_path_unlocked().exists() {
dest.create_dir()?;
exclude_from_backups(dest.as_path_unlocked());
// We need the tempdir created in root instead of $TMP, because only then we can be
// easily sure that rename() will succeed (the new name needs to be on the same mount
// point as the old one).
let tempdir = TempFileBuilder::new()
.prefix("cargo-target")
.tempdir_in(root.as_path_unlocked())?
.into_path();
exclude_from_backups(&tempdir);
// Previously std::fs::create_dir_all() (through paths::create_dir_all()) was used
// here to create the directory directly and fs::create_dir_all() explicitly treats
// the directory being created concurrently by another thread or process as success,
// hence the check below to follow the existing behavior. If we get an error at
// rename() and suddently the directory (which didn't exist a moment earlier) exists
// we can infer from it it's another cargo process doing work.
if let Err(e) = fs::rename(&tempdir, dest.as_path_unlocked()) {
if !dest.as_path_unlocked().exists() {
return Err(anyhow::Error::from(e));
}
}
}

// For now we don't do any more finer-grained locking on the artifact
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy