use super::Recipe;
use crate::cli::Imprint;
use crate::content::{build_walk, make_contents};
use crate::fs_wrappers::{self, current_dir};
use crate::mkdev_error::Context;
use crate::mkdev_error::Error::{self, *};
use crate::{menus, warning};
use std::collections::HashMap;
use std::path::PathBuf;
use ignore::Walk;
use rust_i18n::t;
pub fn imprint_recipe(args: Imprint, user_recipes: HashMap<String, Recipe>) -> Result<(), Error> {
let new = if args.interactive {
menus::imprint()?
} else {
let walker = build_walk(&args)?;
Recipe::imprint(args.recipe, args.description, walker)?
};
if let Some(path) = args.to_nix {
let nix_expression = ser_nix::to_string(&new)
.expect("ser_nix's serialisation is infallible with non-path types.");
fs_wrappers::write(path, nix_expression, Context::Imprint)?;
return Ok(());
}
let destructive = user_recipes.iter().any(|(recipe, _)| recipe == &new.name);
let can_proceed = !destructive
|| if args.interactive {
menus::confirm_action(&t!("menus.recipe_overwrite", recipe => &new.name), false)
.unwrap()
} else {
args.suppress_warnings
};
if destructive && new.is_external()? {
warning!("{}", t!("recipes.external"));
}
if !can_proceed {
return Err(DestructionWarning { name: new.name });
}
let save_location = new.save()?;
println!("{}", &save_location.display());
Ok(())
}
impl Recipe {
pub fn imprint(name: String, description: Option<String>, walker: Walk) -> Result<Self, Error> {
let description = description.unwrap_or("".into());
let languages = Recipe::languages(".");
let contents = make_contents(walker, ¤t_dir()?)?;
Ok(Self {
name,
description,
languages,
contents,
})
}
pub fn to_canonical(&self) -> Result<Self, Error> {
let temp_dir = self.materialise(None)?;
let contents = make_contents(Walk::new(temp_dir.path()), temp_dir.path())?;
let languages = Recipe::languages(temp_dir.path());
Ok(Self {
contents,
languages,
..self.clone()
})
}
pub fn is_external(&self) -> Result<bool, Error> {
let recipe_file = self.dwelling()?;
if !recipe_file.exists() {
return Ok(false);
}
let metadata = std::fs::symlink_metadata(&recipe_file).map_err(|_| Error::FsDenied {
which: recipe_file,
context: Context::Imprint,
})?;
Ok(metadata.is_symlink())
}
pub fn save(self) -> Result<PathBuf, Error> {
let canonical_recipe = self.to_canonical()?;
let recipe_file = self.dwelling()?;
if self.is_external()? {
fs_wrappers::remove_file(&recipe_file, Context::Imprint)?;
}
fs_wrappers::write(
&recipe_file,
toml::to_string_pretty(&canonical_recipe).unwrap(),
Context::Imprint,
)?;
Ok(recipe_file)
}
}