Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 0 additions & 44 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,14 @@ arrayvec = { version = "0.7.6" }
astral-tokio-tar = { version = "0.6.3" }
async-channel = { version = "2.3.1" }
async-compression = { version = "0.4.12", features = [
"bzip2",
"gzip",
"xz",
"zstd",
] }
async-trait = { version = "0.1.82" }
async_http_range_reader = { version = "0.11.0", package = "astral_async_http_range_reader" }
async_zip = { version = "0.0.20", package = "astral_async_zip", features = [
"bzip2",
"deflate",
"lzma",
"tokio",
"xz",
"zstd",
] }
axoupdater = { version = "0.10.0", default-features = false }
Expand Down Expand Up @@ -317,7 +312,6 @@ windows = { version = "0.61.0", features = [
windows-registry = { version = "0.5.0" }
windows-version = { version = "0.1.6" }
wiremock = { version = "0.6.4" }
xz2 = { version = "0.1.7", features = ["static"] }
zeroize = { version = "1.8.1" }

# dev-dependencies
Expand Down
3 changes: 0 additions & 3 deletions crates/uv-bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,3 @@ tempfile = { workspace = true }
tokio = { workspace = true }
tokio-util = { workspace = true }
toml = { workspace = true }

[features]
static = ["uv-extract/static"]
2 changes: 0 additions & 2 deletions crates/uv-bench/benches/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use uv_resolver::Manifest;

const MANY_FILES_WHEEL_FILENAME: &str = "manyfiles-0.0.0-py3-none-any.whl";
const MANY_FILES_WHEEL_FILE_COUNT: usize = 10_000;
const MANY_FILES_SDIST_FILENAME: &str = "manyfiles-0.0.0.tar.gz";
const MANY_FILES_SDIST_TOP_LEVEL: &str = "manyfiles-0.0.0";
const MANY_FILES_SDIST_FILE_COUNT: usize = 10_000;

Expand Down Expand Up @@ -126,7 +125,6 @@ fn unpack_sdist_many_files(c: &mut Criterion<WallTime>) {
|(archive, extracted_sdist)| {
let files = runtime
.block_on(uv_extract::stream::archive(
MANY_FILES_SDIST_FILENAME,
archive,
SourceDistExtension::TarGz,
extracted_sdist.path(),
Expand Down
14 changes: 5 additions & 9 deletions crates/uv-bin-install/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use tokio::io::{AsyncRead, ReadBuf};
use tokio_util::compat::FuturesAsyncReadCompatExt;
use url::Url;
use uv_client::retryable_on_request_failure;
use uv_distribution_filename::LegacySourceDistExtension;
use uv_distribution_filename::SourceDistExtension;
use uv_static::{astral_mirror_base_url, astral_mirror_url_from_env, custom_astral_mirror_url};

Expand Down Expand Up @@ -230,7 +231,7 @@ impl ArchiveFormat {
impl From<ArchiveFormat> for SourceDistExtension {
fn from(val: ArchiveFormat) -> Self {
match val {
ArchiveFormat::Zip => Self::Zip,
ArchiveFormat::Zip => Self::Legacy(LegacySourceDistExtension::Zip),
ArchiveFormat::TarGz => Self::TarGz,
}
}
Expand Down Expand Up @@ -841,14 +842,9 @@ async fn download_and_unpack(

let id = reporter.on_download_start(binary.name(), version, size);
let mut progress_reader = ProgressReader::new(reader, id, reporter);
stream::archive(
&download_url,
&mut progress_reader,
format.into(),
temp_dir.path(),
)
.await
.map_err(|e| Error::Extract { source: e })?;
stream::archive(&mut progress_reader, format.into(), temp_dir.path())
.await
.map_err(|e| Error::Extract { source: e })?;
reporter.on_download_complete(id);

// Find the binary in the extracted files
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ name = "uv-dev"
required-features = ["dev"]

[features]
default = ["performance", "uv-extract/static"]
default = ["performance"]
# Actually build the dev CLI.
dev = []
performance = ["performance-memory-allocator"]
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-dev/src/validate_zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub(crate) async fn validate_zip(

let target = tempfile::TempDir::new()?;

uv_extract::stream::unzip(args.url.into_url(), reader.compat(), target.path()).await?;
uv_extract::stream::unzip(reader.compat(), target.path()).await?;

Ok(())
}
80 changes: 54 additions & 26 deletions crates/uv-distribution-filename/src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,29 @@ pub enum DistExtension {
)]
#[rkyv(derive(Debug))]
pub enum SourceDistExtension {
TarGz,
Legacy(LegacySourceDistExtension),
}

#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Deserialize,
rkyv::Serialize,
)]
#[rkyv(derive(Debug))]
pub enum LegacySourceDistExtension {
Tar,
TarBz2,
TarGz,
TarLz,
TarLzma,
TarXz,
Expand Down Expand Up @@ -83,41 +103,49 @@ impl SourceDistExtension {

match extension {
"gz" if is_tar(path.as_ref()) => Ok(Self::TarGz),
// TODO: Remove these other extensions in the future.
// NOTE: These get parsed from network sources like PyPI, so we don't
// necessarily want to hard-fail, just skip in the future.
"zip" => Ok(Self::Zip),
"tar" => Ok(Self::Tar),
"tgz" => Ok(Self::Tgz),
"tbz" => Ok(Self::Tbz),
"txz" => Ok(Self::Txz),
"tlz" => Ok(Self::Tlz),
"bz2" if is_tar(path.as_ref()) => Ok(Self::TarBz2),
"xz" if is_tar(path.as_ref()) => Ok(Self::TarXz),
"lz" if is_tar(path.as_ref()) => Ok(Self::TarLz),
"lzma" if is_tar(path.as_ref()) => Ok(Self::TarLzma),
"zst" if is_tar(path.as_ref()) => Ok(Self::TarZst),
"zip" => Ok(Self::Legacy(LegacySourceDistExtension::Zip)),
"tar" => Ok(Self::Legacy(LegacySourceDistExtension::Tar)),
"tgz" => Ok(Self::Legacy(LegacySourceDistExtension::Tgz)),
"tbz" => Ok(Self::Legacy(LegacySourceDistExtension::Tbz)),
"txz" => Ok(Self::Legacy(LegacySourceDistExtension::Txz)),
"tlz" => Ok(Self::Legacy(LegacySourceDistExtension::Tlz)),
"bz2" if is_tar(path.as_ref()) => Ok(Self::Legacy(LegacySourceDistExtension::TarBz2)),
"xz" if is_tar(path.as_ref()) => Ok(Self::Legacy(LegacySourceDistExtension::TarXz)),
"lz" if is_tar(path.as_ref()) => Ok(Self::Legacy(LegacySourceDistExtension::TarLz)),
"lzma" if is_tar(path.as_ref()) => Ok(Self::Legacy(LegacySourceDistExtension::TarLzma)),
"zst" if is_tar(path.as_ref()) => Ok(Self::Legacy(LegacySourceDistExtension::TarZst)),
_ => Err(ExtensionError::SourceDist),
}
}

/// Return the name for the extension.
pub(crate) fn name(self) -> &'static str {
match self {
Self::Tar => "tar",
Self::TarBz2 => "tar.bz2",
Self::TarGz => "tar.gz",
Self::TarLz => "tar.lz",
Self::TarLzma => "tar.lzma",
Self::TarXz => "tar.xz",
Self::TarZst => "tar.zst",
Self::Tbz => "tbz",
Self::Tgz => "tgz",
Self::Tlz => "tlz",
Self::Txz => "txz",
Self::Zip => "zip",
Self::Legacy(LegacySourceDistExtension::Tar) => "tar",
Self::Legacy(LegacySourceDistExtension::TarBz2) => "tar.bz2",
Self::Legacy(LegacySourceDistExtension::TarLz) => "tar.lz",
Self::Legacy(LegacySourceDistExtension::TarLzma) => "tar.lzma",
Self::Legacy(LegacySourceDistExtension::TarXz) => "tar.xz",
Self::Legacy(LegacySourceDistExtension::TarZst) => "tar.zst",
Self::Legacy(LegacySourceDistExtension::Tbz) => "tbz",
Self::Legacy(LegacySourceDistExtension::Tgz) => "tgz",
Self::Legacy(LegacySourceDistExtension::Tlz) => "tlz",
Self::Legacy(LegacySourceDistExtension::Txz) => "txz",
Self::Legacy(LegacySourceDistExtension::Zip) => "zip",
}
}

/// Returns `true` if the extension conforms to [PEP 625](https://peps.python.org/pep-0625/)'s
/// naming requirements.
///
/// PEP 625 mandates `.tar.gz`; `.zip` is also accepted for backwards compatibility.
pub fn is_pep625_compliant(&self) -> bool {
matches!(
self,
Self::TarGz | Self::Legacy(LegacySourceDistExtension::Zip)
)
}
}

impl Display for SourceDistExtension {
Expand Down
4 changes: 3 additions & 1 deletion crates/uv-distribution-filename/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use uv_pep440::Version;
pub use build_tag::{BuildTag, BuildTagError};
pub use egg::{EggInfoFilename, EggInfoFilenameError};
pub use expanded_tags::{ExpandedTagError, ExpandedTags};
pub use extension::{DistExtension, ExtensionError, SourceDistExtension};
pub use extension::{
DistExtension, ExtensionError, LegacySourceDistExtension, SourceDistExtension,
};
pub use source_dist::{SourceDistFilename, SourceDistFilenameError};
pub use wheel::{WheelFilename, WheelFilenameError};

Expand Down
24 changes: 17 additions & 7 deletions crates/uv-distribution-filename/src/source_dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ mod tests {

use uv_normalize::PackageName;

use crate::{SourceDistExtension, SourceDistFilename};
use crate::{SourceDistExtension, SourceDistFilename, extension::LegacySourceDistExtension};

/// Only test already normalized names since the parsing is lossy
///
Expand Down Expand Up @@ -239,8 +239,14 @@ mod tests {
fn malformed_non_ascii() {
let package_name = PackageName::from_str("a").unwrap();
for (filename, extension) in [
("é-1.2.3.zip", SourceDistExtension::Zip),
("aé1.2.3.zip", SourceDistExtension::Zip),
(
"é-1.2.3.zip",
SourceDistExtension::Legacy(LegacySourceDistExtension::Zip),
),
(
"aé1.2.3.zip",
SourceDistExtension::Legacy(LegacySourceDistExtension::Zip),
),
("é-1.zip", SourceDistExtension::TarGz),
] {
assert!(SourceDistFilename::parse(filename, extension, &package_name).is_err());
Expand All @@ -257,9 +263,13 @@ mod tests {
"Foo.Bar-1.2.3.zip",
] {
assert_eq!(
SourceDistFilename::parse(filename, SourceDistExtension::Zip, &package_name)
.unwrap()
.name,
SourceDistFilename::parse(
filename,
SourceDistExtension::Legacy(LegacySourceDistExtension::Zip),
&package_name
)
.unwrap()
.name,
package_name
);
}
Expand All @@ -270,7 +280,7 @@ mod tests {
assert!(
SourceDistFilename::parse(
"foo.zip",
SourceDistExtension::Zip,
SourceDistExtension::Legacy(LegacySourceDistExtension::Zip),
&PackageName::from_str("foo-lib").unwrap()
)
.is_err()
Expand Down
5 changes: 5 additions & 0 deletions crates/uv-distribution-types/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ pub enum Error {

#[error("Requested package name `{0}` does not match `{1}` in the distribution filename: {2}")]
PackageNameMismatch(PackageName, PackageName, String),

#[error(
"Source distribution `{0}` has a non-PEP 625-compliant filename; only `.tar.gz` and `.zip` archives are accepted"
)]
NotPep625Filename(String),
}
Loading
Loading