mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Support locking relative paths (#4205)
By splitting `path` into a lockable, relative (or absolute) and an absolute installable path and by splitting between urls and paths by dist type, we can store relative paths in the lockfile.
This commit is contained in:
parent
33cf47182f
commit
44833801b3
28 changed files with 533 additions and 364 deletions
|
@ -158,7 +158,7 @@ impl<'a> From<&'a PathSourceDist> for PathSourceUrl<'a> {
|
|||
fn from(dist: &'a PathSourceDist) -> Self {
|
||||
Self {
|
||||
url: &dist.url,
|
||||
path: Cow::Borrowed(&dist.path),
|
||||
path: Cow::Borrowed(&dist.install_path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ impl<'a> From<&'a DirectorySourceDist> for DirectorySourceUrl<'a> {
|
|||
fn from(dist: &'a DirectorySourceDist) -> Self {
|
||||
Self {
|
||||
url: &dist.url,
|
||||
path: Cow::Borrowed(&dist.path),
|
||||
path: Cow::Borrowed(&dist.install_path),
|
||||
editable: dist.editable,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,12 +116,14 @@ impl CachedDist {
|
|||
Self::Url(dist) => {
|
||||
if dist.editable {
|
||||
assert_eq!(dist.url.scheme(), "file", "{}", dist.url);
|
||||
let path = dist
|
||||
.url
|
||||
.to_file_path()
|
||||
.map_err(|()| anyhow!("Invalid path in file URL"))?;
|
||||
Ok(Some(ParsedUrl::Path(ParsedPathUrl {
|
||||
url: dist.url.raw().clone(),
|
||||
path: dist
|
||||
.url
|
||||
.to_file_path()
|
||||
.map_err(|()| anyhow!("Invalid path in file URL"))?,
|
||||
install_path: path.clone(),
|
||||
lock_path: path,
|
||||
editable: dist.editable,
|
||||
})))
|
||||
} else {
|
||||
|
|
|
@ -259,8 +259,12 @@ pub struct GitSourceDist {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct PathSourceDist {
|
||||
pub name: PackageName,
|
||||
/// The path to the archive.
|
||||
pub path: PathBuf,
|
||||
/// The resolved, absolute path to the distribution which we use for installing.
|
||||
pub install_path: PathBuf,
|
||||
/// The absolute path or path relative to the workspace root pointing to the distribution
|
||||
/// which we use for locking. Unlike `given` on the verbatim URL all environment variables
|
||||
/// are resolved, and unlike the install path, we did not yet join it on the base directory.
|
||||
pub lock_path: PathBuf,
|
||||
/// The URL as it was provided by the user.
|
||||
pub url: VerbatimUrl,
|
||||
}
|
||||
|
@ -269,8 +273,12 @@ pub struct PathSourceDist {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct DirectorySourceDist {
|
||||
pub name: PackageName,
|
||||
/// The path to the directory.
|
||||
pub path: PathBuf,
|
||||
/// The resolved, absolute path to the distribution which we use for installing.
|
||||
pub install_path: PathBuf,
|
||||
/// The absolute path or path relative to the workspace root pointing to the distribution
|
||||
/// which we use for locking. Unlike `given` on the verbatim URL all environment variables
|
||||
/// are resolved, and unlike the install path, we did not yet join it on the base directory.
|
||||
pub lock_path: PathBuf,
|
||||
/// Whether the package should be installed in editable mode.
|
||||
pub editable: bool,
|
||||
/// The URL as it was provided by the user.
|
||||
|
@ -319,11 +327,12 @@ impl Dist {
|
|||
pub fn from_file_url(
|
||||
name: PackageName,
|
||||
url: VerbatimUrl,
|
||||
path: &Path,
|
||||
install_path: &Path,
|
||||
lock_path: &Path,
|
||||
editable: bool,
|
||||
) -> Result<Dist, Error> {
|
||||
// Store the canonicalized path, which also serves to validate that it exists.
|
||||
let path = match path.canonicalize() {
|
||||
let canonicalized_path = match install_path.canonicalize() {
|
||||
Ok(path) => path,
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||
return Err(Error::NotFound(url.to_url()));
|
||||
|
@ -332,14 +341,15 @@ impl Dist {
|
|||
};
|
||||
|
||||
// Determine whether the path represents an archive or a directory.
|
||||
if path.is_dir() {
|
||||
if canonicalized_path.is_dir() {
|
||||
Ok(Self::Source(SourceDist::Directory(DirectorySourceDist {
|
||||
name,
|
||||
path,
|
||||
install_path: canonicalized_path.clone(),
|
||||
lock_path: lock_path.to_path_buf(),
|
||||
editable,
|
||||
url,
|
||||
})))
|
||||
} else if path
|
||||
} else if canonicalized_path
|
||||
.extension()
|
||||
.is_some_and(|ext| ext.eq_ignore_ascii_case("whl"))
|
||||
{
|
||||
|
@ -359,7 +369,7 @@ impl Dist {
|
|||
|
||||
Ok(Self::Built(BuiltDist::Path(PathBuiltDist {
|
||||
filename,
|
||||
path,
|
||||
path: canonicalized_path,
|
||||
url,
|
||||
})))
|
||||
} else {
|
||||
|
@ -369,7 +379,8 @@ impl Dist {
|
|||
|
||||
Ok(Self::Source(SourceDist::Path(PathSourceDist {
|
||||
name,
|
||||
path,
|
||||
install_path: canonicalized_path.clone(),
|
||||
lock_path: canonicalized_path,
|
||||
url,
|
||||
})))
|
||||
}
|
||||
|
@ -396,9 +407,13 @@ impl Dist {
|
|||
ParsedUrl::Archive(archive) => {
|
||||
Self::from_http_url(name, url.verbatim, archive.url, archive.subdirectory)
|
||||
}
|
||||
ParsedUrl::Path(file) => {
|
||||
Self::from_file_url(name, url.verbatim, &file.path, file.editable)
|
||||
}
|
||||
ParsedUrl::Path(file) => Self::from_file_url(
|
||||
name,
|
||||
url.verbatim,
|
||||
&file.install_path,
|
||||
&file.lock_path,
|
||||
file.editable,
|
||||
),
|
||||
ParsedUrl::Git(git) => {
|
||||
Self::from_git_url(name, url.verbatim, git.url, git.subdirectory)
|
||||
}
|
||||
|
@ -517,8 +532,8 @@ impl SourceDist {
|
|||
/// Returns the path to the source distribution, if it's a local distribution.
|
||||
pub fn as_path(&self) -> Option<&Path> {
|
||||
match self {
|
||||
Self::Path(dist) => Some(&dist.path),
|
||||
Self::Directory(dist) => Some(&dist.path),
|
||||
Self::Path(dist) => Some(&dist.install_path),
|
||||
Self::Directory(dist) => Some(&dist.install_path),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,7 +141,8 @@ impl From<&ResolvedDist> for Requirement {
|
|||
}
|
||||
}
|
||||
Dist::Built(BuiltDist::Path(wheel)) => RequirementSource::Path {
|
||||
path: wheel.path.clone(),
|
||||
install_path: wheel.path.clone(),
|
||||
lock_path: wheel.path.clone(),
|
||||
url: wheel.url.clone(),
|
||||
editable: false,
|
||||
},
|
||||
|
@ -168,12 +169,14 @@ impl From<&ResolvedDist> for Requirement {
|
|||
subdirectory: sdist.subdirectory.clone(),
|
||||
},
|
||||
Dist::Source(SourceDist::Path(sdist)) => RequirementSource::Path {
|
||||
path: sdist.path.clone(),
|
||||
install_path: sdist.install_path.clone(),
|
||||
lock_path: sdist.lock_path.clone(),
|
||||
url: sdist.url.clone(),
|
||||
editable: false,
|
||||
},
|
||||
Dist::Source(SourceDist::Directory(sdist)) => RequirementSource::Path {
|
||||
path: sdist.path.clone(),
|
||||
install_path: sdist.install_path.clone(),
|
||||
lock_path: sdist.lock_path.clone(),
|
||||
url: sdist.url.clone(),
|
||||
editable: sdist.editable,
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue