mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +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> {
|
||||
/// The path to stop discovery at.
|
||||
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.
|
||||
no_config: bool,
|
||||
/// Whether `.python-version` or `.python-versions` should be preferred.
|
||||
preference: FilePreference,
|
||||
/// Whether to ignore local version files, and only search for a global one.
|
||||
no_local: bool,
|
||||
}
|
||||
|
||||
impl<'a> DiscoveryOptions<'a> {
|
||||
|
@ -62,6 +65,11 @@ impl<'a> DiscoveryOptions<'a> {
|
|||
..self
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_no_local(self, no_local: bool) -> Self {
|
||||
Self { no_local, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl PythonVersionFile {
|
||||
|
@ -70,33 +78,38 @@ impl PythonVersionFile {
|
|||
working_directory: impl AsRef<Path>,
|
||||
options: &DiscoveryOptions<'_>,
|
||||
) -> Result<Option<Self>, std::io::Error> {
|
||||
let Some(path) = Self::find_nearest(&working_directory, options) else {
|
||||
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()
|
||||
);
|
||||
let allow_local = !options.no_local;
|
||||
let Some(path) = allow_local.then(|| {
|
||||
// First, try to find a local version file.
|
||||
let local = Self::find_nearest(&working_directory, options);
|
||||
if local.is_none() {
|
||||
// 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 {
|
||||
debug!(
|
||||
"No Python version file found between working directory `{}` and workspace root `{}`",
|
||||
working_directory.as_ref().display(),
|
||||
stop_discovery_at.display()
|
||||
"No Python version file found in ancestors of working directory: {}",
|
||||
working_directory.as_ref().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.
|
||||
return Ok(match user_uv_config_dir() {
|
||||
Some(user_dir) => Self::discover_user_config(user_dir, options)
|
||||
.await?
|
||||
.or(None),
|
||||
None => None,
|
||||
});
|
||||
local
|
||||
}).flatten().or_else(|| {
|
||||
// Search for a global config
|
||||
Self::find_global(options)
|
||||
}) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
if options.no_config {
|
||||
|
@ -111,20 +124,9 @@ impl PythonVersionFile {
|
|||
Self::try_from_path(path).await
|
||||
}
|
||||
|
||||
pub async fn discover_user_config(
|
||||
user_config_working_directory: impl AsRef<Path>,
|
||||
options: &DiscoveryOptions<'_>,
|
||||
) -> 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_global(options: &DiscoveryOptions<'_>) -> Option<PathBuf> {
|
||||
let user_config_dir = user_uv_config_dir()?;
|
||||
Self::find_in_directory(&user_config_dir, options)
|
||||
}
|
||||
|
||||
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 {
|
||||
if let Some(path) = user_uv_config_dir() {
|
||||
PythonVersionFile::discover_user_config(path, &VersionFileDiscoveryOptions::default())
|
||||
.await
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
} else {
|
||||
PythonVersionFile::discover(project_dir, &VersionFileDiscoveryOptions::default()).await
|
||||
};
|
||||
// Search for an existing file, we won't necessarily write to this, we'll construct a target
|
||||
// path if there's a request later on.
|
||||
let version_file = PythonVersionFile::discover(
|
||||
project_dir,
|
||||
&VersionFileDiscoveryOptions::default().with_no_local(global),
|
||||
)
|
||||
.await;
|
||||
|
||||
if rm {
|
||||
let Some(file) = version_file? else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue