Use `Box<Path>` in lieu of `PathBuf` for immutable structs (#12346)

## Summary

I don't know if I actually want to commit this, but I did it on the
plane last time and just polished it off (got it to compile) while
waiting to board.
This commit is contained in:
Charlie Marsh 2025-03-25 17:56:06 -04:00 committed by GitHub
parent 9745b76357
commit e4c98e976f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 225 additions and 180 deletions

View File

@ -1185,7 +1185,7 @@ pub enum Refresh {
/// Don't refresh any entries. /// Don't refresh any entries.
None(Timestamp), None(Timestamp),
/// Refresh entries linked to the given packages, if created before the given timestamp. /// Refresh entries linked to the given packages, if created before the given timestamp.
Packages(Vec<PackageName>, Vec<PathBuf>, Timestamp), Packages(Vec<PackageName>, Vec<Box<Path>>, Timestamp),
/// Refresh all entries created before the given timestamp. /// Refresh all entries created before the given timestamp.
All(Timestamp), All(Timestamp),
} }

View File

@ -623,7 +623,7 @@ impl RegistryClient {
.await? .await?
} }
BuiltDist::Path(wheel) => { BuiltDist::Path(wheel) => {
let file = fs_err::tokio::File::open(&wheel.install_path) let file = fs_err::tokio::File::open(wheel.install_path.as_ref())
.await .await
.map_err(ErrorKind::Io)?; .map_err(ErrorKind::Io)?;
let reader = tokio::io::BufReader::new(file); let reader = tokio::io::BufReader::new(file);

View File

@ -1,4 +1,4 @@
use std::path::{Path, PathBuf}; use std::path::Path;
use either::Either; use either::Either;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -20,7 +20,7 @@ pub enum Reinstall {
All, All,
/// Reinstall only the specified packages. /// Reinstall only the specified packages.
Packages(Vec<PackageName>, Vec<PathBuf>), Packages(Vec<PackageName>, Vec<Box<Path>>),
} }
impl Reinstall { impl Reinstall {
@ -89,9 +89,9 @@ impl Reinstall {
} }
} }
/// Add a [`PathBuf`] to the [`Reinstall`] policy. /// Add a [`Box<Path>`] to the [`Reinstall`] policy.
#[must_use] #[must_use]
pub fn with_path(self, path: PathBuf) -> Self { pub fn with_path(self, path: Box<Path>) -> Self {
match self { match self {
Self::None => Self::Packages(vec![], vec![path]), Self::None => Self::Packages(vec![], vec![path]),
Self::All => Self::All, Self::All => Self::All,

View File

@ -1,4 +1,4 @@
use std::path::{Path, PathBuf}; use std::path::Path;
use uv_cache_info::CacheInfo; use uv_cache_info::CacheInfo;
use uv_distribution_filename::WheelFilename; use uv_distribution_filename::WheelFilename;
@ -22,7 +22,7 @@ pub enum CachedDist {
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct CachedRegistryDist { pub struct CachedRegistryDist {
pub filename: WheelFilename, pub filename: WheelFilename,
pub path: PathBuf, pub path: Box<Path>,
pub hashes: HashDigests, pub hashes: HashDigests,
pub cache_info: CacheInfo, pub cache_info: CacheInfo,
} }
@ -31,7 +31,7 @@ pub struct CachedRegistryDist {
pub struct CachedDirectUrlDist { pub struct CachedDirectUrlDist {
pub filename: WheelFilename, pub filename: WheelFilename,
pub url: VerbatimParsedUrl, pub url: VerbatimParsedUrl,
pub path: PathBuf, pub path: Box<Path>,
pub hashes: HashDigests, pub hashes: HashDigests,
pub cache_info: CacheInfo, pub cache_info: CacheInfo,
} }
@ -43,7 +43,7 @@ impl CachedDist {
filename: WheelFilename, filename: WheelFilename,
hashes: HashDigests, hashes: HashDigests,
cache_info: CacheInfo, cache_info: CacheInfo,
path: PathBuf, path: Box<Path>,
) -> Self { ) -> Self {
match remote { match remote {
Dist::Built(BuiltDist::Registry(_dist)) => Self::Registry(CachedRegistryDist { Dist::Built(BuiltDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {

View File

@ -77,7 +77,7 @@ pub enum InstalledDist {
pub struct InstalledRegistryDist { pub struct InstalledRegistryDist {
pub name: PackageName, pub name: PackageName,
pub version: Version, pub version: Version,
pub path: PathBuf, pub path: Box<Path>,
pub cache_info: Option<CacheInfo>, pub cache_info: Option<CacheInfo>,
} }
@ -88,7 +88,7 @@ pub struct InstalledDirectUrlDist {
pub direct_url: Box<DirectUrl>, pub direct_url: Box<DirectUrl>,
pub url: Url, pub url: Url,
pub editable: bool, pub editable: bool,
pub path: PathBuf, pub path: Box<Path>,
pub cache_info: Option<CacheInfo>, pub cache_info: Option<CacheInfo>,
} }
@ -96,24 +96,24 @@ pub struct InstalledDirectUrlDist {
pub struct InstalledEggInfoFile { pub struct InstalledEggInfoFile {
pub name: PackageName, pub name: PackageName,
pub version: Version, pub version: Version,
pub path: PathBuf, pub path: Box<Path>,
} }
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct InstalledEggInfoDirectory { pub struct InstalledEggInfoDirectory {
pub name: PackageName, pub name: PackageName,
pub version: Version, pub version: Version,
pub path: PathBuf, pub path: Box<Path>,
} }
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct InstalledLegacyEditable { pub struct InstalledLegacyEditable {
pub name: PackageName, pub name: PackageName,
pub version: Version, pub version: Version,
pub egg_link: PathBuf, pub egg_link: Box<Path>,
pub target: PathBuf, pub target: Box<Path>,
pub target_url: Url, pub target_url: Url,
pub egg_info: PathBuf, pub egg_info: Box<Path>,
} }
impl InstalledDist { impl InstalledDist {
@ -145,7 +145,7 @@ impl InstalledDist {
editable: matches!(&direct_url, DirectUrl::LocalDirectory { dir_info, .. } if dir_info.editable == Some(true)), editable: matches!(&direct_url, DirectUrl::LocalDirectory { dir_info, .. } if dir_info.editable == Some(true)),
direct_url: Box::new(direct_url), direct_url: Box::new(direct_url),
url, url,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
cache_info, cache_info,
}))), }))),
Err(err) => { Err(err) => {
@ -153,7 +153,7 @@ impl InstalledDist {
Ok(Some(Self::Registry(InstalledRegistryDist { Ok(Some(Self::Registry(InstalledRegistryDist {
name, name,
version, version,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
cache_info, cache_info,
}))) })))
} }
@ -162,7 +162,7 @@ impl InstalledDist {
Ok(Some(Self::Registry(InstalledRegistryDist { Ok(Some(Self::Registry(InstalledRegistryDist {
name, name,
version, version,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
cache_info, cache_info,
}))) })))
}; };
@ -191,7 +191,7 @@ impl InstalledDist {
return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory { return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory {
name: file_name.name, name: file_name.name,
version, version,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
}))); })));
} }
@ -199,7 +199,7 @@ impl InstalledDist {
return Ok(Some(Self::EggInfoFile(InstalledEggInfoFile { return Ok(Some(Self::EggInfoFile(InstalledEggInfoFile {
name: file_name.name, name: file_name.name,
version, version,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
}))); })));
} }
}; };
@ -211,7 +211,7 @@ impl InstalledDist {
return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory { return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory {
name: file_name.name, name: file_name.name,
version: Version::from_str(&egg_metadata.version)?, version: Version::from_str(&egg_metadata.version)?,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
}))); })));
} }
@ -222,7 +222,7 @@ impl InstalledDist {
return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory { return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory {
name: file_name.name, name: file_name.name,
version: Version::from_str(&egg_metadata.version)?, version: Version::from_str(&egg_metadata.version)?,
path: path.to_path_buf(), path: path.to_path_buf().into_boxed_path(),
}))); })));
} }
} }
@ -270,10 +270,10 @@ impl InstalledDist {
return Ok(Some(Self::LegacyEditable(InstalledLegacyEditable { return Ok(Some(Self::LegacyEditable(InstalledLegacyEditable {
name: egg_metadata.name, name: egg_metadata.name,
version: Version::from_str(&egg_metadata.version)?, version: Version::from_str(&egg_metadata.version)?,
egg_link: path.to_path_buf(), egg_link: path.to_path_buf().into_boxed_path(),
target, target: target.into_boxed_path(),
target_url: url, target_url: url,
egg_info, egg_info: egg_info.into_boxed_path(),
}))); })));
} }
@ -344,7 +344,7 @@ impl InstalledDist {
} }
Self::EggInfoFile(_) | Self::EggInfoDirectory(_) | Self::LegacyEditable(_) => { Self::EggInfoFile(_) | Self::EggInfoDirectory(_) | Self::LegacyEditable(_) => {
let path = match self { let path = match self {
Self::EggInfoFile(dist) => Cow::Borrowed(&dist.path), Self::EggInfoFile(dist) => Cow::Borrowed(&*dist.path),
Self::EggInfoDirectory(dist) => Cow::Owned(dist.path.join("PKG-INFO")), Self::EggInfoDirectory(dist) => Cow::Owned(dist.path.join("PKG-INFO")),
Self::LegacyEditable(dist) => Cow::Owned(dist.egg_info.join("PKG-INFO")), Self::LegacyEditable(dist) => Cow::Owned(dist.egg_info.join("PKG-INFO")),
_ => unreachable!(), _ => unreachable!(),

View File

@ -34,7 +34,7 @@
//! Since we read this information from [`direct_url.json`](https://packaging.python.org/en/latest/specifications/direct-url-data-structure/), it doesn't match the information [`Dist`] exactly. //! Since we read this information from [`direct_url.json`](https://packaging.python.org/en/latest/specifications/direct-url-data-structure/), it doesn't match the information [`Dist`] exactly.
use std::borrow::Cow; use std::borrow::Cow;
use std::path; use std::path;
use std::path::{Path, PathBuf}; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
@ -266,7 +266,7 @@ pub struct DirectUrlBuiltDist {
pub struct PathBuiltDist { pub struct PathBuiltDist {
pub filename: WheelFilename, pub filename: WheelFilename,
/// The absolute path to the wheel which we use for installing. /// The absolute path to the wheel which we use for installing.
pub install_path: PathBuf, pub install_path: Box<Path>,
/// The URL as it was provided by the user. /// The URL as it was provided by the user.
pub url: VerbatimUrl, pub url: VerbatimUrl,
} }
@ -299,7 +299,7 @@ pub struct DirectUrlSourceDist {
/// The URL without the subdirectory fragment. /// The URL without the subdirectory fragment.
pub location: Box<Url>, pub location: Box<Url>,
/// The subdirectory within the archive in which the source distribution is located. /// The subdirectory within the archive in which the source distribution is located.
pub subdirectory: Option<PathBuf>, pub subdirectory: Option<Box<Path>>,
/// The file extension, e.g. `tar.gz`, `zip`, etc. /// The file extension, e.g. `tar.gz`, `zip`, etc.
pub ext: SourceDistExtension, pub ext: SourceDistExtension,
/// The URL as it was provided by the user, including the subdirectory fragment. /// The URL as it was provided by the user, including the subdirectory fragment.
@ -313,7 +313,7 @@ pub struct GitSourceDist {
/// The URL without the revision and subdirectory fragment. /// The URL without the revision and subdirectory fragment.
pub git: Box<GitUrl>, pub git: Box<GitUrl>,
/// The subdirectory within the Git repository in which the source distribution is located. /// The subdirectory within the Git repository in which the source distribution is located.
pub subdirectory: Option<PathBuf>, pub subdirectory: Option<Box<Path>>,
/// The URL as it was provided by the user, including the revision and subdirectory fragment. /// The URL as it was provided by the user, including the revision and subdirectory fragment.
pub url: VerbatimUrl, pub url: VerbatimUrl,
} }
@ -324,7 +324,7 @@ pub struct PathSourceDist {
pub name: PackageName, pub name: PackageName,
pub version: Option<Version>, pub version: Option<Version>,
/// The absolute path to the distribution which we use for installing. /// The absolute path to the distribution which we use for installing.
pub install_path: PathBuf, pub install_path: Box<Path>,
/// The file extension, e.g. `tar.gz`, `zip`, etc. /// The file extension, e.g. `tar.gz`, `zip`, etc.
pub ext: SourceDistExtension, pub ext: SourceDistExtension,
/// The URL as it was provided by the user. /// The URL as it was provided by the user.
@ -336,7 +336,7 @@ pub struct PathSourceDist {
pub struct DirectorySourceDist { pub struct DirectorySourceDist {
pub name: PackageName, pub name: PackageName,
/// The absolute path to the distribution which we use for installing. /// The absolute path to the distribution which we use for installing.
pub install_path: PathBuf, pub install_path: Box<Path>,
/// Whether the package should be installed in editable mode. /// Whether the package should be installed in editable mode.
pub editable: bool, pub editable: bool,
/// Whether the package should be built and installed. /// Whether the package should be built and installed.
@ -352,7 +352,7 @@ impl Dist {
name: PackageName, name: PackageName,
url: VerbatimUrl, url: VerbatimUrl,
location: Url, location: Url,
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
ext: DistExtension, ext: DistExtension,
) -> Result<Dist, Error> { ) -> Result<Dist, Error> {
match ext { match ext {
@ -417,7 +417,7 @@ impl Dist {
} }
Ok(Self::Built(BuiltDist::Path(PathBuiltDist { Ok(Self::Built(BuiltDist::Path(PathBuiltDist {
filename, filename,
install_path, install_path: install_path.into_boxed_path(),
url, url,
}))) })))
} }
@ -434,7 +434,7 @@ impl Dist {
Ok(Self::Source(SourceDist::Path(PathSourceDist { Ok(Self::Source(SourceDist::Path(PathSourceDist {
name, name,
version, version,
install_path, install_path: install_path.into_boxed_path(),
ext, ext,
url, url,
}))) })))
@ -464,7 +464,7 @@ impl Dist {
// Determine whether the path represents an archive or a directory. // Determine whether the path represents an archive or a directory.
Ok(Self::Source(SourceDist::Directory(DirectorySourceDist { Ok(Self::Source(SourceDist::Directory(DirectorySourceDist {
name, name,
install_path, install_path: install_path.into_boxed_path(),
editable, editable,
r#virtual, r#virtual,
url, url,
@ -476,7 +476,7 @@ impl Dist {
name: PackageName, name: PackageName,
url: VerbatimUrl, url: VerbatimUrl,
git: GitUrl, git: GitUrl,
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
) -> Result<Dist, Error> { ) -> Result<Dist, Error> {
Ok(Self::Source(SourceDist::Git(GitSourceDist { Ok(Self::Source(SourceDist::Git(GitSourceDist {
name, name,

View File

@ -1,6 +1,6 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use thiserror::Error; use thiserror::Error;
@ -385,7 +385,7 @@ pub enum RequirementSource {
location: Url, location: Url,
/// For source distributions, the path to the distribution if it is not in the archive /// For source distributions, the path to the distribution if it is not in the archive
/// root. /// root.
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
/// The file extension, e.g. `tar.gz`, `zip`, etc. /// The file extension, e.g. `tar.gz`, `zip`, etc.
ext: DistExtension, ext: DistExtension,
/// The PEP 508 style URL in the format /// The PEP 508 style URL in the format
@ -397,7 +397,7 @@ pub enum RequirementSource {
/// The repository URL and reference to the commit to use. /// The repository URL and reference to the commit to use.
git: GitUrl, git: GitUrl,
/// The path to the source distribution if it is not in the repository root. /// The path to the source distribution if it is not in the repository root.
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
/// The PEP 508 style url in the format /// The PEP 508 style url in the format
/// `git+<scheme>://<domain>/<path>@<rev>#subdirectory=<subdirectory>`. /// `git+<scheme>://<domain>/<path>@<rev>#subdirectory=<subdirectory>`.
url: VerbatimUrl, url: VerbatimUrl,
@ -407,7 +407,7 @@ pub enum RequirementSource {
/// `.tar.gz` file). /// `.tar.gz` file).
Path { Path {
/// The absolute path to the distribution which we use for installing. /// The absolute path to the distribution which we use for installing.
install_path: PathBuf, install_path: Box<Path>,
/// The file extension, e.g. `tar.gz`, `zip`, etc. /// The file extension, e.g. `tar.gz`, `zip`, etc.
ext: DistExtension, ext: DistExtension,
/// The PEP 508 style URL in the format /// The PEP 508 style URL in the format
@ -418,7 +418,7 @@ pub enum RequirementSource {
/// source distribution with only a setup.py but non pyproject.toml in it). /// source distribution with only a setup.py but non pyproject.toml in it).
Directory { Directory {
/// The absolute path to the distribution which we use for installing. /// The absolute path to the distribution which we use for installing.
install_path: PathBuf, install_path: Box<Path>,
/// For a source tree (a directory), whether to install as an editable. /// For a source tree (a directory), whether to install as an editable.
editable: bool, editable: bool,
/// For a source tree (a directory), whether the project should be built and installed. /// For a source tree (a directory), whether the project should be built and installed.
@ -572,7 +572,8 @@ impl RequirementSource {
url, url,
} => Ok(Self::Path { } => Ok(Self::Path {
install_path: relative_to(&install_path, path) install_path: relative_to(&install_path, path)
.or_else(|_| std::path::absolute(install_path))?, .or_else(|_| std::path::absolute(install_path))?
.into_boxed_path(),
ext, ext,
url, url,
}), }),
@ -584,7 +585,8 @@ impl RequirementSource {
.. ..
} => Ok(Self::Directory { } => Ok(Self::Directory {
install_path: relative_to(&install_path, path) install_path: relative_to(&install_path, path)
.or_else(|_| std::path::absolute(install_path))?, .or_else(|_| std::path::absolute(install_path))?
.into_boxed_path(),
editable, editable,
r#virtual, r#virtual,
url, url,
@ -821,7 +823,7 @@ impl TryFrom<RequirementSourceWire> for RequirementSource {
Ok(Self::Git { Ok(Self::Git {
git: GitUrl::from_fields(repository, reference, precise)?, git: GitUrl::from_fields(repository, reference, precise)?,
subdirectory: subdirectory.map(PathBuf::from), subdirectory: subdirectory.map(Box::<Path>::from),
url, url,
}) })
} }
@ -836,7 +838,7 @@ impl TryFrom<RequirementSourceWire> for RequirementSource {
Ok(Self::Url { Ok(Self::Url {
location, location,
subdirectory: subdirectory.map(PathBuf::from), subdirectory: subdirectory.map(Box::<Path>::from),
ext: DistExtension::from_path(url.path()) ext: DistExtension::from_path(url.path())
.map_err(|err| ParsedUrlError::MissingExtensionUrl(url.to_string(), err))?, .map_err(|err| ParsedUrlError::MissingExtensionUrl(url.to_string(), err))?,
url: VerbatimUrl::from_url(url.clone()), url: VerbatimUrl::from_url(url.clone()),
@ -847,18 +849,19 @@ impl TryFrom<RequirementSourceWire> for RequirementSource {
// sources in the lockfile, we replace the URL anyway. Ideally, we'd either remove the // sources in the lockfile, we replace the URL anyway. Ideally, we'd either remove the
// URL field or make it optional. // URL field or make it optional.
RequirementSourceWire::Path { path } => { RequirementSourceWire::Path { path } => {
let path = PathBuf::from(path); let path = Box::<Path>::from(path);
let url = let url =
VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf(CWD.join(&path)))?; VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf(CWD.join(&path)))?;
Ok(Self::Path { Ok(Self::Path {
ext: DistExtension::from_path(path.as_path()) ext: DistExtension::from_path(&path).map_err(|err| {
.map_err(|err| ParsedUrlError::MissingExtensionPath(path.clone(), err))?, ParsedUrlError::MissingExtensionPath(path.to_path_buf(), err)
})?,
install_path: path, install_path: path,
url, url,
}) })
} }
RequirementSourceWire::Directory { directory } => { RequirementSourceWire::Directory { directory } => {
let directory = PathBuf::from(directory); let directory = Box::<Path>::from(directory);
let url = VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf( let url = VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf(
CWD.join(&directory), CWD.join(&directory),
))?; ))?;
@ -870,7 +873,7 @@ impl TryFrom<RequirementSourceWire> for RequirementSource {
}) })
} }
RequirementSourceWire::Editable { editable } => { RequirementSourceWire::Editable { editable } => {
let editable = PathBuf::from(editable); let editable = Box::<Path>::from(editable);
let url = VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf( let url = VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf(
CWD.join(&editable), CWD.join(&editable),
))?; ))?;
@ -882,7 +885,7 @@ impl TryFrom<RequirementSourceWire> for RequirementSource {
}) })
} }
RequirementSourceWire::Virtual { r#virtual } => { RequirementSourceWire::Virtual { r#virtual } => {
let r#virtual = PathBuf::from(r#virtual); let r#virtual = Box::<Path>::from(r#virtual);
let url = VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf( let url = VerbatimUrl::from_normalized_path(uv_fs::normalize_path_buf(
CWD.join(&r#virtual), CWD.join(&r#virtual),
))?; ))?;
@ -947,7 +950,7 @@ mod tests {
groups: Box::new([]), groups: Box::new([]),
marker: MarkerTree::TRUE, marker: MarkerTree::TRUE,
source: RequirementSource::Directory { source: RequirementSource::Directory {
install_path: PathBuf::from(path), install_path: PathBuf::from(path).into_boxed_path(),
editable: false, editable: false,
r#virtual: false, r#virtual: false,
url: VerbatimUrl::from_absolute_path(path).unwrap(), url: VerbatimUrl::from_absolute_path(path).unwrap(),

View File

@ -216,7 +216,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
{ {
Ok(archive) => Ok(LocalWheel { Ok(archive) => Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: wheel.filename.clone(), filename: wheel.filename.clone(),
cache: CacheInfo::default(), cache: CacheInfo::default(),
@ -247,7 +251,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
Ok(LocalWheel { Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: wheel.filename.clone(), filename: wheel.filename.clone(),
cache: CacheInfo::default(), cache: CacheInfo::default(),
@ -279,7 +287,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
{ {
Ok(archive) => Ok(LocalWheel { Ok(archive) => Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: wheel.filename.clone(), filename: wheel.filename.clone(),
cache: CacheInfo::default(), cache: CacheInfo::default(),
@ -303,7 +315,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
.await?; .await?;
Ok(LocalWheel { Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: wheel.filename.clone(), filename: wheel.filename.clone(),
cache: CacheInfo::default(), cache: CacheInfo::default(),
@ -368,7 +384,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
Ok(archive) => { Ok(archive) => {
return Ok(LocalWheel { return Ok(LocalWheel {
dist: Dist::Source(dist.clone()), dist: Dist::Source(dist.clone()),
archive, archive: archive.into_boxed_path(),
filename: built_wheel.filename, filename: built_wheel.filename,
hashes: built_wheel.hashes, hashes: built_wheel.hashes,
cache: built_wheel.cache_info, cache: built_wheel.cache_info,
@ -385,7 +401,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
Ok(LocalWheel { Ok(LocalWheel {
dist: Dist::Source(dist.clone()), dist: Dist::Source(dist.clone()),
archive: self.build_context.cache().archive(&id), archive: self.build_context.cache().archive(&id).into_boxed_path(),
hashes: built_wheel.hashes, hashes: built_wheel.hashes,
filename: built_wheel.filename, filename: built_wheel.filename,
cache: built_wheel.cache_info, cache: built_wheel.cache_info,
@ -837,7 +853,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
if let Some(archive) = archive { if let Some(archive) = archive {
Ok(LocalWheel { Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: filename.clone(), filename: filename.clone(),
cache: CacheInfo::from_timestamp(modified), cache: CacheInfo::from_timestamp(modified),
@ -859,7 +879,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
Ok(LocalWheel { Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: filename.clone(), filename: filename.clone(),
cache: CacheInfo::from_timestamp(modified), cache: CacheInfo::from_timestamp(modified),
@ -905,7 +929,11 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
Ok(LocalWheel { Ok(LocalWheel {
dist: Dist::Built(dist.clone()), dist: Dist::Built(dist.clone()),
archive: self.build_context.cache().archive(&archive.id), archive: self
.build_context
.cache()
.archive(&archive.id)
.into_boxed_path(),
hashes: archive.hashes, hashes: archive.hashes,
filename: filename.clone(), filename: filename.clone(),
cache: CacheInfo::from_timestamp(modified), cache: CacheInfo::from_timestamp(modified),

View File

@ -1,12 +1,12 @@
use std::path::{Path, PathBuf}; use std::path::Path;
use crate::Error; use uv_cache_info::CacheInfo;
use uv_distribution_filename::WheelFilename; use uv_distribution_filename::WheelFilename;
use uv_distribution_types::{CachedDist, Dist, Hashed}; use uv_distribution_types::{CachedDist, Dist, Hashed};
use uv_metadata::read_flat_wheel_metadata; use uv_metadata::read_flat_wheel_metadata;
use uv_pypi_types::{HashDigest, HashDigests, ResolutionMetadata}; use uv_pypi_types::{HashDigest, HashDigests, ResolutionMetadata};
use uv_cache_info::CacheInfo; use crate::Error;
/// A locally available wheel. /// A locally available wheel.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -17,7 +17,7 @@ pub struct LocalWheel {
pub(crate) filename: WheelFilename, pub(crate) filename: WheelFilename,
/// The canonicalized path in the cache directory to which the wheel was downloaded. /// The canonicalized path in the cache directory to which the wheel was downloaded.
/// Typically, a directory within the archive bucket. /// Typically, a directory within the archive bucket.
pub(crate) archive: PathBuf, pub(crate) archive: Box<Path>,
/// The cache index of the wheel. /// The cache index of the wheel.
pub(crate) cache: CacheInfo, pub(crate) cache: CacheInfo,
/// The computed hashes of the wheel. /// The computed hashes of the wheel.
@ -43,7 +43,7 @@ impl LocalWheel {
/// Read the [`ResolutionMetadata`] from a wheel. /// Read the [`ResolutionMetadata`] from a wheel.
pub fn metadata(&self) -> Result<ResolutionMetadata, Error> { pub fn metadata(&self) -> Result<ResolutionMetadata, Error> {
read_flat_wheel_metadata(&self.filename, &self.archive) read_flat_wheel_metadata(&self.filename, &self.archive)
.map_err(|err| Error::WheelMetadata(self.archive.clone(), Box::new(err))) .map_err(|err| Error::WheelMetadata(self.archive.to_path_buf(), Box::new(err)))
} }
} }

View File

@ -50,7 +50,7 @@ impl CachedWheel {
pub fn into_registry_dist(self) -> CachedRegistryDist { pub fn into_registry_dist(self) -> CachedRegistryDist {
CachedRegistryDist { CachedRegistryDist {
filename: self.filename, filename: self.filename,
path: self.entry.into_path_buf(), path: self.entry.into_path_buf().into_boxed_path(),
hashes: self.hashes, hashes: self.hashes,
cache_info: self.cache_info, cache_info: self.cache_info,
} }
@ -65,7 +65,7 @@ impl CachedWheel {
parsed_url: dist.parsed_url(), parsed_url: dist.parsed_url(),
verbatim: dist.url.clone(), verbatim: dist.url.clone(),
}, },
path: self.entry.into_path_buf(), path: self.entry.into_path_buf().into_boxed_path(),
hashes: self.hashes, hashes: self.hashes,
cache_info: self.cache_info, cache_info: self.cache_info,
} }
@ -80,7 +80,7 @@ impl CachedWheel {
parsed_url: dist.parsed_url(), parsed_url: dist.parsed_url(),
verbatim: dist.url.clone(), verbatim: dist.url.clone(),
}, },
path: self.entry.into_path_buf(), path: self.entry.into_path_buf().into_boxed_path(),
hashes: self.hashes, hashes: self.hashes,
cache_info: self.cache_info, cache_info: self.cache_info,
} }
@ -95,7 +95,7 @@ impl CachedWheel {
parsed_url: dist.parsed_url(), parsed_url: dist.parsed_url(),
verbatim: dist.url.clone(), verbatim: dist.url.clone(),
}, },
path: self.entry.into_path_buf(), path: self.entry.into_path_buf().into_boxed_path(),
hashes: self.hashes, hashes: self.hashes,
cache_info: self.cache_info, cache_info: self.cache_info,
} }
@ -110,7 +110,7 @@ impl CachedWheel {
parsed_url: dist.parsed_url(), parsed_url: dist.parsed_url(),
verbatim: dist.url.clone(), verbatim: dist.url.clone(),
}, },
path: self.entry.into_path_buf(), path: self.entry.into_path_buf().into_boxed_path(),
hashes: self.hashes, hashes: self.hashes,
cache_info: self.cache_info, cache_info: self.cache_info,
} }

View File

@ -171,7 +171,7 @@ impl LoweredRequirement {
} => { } => {
let source = git_source( let source = git_source(
&git, &git,
subdirectory.map(PathBuf::from), subdirectory.map(Box::<Path>::from),
rev, rev,
tag, tag,
branch, branch,
@ -185,7 +185,7 @@ impl LoweredRequirement {
.. ..
} => { } => {
let source = let source =
url_source(&requirement, url, subdirectory.map(PathBuf::from))?; url_source(&requirement, url, subdirectory.map(Box::<Path>::from))?;
(source, marker) (source, marker)
} }
Source::Path { Source::Path {
@ -196,7 +196,7 @@ impl LoweredRequirement {
.. ..
} => { } => {
let source = path_source( let source = path_source(
PathBuf::from(path), path,
git_member, git_member,
origin, origin,
project_dir, project_dir,
@ -298,20 +298,20 @@ impl LoweredRequirement {
subdirectory: if subdirectory == PathBuf::new() { subdirectory: if subdirectory == PathBuf::new() {
None None
} else { } else {
Some(subdirectory) Some(subdirectory.into_boxed_path())
}, },
url, url,
} }
} else if member.pyproject_toml().is_package() { } else if member.pyproject_toml().is_package() {
RequirementSource::Directory { RequirementSource::Directory {
install_path, install_path: install_path.into_boxed_path(),
url, url,
editable: true, editable: true,
r#virtual: false, r#virtual: false,
} }
} else { } else {
RequirementSource::Directory { RequirementSource::Directory {
install_path, install_path: install_path.into_boxed_path(),
url, url,
editable: false, editable: false,
r#virtual: true, r#virtual: true,
@ -404,7 +404,7 @@ impl LoweredRequirement {
} => { } => {
let source = git_source( let source = git_source(
&git, &git,
subdirectory.map(PathBuf::from), subdirectory.map(Box::<Path>::from),
rev, rev,
tag, tag,
branch, branch,
@ -418,7 +418,7 @@ impl LoweredRequirement {
.. ..
} => { } => {
let source = let source =
url_source(&requirement, url, subdirectory.map(PathBuf::from))?; url_source(&requirement, url, subdirectory.map(Box::<Path>::from))?;
(source, marker) (source, marker)
} }
Source::Path { Source::Path {
@ -429,7 +429,7 @@ impl LoweredRequirement {
.. ..
} => { } => {
let source = path_source( let source = path_source(
PathBuf::from(path), path,
None, None,
RequirementOrigin::Project, RequirementOrigin::Project,
dir, dir,
@ -554,7 +554,7 @@ impl std::fmt::Display for SourceKind {
/// Convert a Git source into a [`RequirementSource`]. /// Convert a Git source into a [`RequirementSource`].
fn git_source( fn git_source(
git: &Url, git: &Url,
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
rev: Option<String>, rev: Option<String>,
tag: Option<String>, tag: Option<String>,
branch: Option<String>, branch: Option<String>,
@ -575,7 +575,7 @@ fn git_source(
if let Some(subdirectory) = subdirectory.as_ref() { if let Some(subdirectory) = subdirectory.as_ref() {
let subdirectory = subdirectory let subdirectory = subdirectory
.to_str() .to_str()
.ok_or_else(|| LoweringError::NonUtf8Path(subdirectory.clone()))?; .ok_or_else(|| LoweringError::NonUtf8Path(subdirectory.to_path_buf()))?;
url.set_fragment(Some(&format!("subdirectory={subdirectory}"))); url.set_fragment(Some(&format!("subdirectory={subdirectory}")));
} }
let url = VerbatimUrl::from_url(url); let url = VerbatimUrl::from_url(url);
@ -593,7 +593,7 @@ fn git_source(
fn url_source( fn url_source(
requirement: &uv_pep508::Requirement<VerbatimParsedUrl>, requirement: &uv_pep508::Requirement<VerbatimParsedUrl>,
url: Url, url: Url,
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
) -> Result<RequirementSource, LoweringError> { ) -> Result<RequirementSource, LoweringError> {
let mut verbatim_url = url.clone(); let mut verbatim_url = url.clone();
if verbatim_url.fragment().is_some() { if verbatim_url.fragment().is_some() {
@ -602,7 +602,7 @@ fn url_source(
if let Some(subdirectory) = subdirectory.as_ref() { if let Some(subdirectory) = subdirectory.as_ref() {
let subdirectory = subdirectory let subdirectory = subdirectory
.to_str() .to_str()
.ok_or_else(|| LoweringError::NonUtf8Path(subdirectory.clone()))?; .ok_or_else(|| LoweringError::NonUtf8Path(subdirectory.to_path_buf()))?;
verbatim_url.set_fragment(Some(&format!("subdirectory={subdirectory}"))); verbatim_url.set_fragment(Some(&format!("subdirectory={subdirectory}")));
} }
@ -691,7 +691,7 @@ fn path_source(
subdirectory: if subdirectory == PathBuf::new() { subdirectory: if subdirectory == PathBuf::new() {
None None
} else { } else {
Some(subdirectory) Some(subdirectory.into_boxed_path())
}, },
url, url,
}); });
@ -699,7 +699,7 @@ fn path_source(
if editable == Some(true) { if editable == Some(true) {
Ok(RequirementSource::Directory { Ok(RequirementSource::Directory {
install_path, install_path: install_path.into_boxed_path(),
url, url,
editable: true, editable: true,
r#virtual: false, r#virtual: false,
@ -716,7 +716,7 @@ fn path_source(
}); });
Ok(RequirementSource::Directory { Ok(RequirementSource::Directory {
install_path, install_path: install_path.into_boxed_path(),
url, url,
editable: false, editable: false,
// If a project is not a package, treat it as a virtual dependency. // If a project is not a package, treat it as a virtual dependency.
@ -737,7 +737,7 @@ fn path_source(
Ok(RequirementSource::Path { Ok(RequirementSource::Path {
ext: DistExtension::from_path(&install_path) ext: DistExtension::from_path(&install_path)
.map_err(|err| ParsedUrlError::MissingExtensionPath(path.to_path_buf(), err))?, .map_err(|err| ParsedUrlError::MissingExtensionPath(path.to_path_buf(), err))?,
install_path, install_path: install_path.into_boxed_path(),
url, url,
}) })
} }

View File

@ -1,4 +1,4 @@
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use uv_cache::CacheShard; use uv_cache::CacheShard;
@ -15,9 +15,9 @@ use uv_pypi_types::{HashDigest, HashDigests};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct BuiltWheelMetadata { pub(crate) struct BuiltWheelMetadata {
/// The path to the built wheel. /// The path to the built wheel.
pub(crate) path: PathBuf, pub(crate) path: Box<Path>,
/// The expected path to the downloaded wheel's entry in the cache. /// The expected path to the downloaded wheel's entry in the cache.
pub(crate) target: PathBuf, pub(crate) target: Box<Path>,
/// The parsed filename. /// The parsed filename.
pub(crate) filename: WheelFilename, pub(crate) filename: WheelFilename,
/// The computed hashes of the source distribution from which the wheel was built. /// The computed hashes of the source distribution from which the wheel was built.
@ -48,8 +48,8 @@ impl BuiltWheelMetadata {
let filename = path.file_name()?.to_str()?; let filename = path.file_name()?.to_str()?;
let filename = WheelFilename::from_str(filename).ok()?; let filename = WheelFilename::from_str(filename).ok()?;
Some(Self { Some(Self {
target: cache_shard.join(filename.stem()), target: cache_shard.join(filename.stem()).into_boxed_path(),
path, path: path.into_boxed_path(),
filename, filename,
cache_info: CacheInfo::default(), cache_info: CacheInfo::default(),
hashes: HashDigests::empty(), hashes: HashDigests::empty(),

View File

@ -487,8 +487,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.map_err(Error::CacheWrite)?; .map_err(Error::CacheWrite)?;
Ok(BuiltWheelMetadata { Ok(BuiltWheelMetadata {
path: cache_shard.join(&disk_filename), path: cache_shard.join(&disk_filename).into_boxed_path(),
target: cache_shard.join(wheel_filename.stem()), target: cache_shard.join(wheel_filename.stem()).into_boxed_path(),
filename: wheel_filename, filename: wheel_filename,
hashes: revision.into_hashes(), hashes: revision.into_hashes(),
cache_info: CacheInfo::default(), cache_info: CacheInfo::default(),
@ -840,8 +840,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.map_err(Error::CacheWrite)?; .map_err(Error::CacheWrite)?;
Ok(BuiltWheelMetadata { Ok(BuiltWheelMetadata {
path: cache_shard.join(&disk_filename), path: cache_shard.join(&disk_filename).into_boxed_path(),
target: cache_shard.join(filename.stem()), target: cache_shard.join(filename.stem()).into_boxed_path(),
filename, filename,
hashes: revision.into_hashes(), hashes: revision.into_hashes(),
cache_info, cache_info,
@ -1137,8 +1137,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.map_err(Error::CacheWrite)?; .map_err(Error::CacheWrite)?;
Ok(BuiltWheelMetadata { Ok(BuiltWheelMetadata {
path: cache_shard.join(&disk_filename), path: cache_shard.join(&disk_filename).into_boxed_path(),
target: cache_shard.join(filename.stem()), target: cache_shard.join(filename.stem()).into_boxed_path(),
filename, filename,
hashes: revision.into_hashes(), hashes: revision.into_hashes(),
cache_info, cache_info,
@ -1527,8 +1527,8 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.map_err(Error::CacheWrite)?; .map_err(Error::CacheWrite)?;
Ok(BuiltWheelMetadata { Ok(BuiltWheelMetadata {
path: cache_shard.join(&disk_filename), path: cache_shard.join(&disk_filename).into_boxed_path(),
target: cache_shard.join(filename.stem()), target: cache_shard.join(filename.stem()).into_boxed_path(),
filename, filename,
hashes: HashDigests::empty(), hashes: HashDigests::empty(),
cache_info: CacheInfo::default(), cache_info: CacheInfo::default(),

View File

@ -344,7 +344,7 @@ pub fn relative_to(
pub struct PortablePath<'a>(&'a Path); pub struct PortablePath<'a>(&'a Path);
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct PortablePathBuf(PathBuf); pub struct PortablePathBuf(Box<Path>);
#[cfg(feature = "schemars")] #[cfg(feature = "schemars")]
impl schemars::JsonSchema for PortablePathBuf { impl schemars::JsonSchema for PortablePathBuf {
@ -397,21 +397,21 @@ impl std::fmt::Display for PortablePathBuf {
impl From<&str> for PortablePathBuf { impl From<&str> for PortablePathBuf {
fn from(path: &str) -> Self { fn from(path: &str) -> Self {
if path == "." { if path == "." {
Self(PathBuf::new()) Self(PathBuf::new().into_boxed_path())
} else { } else {
Self(PathBuf::from(path)) Self(PathBuf::from(path).into_boxed_path())
} }
} }
} }
impl From<PortablePathBuf> for PathBuf { impl From<PortablePathBuf> for Box<Path> {
fn from(portable: PortablePathBuf) -> Self { fn from(portable: PortablePathBuf) -> Self {
portable.0 portable.0
} }
} }
impl From<PathBuf> for PortablePathBuf { impl From<Box<Path>> for PortablePathBuf {
fn from(path: PathBuf) -> Self { fn from(path: Box<Path>) -> Self {
Self(path) Self(path)
} }
} }
@ -444,13 +444,19 @@ impl<'de> serde::de::Deserialize<'de> for PortablePathBuf {
{ {
let s = String::deserialize(deserializer)?; let s = String::deserialize(deserializer)?;
if s == "." { if s == "." {
Ok(Self(PathBuf::new())) Ok(Self(PathBuf::new().into_boxed_path()))
} else { } else {
Ok(Self(PathBuf::from(s))) Ok(Self(PathBuf::from(s).into_boxed_path()))
} }
} }
} }
impl AsRef<Path> for PortablePathBuf {
fn as_ref(&self) -> &Path {
&self.0
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -33,9 +33,9 @@ pub enum GitError {
/// A global cache of the result of `which git`. /// A global cache of the result of `which git`.
pub static GIT: LazyLock<Result<PathBuf, GitError>> = LazyLock::new(|| { pub static GIT: LazyLock<Result<PathBuf, GitError>> = LazyLock::new(|| {
which::which("git").map_err(|e| match e { which::which("git").map_err(|err| match err {
which::Error::CannotFindBinaryPath => GitError::GitNotFound, which::Error::CannotFindBinaryPath => GitError::GitNotFound,
e => GitError::Other(e), err => GitError::Other(err),
}) })
}); });

View File

@ -196,7 +196,7 @@ impl<'a> Planner<'a> {
}, },
hashes: archive.hashes, hashes: archive.hashes,
cache_info, cache_info,
path: cache.archive(&archive.id), path: cache.archive(&archive.id).into_boxed_path(),
}; };
debug!("URL wheel requirement already cached: {cached_dist}"); debug!("URL wheel requirement already cached: {cached_dist}");
@ -256,7 +256,7 @@ impl<'a> Planner<'a> {
}, },
hashes: archive.hashes, hashes: archive.hashes,
cache_info, cache_info,
path: cache.archive(&archive.id), path: cache.archive(&archive.id).into_boxed_path(),
}; };
debug!("Path wheel requirement already cached: {cached_dist}"); debug!("Path wheel requirement already cached: {cached_dist}");

View File

@ -189,7 +189,7 @@ impl RequirementSatisfaction {
return Self::Mismatch; return Self::Mismatch;
}; };
if !(*requested_path == installed_path if !(**requested_path == installed_path
|| is_same_file(requested_path, &installed_path).unwrap_or(false)) || is_same_file(requested_path, &installed_path).unwrap_or(false))
{ {
trace!( trace!(
@ -258,7 +258,7 @@ impl RequirementSatisfaction {
return Self::Mismatch; return Self::Mismatch;
}; };
if !(*requested_path == installed_path if !(**requested_path == installed_path
|| is_same_file(requested_path, &installed_path).unwrap_or(false)) || is_same_file(requested_path, &installed_path).unwrap_or(false))
{ {
trace!( trace!(

View File

@ -1,5 +1,5 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::path::PathBuf; use std::path::Path;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use url::Url; use url::Url;
@ -27,7 +27,7 @@ pub enum DirectUrl {
url: String, url: String,
archive_info: ArchiveInfo, archive_info: ArchiveInfo,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
}, },
/// The direct URL is path to a VCS repository. For example: /// The direct URL is path to a VCS repository. For example:
/// ```json /// ```json
@ -37,7 +37,7 @@ pub enum DirectUrl {
url: String, url: String,
vcs_info: VcsInfo, vcs_info: VcsInfo,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
}, },
} }

View File

@ -73,17 +73,19 @@ impl UnnamedRequirementUrl for VerbatimParsedUrl {
} else { } else {
verbatim_path.extension().is_none() verbatim_path.extension().is_none()
}; };
let url = verbatim.to_url();
let install_path = verbatim.as_path()?.into_boxed_path();
let parsed_url = if is_dir { let parsed_url = if is_dir {
ParsedUrl::Directory(ParsedDirectoryUrl { ParsedUrl::Directory(ParsedDirectoryUrl {
url: verbatim.to_url(), url,
install_path: verbatim.as_path()?, install_path,
editable: false, editable: false,
r#virtual: false, r#virtual: false,
}) })
} else { } else {
ParsedUrl::Path(ParsedPathUrl { ParsedUrl::Path(ParsedPathUrl {
url: verbatim.to_url(), url,
install_path: verbatim.as_path()?, install_path,
ext: DistExtension::from_path(&path).map_err(|err| { ext: DistExtension::from_path(&path).map_err(|err| {
ParsedUrlError::MissingExtensionPath(path.as_ref().to_path_buf(), err) ParsedUrlError::MissingExtensionPath(path.as_ref().to_path_buf(), err)
})?, })?,
@ -103,17 +105,19 @@ impl UnnamedRequirementUrl for VerbatimParsedUrl {
} else { } else {
verbatim_path.extension().is_none() verbatim_path.extension().is_none()
}; };
let url = verbatim.to_url();
let install_path = verbatim.as_path()?.into_boxed_path();
let parsed_url = if is_dir { let parsed_url = if is_dir {
ParsedUrl::Directory(ParsedDirectoryUrl { ParsedUrl::Directory(ParsedDirectoryUrl {
url: verbatim.to_url(), url,
install_path: verbatim.as_path()?, install_path,
editable: false, editable: false,
r#virtual: false, r#virtual: false,
}) })
} else { } else {
ParsedUrl::Path(ParsedPathUrl { ParsedUrl::Path(ParsedPathUrl {
url: verbatim.to_url(), url,
install_path: verbatim.as_path()?, install_path,
ext: DistExtension::from_path(&path).map_err(|err| { ext: DistExtension::from_path(&path).map_err(|err| {
ParsedUrlError::MissingExtensionPath(path.as_ref().to_path_buf(), err) ParsedUrlError::MissingExtensionPath(path.as_ref().to_path_buf(), err)
})?, })?,
@ -190,14 +194,14 @@ impl ParsedUrl {
pub struct ParsedPathUrl { pub struct ParsedPathUrl {
pub url: Url, pub url: Url,
/// The absolute path to the distribution which we use for installing. /// The absolute path to the distribution which we use for installing.
pub install_path: PathBuf, pub install_path: Box<Path>,
/// The file extension, e.g. `tar.gz`, `zip`, etc. /// The file extension, e.g. `tar.gz`, `zip`, etc.
pub ext: DistExtension, pub ext: DistExtension,
} }
impl ParsedPathUrl { impl ParsedPathUrl {
/// Construct a [`ParsedPathUrl`] from a path requirement source. /// Construct a [`ParsedPathUrl`] from a path requirement source.
pub fn from_source(install_path: PathBuf, ext: DistExtension, url: Url) -> Self { pub fn from_source(install_path: Box<Path>, ext: DistExtension, url: Url) -> Self {
Self { Self {
url, url,
install_path, install_path,
@ -214,14 +218,14 @@ impl ParsedPathUrl {
pub struct ParsedDirectoryUrl { pub struct ParsedDirectoryUrl {
pub url: Url, pub url: Url,
/// The absolute path to the distribution which we use for installing. /// The absolute path to the distribution which we use for installing.
pub install_path: PathBuf, pub install_path: Box<Path>,
pub editable: bool, pub editable: bool,
pub r#virtual: bool, pub r#virtual: bool,
} }
impl ParsedDirectoryUrl { impl ParsedDirectoryUrl {
/// Construct a [`ParsedDirectoryUrl`] from a path requirement source. /// Construct a [`ParsedDirectoryUrl`] from a path requirement source.
pub fn from_source(install_path: PathBuf, editable: bool, r#virtual: bool, url: Url) -> Self { pub fn from_source(install_path: Box<Path>, editable: bool, r#virtual: bool, url: Url) -> Self {
Self { Self {
url, url,
install_path, install_path,
@ -239,12 +243,12 @@ impl ParsedDirectoryUrl {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)]
pub struct ParsedGitUrl { pub struct ParsedGitUrl {
pub url: GitUrl, pub url: GitUrl,
pub subdirectory: Option<PathBuf>, pub subdirectory: Option<Box<Path>>,
} }
impl ParsedGitUrl { impl ParsedGitUrl {
/// Construct a [`ParsedGitUrl`] from a Git requirement source. /// Construct a [`ParsedGitUrl`] from a Git requirement source.
pub fn from_source(url: GitUrl, subdirectory: Option<PathBuf>) -> Self { pub fn from_source(url: GitUrl, subdirectory: Option<Box<Path>>) -> Self {
Self { url, subdirectory } Self { url, subdirectory }
} }
} }
@ -257,7 +261,7 @@ impl TryFrom<Url> for ParsedGitUrl {
/// When the URL includes a prefix, it's presumed to come from a PEP 508 requirement; when it's /// When the URL includes a prefix, it's presumed to come from a PEP 508 requirement; when it's
/// excluded, it's presumed to come from `tool.uv.sources`. /// excluded, it's presumed to come from `tool.uv.sources`.
fn try_from(url_in: Url) -> Result<Self, Self::Error> { fn try_from(url_in: Url) -> Result<Self, Self::Error> {
let subdirectory = get_subdirectory(&url_in); let subdirectory = get_subdirectory(&url_in).map(PathBuf::into_boxed_path);
let url = url_in let url = url_in
.as_str() .as_str()
@ -278,13 +282,13 @@ impl TryFrom<Url> for ParsedGitUrl {
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct ParsedArchiveUrl { pub struct ParsedArchiveUrl {
pub url: Url, pub url: Url,
pub subdirectory: Option<PathBuf>, pub subdirectory: Option<Box<Path>>,
pub ext: DistExtension, pub ext: DistExtension,
} }
impl ParsedArchiveUrl { impl ParsedArchiveUrl {
/// Construct a [`ParsedArchiveUrl`] from a URL requirement source. /// Construct a [`ParsedArchiveUrl`] from a URL requirement source.
pub fn from_source(location: Url, subdirectory: Option<PathBuf>, ext: DistExtension) -> Self { pub fn from_source(location: Url, subdirectory: Option<Box<Path>>, ext: DistExtension) -> Self {
Self { Self {
url: location, url: location,
subdirectory, subdirectory,
@ -298,7 +302,7 @@ impl TryFrom<Url> for ParsedArchiveUrl {
fn try_from(mut url: Url) -> Result<Self, Self::Error> { fn try_from(mut url: Url) -> Result<Self, Self::Error> {
// Extract the `#subdirectory` fragment, if present. // Extract the `#subdirectory` fragment, if present.
let subdirectory = get_subdirectory(&url); let subdirectory = get_subdirectory(&url).map(PathBuf::into_boxed_path);
url.set_fragment(None); url.set_fragment(None);
// Infer the extension from the path. // Infer the extension from the path.
@ -377,7 +381,7 @@ impl TryFrom<Url> for ParsedUrl {
if is_dir { if is_dir {
Ok(Self::Directory(ParsedDirectoryUrl { Ok(Self::Directory(ParsedDirectoryUrl {
url, url,
install_path: path.clone(), install_path: path.into_boxed_path(),
editable: false, editable: false,
r#virtual: false, r#virtual: false,
})) }))
@ -386,7 +390,7 @@ impl TryFrom<Url> for ParsedUrl {
url, url,
ext: DistExtension::from_path(&path) ext: DistExtension::from_path(&path)
.map_err(|err| ParsedUrlError::MissingExtensionPath(path.clone(), err))?, .map_err(|err| ParsedUrlError::MissingExtensionPath(path.clone(), err))?,
install_path: path.clone(), install_path: path.into_boxed_path(),
})) }))
} }
} else { } else {

View File

@ -680,7 +680,7 @@ impl Lock {
let (Source::Editable(path) | Source::Virtual(path)) = &package.id.source else { let (Source::Editable(path) | Source::Virtual(path)) = &package.id.source else {
return false; return false;
}; };
path == Path::new("") path.as_ref() == Path::new("")
}) })
} }
@ -1356,7 +1356,8 @@ impl Lock {
let path = url.to_file_path().ok()?; let path = url.to_file_path().ok()?;
let path = relative_to(&path, root) let path = relative_to(&path, root)
.or_else(|_| std::path::absolute(path)) .or_else(|_| std::path::absolute(path))
.ok()?; .ok()?
.into_boxed_path();
Some(path) Some(path)
} }
}) })
@ -1698,7 +1699,7 @@ pub enum SatisfiesResult<'lock> {
/// The lockfile referenced a remote index that was not provided /// The lockfile referenced a remote index that was not provided
MissingRemoteIndex(&'lock PackageName, &'lock Version, &'lock UrlString), MissingRemoteIndex(&'lock PackageName, &'lock Version, &'lock UrlString),
/// The lockfile referenced a local index that was not provided /// The lockfile referenced a local index that was not provided
MissingLocalIndex(&'lock PackageName, &'lock Version, &'lock PathBuf), MissingLocalIndex(&'lock PackageName, &'lock Version, &'lock Path),
/// A package in the lockfile contains different `requires-dist` metadata than expected. /// A package in the lockfile contains different `requires-dist` metadata than expected.
MismatchedPackageRequirements( MismatchedPackageRequirements(
&'lock PackageName, &'lock PackageName,
@ -2151,7 +2152,7 @@ impl Package {
let path_dist = PathBuiltDist { let path_dist = PathBuiltDist {
filename, filename,
url: verbatim_url(&install_path, &self.id)?, url: verbatim_url(&install_path, &self.id)?,
install_path: absolute_path(workspace_root, path)?, install_path: absolute_path(workspace_root, path)?.into_boxed_path(),
}; };
let built_dist = BuiltDist::Path(path_dist); let built_dist = BuiltDist::Path(path_dist);
Ok(Dist::Built(built_dist)) Ok(Dist::Built(built_dist))
@ -2330,7 +2331,7 @@ impl Package {
name: self.id.name.clone(), name: self.id.name.clone(),
version: self.id.version.clone(), version: self.id.version.clone(),
url: verbatim_url(&install_path, &self.id)?, url: verbatim_url(&install_path, &self.id)?,
install_path, install_path: install_path.into_boxed_path(),
ext, ext,
}; };
uv_distribution_types::SourceDist::Path(path_dist) uv_distribution_types::SourceDist::Path(path_dist)
@ -2340,7 +2341,7 @@ impl Package {
let dir_dist = DirectorySourceDist { let dir_dist = DirectorySourceDist {
name: self.id.name.clone(), name: self.id.name.clone(),
url: verbatim_url(&install_path, &self.id)?, url: verbatim_url(&install_path, &self.id)?,
install_path, install_path: install_path.into_boxed_path(),
editable: false, editable: false,
r#virtual: false, r#virtual: false,
}; };
@ -2351,7 +2352,7 @@ impl Package {
let dir_dist = DirectorySourceDist { let dir_dist = DirectorySourceDist {
name: self.id.name.clone(), name: self.id.name.clone(),
url: verbatim_url(&install_path, &self.id)?, url: verbatim_url(&install_path, &self.id)?,
install_path, install_path: install_path.into_boxed_path(),
editable: true, editable: true,
r#virtual: false, r#virtual: false,
}; };
@ -2362,7 +2363,7 @@ impl Package {
let dir_dist = DirectorySourceDist { let dir_dist = DirectorySourceDist {
name: self.id.name.clone(), name: self.id.name.clone(),
url: verbatim_url(&install_path, &self.id)?, url: verbatim_url(&install_path, &self.id)?,
install_path, install_path: install_path.into_boxed_path(),
editable: false, editable: false,
r#virtual: true, r#virtual: true,
}; };
@ -2402,16 +2403,15 @@ impl Package {
return Ok(None); return Ok(None);
}; };
let location = url.to_url().map_err(LockErrorKind::InvalidUrl)?; let location = url.to_url().map_err(LockErrorKind::InvalidUrl)?;
let subdirectory = direct.subdirectory.as_ref().map(PathBuf::from);
let url = Url::from(ParsedArchiveUrl { let url = Url::from(ParsedArchiveUrl {
url: location.clone(), url: location.clone(),
subdirectory: subdirectory.clone(), subdirectory: direct.subdirectory.clone(),
ext: DistExtension::Source(ext), ext: DistExtension::Source(ext),
}); });
let direct_dist = DirectUrlSourceDist { let direct_dist = DirectUrlSourceDist {
name: self.id.name.clone(), name: self.id.name.clone(),
location: Box::new(location), location: Box::new(location),
subdirectory: subdirectory.clone(), subdirectory: direct.subdirectory.clone(),
ext, ext,
url: VerbatimUrl::from_url(url), url: VerbatimUrl::from_url(url),
}; };
@ -3060,13 +3060,13 @@ enum Source {
/// A direct HTTP(S) URL. /// A direct HTTP(S) URL.
Direct(UrlString, DirectSource), Direct(UrlString, DirectSource),
/// A path to a local source or built archive. /// A path to a local source or built archive.
Path(PathBuf), Path(Box<Path>),
/// A path to a local directory. /// A path to a local directory.
Directory(PathBuf), Directory(Box<Path>),
/// A path to a local directory that should be installed as editable. /// A path to a local directory that should be installed as editable.
Editable(PathBuf), Editable(Box<Path>),
/// A path to a local directory that should not be built or installed. /// A path to a local directory that should not be built or installed.
Virtual(PathBuf), Virtual(Box<Path>),
} }
impl Source { impl Source {
@ -3152,14 +3152,14 @@ impl Source {
let path = relative_to(&path_dist.install_path, root) let path = relative_to(&path_dist.install_path, root)
.or_else(|_| std::path::absolute(&path_dist.install_path)) .or_else(|_| std::path::absolute(&path_dist.install_path))
.map_err(LockErrorKind::DistributionRelativePath)?; .map_err(LockErrorKind::DistributionRelativePath)?;
Ok(Source::Path(path)) Ok(Source::Path(path.into_boxed_path()))
} }
fn from_path_source_dist(path_dist: &PathSourceDist, root: &Path) -> Result<Source, LockError> { fn from_path_source_dist(path_dist: &PathSourceDist, root: &Path) -> Result<Source, LockError> {
let path = relative_to(&path_dist.install_path, root) let path = relative_to(&path_dist.install_path, root)
.or_else(|_| std::path::absolute(&path_dist.install_path)) .or_else(|_| std::path::absolute(&path_dist.install_path))
.map_err(LockErrorKind::DistributionRelativePath)?; .map_err(LockErrorKind::DistributionRelativePath)?;
Ok(Source::Path(path)) Ok(Source::Path(path.into_boxed_path()))
} }
fn from_directory_source_dist( fn from_directory_source_dist(
@ -3170,11 +3170,11 @@ impl Source {
.or_else(|_| std::path::absolute(&directory_dist.install_path)) .or_else(|_| std::path::absolute(&directory_dist.install_path))
.map_err(LockErrorKind::DistributionRelativePath)?; .map_err(LockErrorKind::DistributionRelativePath)?;
if directory_dist.editable { if directory_dist.editable {
Ok(Source::Editable(path)) Ok(Source::Editable(path.into_boxed_path()))
} else if directory_dist.r#virtual { } else if directory_dist.r#virtual {
Ok(Source::Virtual(path)) Ok(Source::Virtual(path.into_boxed_path()))
} else { } else {
Ok(Source::Directory(path)) Ok(Source::Directory(path.into_boxed_path()))
} }
} }
@ -3191,7 +3191,7 @@ impl Source {
let path = relative_to(&path, root) let path = relative_to(&path, root)
.or_else(|_| std::path::absolute(&path)) .or_else(|_| std::path::absolute(&path))
.map_err(LockErrorKind::IndexRelativePath)?; .map_err(LockErrorKind::IndexRelativePath)?;
let source = RegistrySource::Path(path); let source = RegistrySource::Path(path.into_boxed_path());
Ok(Source::Registry(source)) Ok(Source::Registry(source))
} }
} }
@ -3418,7 +3418,7 @@ impl TryFrom<SourceWire> for Source {
Direct { url, subdirectory } => Ok(Source::Direct( Direct { url, subdirectory } => Ok(Source::Direct(
url, url,
DirectSource { DirectSource {
subdirectory: subdirectory.map(PathBuf::from), subdirectory: subdirectory.map(Box::<std::path::Path>::from),
}, },
)), )),
Path { path } => Ok(Source::Path(path.into())), Path { path } => Ok(Source::Path(path.into())),
@ -3435,7 +3435,7 @@ enum RegistrySource {
/// Ex) `https://pypi.org/simple` /// Ex) `https://pypi.org/simple`
Url(UrlString), Url(UrlString),
/// Ex) `../path/to/local/index` /// Ex) `../path/to/local/index`
Path(PathBuf), Path(Box<Path>),
} }
impl Display for RegistrySource { impl Display for RegistrySource {
@ -3506,7 +3506,7 @@ impl From<RegistrySourceWire> for RegistrySource {
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize)] #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize)]
struct DirectSource { struct DirectSource {
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
} }
/// NOTE: Care should be taken when adding variants to this enum. Namely, new /// NOTE: Care should be taken when adding variants to this enum. Namely, new
@ -3516,7 +3516,7 @@ struct DirectSource {
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
struct GitSource { struct GitSource {
precise: GitOid, precise: GitOid,
subdirectory: Option<PathBuf>, subdirectory: Option<Box<Path>>,
kind: GitSourceKind, kind: GitSourceKind,
} }
@ -3585,7 +3585,7 @@ enum SourceDist {
metadata: SourceDistMetadata, metadata: SourceDistMetadata,
}, },
Path { Path {
path: PathBuf, path: Box<Path>,
#[serde(flatten)] #[serde(flatten)]
metadata: SourceDistMetadata, metadata: SourceDistMetadata,
}, },
@ -3733,7 +3733,8 @@ impl SourceDist {
.map_err(|()| LockErrorKind::UrlToPath)?; .map_err(|()| LockErrorKind::UrlToPath)?;
let path = relative_to(&reg_dist_path, index_path) let path = relative_to(&reg_dist_path, index_path)
.or_else(|_| std::path::absolute(&reg_dist_path)) .or_else(|_| std::path::absolute(&reg_dist_path))
.map_err(LockErrorKind::DistributionRelativePath)?; .map_err(LockErrorKind::DistributionRelativePath)?
.into_boxed_path();
let hash = reg_dist.file.hashes.iter().max().cloned().map(Hash::from); let hash = reg_dist.file.hashes.iter().max().cloned().map(Hash::from);
let size = reg_dist.file.size; let size = reg_dist.file.size;
Ok(Some(SourceDist::Path { Ok(Some(SourceDist::Path {
@ -4036,7 +4037,8 @@ impl Wheel {
.map_err(|()| LockErrorKind::UrlToPath)?; .map_err(|()| LockErrorKind::UrlToPath)?;
let path = relative_to(&wheel_path, index_path) let path = relative_to(&wheel_path, index_path)
.or_else(|_| std::path::absolute(&wheel_path)) .or_else(|_| std::path::absolute(&wheel_path))
.map_err(LockErrorKind::DistributionRelativePath)?; .map_err(LockErrorKind::DistributionRelativePath)?
.into_boxed_path();
Ok(Wheel { Ok(Wheel {
url: WheelWireSource::Path { path }, url: WheelWireSource::Path { path },
hash: None, hash: None,
@ -4174,7 +4176,7 @@ enum WheelWireSource {
/// Used for wheels that come from local registries (like `--find-links`). /// Used for wheels that come from local registries (like `--find-links`).
Path { Path {
/// The path to the wheel, relative to the index. /// The path to the wheel, relative to the index.
path: PathBuf, path: Box<Path>,
}, },
/// Used for path wheels. /// Used for path wheels.
/// ///
@ -4520,7 +4522,8 @@ fn normalize_requirement(
ext, ext,
url: _, url: _,
} => { } => {
let install_path = uv_fs::normalize_path_buf(root.join(&install_path)); let install_path =
uv_fs::normalize_path_buf(root.join(&install_path)).into_boxed_path();
let url = VerbatimUrl::from_normalized_path(&install_path) let url = VerbatimUrl::from_normalized_path(&install_path)
.map_err(LockErrorKind::RequirementVerbatimUrl)?; .map_err(LockErrorKind::RequirementVerbatimUrl)?;
@ -4543,7 +4546,8 @@ fn normalize_requirement(
r#virtual, r#virtual,
url: _, url: _,
} => { } => {
let install_path = uv_fs::normalize_path_buf(root.join(&install_path)); let install_path =
uv_fs::normalize_path_buf(root.join(&install_path)).into_boxed_path();
let url = VerbatimUrl::from_normalized_path(&install_path) let url = VerbatimUrl::from_normalized_path(&install_path)
.map_err(LockErrorKind::RequirementVerbatimUrl)?; .map_err(LockErrorKind::RequirementVerbatimUrl)?;

View File

@ -524,16 +524,15 @@ impl std::fmt::Display for RequirementsTxtExport<'_> {
// Reconstruct the PEP 508-compatible URL from the `GitSource`. // Reconstruct the PEP 508-compatible URL from the `GitSource`.
let url = Url::from(ParsedGitUrl { let url = Url::from(ParsedGitUrl {
url: git_url.clone(), url: git_url.clone(),
subdirectory: git.subdirectory.as_ref().map(PathBuf::from), subdirectory: git.subdirectory.clone(),
}); });
write!(f, "{} @ {}", package.id.name, url)?; write!(f, "{} @ {}", package.id.name, url)?;
} }
Source::Direct(url, direct) => { Source::Direct(url, direct) => {
let subdirectory = direct.subdirectory.as_ref().map(PathBuf::from);
let url = Url::from(ParsedArchiveUrl { let url = Url::from(ParsedArchiveUrl {
url: url.to_url().map_err(|_| std::fmt::Error)?, url: url.to_url().map_err(|_| std::fmt::Error)?,
subdirectory: subdirectory.clone(), subdirectory: direct.subdirectory.clone(),
ext: DistExtension::Source(SourceDistExtension::TarGz), ext: DistExtension::Source(SourceDistExtension::TarGz),
}); });
write!(f, "{} @ {}", package.id.name, url)?; write!(f, "{} @ {}", package.id.name, url)?;

View File

@ -1452,7 +1452,8 @@ impl Source {
path: PortablePathBuf::from( path: PortablePathBuf::from(
relative_to(&install_path, root) relative_to(&install_path, root)
.or_else(|_| std::path::absolute(&install_path)) .or_else(|_| std::path::absolute(&install_path))
.map_err(SourceError::Absolute)?, .map_err(SourceError::Absolute)?
.into_boxed_path(),
), ),
marker: MarkerTree::TRUE, marker: MarkerTree::TRUE,
extra: None, extra: None,

View File

@ -311,14 +311,14 @@ impl Workspace {
marker: MarkerTree::TRUE, marker: MarkerTree::TRUE,
source: if member.pyproject_toml.is_package() { source: if member.pyproject_toml.is_package() {
RequirementSource::Directory { RequirementSource::Directory {
install_path: member.root.clone(), install_path: member.root.clone().into_boxed_path(),
editable: true, editable: true,
r#virtual: false, r#virtual: false,
url, url,
} }
} else { } else {
RequirementSource::Directory { RequirementSource::Directory {
install_path: member.root.clone(), install_path: member.root.clone().into_boxed_path(),
editable: false, editable: false,
r#virtual: true, r#virtual: true,
url, url,
@ -367,14 +367,14 @@ impl Workspace {
marker: MarkerTree::TRUE, marker: MarkerTree::TRUE,
source: if member.pyproject_toml.is_package() { source: if member.pyproject_toml.is_package() {
RequirementSource::Directory { RequirementSource::Directory {
install_path: member.root.clone(), install_path: member.root.clone().into_boxed_path(),
editable: true, editable: true,
r#virtual: false, r#virtual: false,
url, url,
} }
} else { } else {
RequirementSource::Directory { RequirementSource::Directory {
install_path: member.root.clone(), install_path: member.root.clone().into_boxed_path(),
editable: false, editable: false,
r#virtual: true, r#virtual: true,
url, url,