Skip to content

Commit 1653daa

Browse files
authored
Eliminate dependencies on directores and dirs-sys (#8048)
## Summary Migrate all directory related logic to `etcetera`, eliminated two dependecies.
1 parent 12576bc commit 1653daa

File tree

10 files changed

+48
-87
lines changed

10 files changed

+48
-87
lines changed

Cargo.lock

Lines changed: 3 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ csv = { version = "1.3.0" }
9090
ctrlc = { version = "3.4.5" }
9191
dashmap = { version = "6.1.0" }
9292
data-encoding = { version = "2.6.0" }
93-
directories = { version = "5.0.1" }
94-
dirs-sys = { version = "0.4.1" }
9593
dunce = { version = "1.0.5" }
9694
either = { version = "1.13.0" }
9795
encoding_rs_io = { version = "0.1.7" }

crates/uv-cache/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ uv-pypi-types = { workspace = true }
2626
uv-static = { workspace = true }
2727

2828
clap = { workspace = true, features = ["derive", "env"], optional = true }
29-
directories = { workspace = true }
3029
etcetera = { workspace = true }
3130
fs-err = { workspace = true, features = ["tokio"] }
3231
nanoid = { workspace = true }

crates/uv-cache/src/cli.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use uv_static::EnvVars;
44

55
use crate::Cache;
66
use clap::Parser;
7-
use directories::ProjectDirs;
87
use etcetera::BaseStrategy;
98
use tracing::{debug, warn};
109

@@ -31,6 +30,19 @@ pub struct CacheArgs {
3130
pub cache_dir: Option<PathBuf>,
3231
}
3332

33+
fn legacy_cache_dir() -> Option<PathBuf> {
34+
etcetera::base_strategy::choose_native_strategy()
35+
.ok()
36+
.map(|dirs| dirs.cache_dir().join("uv"))
37+
.map(|dir| {
38+
if cfg!(windows) {
39+
dir.join("cache")
40+
} else {
41+
dir
42+
}
43+
})
44+
}
45+
3446
impl Cache {
3547
/// Prefer, in order:
3648
///
@@ -45,10 +57,7 @@ impl Cache {
4557
Self::temp()
4658
} else if let Some(cache_dir) = cache_dir {
4759
Ok(Self::from_path(cache_dir))
48-
} else if let Some(cache_dir) = ProjectDirs::from("", "", "uv")
49-
.map(|dirs| dirs.cache_dir().to_path_buf())
50-
.filter(|dir| dir.exists())
51-
{
60+
} else if let Some(cache_dir) = legacy_cache_dir().filter(|dir| dir.exists()) {
5261
// If the user has an existing directory at (e.g.) `/Users/user/Library/Caches/uv`,
5362
// respect it for backwards compatibility. Otherwise, prefer the XDG strategy, even on
5463
// macOS.

crates/uv-settings/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ uv-static = { workspace = true }
3232
uv-warnings = { workspace = true }
3333

3434
clap = { workspace = true }
35-
dirs-sys = { workspace = true }
35+
etcetera = { workspace = true }
3636
fs-err = { workspace = true }
3737
schemars = { workspace = true, optional = true }
3838
serde = { workspace = true }

crates/uv-settings/src/lib.rs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::ops::Deref;
22
use std::path::{Path, PathBuf};
33

4+
use etcetera::BaseStrategy;
45
use tracing::debug;
56

67
use uv_fs::Simplified;
7-
#[cfg(not(windows))]
8-
use uv_static::EnvVars;
98
use uv_warnings::warn_user;
109

1110
pub use crate::combine::*;
@@ -168,23 +167,12 @@ impl From<Options> for FilesystemOptions {
168167

169168
/// Returns the path to the user configuration directory.
170169
///
171-
/// This is similar to the `config_dir()` returned by the `dirs` crate, but it uses the
172-
/// `XDG_CONFIG_HOME` environment variable on both Linux _and_ macOS, rather than the
173-
/// `Application Support` directory on macOS.
170+
/// On Windows, use, e.g., C:\Users\Alice\AppData\Roaming
171+
/// On Linux and macOS, use `XDG_CONFIG_HOME` or $HOME/.config, e.g., /home/alice/.config.
174172
fn config_dir() -> Option<PathBuf> {
175-
// On Windows, use, e.g., C:\Users\Alice\AppData\Roaming
176-
#[cfg(windows)]
177-
{
178-
dirs_sys::known_folder_roaming_app_data()
179-
}
180-
181-
// On Linux and macOS, use, e.g., /home/alice/.config.
182-
#[cfg(not(windows))]
183-
{
184-
std::env::var_os(EnvVars::XDG_CONFIG_HOME)
185-
.and_then(dirs_sys::is_absolute_path)
186-
.or_else(|| dirs_sys::home_dir().map(|path| path.join(".config")))
187-
}
173+
etcetera::choose_base_strategy()
174+
.map(|dirs| dirs.config_dir())
175+
.ok()
188176
}
189177

190178
/// Load [`Options`] from a `uv.toml` file.

crates/uv-state/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ doctest = false
1616
workspace = true
1717

1818
[dependencies]
19-
directories = { workspace = true }
2019
etcetera = { workspace = true }
2120
tempfile = { workspace = true }
2221
fs-err = { workspace = true }

crates/uv-state/src/lib.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::{
44
sync::Arc,
55
};
66

7-
use directories::ProjectDirs;
87
use etcetera::BaseStrategy;
98
use fs_err as fs;
109
use tempfile::{tempdir, TempDir};
@@ -85,10 +84,7 @@ impl StateStore {
8584
pub fn from_settings(state_dir: Option<PathBuf>) -> Result<Self, io::Error> {
8685
if let Some(state_dir) = state_dir {
8786
StateStore::from_path(state_dir)
88-
} else if let Some(data_dir) = ProjectDirs::from("", "", "uv")
89-
.map(|dirs| dirs.data_dir().to_path_buf())
90-
.filter(|dir| dir.exists())
91-
{
87+
} else if let Some(data_dir) = legacy_data_dir().filter(|dir| dir.exists()) {
9288
// If the user has an existing directory at (e.g.) `/Users/user/Library/Application Support/uv`,
9389
// respect it for backwards compatibility. Otherwise, prefer the XDG strategy, even on
9490
// macOS.
@@ -104,6 +100,13 @@ impl StateStore {
104100
}
105101
}
106102

103+
fn legacy_data_dir() -> Option<PathBuf> {
104+
etcetera::base_strategy::choose_native_strategy()
105+
.ok()
106+
.map(|dirs| dirs.data_dir().join("uv"))
107+
.map(|dir| if cfg!(windows) { dir.join("data") } else { dir })
108+
}
109+
107110
/// The different kinds of data in the state store are stored in different bucket, which in our case
108111
/// are subdirectories of the state store root.
109112
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]

crates/uv-tool/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ uv-state = { workspace = true }
2929
uv-static = { workspace = true }
3030
uv-virtualenv = { workspace = true }
3131

32-
dirs-sys = { workspace = true }
32+
etcetera = { workspace = true }
3333
fs-err = { workspace = true }
3434
pathdiff = { workspace = true }
3535
serde = { workspace = true }

crates/uv-tool/src/lib.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::fmt;
2-
32
use fs_err as fs;
3+
use std::ffi::OsString;
44

55
use uv_pep440::Version;
66
use uv_pep508::{InvalidNameError, PackageName};
@@ -354,6 +354,15 @@ impl fmt::Display for InstalledTool {
354354
}
355355
}
356356

357+
fn is_absolute_path(path: OsString) -> Option<PathBuf> {
358+
let path = PathBuf::from(path);
359+
if path.is_absolute() {
360+
Some(path)
361+
} else {
362+
None
363+
}
364+
}
365+
357366
/// Find a directory to place executables in.
358367
///
359368
/// This follows, in order:
@@ -368,20 +377,16 @@ impl fmt::Display for InstalledTool {
368377
/// Errors if a directory cannot be found.
369378
pub fn find_executable_directory() -> Result<PathBuf, Error> {
370379
std::env::var_os(EnvVars::UV_TOOL_BIN_DIR)
371-
.and_then(dirs_sys::is_absolute_path)
372-
.or_else(|| std::env::var_os(EnvVars::XDG_BIN_HOME).and_then(dirs_sys::is_absolute_path))
380+
.and_then(is_absolute_path)
381+
.or_else(|| std::env::var_os(EnvVars::XDG_BIN_HOME).and_then(is_absolute_path))
373382
.or_else(|| {
374383
std::env::var_os(EnvVars::XDG_DATA_HOME)
375-
.and_then(dirs_sys::is_absolute_path)
384+
.and_then(is_absolute_path)
376385
.map(|path| path.join("../bin"))
377386
})
378387
.or_else(|| {
379-
// See https://github.com/dirs-dev/dirs-rs/blob/50b50f31f3363b7656e5e63b3fa1060217cbc844/src/win.rs#L5C58-L5C78
380-
#[cfg(windows)]
381-
let home_dir = dirs_sys::known_folder_profile();
382-
#[cfg(not(windows))]
383-
let home_dir = dirs_sys::home_dir();
384-
home_dir.map(|path| path.join(".local").join("bin"))
388+
let home_dir = etcetera::home_dir();
389+
home_dir.map(|path| path.join(".local").join("bin")).ok()
385390
})
386391
.ok_or(Error::NoExecutableDirectory)
387392
}

0 commit comments

Comments
 (0)