1use std::path::{Path, PathBuf};
2
3use serde::{Deserialize, Serialize};
4
5use self::configs::{BinaryConfig, SolidBinaryConfig};
6use crate::prelude::*;
7use crate::{read_file_contents, NameString};
8
9pub mod configs;
10
11pub const MANIFEST_FILE_NAME: &str = "soma.toml";
12
13#[derive(Debug)]
14pub struct Problem {
15 repo_name: NameString,
16 prob_name: NameString,
17 path: PathBuf,
18}
19
20impl Problem {
21 pub fn new(repo_name: NameString, prob_name: NameString, path: PathBuf) -> Self {
22 Problem {
23 repo_name,
24 prob_name,
25 path,
26 }
27 }
28
29 pub fn fully_qualified_name(&self) -> String {
30 format!("{}.{}", &self.repo_name, &self.prob_name)
31 }
32
33 pub fn docker_image_name(&self, user_name: &str) -> String {
34 format!("soma.{}/{}", user_name, self.fully_qualified_name())
35 }
36
37 pub fn repo_name(&self) -> &NameString {
38 &self.repo_name
39 }
40
41 pub fn prob_name(&self) -> &NameString {
42 &self.prob_name
43 }
44
45 pub fn path(&self) -> &PathBuf {
46 &self.path
47 }
48
49 pub fn load_manifest(&self) -> SomaResult<Manifest> {
50 let manifest_path = self.path().join(MANIFEST_FILE_NAME);
51 read_manifest(manifest_path)
52 }
53}
54
55#[derive(Deserialize)]
56pub struct Manifest {
57 name: NameString,
58 work_dir: Option<PathBuf>,
59 binary: BinaryConfig,
60}
61
62#[derive(Serialize)]
63pub struct SolidManifest {
64 name: NameString,
65 work_dir: PathBuf,
66 binary: SolidBinaryConfig,
67}
68
69impl Manifest {
70 pub fn name(&self) -> &NameString {
71 &self.name
72 }
73
74 pub fn public_files(&self) -> Vec<&PathBuf> {
75 let binary = &self.binary;
76 let executables = binary.executable().iter();
77 let readonly = binary.readonly().iter();
78
79 executables
80 .chain(readonly)
81 .filter(|file_entry| file_entry.public())
82 .map(|file_entry| file_entry.path())
83 .collect()
84 }
85
86 pub fn solidify(&self) -> SomaResult<SolidManifest> {
87 let work_dir = match &self.work_dir {
88 Some(path) => path.clone(),
89 None => PathBuf::from(format!("/home/{}", self.name)),
90 };
91
92 if !work_dir.has_root() {
94 Err(SomaError::InvalidManifest)?;
95 }
96
97 let binary = self.binary.solidify(&work_dir)?;
98
99 Ok(SolidManifest {
100 name: self.name.clone(),
101 work_dir,
102 binary,
103 })
104 }
105}
106
107impl SolidManifest {
108 pub fn binary(&self) -> &SolidBinaryConfig {
109 &self.binary
110 }
111}
112
113pub fn read_manifest(path: impl AsRef<Path>) -> SomaResult<Manifest> {
114 Ok(toml::from_slice(&read_file_contents(path)?)?)
115}