1use std::fs;
4use std::io::{self, Write};
5use std::path::Path;
6
7pub const MANIFOLD_DIR: &str = ".manifold";
9
10pub const EPOCHS_DIR: &str = "epochs";
12
13pub const ARTIFACTS_DIR: &str = "artifacts";
15
16pub const WS_ARTIFACTS_DIR: &str = "ws";
18
19pub const MERGE_ARTIFACTS_DIR: &str = "merge";
21
22pub const CONFIG_FILE: &str = "config.toml";
24
25#[allow(clippy::missing_errors_doc)]
32pub fn init_manifold_dir(root: &Path) -> io::Result<()> {
33 let manifold_path = root.join(MANIFOLD_DIR);
34
35 create_dir_all_idempotent(&manifold_path)?;
37 create_dir_all_idempotent(&manifold_path.join(EPOCHS_DIR))?;
38
39 let artifacts_path = manifold_path.join(ARTIFACTS_DIR);
40 create_dir_all_idempotent(&artifacts_path)?;
41 create_dir_all_idempotent(&artifacts_path.join(WS_ARTIFACTS_DIR))?;
42 create_dir_all_idempotent(&artifacts_path.join(MERGE_ARTIFACTS_DIR))?;
43
44 init_config_if_missing(&manifold_path.join(CONFIG_FILE))?;
46
47 Ok(())
48}
49
50fn create_dir_all_idempotent(path: &Path) -> io::Result<()> {
51 if !path.exists() {
52 fs::create_dir_all(path)?;
53 }
54 Ok(())
55}
56
57fn init_config_if_missing(path: &Path) -> io::Result<()> {
58 if !path.exists() {
59 let mut file = fs::File::create(path)?;
60 writeln!(file, "# Manifold repository configuration")?;
61 writeln!(
62 file,
63 "# For full options see: https://github.com/mariozechner/manifold"
64 )?;
65 writeln!(file)?;
66 writeln!(file, "[repo]")?;
67 writeln!(file, "branch = \"main\"")?;
68 }
69 Ok(())
70}
71
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use tempfile::tempdir;
77
78 #[test]
79 fn test_init_manifold_dir() {
80 let dir = tempdir().unwrap();
81 let root = dir.path();
82
83 init_manifold_dir(root).unwrap();
84
85 assert!(root.join(".manifold").is_dir());
86 assert!(root.join(".manifold/epochs").is_dir());
87 assert!(root.join(".manifold/artifacts").is_dir());
88 assert!(root.join(".manifold/artifacts/ws").is_dir());
89 assert!(root.join(".manifold/artifacts/merge").is_dir());
90 assert!(root.join(".manifold/config.toml").is_file());
91 assert!(!root.join(".gitignore").exists());
92 }
93
94 #[test]
95 fn test_idempotency() {
96 let dir = tempdir().unwrap();
97 let root = dir.path();
98
99 init_manifold_dir(root).unwrap();
100 let config_first = fs::read_to_string(root.join(".manifold/config.toml")).unwrap();
101
102 init_manifold_dir(root).unwrap();
103 let config_second = fs::read_to_string(root.join(".manifold/config.toml")).unwrap();
104
105 assert_eq!(config_first, config_second);
106 }
107}