use glob::glob;
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fs,
path::{Path, PathBuf},
};
use toml::Value;
use walkdir::WalkDir;
pub fn get_subfolder_prefix<P: AsRef<Path>>(functions_path: &P) -> String {
let mut after_functions = PathBuf::from(
functions_path
.as_ref()
.to_str()
.unwrap()
.split("functions")
.last()
.unwrap(),
);
after_functions.pop();
let prefix = after_functions.to_str().unwrap().replace('\\', "/");
if prefix == "/" {
String::new()
} else if let Some(new) = prefix.strip_prefix('/') {
format!("{}/", new)
} else {
format!("{}/", prefix)
}
}
pub fn get_namespace<P: AsRef<Path>>(functions_path: &P) -> Result<&str, &str> {
let namespace_folder = functions_path
.as_ref()
.to_str()
.unwrap()
.split("functions")
.next()
.unwrap();
let namespace_folder =
if let Some(new) = namespace_folder.strip_suffix(|x: char| ['\\', '/'].contains(&x)) {
new
} else {
namespace_folder
};
let folders = namespace_folder.split(|x: char| ['\\', '/'].contains(&x));
Ok(folders.last().unwrap())
}
pub fn merge_globs(globs: &[String], prefix: &str) -> Vec<PathBuf> {
let mut merged_globs: Vec<PathBuf> = Vec::new();
for files_glob in globs.iter() {
let relative_files_glob = format!("{}/{}", prefix, files_glob);
let mut files: Vec<PathBuf> = glob(&relative_files_glob)
.expect(&format!("Failed to parse glob {}", files_glob)[..])
.filter_map(Result::ok)
.collect();
merged_globs.append(&mut files);
}
merged_globs
}
pub fn find_config_in_parents(
start: &dyn AsRef<Path>,
config_file: String,
) -> Result<PathBuf, &str> {
let mut start = PathBuf::from(start.as_ref());
let mut last = PathBuf::new();
while start != last {
start.push(&config_file);
if start.exists() && start.is_file() {
return Ok(start);
}
start.pop();
last = start.clone();
start.pop();
}
Err("Did not find databind.toml in parents")
}
pub fn create_tag_files<P: AsRef<Path>>(
src_dir: P,
target_folder: P,
tag_map: &HashMap<String, Vec<String>>,
) -> std::io::Result<()> {
#[derive(Deserialize, Serialize)]
struct TagFile {
values: Vec<String>,
}
let target = target_folder.as_ref().display();
fs::create_dir_all(format!("{}/data/minecraft/tags/functions", target))?;
for (tag, funcs) in tag_map.iter() {
let mut tag_file = TagFile {
values: funcs.clone(),
};
{
let path_str = format!(
"{}/data/minecraft/tags/functions/{}.json",
src_dir.as_ref().display(),
tag
);
let path = Path::new(&path_str);
if path.exists() && path.is_file() {
let contents = fs::read_to_string(&path)?;
let mut existing_tags: TagFile = serde_json::from_str(&contents)?;
tag_file.values.append(&mut existing_tags.values);
}
}
let json = serde_json::to_string(&tag_file)?;
fs::write(
&format!("{}/data/minecraft/tags/functions/{}.json", target, tag),
json,
)?;
}
Ok(())
}
pub fn prioritize_macro_files<P: AsRef<Path>>(src_dir: P) -> Vec<PathBuf> {
let mut global_macros: Vec<PathBuf> = Vec::new();
let mut normal: Vec<PathBuf> = Vec::new();
let unsorted_paths = WalkDir::new(src_dir)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.path().is_file())
.map(|e| e.path().to_path_buf());
for path in unsorted_paths {
if path.file_name().unwrap().to_str().unwrap().starts_with('!') {
global_macros.push(path);
} else {
normal.push(path);
}
}
global_macros.append(&mut normal);
global_macros
}
pub fn read_vars_toml<P: AsRef<Path>>(vars_toml: P) -> HashMap<String, String> {
let contents = fs::read_to_string(vars_toml).unwrap();
let vars_multi_type: HashMap<String, Value> = toml::from_str(&contents).unwrap();
let mut vars: HashMap<String, String> = HashMap::new();
for (k, v) in vars_multi_type.iter() {
let new_v: String = match v {
Value::String(value) => value.clone(),
Value::Boolean(value) => {
if *value {
"1".into()
} else {
"0".into()
}
}
Value::Float(value) => value.to_string(),
Value::Integer(value) => value.to_string(),
Value::Datetime(value) => value.to_string(),
_ => {
eprintln!(
"error: Unsupported type found in vars.toml file (key: {}, value: {})",
k, v
);
std::process::exit(1);
}
};
vars.entry(format!("&{}", k)).or_insert(new_v);
}
vars
}