use std::path::Path;
use std::path::PathBuf;
use std::sync::atomic::AtomicUsize;
pub static VERBOSITY: AtomicUsize = AtomicUsize::new(0);
#[macro_export]
#[allow(unused_macros)]
macro_rules! always {
() => { println!() };
($($arg:tt)*) => {{ println!($($arg)*); }};
}
#[macro_export]
#[allow(unused_macros)]
macro_rules! error {
() => { eprintln!() };
($($arg:tt)*) => {{ eprintln!($($arg)*); }};
}
#[macro_export]
#[allow(unused_macros)]
macro_rules! normal {
() => { if crate::util::VERBOSITY.load(Ordering::Relaxed) > 0 { println!() } };
($($arg:tt)*) => {{ if crate::util::VERBOSITY.load(Ordering::Relaxed) > 0 { println!($($arg)*); } }};
}
#[macro_export]
#[allow(unused_macros)]
macro_rules! normal_noln {
() => { if crate::util::VERBOSITY.load(Ordering::Relaxed) > 0 { print!(); let _ = std::io::stdout().flush(); } };
($($arg:tt)*) => { if crate::util::VERBOSITY.load(Ordering::Relaxed) > 0 { {print!($($arg)*);}; let _ = std::io::stdout().flush(); }};
}
#[macro_export]
#[allow(unused_macros)]
macro_rules! loud {
() => { if crate::util::VERBOSITY.load(Ordering::Relaxed) > 1 { println!() } };
($($arg:tt)*) => {{ if crate::util::VERBOSITY.load(Ordering::Relaxed) > 1 { println!($($arg)*); } }};
}
#[macro_export]
#[allow(unused_macros)]
macro_rules! louder {
() => { if crate::util::VERBOSITY.load(Ordering::Relaxed) > 2 { println!() } };
($($arg:tt)*) => {{ if crate::util::VERBOSITY.load(Ordering::Relaxed) > 2 { println!($($arg)*); } }};
}
#[macro_export]
#[allow(unused_macros)]
macro_rules! loudest {
() => { if crate::util::VERBOSITY.load(Ordering::Relaxed) > 3 { println!() } };
($($arg:tt)*) => {{ if crate::util::VERBOSITY.load(Ordering::Relaxed) > 3 { println!($($arg)*); } }};
}
#[derive(Default, Clone)]
#[allow(dead_code)]
pub enum GitsyErrorKind {
#[default]
Unknown,
Settings,
Template,
Git,
}
#[derive(Default)]
pub struct GitsyError {
msg: Option<String>,
kind: GitsyErrorKind,
source: Option<Box<dyn std::error::Error>>,
}
unsafe impl Send for GitsyError {}
impl Clone for GitsyError {
fn clone(&self) -> Self {
GitsyError {
msg: self.msg.clone(),
kind: self.kind.clone(),
source: None,
}
}
}
#[allow(dead_code)]
impl GitsyError {
pub fn kind(kind: GitsyErrorKind, msg: Option<&str>) -> Self {
GitsyError {
kind,
msg: msg.map(|x| x.to_owned()),
source: None,
}
}
pub fn sourced_kind(kind: GitsyErrorKind, msg: Option<&str>, source: impl std::error::Error + 'static) -> Self {
GitsyError {
kind,
msg: msg.map(|x| x.to_owned()),
source: Some(Box::new(source)),
}
}
}
impl std::fmt::Display for GitsyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.kind {
GitsyErrorKind::Git => write!(f, "gitsy error (git)")?,
GitsyErrorKind::Settings => write!(f, "gitsy error (settings)")?,
GitsyErrorKind::Template => write!(f, "gitsy error (template)")?,
_ => write!(f, "gitsy error (unknown)")?,
}
write!(f, ": {}", self.msg.as_deref().unwrap_or_default())
}
}
impl std::fmt::Debug for GitsyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
}
}
impl std::error::Error for GitsyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source.as_deref()
}
}
impl From<git2::Error> for GitsyError {
fn from(source: git2::Error) -> Self {
GitsyError::sourced_kind(GitsyErrorKind::Git, Some(&source.message().to_owned()), source)
}
}
impl From<tera::Error> for GitsyError {
fn from(source: tera::Error) -> Self {
GitsyError::sourced_kind(GitsyErrorKind::Template, Some(&source.to_string()), source)
}
}
pub fn sanitize_path_component(var: &str) -> String {
let nasty_chars = r###"<>:"/\|?*&"###.to_string() + "\n\t\0";
let mut safe_str = var.to_string();
safe_str.retain(|c| !nasty_chars.contains(c));
safe_str
}
pub fn urlify_path(path: &str) -> String {
let path = path.replace("/", "+").replace("\\", "+");
path.trim().to_string()
}
pub trait SafePathVar {
fn safe_substitute(&self, path: &impl AsRef<Path>) -> PathBuf;
}