Build a single layer from an in-memory set of `(relative_path, bytes)` files plus optional whiteouts. Whiteouts mark deletions relative to a lower layer: a deleted path `foo/bar` is encoded as a zero-byte tar entry `foo/.wh.bar`, per the OCI spec. Entries are emitted in a deterministic (sorted) order. Useful for delta layers where staging files on disk is undesirable.
(
files: &[(String, Vec<u8>)],
whiteouts: &[String],
)
| 138 | /// are emitted in a deterministic (sorted) order. Useful for delta layers where |
| 139 | /// staging files on disk is undesirable. |
| 140 | pub fn layer_from_entries( |
| 141 | files: &[(String, Vec<u8>)], |
| 142 | whiteouts: &[String], |
| 143 | ) -> std::io::Result<OciLayer> { |
| 144 | let mut items: Vec<(String, Vec<u8>)> = Vec::with_capacity(files.len() + whiteouts.len()); |
| 145 | for (path, bytes) in files { |
| 146 | items.push((path.clone(), bytes.clone())); |
| 147 | } |
| 148 | for path in whiteouts { |
| 149 | items.push((whiteout_path(path), Vec::new())); |
| 150 | } |
| 151 | items.sort_by(|a, b| a.0.cmp(&b.0)); |
| 152 | |
| 153 | let mut tar_buf = Vec::new(); |
| 154 | { |
| 155 | let mut builder = Builder::new(&mut tar_buf); |
| 156 | for (path, data) in &items { |
| 157 | let mut header = Header::new_gnu(); |
| 158 | header.set_entry_type(EntryType::Regular); |
| 159 | header.set_size(data.len() as u64); |
| 160 | header.set_mode(0o644); |
| 161 | header.set_mtime(0); |
| 162 | builder.append_data(&mut header, path, data.as_slice())?; |
| 163 | } |
| 164 | builder.finish()?; |
| 165 | } |
| 166 | |
| 167 | finish_layer(tar_buf) |
| 168 | } |
| 169 | |
| 170 | /// Write a complete OCI image layout under `out` (created if needed): |
| 171 | /// `out/oci-layout`, `out/index.json`, and `out/blobs/sha256/<...>` blobs. |