MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / stage

Method stage

atomic-repository/src/repository/sandbox.rs:255–321  ·  view source on GitHub ↗

Produce a two-layer OCI image: a base layer (the `base_view` materialized) plus a thin delta layer (files that differ on `view` versus `base_view`, with whiteouts for files removed on `view`). Built for the inner loop: the base is content-addressed by its `diff_id` and can be pulled once and cached, so each iteration ships only the small delta. Provenance (view names and Merkle states) is recorde

(&self, opts: StageOptions)

Source from the content-addressed store, hash-verified

253 /// delta. Provenance (view names and Merkle states) is recorded in the
254 /// manifest annotations. Returns the manifest digest and base `diff_id`.
255 pub fn stage(&self, opts: StageOptions) -> Result<StageResult, RepositoryError> {
256 // 1. Base layer: materialize the shared base view to a temp dir.
257 let base_dir = tempfile::tempdir()?;
258 self.materialize_view_to(&opts.base_view, base_dir.path())?;
259 let base_layer = oci::layer_from_dir(base_dir.path())?;
260 let base_diff_id = base_layer.diff_id.clone();
261
262 // 2. Delta: files new or changed on `view` vs. `base_view`, plus
263 // whiteouts for files present on the base but gone on `view`.
264 let view_paths = self.visible_file_paths(&opts.view)?;
265 let base_paths = self.visible_file_paths(&opts.base_view)?;
266
267 let mut changed: Vec<(String, Vec<u8>)> = Vec::new();
268 for path in &view_paths {
269 let view_bytes = match self.get_file_content_on_view(path, &opts.view)? {
270 Some(bytes) => bytes,
271 None => continue,
272 };
273 let base_bytes = self.get_file_content_on_view(path, &opts.base_view)?;
274 if base_bytes.as_deref() != Some(view_bytes.as_slice()) {
275 changed.push((path.clone(), view_bytes));
276 }
277 }
278
279 let mut whiteouts: Vec<String> = Vec::new();
280 for path in &base_paths {
281 if !view_paths.contains(path) {
282 whiteouts.push(path.clone());
283 }
284 }
285
286 let delta_files = changed.len();
287 let delta_layer = oci::layer_from_entries(&changed, &whiteouts)?;
288
289 // 3. Assemble the layout with provenance annotations.
290 let view_info = self.get_view_info(&opts.view)?;
291 let base_info = self.get_view_info(&opts.base_view)?;
292 let mut annotations = BTreeMap::new();
293 annotations.insert("org.atomic.view".to_string(), opts.view.clone());
294 annotations.insert("org.atomic.base-view".to_string(), opts.base_view.clone());
295 annotations.insert(
296 "org.atomic.view-merkle".to_string(),
297 view_info.state_base32(),
298 );
299 annotations.insert(
300 "org.atomic.base-merkle".to_string(),
301 base_info.state_base32(),
302 );
303
304 let config = OciImageConfig {
305 architecture: oci::host_arch(),
306 os: "linux".to_string(),
307 env: Vec::new(),
308 entrypoint: Vec::new(),
309 annotations,
310 };
311
312 let manifest_digest =

Callers 1

runMethod · 0.80

Calls 15

layer_from_dirFunction · 0.85
layer_from_entriesFunction · 0.85
host_archFunction · 0.85
write_image_layoutFunction · 0.85
materialize_view_toMethod · 0.80
visible_file_pathsMethod · 0.80
get_view_infoMethod · 0.80
state_base32Method · 0.80
pathMethod · 0.45
cloneMethod · 0.45
as_sliceMethod · 0.45

Tested by

no test coverage detected