Skip to content

Commit

Permalink
Handle .cargo-ok being truncated
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed Jan 31, 2023
1 parent 2c30ebe commit 5c160dd
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 6 deletions.
19 changes: 13 additions & 6 deletions src/cargo/sources/registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,12 @@ use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::task::Poll;

use anyhow::Context as _;
use cargo_util::paths::exclude_from_backups_and_indexing;
use cargo_util::paths::{self, exclude_from_backups_and_indexing};
use flate2::read::GzDecoder;
use log::debug;
use semver::Version;
Expand Down Expand Up @@ -619,15 +619,22 @@ impl<'cfg> RegistrySource<'cfg> {
// unpacked.
let package_dir = format!("{}-{}", pkg.name(), pkg.version());
let dst = self.src_path.join(&package_dir);
dst.create_dir()?;
let path = dst.join(PACKAGE_SOURCE_LOCK);
let path = self.config.assert_package_cache_locked(&path);
let unpack_dir = path.parent().unwrap();
if let Ok(meta) = path.metadata() {
if meta.len() > 0 {
return Ok(unpack_dir.to_path_buf());
match path.metadata() {
Ok(meta) if meta.len() > 0 => return Ok(unpack_dir.to_path_buf()),
Ok(_meta) => {
// The file appears to be corrupted. Perhaps it failed to flush,

This comment has been minimized.

Copy link
@caldwell

caldwell Feb 14, 2023

This can also happen if the cargo directory happens to be old. The code use to create empty .cargo-ok files prior to this commit.

This comment has been minimized.

Copy link
@ehuss

ehuss Feb 15, 2023

Author Contributor

@caldwell Thanks for the sleuthing. I think I misunderstood why this was happening. I opened #11724 to update the comment here to clarify.

This comment has been minimized.

Copy link
@caldwell

caldwell Feb 16, 2023

Oh wow, that new comment is fantastic! Sorry if I sent you down a rabbit hole 🙂.

// or the filesystem was corrupted in some way. To be safe, let's
// assume something is wrong and clear it and start over.
log::warn!("unexpected length of {path:?}, clearing cache");
paths::remove_dir_all(dst.as_path_unlocked())?;
}
Err(e) if e.kind() == io::ErrorKind::NotFound => {}
Err(e) => anyhow::bail!("failed to access package completion {path:?}: {e}"),
}
dst.create_dir()?;
let mut tar = {
let size_limit = max_unpack_size(tarball.metadata()?.len());
let gz = GzDecoder::new(tarball);
Expand Down
45 changes: 45 additions & 0 deletions tests/testsuite/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2866,3 +2866,48 @@ required by package `foo v0.1.0 ([ROOT]/foo)`
.with_status(101)
.run();
}

#[cargo_test]
fn corrupted_ok_overwritten() {
// Checks what happens if .cargo-ok gets truncated, such as if the file is
// created, but the flush/close is interrupted.
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "1"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("fetch")
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
",
)
.run();
let ok = glob::glob(
paths::home()
.join(".cargo/registry/src/*/bar-1.0.0/.cargo-ok")
.to_str()
.unwrap(),
)
.unwrap()
.next()
.unwrap()
.unwrap();
// Simulate cargo being interrupted, or filesystem corruption.
fs::write(&ok, "").unwrap();
assert_eq!(fs::read_to_string(&ok).unwrap(), "");
p.cargo("fetch").with_stderr("").run();
assert_eq!(fs::read_to_string(&ok).unwrap(), "ok");
}

0 comments on commit 5c160dd

Please sign in to comment.