mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Unify subdirectory handling in source.rs
(#314)
Avoids having to encode all the `git+` and `subdirectory=` logic in multiple places.
This commit is contained in:
parent
edce4ccb24
commit
643cf3b3aa
3 changed files with 43 additions and 29 deletions
|
@ -1,6 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Error, Result};
|
||||
|
||||
use url::Url;
|
||||
|
||||
use puffin_distribution::RemoteDistributionRef;
|
||||
|
@ -50,3 +51,28 @@ impl<'a> TryFrom<&'a RemoteDistributionRef<'_>> for Source<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Source<'_>> for Url {
|
||||
fn from(value: Source) -> Self {
|
||||
match value {
|
||||
Source::RegistryUrl(url) => url,
|
||||
Source::RemoteUrl(url, subdirectory) => {
|
||||
if let Some(subdirectory) = subdirectory {
|
||||
let mut url = (*url).clone();
|
||||
url.set_fragment(Some(&format!("subdirectory={}", subdirectory.display())));
|
||||
url
|
||||
} else {
|
||||
url.clone()
|
||||
}
|
||||
}
|
||||
Source::Git(git, subdirectory) => {
|
||||
let mut url = Url::parse(&format!("{}{}", "git+", Url::from(git).as_str()))
|
||||
.expect("git url is valid");
|
||||
if let Some(subdirectory) = subdirectory {
|
||||
url.set_fragment(Some(&format!("subdirectory={}", subdirectory.display())));
|
||||
}
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ impl<'a, T: BuildContext> SourceDistributionFetcher<'a, T> {
|
|||
Ok(metadata21)
|
||||
}
|
||||
|
||||
/// Given a URL dependency for a source distribution, return a precise variant, if possible.
|
||||
/// Given a remote source distribution, return a precise variant, if possible.
|
||||
///
|
||||
/// For example, given a Git dependency with a reference to a branch or tag, return a URL
|
||||
/// with a precise reference to the current commit of that branch or tag.
|
||||
|
@ -133,35 +133,24 @@ impl<'a, T: BuildContext> SourceDistributionFetcher<'a, T> {
|
|||
/// This method takes into account various normalizations that are independent from the Git
|
||||
/// layer. For example: removing `#subdirectory=pkg_dir`-like fragments, and removing `git+`
|
||||
/// prefix kinds.
|
||||
pub(crate) async fn precise(&self, url: &Url) -> Result<Option<Url>> {
|
||||
// Extract the subdirectory.
|
||||
let subdirectory = url.fragment().and_then(|fragment| {
|
||||
fragment
|
||||
.split('&')
|
||||
.find_map(|fragment| fragment.strip_prefix("subdirectory="))
|
||||
});
|
||||
|
||||
let Some(url) = url.as_str().strip_prefix("git+") else {
|
||||
pub(crate) async fn precise(
|
||||
&self,
|
||||
distribution: &RemoteDistributionRef<'_>,
|
||||
) -> Result<Option<Url>> {
|
||||
let source = Source::try_from(distribution)?;
|
||||
let Source::Git(git, subdirectory) = source else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Fetch the precise SHA of the Git reference (which could be a branch, a tag, a partial
|
||||
// commit, etc.).
|
||||
let git = Git::try_from(Url::parse(url)?)?;
|
||||
let dir = self.0.cache().join(GIT_CACHE);
|
||||
let source = GitSource::new(git, dir);
|
||||
let precise = tokio::task::spawn_blocking(move || source.fetch()).await??;
|
||||
let git = Git::from(precise);
|
||||
|
||||
// TODO(charlie): Avoid this double-parse by encoding the source kind separately from the
|
||||
// URL.
|
||||
let mut url = Url::parse(&format!("{}{}", "git+", Url::from(git).as_str()))?;
|
||||
|
||||
// Re-add the subdirectory fragment.
|
||||
if let Some(subdirectory) = subdirectory {
|
||||
url.set_fragment(Some(&format!("subdirectory={subdirectory}")));
|
||||
}
|
||||
|
||||
Ok(Some(url))
|
||||
// Re-encode as a URL.
|
||||
let source = Source::Git(git, subdirectory);
|
||||
Ok(Some(source.into()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -705,14 +705,13 @@ impl<'a, Context: BuildContext + Sync> Resolver<'a, Context> {
|
|||
let _guard = lock.lock().await;
|
||||
|
||||
let fetcher = SourceDistributionFetcher::new(self.build_context);
|
||||
let precise =
|
||||
fetcher
|
||||
.precise(&url)
|
||||
.await
|
||||
.map_err(|err| ResolveError::UrlDistribution {
|
||||
url: url.clone(),
|
||||
err,
|
||||
})?;
|
||||
let precise = fetcher
|
||||
.precise(&RemoteDistributionRef::from_url(&package_name, &url))
|
||||
.await
|
||||
.map_err(|err| ResolveError::UrlDistribution {
|
||||
url: url.clone(),
|
||||
err,
|
||||
})?;
|
||||
|
||||
let distribution = RemoteDistributionRef::from_url(
|
||||
&package_name,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue