cargo_prosa/package/
container.rs1use std::{
2 fmt, fs, io,
3 path::{Path, PathBuf},
4};
5
6use clap::ArgMatches;
7use tera::Tera;
8
9use crate::cargo::CargoMetadata;
10
11pub struct ContainerFile {
13 is_docker: bool,
14 ctx: tera::Context,
15 path: Option<String>,
16}
17
18impl ContainerFile {
19 pub fn new(args: &ArgMatches) -> io::Result<ContainerFile> {
21 let package_metadata = CargoMetadata::load_package_metadata()?;
22 let is_docker = args.get_flag("docker");
23 let mut ctx = tera::Context::new();
24 package_metadata.j2_context(&mut ctx);
25 ctx.insert("docker", &is_docker);
26 ctx.insert(
27 "image",
28 args.get_one::<String>("image")
29 .expect("required container base image"),
30 );
31 ctx.insert(
32 "package_manager",
33 args.get_one::<String>("package_manager")
34 .expect("required package manager"),
35 );
36 let builder_img = args.get_one::<String>("builder");
37 if let Some(img) = builder_img {
38 ctx.insert("builder_image", img);
39 }
40
41 Ok(ContainerFile {
42 is_docker,
43 ctx,
44 path: args.get_one::<String>("PATH").cloned(),
45 })
46 }
47
48 pub fn get_path(&self) -> PathBuf {
50 if let Some(p) = &self.path {
51 let path = Path::new(p);
52 if path.is_dir() {
53 if self.is_docker {
54 path.join("Dockerfile")
55 } else {
56 path.join("Containerfile")
57 }
58 } else {
59 path.to_path_buf()
60 }
61 } else if self.is_docker {
62 Path::new("Dockerfile").to_path_buf()
63 } else {
64 Path::new("Containerfile").to_path_buf()
65 }
66 }
67
68 pub fn create_container_file(&self) -> tera::Result<()> {
70 let template_name = if self.is_docker {
71 "Dockerfile"
72 } else {
73 "Containerfile"
74 };
75
76 let mut tera_build = Tera::default();
77 tera_build.add_raw_template(
78 template_name,
79 include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/container.j2")),
80 )?;
81
82 let build_file = fs::File::create(self.get_path()).map_err(tera::Error::io_error)?;
83 tera_build.render_to(template_name, &self.ctx, build_file)
84 }
85}
86
87impl fmt::Display for ContainerFile {
88 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89 let img_name = format!(
90 "{}:{}",
91 self.ctx.get("name").unwrap().as_str().unwrap(),
92 self.ctx.get("version").unwrap().as_str().unwrap()
93 );
94 writeln!(f, "To build your container, use the command:")?;
95 if self.is_docker {
96 write!(f, " `docker build")?;
97 if self.path.is_some() {
98 write!(f, " -f {}", self.get_path().display())?;
99 }
100 writeln!(f, " -t {img_name} .`")?;
101
102 if self.ctx.contains_key("builder_image") {
103 writeln!(
104 f,
105 "If you have an external git dependency, specify your ssh agent with:"
106 )?;
107
108 write!(f, " `docker build")?;
109 if self.path.is_some() {
110 write!(f, " -f {}", self.get_path().display())?;
111 }
112 writeln!(f, " --ssh default=$SSH_AUTH_SOCK -t {img_name} .`")
113 } else {
114 Ok(())
115 }
116 } else if self.path.is_some() {
117 writeln!(
118 f,
119 " `podman build -f {} -t {} .`",
120 self.get_path().display(),
121 img_name
122 )
123 } else {
124 writeln!(f, " `podman build -t {img_name} .`")
125 }
126 }
127}