mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Use fs_err for cachedir errors (#3304)
When running ``` set UV_CACHE_DIR=%LOCALAPPDATA%\uv\cache-foo && uv venv venv ``` in windows CMD, the error would be just ``` error: The system cannot find the path specified. (os error 3) ``` The problem is that the first action in the cache dir is adding the tag, and the `cachedir` crate is using `std::fs` instead of `fs_err`. I've copied the two functions we use from the crate and changed the import from `std::fs` to `fs_err`. The new error is ``` error: failed to open file `C:\Users\Konstantin\AppData\Local\uv\cache-foo \CACHEDIR.TAG` Caused by: The system cannot find the path specified. (os error 3) ``` which correctly explains the problem. Closes #3280
This commit is contained in:
parent
22d8619c37
commit
1344cfae4b
10 changed files with 78 additions and 7 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -4540,7 +4540,6 @@ name = "uv-cache"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cache-key",
|
"cache-key",
|
||||||
"cachedir",
|
|
||||||
"clap",
|
"clap",
|
||||||
"directories",
|
"directories",
|
||||||
"distribution-types",
|
"distribution-types",
|
||||||
|
@ -4761,6 +4760,7 @@ name = "uv-fs"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backoff",
|
"backoff",
|
||||||
|
"cachedir",
|
||||||
"dunce",
|
"dunce",
|
||||||
"encoding_rs_io",
|
"encoding_rs_io",
|
||||||
"fs-err",
|
"fs-err",
|
||||||
|
@ -5011,7 +5011,6 @@ name = "uv-virtualenv"
|
||||||
version = "0.0.4"
|
version = "0.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"cachedir",
|
|
||||||
"clap",
|
"clap",
|
||||||
"directories",
|
"directories",
|
||||||
"fs-err",
|
"fs-err",
|
||||||
|
|
|
@ -20,7 +20,6 @@ pypi-types = { workspace = true }
|
||||||
uv-fs = { workspace = true, features = ["tokio"] }
|
uv-fs = { workspace = true, features = ["tokio"] }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
|
|
||||||
cachedir = { workspace = true }
|
|
||||||
clap = { workspace = true, features = ["derive", "env"], optional = true }
|
clap = { workspace = true, features = ["derive", "env"], optional = true }
|
||||||
directories = { workspace = true }
|
directories = { workspace = true }
|
||||||
fs-err = { workspace = true, features = ["tokio"] }
|
fs-err = { workspace = true, features = ["tokio"] }
|
||||||
|
|
|
@ -13,7 +13,7 @@ use tracing::debug;
|
||||||
|
|
||||||
use distribution_types::InstalledDist;
|
use distribution_types::InstalledDist;
|
||||||
use pypi_types::Metadata23;
|
use pypi_types::Metadata23;
|
||||||
use uv_fs::directories;
|
use uv_fs::{cachedir, directories};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
|
||||||
pub use crate::by_timestamp::CachedByTimestamp;
|
pub use crate::by_timestamp::CachedByTimestamp;
|
||||||
|
|
|
@ -16,6 +16,7 @@ workspace = true
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
||||||
backoff = { workspace = true }
|
backoff = { workspace = true }
|
||||||
|
cachedir = { workspace = true }
|
||||||
dunce = { workspace = true }
|
dunce = { workspace = true }
|
||||||
encoding_rs_io = { workspace = true }
|
encoding_rs_io = { workspace = true }
|
||||||
fs-err = { workspace = true }
|
fs-err = { workspace = true }
|
||||||
|
|
42
crates/uv-fs/src/cachedir.rs
Normal file
42
crates/uv-fs/src/cachedir.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
//! Vendored from cachedir 0.3.1 to replace `std::fs` with `fs_err`.
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
use std::{io, path};
|
||||||
|
|
||||||
|
use cachedir::HEADER;
|
||||||
|
|
||||||
|
/// Adds a tag to the specified `directory`.
|
||||||
|
///
|
||||||
|
/// Will return an error if:
|
||||||
|
///
|
||||||
|
/// * The `directory` exists and contains a `CACHEDIR.TAG` file, regardless of its content.
|
||||||
|
/// * The file can't be created for any reason (the `directory` doesn't exist, permission error,
|
||||||
|
/// can't write to the file etc.)
|
||||||
|
pub fn add_tag<P: AsRef<path::Path>>(directory: P) -> io::Result<()> {
|
||||||
|
let directory = directory.as_ref();
|
||||||
|
match fs_err::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create_new(true)
|
||||||
|
.open(directory.join("CACHEDIR.TAG"))
|
||||||
|
{
|
||||||
|
Ok(mut cachedir_tag) => cachedir_tag.write_all(HEADER),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensures the tag exists in `directory`.
|
||||||
|
///
|
||||||
|
/// This function considers the `CACHEDIR.TAG` file in `directory` existing, regardless of its
|
||||||
|
/// content, as a success.
|
||||||
|
///
|
||||||
|
/// Will return an error if The tag file doesn't exist and can't be created for any reason
|
||||||
|
/// (the `directory` doesn't exist, permission error, can't write to the file etc.).
|
||||||
|
pub fn ensure_tag<P: AsRef<path::Path>>(directory: P) -> io::Result<()> {
|
||||||
|
match add_tag(directory) {
|
||||||
|
Err(e) => match e.kind() {
|
||||||
|
io::ErrorKind::AlreadyExists => Ok(()),
|
||||||
|
_ => Err(e),
|
||||||
|
},
|
||||||
|
other => other,
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ use uv_warnings::warn_user;
|
||||||
|
|
||||||
pub use crate::path::*;
|
pub use crate::path::*;
|
||||||
|
|
||||||
|
pub mod cachedir;
|
||||||
mod path;
|
mod path;
|
||||||
|
|
||||||
/// Reads data from the path and requires that it be valid UTF-8.
|
/// Reads data from the path and requires that it be valid UTF-8.
|
||||||
|
|
|
@ -29,7 +29,6 @@ uv-interpreter = { workspace = true }
|
||||||
uv-version = { workspace = true }
|
uv-version = { workspace = true }
|
||||||
|
|
||||||
anstream = { workspace = true }
|
anstream = { workspace = true }
|
||||||
cachedir = { workspace = true }
|
|
||||||
clap = { workspace = true, features = ["derive"], optional = true }
|
clap = { workspace = true, features = ["derive"], optional = true }
|
||||||
directories = { workspace = true }
|
directories = { workspace = true }
|
||||||
fs-err = { workspace = true }
|
fs-err = { workspace = true }
|
||||||
|
|
|
@ -12,7 +12,7 @@ use pypi_types::Scheme;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{Error, Prompt};
|
use crate::{Error, Prompt};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::{cachedir, Simplified};
|
||||||
use uv_interpreter::{Interpreter, Virtualenv};
|
use uv_interpreter::{Interpreter, Virtualenv};
|
||||||
use uv_version::version;
|
use uv_version::version;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ use std::vec;
|
||||||
|
|
||||||
use anstream::eprint;
|
use anstream::eprint;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use miette::{Diagnostic, IntoDiagnostic};
|
use miette::{Diagnostic, IntoDiagnostic};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
|
|
@ -527,3 +527,34 @@ fn verify_nested_pyvenv_cfg() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See <https://github.com/astral-sh/uv/issues/3280>
|
||||||
|
#[test]
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn path_with_trailing_space_gives_proper_error() {
|
||||||
|
let context = VenvTestContext::new(&["3.12"]);
|
||||||
|
|
||||||
|
let mut filters = context.filters();
|
||||||
|
filters.push((
|
||||||
|
regex::escape(&context.cache_dir.path().display().to_string()).to_string(),
|
||||||
|
r"C:\Path\to\Cache\dir".to_string(),
|
||||||
|
));
|
||||||
|
// Create a virtual environment at `.venv`.
|
||||||
|
uv_snapshot!(filters, Command::new(get_bin())
|
||||||
|
.arg("venv")
|
||||||
|
.arg(context.venv.as_os_str())
|
||||||
|
.arg("--python")
|
||||||
|
.arg("3.12")
|
||||||
|
.env("UV_CACHE_DIR", format!("{} ", context.cache_dir.path().display()))
|
||||||
|
.env("UV_TEST_PYTHON_PATH", context.python_path.clone())
|
||||||
|
.current_dir(context.temp_dir.path()), @r###"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: failed to open file `C:\Path\to\Cache\dir \CACHEDIR.TAG`
|
||||||
|
Caused by: The system cannot find the path specified. (os error 3)
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue