build.rs/src/log.rs

224 lines
6.5 KiB
Rust
Raw Normal View History

2020-04-30 16:53:49 +00:00
use std::collections::HashMap;
2020-11-25 22:59:39 +00:00
use std::env;
2020-04-30 16:53:49 +00:00
use std::fs;
2020-12-01 17:19:53 +00:00
use std::path::{Path, PathBuf};
2021-01-04 15:25:47 +00:00
// To get effective user id (EUID) so that setuid works
use users::{get_effective_uid,get_user_by_uid};
// For home directory
use users::os::unix::UserExt;
2020-04-30 16:53:49 +00:00
use lazy_static::lazy_static;
2020-11-25 22:59:39 +00:00
lazy_static! {
2020-04-30 16:53:49 +00:00
static ref LOGLEVEL: LogLevel = LogLevel::from_env();
2020-11-28 15:48:23 +00:00
static ref LANG: Lang = Lang::from_env();
2020-04-30 16:53:49 +00:00
static ref TRANSLATIONS: HashMap<String, String> = load_translations();
}
/// Lang configures how to deal with translations. It has three possible values:
/// None: translations return their own key name
/// Some(code): where code is the language code for the JSON translation file
2020-11-28 19:36:11 +00:00
/// JsonContext: debug output for Context as JSON
2020-12-01 17:19:53 +00:00
/// File(PathBuf): fixed translation file (instead of language code)
pub enum Lang {
None,
2020-11-28 19:36:11 +00:00
JsonContext,
2020-12-01 17:19:53 +00:00
Some(String),
File(PathBuf),
}
2020-11-28 15:48:23 +00:00
impl Lang {
fn from_env() -> Lang {
let lang =
env::var("LANG").expect("$LANG not set in environment. Your machine is misconfigured!");
2020-12-01 17:19:53 +00:00
match lang.to_uppercase().as_str() {
2020-11-28 15:48:23 +00:00
"NONE" => Lang::None,
2020-11-28 19:36:11 +00:00
"JSON" => Lang::JsonContext,
"C" => {
// Special case: when no lang is specified, default to english
Lang::Some("en".to_string())
},
2020-12-01 17:19:53 +00:00
_ => {
let p = PathBuf::from(&lang);
if p.is_file() {
// LANG env variable contains a path to a full (JSON) file
Lang::File(p)
} else {
Lang::Some(lang[0..2].to_string())
}
}
2020-11-28 15:48:23 +00:00
}
}
}
pub type Context = HashMap<String, String>;
2020-04-30 23:45:48 +00:00
2020-11-23 18:45:35 +00:00
/// Returns a PathBuf containing the translations. Does not mean
/// the translations are in there!
/// First attempts to find $FORGEBUILDI18N from env, otherwise tries
/// $HOME/.local/share/forgebuild/i18n or /usr/local/share/forgebuild/i18n
fn find_translations() -> PathBuf {
match env::var("FORGEBUILDI18N") {
Ok(dir) => PathBuf::from(dir),
Err(_) => {
2021-01-04 15:25:47 +00:00
//let mut path = home_dir().expect("$HOME folder not found");
let owner = get_effective_uid();
let mut path = get_user_by_uid(owner).expect("Failed owner profile")
.home_dir().to_path_buf();
2020-11-23 18:45:35 +00:00
path.push(".local/share/forgebuild/i18n");
2021-01-04 15:25:47 +00:00
println!("{}", path.to_str().unwrap());
2020-11-23 18:45:35 +00:00
if path.is_dir() {
path
} else {
// Didn't find from env or in home directory,
// return default /usr/share/local/forgebuild/i18n
PathBuf::from("/usr/share/local/forgebuild/i18n")
}
}
}
}
2020-12-01 17:19:53 +00:00
fn load_translations_from_file(path: &Path) -> HashMap<String, String> {
match fs::read_to_string(&path) {
Ok(content) => {
//let trans: HashMap<String, String> = serde_json::from_str(&content).expect("Could not load translations");
//return trans
match serde_json::from_str(&content) {
Ok(trans) => trans,
Err(e) => panic!("JSON ERROR: {}", e),
}
}
Err(e) => {
panic!("IO ERROR: {}", e);
}
}
}
2020-04-30 16:53:49 +00:00
fn load_translations() -> HashMap<String, String> {
match &*LANG {
2020-12-01 17:19:53 +00:00
Lang::File(path) => {
load_translations_from_file(&path)
},
Lang::Some(lang) => {
let mut path = find_translations();
if !path.is_dir() {
panic!("Could not find translations in {:?}", path);
}
path.push(format!("{}.json", lang));
2020-04-30 16:53:49 +00:00
if !path.is_file() {
panic!("Could not find translation file: {:?}", path);
}
2020-04-30 16:53:49 +00:00
2020-12-01 17:19:53 +00:00
load_translations_from_file(&path)
},
_ => {
HashMap::new()
2020-04-30 16:53:49 +00:00
}
}
}
fn trans(key: &str) -> String {
match &*LANG {
2020-12-01 17:19:53 +00:00
Lang::File(path) => {
if let Some(t) = TRANSLATIONS.get(key) {
t.to_string()
} else {
panic!("Missing translation for {} in translation file: {}", key, path.to_str().unwrap())
}
},
2020-11-28 19:36:11 +00:00
Lang::Some(lang) => {
if let Some(t) = TRANSLATIONS.get(key) {
t.to_string()
} else {
panic!("Missing translation for {} in lang {}", key, lang)
}
},
2020-11-28 19:36:11 +00:00
Lang::JsonContext => String::new(),
Lang::None => key.to_string(),
2020-04-30 16:53:49 +00:00
}
}
2020-11-28 19:36:11 +00:00
fn trans_context(key: &str, context: &Context) -> String {
match &*LANG {
Lang::JsonContext => {
// Serialize the context to JSON for debugging
serde_json::to_string(context).expect("Failed to serialize to JSON")
},
_ => expand(&trans(key), context)
}
}
2020-04-30 16:53:49 +00:00
struct LogLevel {
info: bool,
debug: bool,
2020-11-25 22:59:39 +00:00
error: bool,
2020-04-30 16:53:49 +00:00
}
impl LogLevel {
fn from_env() -> LogLevel {
// Default values
let error = true;
let mut info = true;
let mut debug = false;
let env_log = env::var("LOG").unwrap_or("info".to_string());
match env_log.to_lowercase().as_str() {
2020-11-25 22:59:39 +00:00
"info" => {}
"debug" => {
debug = true;
}
"error" => {
info = false;
}
2020-04-30 16:53:49 +00:00
_ => {
// This happens before loglevel initialization
// so we can't use warn function
2020-11-25 22:59:39 +00:00
eprintln!(
"$LOG level is incorrect: {} (can be: debug, info, error",
env_log
);
2020-04-30 16:53:49 +00:00
}
}
2020-11-25 22:59:39 +00:00
return LogLevel { info, debug, error };
2020-04-30 16:53:49 +00:00
}
}
2020-11-28 15:48:23 +00:00
/// Expands variables from the vars Context. If the
/// context is empty, the string is returned untouched
fn expand(msg: &str, vars: &Context) -> String {
if vars.is_empty() {
return msg.to_string();
2020-04-30 16:53:49 +00:00
}
2020-11-28 15:48:23 +00:00
return vars
.iter()
.fold(msg.to_string(), |prev, (key, val)| prev.replace(key, val));
2020-04-30 16:53:49 +00:00
}
2020-11-28 15:48:23 +00:00
pub fn info(msg: &str, vars: &Context) {
2020-04-30 16:53:49 +00:00
if LOGLEVEL.info {
2020-12-01 17:19:53 +00:00
println!("{}{}", trans("info"), trans_context(msg, vars));
2020-04-30 16:53:49 +00:00
}
}
2020-11-28 15:48:23 +00:00
pub fn error(msg: &str, vars: &Context) {
2020-04-30 16:53:49 +00:00
if LOGLEVEL.error {
2020-11-28 19:36:11 +00:00
eprintln!("{}{}", trans("error"), trans_context(msg, vars));
2020-04-30 16:53:49 +00:00
}
}
2020-11-28 15:48:23 +00:00
pub fn warn(msg: &str, vars: &Context) {
2020-04-30 16:53:49 +00:00
if LOGLEVEL.error {
2020-11-28 19:36:11 +00:00
eprintln!("{}{}", trans("warning"), trans_context(msg, vars));
2020-04-30 16:53:49 +00:00
}
}
2020-11-28 15:48:23 +00:00
pub fn debug(msg: &str, vars: &Context) {
2020-04-30 16:53:49 +00:00
if LOGLEVEL.debug {
2020-11-28 19:36:11 +00:00
println!("{}{}", trans("debug"), trans_context(msg, vars));
2020-04-30 16:53:49 +00:00
}
}