1use std::{
3 ffi::OsStr,
4 fs,
5 io::Write,
6 path::{Component, Path, PathBuf},
7};
8
9use super::scratch_name;
10use crate::buildservice::BuildRequest;
11use anyhow::Context;
12use tracing::{debug, instrument};
13
14#[instrument(err)]
17pub(crate) fn make_bundle(
18 request: &BuildRequest,
19 runtime_spec: &oci_spec::runtime::Spec,
20 path: &Path,
21) -> anyhow::Result<()> {
22 fs::create_dir_all(path).context("failed to create bundle path")?;
23
24 let spec_json = serde_json::to_string(runtime_spec).context("failed to render spec to json")?;
25 fs::write(path.join("config.json"), spec_json).context("failed to write config.json")?;
26
27 fs::create_dir_all(path.join("inputs")).context("failed to create inputs dir")?;
28
29 let root_path = path.join("root");
30
31 fs::create_dir_all(&root_path).context("failed to create root path dir")?;
32 fs::create_dir_all(root_path.join("etc")).context("failed to create root/etc dir")?;
33
34 let scratch_root = path.join("scratch");
37 fs::create_dir_all(&scratch_root).context("failed to create scratch/ dir")?;
38
39 for p in request.scratch_paths.iter() {
42 let scratch_path = scratch_root.join(scratch_name(p));
43 debug!(scratch_path=?scratch_path, path=?p, "about to create scratch dir");
44 fs::create_dir_all(scratch_path.clone()).context("Unable to create scratch dir")?;
45
46 if p == Path::new("build") {
51 for file in request.additional_files.iter() {
52 if file.path.components().count() < 2
53 || file.path.components().next() != Some(Component::Normal(OsStr::new("build")))
54 {
55 Err(std::io::Error::other(
56 "Additional files must start with build/",
57 ))?
58 }
59
60 let p = file.path.components().skip(1).collect::<PathBuf>();
62 if let Some(parent) = p.parent() {
63 fs::create_dir_all(scratch_path.clone().join(parent))
64 .context("Failed to create dir for additional file")?;
65 }
66 let p = scratch_path.join(p);
67 let mut out = std::fs::File::create(p).context("could not create file")?;
68 out.write_all(&file.contents)?;
69 }
70 }
71 }
72
73 Ok(())
74}