Skip to content

Commit

Permalink
feat: List tag manifests async
Browse files Browse the repository at this point in the history
  • Loading branch information
AllexVeldman committed May 27, 2024
1 parent 7b3f96f commit 71b5377
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 34 deletions.
29 changes: 29 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ console_error_panic_hook = "0.1.7"
wasm-bindgen = "0.2.92"
worker = {version = "0.3.0"}
tracing-web = "0.1.3"
futures = "0.3.30"

[dependencies.web-sys]
version = "0.3.63"
Expand Down
84 changes: 50 additions & 34 deletions src/pyoci.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use core::fmt;
use futures::stream::FuturesUnordered;
use futures::stream::StreamExt;
use reqwest::Response;
use std::error;
use std::io::{Cursor, Read};
use url::{ParseError, Url};

use oci_spec::{
Expand Down Expand Up @@ -159,41 +160,56 @@ impl PyOci {
) -> Result<Vec<package::Info>, Error> {
let tags = self.list_tags(&package.oci_name()).await?;
let mut files: Vec<package::Info> = Vec::new();
let futures = FuturesUnordered::new();

for tag in tags.tags() {
let manifest = self.pull_manifest(tags.name(), tag).await?;
match manifest {
Manifest::Manifest(_) => {
return Err(Error::Other(
"Manifest without Index not supported".to_string(),
))
}
Manifest::Index(index) => {
let artifact_type = index.artifact_type();
match artifact_type {
// Artifact type is as expected, do nothing
Some(MediaType::Other(value))
if value == "application/pyoci.package.v1" => {}
// Artifact type has unexpected value, err
Some(value) => return Err(Error::UnknownArtifactType(value.to_string())),
// Artifact type is not set, err
None => return Err(Error::UnknownArtifactType(String::new())),
};
for manifest in index.manifests() {
match manifest.platform().as_ref().unwrap().architecture() {
oci_spec::image::Arch::Other(arch) => {
let mut file = package.clone();
file.file = package
.file
.clone()
.with_version(tag)
.with_architecture(arch)
.unwrap();
files.push(file);
}
arch => return Err(Error::UnknownArchitecture(arch.to_string())),
};
}
futures.push(self.package_info_for_ref(package, tags.name(), tag));
}
for result in futures
.collect::<Vec<Result<Vec<package::Info>, Error>>>()
.await
{
match result {
Ok(mut value) => files.append(&mut value),
Err(err) => return Err(err),
}
}
Ok(files)
}

async fn package_info_for_ref(
&self,
package: &package::Info,
name: &str,
reference: &str,
) -> Result<Vec<package::Info>, Error> {
let manifest = self.pull_manifest(name, reference).await?;
let Manifest::Index(index) = manifest else {
return Err(Error::Other("Expected Index, got Manifest".to_string()));
};
let artifact_type = index.artifact_type();
match artifact_type {
// Artifact type is as expected, do nothing
Some(MediaType::Other(value)) if value == "application/pyoci.package.v1" => {}
// Artifact type has unexpected value, err
Some(value) => return Err(Error::UnknownArtifactType(value.to_string())),
// Artifact type is not set, err
None => return Err(Error::UnknownArtifactType(String::new())),
};
let mut files: Vec<package::Info> = Vec::new();
for manifest in index.manifests() {
match manifest.platform().as_ref().unwrap().architecture() {
oci_spec::image::Arch::Other(arch) => {
let mut file = package.clone();
file.file = package
.file
.clone()
.with_version(reference)
.with_architecture(arch)
.unwrap();
files.push(file);
}
arch => return Err(Error::UnknownArchitecture(arch.to_string())),
};
}
Ok(files)
Expand Down

0 comments on commit 71b5377

Please sign in to comment.