soma/
problem.rs

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        // TODO: More descriptive error
93        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}