CP4.1: review — a staging folder left by an earlier process with the same id is cleared before use

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
This commit is contained in:
Martin BallandClaude Opus 5.5 committed 2026-11-01 18:38:59 +00:00
1 parent 98321781d9
commit 1704bef581
2 files changed
+19

No files matched your search

@@ -318,3 +318,18 @@ fn hostile_archives_are_refused() {
unpack(&pack_archive("nl", "x"), &dest).unwrap();
assert!(dest.join("LICENCES/COPYING").is_file());
}
/// A staging folder an earlier process with the same id left behind is cleared, so an unpack
/// (`create_new`) can't fail on, or mix in, its files.
#[test]
fn a_stale_stage_folder_is_cleared() {
let store = temp("stale-stage");
let staging = store.join(".staging");
for n in 0..512 {
let d = staging.join(format!("{}-{n}", std::process::id()));
std::fs::create_dir_all(d.join("nl")).unwrap();
std::fs::write(d.join("nl/pack.toml"), b"old").unwrap();
}
let stage = Stage::new(&store).unwrap();
assert_eq!(std::fs::read_dir(&stage.dir).unwrap().count(), 0, "{}", stage.dir.display());
}
+4
View File
@@ -840,6 +840,10 @@ impl Stage {
pub(crate) fn new(store: &Path) -> Result<Self, Error> {
static N: AtomicU64 = AtomicU64::new(0);
let dir = store.join(STAGING).join(format!("{}-{}", std::process::id(), N.fetch_add(1, Ordering::Relaxed)));
// A folder left by an earlier process with the same id is cleared, not mixed in.
if std::fs::symlink_metadata(&dir).is_ok() {
std::fs::remove_dir_all(&dir).map_err(io("clearing an old download folder"))?;
}
std::fs::create_dir_all(&dir).map_err(io("creating a download folder"))?;
Ok(Self { dir })
}