Skip to content

Commit 6817b48

Browse files
authored
Merge pull request #28 from ariel-miculas/add-helper-functions
Add find_manifest_descriptor_with_tag
2 parents 111ed71 + 7f58190 commit 6817b48

File tree

2 files changed

+43
-35
lines changed

2 files changed

+43
-35
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ To access an existing OCI directory:
3030
# fn main() -> anyhow::Result<()> {
3131
let d = cap_std::fs::Dir::open_ambient_dir("/path/to/ocidir", cap_std::ambient_authority())?;
3232
let d = ocidir::OciDir::open(d)?;
33-
println!("{:?}", d.read_index()?.ok_or_else(|| anyhow!("missing Image Index"))?);
33+
println!("{:?}", d.read_index()?);
3434
# Ok(())
3535
# }
3636
```

src/lib.rs

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub enum Error {
5454
#[error("Expected digest algorithm sha256 but found {found}")]
5555
/// Returned when a digest algorithm is not supported
5656
UnsupportedDigestAlgorithm { found: Box<str> },
57+
#[error("Cannot find the Image Index (index.json)")]
58+
/// Returned when the OCI Image Index (index.json) is missing
59+
MissingImageIndex,
5760
#[error("error")]
5861
/// An unknown other error
5962
Other(Box<str>),
@@ -384,9 +387,7 @@ impl OciDir {
384387

385388
/// Returns `true` if the manifest is already present.
386389
pub fn has_manifest(&self, desc: &oci_spec::image::Descriptor) -> Result<bool> {
387-
let Some(index) = self.read_index()? else {
388-
return Ok(false);
389-
};
390+
let index = self.read_index()?;
390391
Ok(index
391392
.manifests()
392393
.iter()
@@ -414,11 +415,11 @@ impl OciDir {
414415
}
415416

416417
/// Read the image index.
417-
pub fn read_index(&self) -> Result<Option<ImageIndex>> {
418+
pub fn read_index(&self) -> Result<ImageIndex> {
418419
let r = if let Some(index) = self.dir.open_optional("index.json")?.map(BufReader::new) {
419-
Some(oci_image::ImageIndex::from_reader(index)?)
420+
oci_image::ImageIndex::from_reader(index)?
420421
} else {
421-
None
422+
return Err(Error::MissingImageIndex);
422423
};
423424
Ok(r)
424425
}
@@ -442,21 +443,23 @@ impl OciDir {
442443
manifest.set_annotations(Some(annotations));
443444
}
444445

445-
let index = self.read_index()?;
446-
let index = if let Some(mut index) = index {
447-
let mut manifests = index.manifests().clone();
448-
if let Some(tag) = tag {
449-
manifests.retain(|d| !Self::descriptor_is_tagged(d, tag));
446+
let index = match self.read_index() {
447+
Ok(mut index) => {
448+
let mut manifests = index.manifests().clone();
449+
if let Some(tag) = tag {
450+
manifests.retain(|d| !Self::descriptor_is_tagged(d, tag));
451+
}
452+
manifests.push(manifest.clone());
453+
index.set_manifests(manifests);
454+
index
450455
}
451-
manifests.push(manifest.clone());
452-
index.set_manifests(manifests);
453-
index
454-
} else {
455-
oci_image::ImageIndexBuilder::default()
456+
Err(Error::MissingImageIndex) => oci_image::ImageIndexBuilder::default()
456457
.schema_version(oci_image::SCHEMA_VERSION)
457458
.manifests(vec![manifest.clone()])
458-
.build()
459-
.unwrap()
459+
.build()?,
460+
Err(e) => {
461+
return Err(e);
462+
}
460463
};
461464

462465
self.dir
@@ -519,14 +522,21 @@ impl OciDir {
519522

520523
/// Find the manifest with the provided tag
521524
pub fn find_manifest_with_tag(&self, tag: &str) -> Result<Option<oci_image::ImageManifest>> {
522-
let f = self.dir.open("index.json")?;
523-
let idx: oci_image::ImageIndex = serde_json::from_reader(BufReader::new(f))?;
524-
for img in idx.manifests() {
525-
if Self::descriptor_is_tagged(img, tag) {
526-
return self.read_json_blob(img).map(Some);
527-
}
528-
}
529-
Ok(None)
525+
let desc = self.find_manifest_descriptor_with_tag(tag)?;
526+
desc.map(|img| self.read_json_blob(&img)).transpose()
527+
}
528+
529+
/// Find the manifest descriptor with the provided tag
530+
pub fn find_manifest_descriptor_with_tag(
531+
&self,
532+
tag: &str,
533+
) -> Result<Option<oci_image::Descriptor>> {
534+
let idx = self.read_index()?;
535+
Ok(idx
536+
.manifests()
537+
.iter()
538+
.find(|desc| Self::descriptor_is_tagged(desc, tag))
539+
.cloned())
530540
}
531541

532542
/// Verify a single manifest and all of its referenced objects.
@@ -567,9 +577,7 @@ impl OciDir {
567577
/// Verify consistency of the index, its manifests, the config and blobs (all the latter)
568578
/// by verifying their descriptor.
569579
pub fn fsck(&self) -> Result<u64> {
570-
let Some(index) = self.read_index()? else {
571-
return Ok(0);
572-
};
580+
let index = self.read_index()?;
573581
let mut validated_blobs = HashSet::new();
574582
for manifest_descriptor in index.manifests() {
575583
let expected_sha256 = sha256_of_descriptor(manifest_descriptor)?;
@@ -813,7 +821,7 @@ mod tests {
813821
"349438e5faf763e8875b43de4d7101540ef4d865190336c2cc549a11f33f8d7c"
814822
);
815823
// Nothing referencing this blob yet
816-
assert_eq!(w.fsck().unwrap(), 0);
824+
assert!(matches!(w.fsck().unwrap_err(), Error::MissingImageIndex));
817825
assert!(w.has_blob(&root_layer_desc).unwrap());
818826

819827
// Check that we don't find nonexistent blobs
@@ -834,7 +842,7 @@ mod tests {
834842
let config = w.write_config(config)?;
835843
manifest.set_config(config);
836844
w.replace_with_single_manifest(manifest.clone(), oci_image::Platform::default())?;
837-
assert_eq!(w.read_index().unwrap().unwrap().manifests().len(), 1);
845+
assert_eq!(w.read_index().unwrap().manifests().len(), 1);
838846
assert_eq!(w.fsck().unwrap(), 3);
839847
// Also verify that corrupting a blob is found
840848
{
@@ -851,7 +859,7 @@ mod tests {
851859
assert_eq!(w.fsck().unwrap(), 3);
852860
}
853861

854-
let idx = w.read_index()?.unwrap();
862+
let idx = w.read_index()?;
855863
let manifest_desc = idx.manifests().first().unwrap();
856864
let read_manifest = w.read_json_blob(manifest_desc).unwrap();
857865
assert_eq!(&read_manifest, &manifest);
@@ -860,7 +868,7 @@ mod tests {
860868
w.insert_manifest(manifest, Some("latest"), oci_image::Platform::default())?;
861869
assert!(w.has_manifest(&desc).unwrap());
862870
// There's more than one now
863-
assert_eq!(w.read_index().unwrap().unwrap().manifests().len(), 2);
871+
assert_eq!(w.read_index().unwrap().manifests().len(), 2);
864872

865873
assert!(w.find_manifest_with_tag("noent").unwrap().is_none());
866874
let found_via_tag = w.find_manifest_with_tag("latest").unwrap().unwrap();
@@ -880,7 +888,7 @@ mod tests {
880888
Some("latest"),
881889
oci_image::Platform::default(),
882890
)?;
883-
assert_eq!(w.read_index().unwrap().unwrap().manifests().len(), 2);
891+
assert_eq!(w.read_index().unwrap().manifests().len(), 2);
884892
assert_eq!(w.fsck().unwrap(), 6);
885893
Ok(())
886894
}

0 commit comments

Comments
 (0)