Skip to content

Commit 62ff217

Browse files
authored
Merge pull request #37 from containers/push-history
Add a push_layer_with_history
2 parents db8d90c + 59083d3 commit 62ff217

File tree

1 file changed

+76
-6
lines changed

1 file changed

+76
-6
lines changed

src/lib.rs

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,25 @@ impl OciDir {
358358
annotations: Option<impl Into<HashMap<String, String>>>,
359359
description: &str,
360360
created: chrono::DateTime<chrono::Utc>,
361+
) {
362+
let history = oci_image::HistoryBuilder::default()
363+
.created(created.to_rfc3339_opts(chrono::SecondsFormat::Secs, true))
364+
.created_by(description.to_string())
365+
.build()
366+
.unwrap();
367+
self.push_layer_with_history_annotated(manifest, config, layer, annotations, Some(history));
368+
}
369+
370+
/// Add a layer to the top of the image stack with optional annotations and desired history entry.
371+
///
372+
/// This is otherwise equivalent to [`Self::push_layer_annotated`].
373+
pub fn push_layer_with_history_annotated(
374+
&self,
375+
manifest: &mut oci_image::ImageManifest,
376+
config: &mut oci_image::ImageConfiguration,
377+
layer: Layer,
378+
annotations: Option<impl Into<HashMap<String, String>>>,
379+
history: Option<oci_image::History>,
361380
) {
362381
let mut builder = layer.descriptor();
363382
if let Some(annotations) = annotations {
@@ -370,12 +389,26 @@ impl OciDir {
370389
.diff_ids_mut()
371390
.push(layer.uncompressed_sha256_as_digest().to_string());
372391
config.set_rootfs(rootfs);
373-
let h = oci_image::HistoryBuilder::default()
374-
.created(created.to_rfc3339_opts(chrono::SecondsFormat::Secs, true))
375-
.created_by(description.to_string())
376-
.build()
377-
.unwrap();
378-
config.history_mut().push(h);
392+
let history = if let Some(history) = history {
393+
history
394+
} else {
395+
oci_image::HistoryBuilder::default().build().unwrap()
396+
};
397+
config.history_mut().push(history);
398+
}
399+
400+
/// Add a layer to the top of the image stack with desired history entry.
401+
///
402+
/// This is otherwise equivalent to [`Self::push_layer`].
403+
pub fn push_layer_with_history(
404+
&self,
405+
manifest: &mut oci_image::ImageManifest,
406+
config: &mut oci_image::ImageConfiguration,
407+
layer: Layer,
408+
history: Option<oci_image::History>,
409+
) {
410+
let annotations: Option<HashMap<_, _>> = None;
411+
self.push_layer_with_history_annotated(manifest, config, layer, annotations, history);
379412
}
380413

381414
fn parse_descriptor_to_path(desc: &oci_spec::image::Descriptor) -> Result<PathBuf> {
@@ -797,6 +830,7 @@ where
797830
#[cfg(test)]
798831
mod tests {
799832
use cap_std::fs::OpenOptions;
833+
use oci_spec::image::HistoryBuilder;
800834

801835
use super::*;
802836

@@ -867,6 +901,16 @@ mod tests {
867901
.unwrap();
868902
let annotations: Option<HashMap<String, String>> = None;
869903
w.push_layer(&mut manifest, &mut config, root_layer, "root", annotations);
904+
{
905+
let history = config.history().first().unwrap();
906+
assert_eq!(history.created_by().as_ref().unwrap(), "root");
907+
let created = history.created().as_deref().unwrap();
908+
let ts = chrono::DateTime::parse_from_rfc3339(created)
909+
.unwrap()
910+
.to_utc();
911+
let now = chrono::offset::Utc::now();
912+
assert_eq!(now.years_since(ts).unwrap(), 0);
913+
}
870914
let config = w.write_config(config)?;
871915
manifest.set_config(config);
872916
w.replace_with_single_manifest(manifest.clone(), oci_image::Platform::default())?;
@@ -985,4 +1029,30 @@ mod tests {
9851029
assert_eq!(w.fsck()?, 2);
9861030
Ok(())
9871031
}
1032+
1033+
#[test]
1034+
fn test_push_layer_with_history() -> Result<()> {
1035+
let td = cap_tempfile::tempdir(cap_std::ambient_authority())?;
1036+
let w = OciDir::ensure(td.try_clone()?)?;
1037+
1038+
let mut manifest = w.new_empty_manifest()?.build()?;
1039+
let mut config = oci_image::ImageConfigurationBuilder::default()
1040+
.build()
1041+
.unwrap();
1042+
let mut layerw = w.create_gzip_layer(None)?;
1043+
layerw.write_all(b"pretend this is a tarball")?;
1044+
let root_layer = layerw.complete()?;
1045+
1046+
let history = HistoryBuilder::default()
1047+
.created_by("/bin/pretend-tar")
1048+
.build()
1049+
.unwrap();
1050+
w.push_layer_with_history(&mut manifest, &mut config, root_layer, Some(history));
1051+
{
1052+
let history = config.history().first().unwrap();
1053+
assert_eq!(history.created_by().as_deref().unwrap(), "/bin/pretend-tar");
1054+
assert_eq!(history.created().as_ref(), None);
1055+
}
1056+
Ok(())
1057+
}
9881058
}

0 commit comments

Comments
 (0)