mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 10:58:28 +00:00
Refactor PythonVersionFile
global loading (#14107)
I was looking into `uv tool` not supporting version files, and noticed this implementation was confusing and skipped handling like a tracing log if `--no-config` excludes selection a file. I've refactored it in preparation for the next change.
This commit is contained in:
parent
563e9495ba
commit
1dbe750452
2 changed files with 46 additions and 47 deletions
|
@ -37,11 +37,14 @@ pub enum FilePreference {
|
||||||
pub struct DiscoveryOptions<'a> {
|
pub struct DiscoveryOptions<'a> {
|
||||||
/// The path to stop discovery at.
|
/// The path to stop discovery at.
|
||||||
stop_discovery_at: Option<&'a Path>,
|
stop_discovery_at: Option<&'a Path>,
|
||||||
/// When `no_config` is set, Python version files will be ignored.
|
/// Ignore Python version files.
|
||||||
///
|
///
|
||||||
/// Discovery will still run in order to display a log about the ignored file.
|
/// Discovery will still run in order to display a log about the ignored file.
|
||||||
no_config: bool,
|
no_config: bool,
|
||||||
|
/// Whether `.python-version` or `.python-versions` should be preferred.
|
||||||
preference: FilePreference,
|
preference: FilePreference,
|
||||||
|
/// Whether to ignore local version files, and only search for a global one.
|
||||||
|
no_local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DiscoveryOptions<'a> {
|
impl<'a> DiscoveryOptions<'a> {
|
||||||
|
@ -62,6 +65,11 @@ impl<'a> DiscoveryOptions<'a> {
|
||||||
..self
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_no_local(self, no_local: bool) -> Self {
|
||||||
|
Self { no_local, ..self }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PythonVersionFile {
|
impl PythonVersionFile {
|
||||||
|
@ -70,33 +78,38 @@ impl PythonVersionFile {
|
||||||
working_directory: impl AsRef<Path>,
|
working_directory: impl AsRef<Path>,
|
||||||
options: &DiscoveryOptions<'_>,
|
options: &DiscoveryOptions<'_>,
|
||||||
) -> Result<Option<Self>, std::io::Error> {
|
) -> Result<Option<Self>, std::io::Error> {
|
||||||
let Some(path) = Self::find_nearest(&working_directory, options) else {
|
let allow_local = !options.no_local;
|
||||||
if let Some(stop_discovery_at) = options.stop_discovery_at {
|
let Some(path) = allow_local.then(|| {
|
||||||
if stop_discovery_at == working_directory.as_ref() {
|
// First, try to find a local version file.
|
||||||
debug!(
|
let local = Self::find_nearest(&working_directory, options);
|
||||||
"No Python version file found in workspace: {}",
|
if local.is_none() {
|
||||||
working_directory.as_ref().display()
|
// Log where we searched for the file, if not found
|
||||||
);
|
if let Some(stop_discovery_at) = options.stop_discovery_at {
|
||||||
|
if stop_discovery_at == working_directory.as_ref() {
|
||||||
|
debug!(
|
||||||
|
"No Python version file found in workspace: {}",
|
||||||
|
working_directory.as_ref().display()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
debug!(
|
||||||
|
"No Python version file found between working directory `{}` and workspace root `{}`",
|
||||||
|
working_directory.as_ref().display(),
|
||||||
|
stop_discovery_at.display()
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!(
|
debug!(
|
||||||
"No Python version file found between working directory `{}` and workspace root `{}`",
|
"No Python version file found in ancestors of working directory: {}",
|
||||||
working_directory.as_ref().display(),
|
working_directory.as_ref().display()
|
||||||
stop_discovery_at.display()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
debug!(
|
|
||||||
"No Python version file found in ancestors of working directory: {}",
|
|
||||||
working_directory.as_ref().display()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Not found in directory or its ancestors. Looking in user-level config.
|
local
|
||||||
return Ok(match user_uv_config_dir() {
|
}).flatten().or_else(|| {
|
||||||
Some(user_dir) => Self::discover_user_config(user_dir, options)
|
// Search for a global config
|
||||||
.await?
|
Self::find_global(options)
|
||||||
.or(None),
|
}) else {
|
||||||
None => None,
|
return Ok(None);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if options.no_config {
|
if options.no_config {
|
||||||
|
@ -111,20 +124,9 @@ impl PythonVersionFile {
|
||||||
Self::try_from_path(path).await
|
Self::try_from_path(path).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn discover_user_config(
|
fn find_global(options: &DiscoveryOptions<'_>) -> Option<PathBuf> {
|
||||||
user_config_working_directory: impl AsRef<Path>,
|
let user_config_dir = user_uv_config_dir()?;
|
||||||
options: &DiscoveryOptions<'_>,
|
Self::find_in_directory(&user_config_dir, options)
|
||||||
) -> Result<Option<Self>, std::io::Error> {
|
|
||||||
if !options.no_config {
|
|
||||||
if let Some(path) =
|
|
||||||
Self::find_in_directory(user_config_working_directory.as_ref(), options)
|
|
||||||
.into_iter()
|
|
||||||
.find(|path| path.is_file())
|
|
||||||
{
|
|
||||||
return Self::try_from_path(path).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_nearest(path: impl AsRef<Path>, options: &DiscoveryOptions<'_>) -> Option<PathBuf> {
|
fn find_nearest(path: impl AsRef<Path>, options: &DiscoveryOptions<'_>) -> Option<PathBuf> {
|
||||||
|
|
|
@ -57,16 +57,13 @@ pub(crate) async fn pin(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let version_file = if global {
|
// Search for an existing file, we won't necessarily write to this, we'll construct a target
|
||||||
if let Some(path) = user_uv_config_dir() {
|
// path if there's a request later on.
|
||||||
PythonVersionFile::discover_user_config(path, &VersionFileDiscoveryOptions::default())
|
let version_file = PythonVersionFile::discover(
|
||||||
.await
|
project_dir,
|
||||||
} else {
|
&VersionFileDiscoveryOptions::default().with_no_local(global),
|
||||||
Ok(None)
|
)
|
||||||
}
|
.await;
|
||||||
} else {
|
|
||||||
PythonVersionFile::discover(project_dir, &VersionFileDiscoveryOptions::default()).await
|
|
||||||
};
|
|
||||||
|
|
||||||
if rm {
|
if rm {
|
||||||
let Some(file) = version_file? else {
|
let Some(file) = version_file? else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue