use std::{
fs::{self, OpenOptions},
io::{ErrorKind, Write},
path::Path,
};
use lazin_error::{Context, LazinResult};
use crate::error::LazinError;
const LAZIN_DEFAULT_WORKSPACE_FILE: &str = "workspace.toml";
const LAZIN_DEFAULT_MODULE_FILE: &str = "modules.toml";
const LAZIN_DEFAULT_WORKSPACE: &str = r#"#workspace_name = [
# "module1",
# "module2",
#]
"#;
const LAZIN_DEFAULT_MODULE: &str = r#"#[my_module]
#config = {
# encrypt = false, # When setting to false, recipient field is optional
#}
#source_file="/.config/my_program/source_file"
#source_dir="/.config/source_dir"
#"more/specific/path/to/source_file"="/.config/my_program/source_file"
#source_file_with_attributes = {
# path = "/.config/my_program/source_file_with_attributes",
# config = {
# encrypt = true # override module level encrypt
# recipient = "gpg-recipient"
# }
#}
"#;
enum WriteFileState {
Written,
Skipped,
}
fn try_write_file(base_dir: &Path, filename: &str, data: &[u8]) -> LazinResult<WriteFileState> {
let mut write_state = WriteFileState::Written;
let new_file = OpenOptions::new()
.create_new(true)
.write(true)
.open(base_dir.to_path_buf().join(filename));
if let Ok(mut file) = new_file {
file.write_all(data).context("Failed to write file")?;
} else if let Err(e) = new_file {
match e.kind() {
ErrorKind::AlreadyExists => write_state = WriteFileState::Skipped,
_ => return Err(LazinError::Io(e)).context("File write error"),
}
}
Ok(write_state)
}
pub fn init_directory(directory: &Path) -> LazinResult<()> {
fs::create_dir_all(directory).context("Failed to create directories")
}
pub fn init_default_config(base_dir: &Path) -> LazinResult<()> {
let lazin_default_workspace = try_write_file(
base_dir,
LAZIN_DEFAULT_WORKSPACE_FILE,
LAZIN_DEFAULT_WORKSPACE.as_bytes(),
)?;
match lazin_default_workspace {
WriteFileState::Written => (),
WriteFileState::Skipped => lazin_logger::info!(
"Skipped writing {} file. File already exists.",
LAZIN_DEFAULT_WORKSPACE_FILE
),
}
let lazin_default_module = try_write_file(
base_dir,
LAZIN_DEFAULT_MODULE_FILE,
LAZIN_DEFAULT_MODULE.as_bytes(),
)?;
match lazin_default_module {
WriteFileState::Written => (),
WriteFileState::Skipped => lazin_logger::info!(
"Skipped writing {} file. File already exists.",
LAZIN_DEFAULT_MODULE_FILE
),
}
Ok(())
}
#[cfg(test)]
mod test {
use std::fs;
use crate::{
filesystem::init::{init_default_config, init_directory},
test::filesystem::tmp::TempDir,
};
#[test]
fn temp_default_config() {
let temp_dir = TempDir::new();
init_default_config(temp_dir.path()).expect("initialized config file examples")
}
#[test]
fn temp_init_directory() {
let temp_dir = TempDir::new();
init_directory(temp_dir.path()).expect("initialized temp directory");
assert!(
fs::metadata(temp_dir.path())
.expect("valid metadata")
.is_dir()
);
}
#[test]
fn temp_init_directory_nested() {
let temp_dir = TempDir::new();
let temp_dir = temp_dir.path().join("child1").join("child2");
init_directory(&temp_dir).expect("initialized temp directory");
assert!(fs::metadata(&temp_dir).expect("valid metadata").is_dir());
}
}