1use anyhow::bail;
18use rust_embed::RustEmbed;
19use std::env;
20use std::fs;
21#[cfg(unix)]
22use std::os::unix::fs::PermissionsExt;
23use std::path::PathBuf;
24
25#[derive(Debug, RustEmbed)]
26#[folder = "scripts/"]
27struct Scripts;
28
29pub struct Init {}
30
31impl Init {
32 pub fn create(dir: &PathBuf) -> anyhow::Result<()> {
33 let initdir = if dir.is_absolute() {
34 dir.to_path_buf()
35 } else {
36 env::current_dir()?.join(dir)
37 };
38 if initdir.exists() {
39 if !initdir.is_dir() {
40 bail!("{} exists and is not a directory", initdir.display());
41 }
42 if fs::read_dir(&initdir)?.next().is_some() {
43 bail!("{} exists and is not empty", initdir.display());
44 }
45 }
46
47 let Some(initdir_str) = initdir.to_str() else {
48 bail!("Sorry, configuration directory must be valid UTF-8");
49 };
50
51 println!("Initialising new configuration directory {}:", initdir_str);
52
53 let (current_os, confstr) = match env::consts::OS {
54 "illumos" => ("illumos", include_str!("../config/illumos.lua")),
55 "linux" => ("linux", include_str!("../config/linux.lua")),
56 "macos" => ("macos", include_str!("../config/macos.lua")),
57 "netbsd" => ("netbsd", include_str!("../config/netbsd.lua")),
58 "solaris" => ("illumos", include_str!("../config/illumos.lua")),
59 os => {
60 eprintln!(
61 "WARNING: OS '{}' not explicitly supported, using generic config",
62 os
63 );
64 (os, include_str!("../config/generic.lua"))
65 }
66 };
67
68 let confstr = confstr.replace("@INITDIR@", initdir_str);
69 let conffile = initdir.join("config.lua");
70 fs::create_dir_all(conffile.parent().unwrap())?;
71 fs::write(&conffile, confstr)?;
72 println!("\t{}", conffile.display());
73
74 for script in Scripts::iter() {
75 let script_path = PathBuf::from(&*script);
76 let components: Vec<_> = script_path.components().collect();
77
78 let dest = if components.len() > 1 {
85 if components[0].as_os_str().to_str() != Some(current_os) {
86 continue;
87 }
88 components[1..].iter().collect()
89 } else {
90 script_path
91 };
92
93 if let Some(content) = Scripts::get(&script) {
94 let fp = initdir.join("scripts").join(&dest);
95 fs::create_dir_all(fp.parent().unwrap())?;
96 fs::write(&fp, content.data)?;
97 #[cfg(unix)]
98 {
99 let mut perms = fs::metadata(&fp)?.permissions();
100 perms.set_mode(0o755);
101 fs::set_permissions(&fp, perms)?;
102 }
103 println!("\t{}", fp.display());
104 }
105 }
106
107 Ok(())
108 }
109}