feat: multiline logging
This commit is contained in:
parent
401efe3862
commit
9a852ee88e
7 changed files with 75 additions and 38 deletions
|
@ -107,11 +107,11 @@ impl Command {
|
||||||
error!("Update is not yet implemented.");
|
error!("Update is not yet implemented.");
|
||||||
}
|
}
|
||||||
Command::Debug => {
|
Command::Debug => {
|
||||||
trace!("Trace message.");
|
trace!("Trace message.\nWith newline.");
|
||||||
debug!("Debug message.");
|
debug!("Debug message.\nWith newline.");
|
||||||
info!("Info message.");
|
info!("Info message.\nWith newline.");
|
||||||
warn!("Warning message.");
|
warn!("Warning message.\nWith newline.");
|
||||||
error!("Error message.");
|
error!("Error message.\nWith newline.");
|
||||||
|
|
||||||
info!("");
|
info!("");
|
||||||
Process::command(vec!["sh", "-c", "echo whoami: $(whoami)"])
|
Process::command(vec!["sh", "-c", "echo whoami: $(whoami)"])
|
||||||
|
|
|
@ -4,12 +4,15 @@ use serde::{Deserialize, Serialize};
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub build_by_default: bool,
|
pub build_by_default: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub tmp_dir: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Config {
|
fn default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
build_by_default: false,
|
build_by_default: false,
|
||||||
|
tmp_dir: Some(String::from("/tmp/pkgr"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,57 @@
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use fern::Dispatch;
|
use fern::Dispatch;
|
||||||
use log::SetLoggerError;
|
use log::{Record, SetLoggerError};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
fn format_regular<S: Into<String>>(log: S, record: &Record) -> String {
|
||||||
|
let log = log.into();
|
||||||
|
let line_prefix = |line: String, extend: bool| {
|
||||||
|
let prefix = if extend {
|
||||||
|
match record.level() {
|
||||||
|
log::Level::Trace => " :".bright_blue(),
|
||||||
|
log::Level::Debug => " :".green(),
|
||||||
|
log::Level::Info => " :".blue(),
|
||||||
|
log::Level::Warn => " :".yellow(),
|
||||||
|
log::Level::Error => " :".red(),
|
||||||
|
}.to_string()
|
||||||
|
} else {
|
||||||
|
match record.level() {
|
||||||
|
log::Level::Trace => "[TRACE]".bright_blue(),
|
||||||
|
log::Level::Debug => "??".green(),
|
||||||
|
log::Level::Info => "=>".blue(),
|
||||||
|
log::Level::Warn => "##".yellow(),
|
||||||
|
log::Level::Error => "!!".red()
|
||||||
|
}.to_string()
|
||||||
|
};
|
||||||
|
return format!("{} {}", prefix, line);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut lines = log.lines().peekable();
|
||||||
|
let mut output = match lines.peek() {
|
||||||
|
Some(line) => line_prefix(lines.next().unwrap().to_string(), false),
|
||||||
|
None => return "".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
output.push_str(&*format!("\n{}", line_prefix(line.to_string(), true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setup_logger() -> Result<(), SetLoggerError> {
|
pub fn setup_logger() -> Result<(), SetLoggerError> {
|
||||||
Dispatch::new()
|
Dispatch::new()
|
||||||
.format(|out, message, record| {
|
.format(|out, message, record| {
|
||||||
match record.metadata().target() {
|
match record.metadata().target() {
|
||||||
"command:stdout" => {
|
"command:stdout" => {
|
||||||
out.finish(format_args!("{} {}", "::".cyan(), message.to_string()));
|
out.finish(format_args!("{} {}", ">>".cyan(), message.to_string()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
"command:stderr" => {
|
"command:stderr" => {
|
||||||
out.finish(format_args!("{} {}", "!!".red(), message.to_string()));
|
out.finish(format_args!("{} {}", ">>".red(), message.to_string()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => out.finish(format_args!("{}", format_regular(message.to_string(), record))),
|
||||||
out.finish(format_args!(
|
|
||||||
"{} {}",
|
|
||||||
// Some logic so messages look nice
|
|
||||||
if message.to_string().len() > 0 {
|
|
||||||
match record.level().to_string().chars().nth(0).unwrap_or('T') {
|
|
||||||
'T' => "[TRACE]".bright_blue(),
|
|
||||||
'D' => "??".green(),
|
|
||||||
'I' => "=>".blue(),
|
|
||||||
'W' => "##".yellow(),
|
|
||||||
'E' => "!!".red(),
|
|
||||||
_ => "**".blue(),
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
} else {
|
|
||||||
"".to_string()
|
|
||||||
},
|
|
||||||
message.to_string().bright_white()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.level(
|
.level(
|
||||||
|
|
|
@ -7,15 +7,15 @@ use regex::Regex;
|
||||||
pub enum PackageIdentifierError {
|
pub enum PackageIdentifierError {
|
||||||
InvalidPackageLocator(String),
|
InvalidPackageLocator(String),
|
||||||
InvalidURI(String),
|
InvalidURI(String),
|
||||||
|
InvalidPath(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for PackageIdentifierError {
|
impl std::fmt::Display for PackageIdentifierError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
PackageIdentifierError::InvalidPackageLocator(s) => {
|
PackageIdentifierError::InvalidPackageLocator(s) => write!(f, "Invalid package locator: {}", s),
|
||||||
write!(f, "Invalid package locator: {}", s)
|
|
||||||
}
|
|
||||||
PackageIdentifierError::InvalidURI(s) => write!(f, "Invalid URI: {}", s),
|
PackageIdentifierError::InvalidURI(s) => write!(f, "Invalid URI: {}", s),
|
||||||
|
PackageIdentifierError::InvalidPath(s) => write!(f, "Invalid path: {}", s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,18 @@ impl FromStr for PackageIdentifier {
|
||||||
return Err(PackageIdentifierError::InvalidURI(s.to_string()));
|
return Err(PackageIdentifierError::InvalidURI(s.to_string()));
|
||||||
}
|
}
|
||||||
Ok(PackageIdentifier::URI(s.to_string()))
|
Ok(PackageIdentifier::URI(s.to_string()))
|
||||||
} else if std::path::Path::new(s).exists() {
|
} else if s.starts_with("/")
|
||||||
|
|| s.starts_with("./")
|
||||||
|
|| s.starts_with("../")
|
||||||
|
|| s.starts_with("~/")
|
||||||
|
{
|
||||||
|
let path = std::path::Path::new(s);
|
||||||
|
if s.ends_with("/")
|
||||||
|
|| !path.exists()
|
||||||
|
|| path.is_dir()
|
||||||
|
{
|
||||||
|
return Err(PackageIdentifierError::InvalidPath(s.to_string()));
|
||||||
|
}
|
||||||
return Ok(PackageIdentifier::Path(s.to_string()));
|
return Ok(PackageIdentifier::Path(s.to_string()));
|
||||||
} else {
|
} else {
|
||||||
let pl = match PackageLocator::from_str(s) {
|
let pl = match PackageLocator::from_str(s) {
|
||||||
|
|
|
@ -37,8 +37,8 @@ pub enum InstallError {
|
||||||
impl ToString for InstallError {
|
impl ToString for InstallError {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
InstallError::BuildError(e) => format!("Build error: {}", e),
|
InstallError::BuildError(e) => format!("Build error: \n{}", e),
|
||||||
InstallError::BinError(e) => format!("Bin error: {}", e),
|
InstallError::BinError(e) => format!("Bin error: \n{}", e),
|
||||||
InstallError::InvalidManifest => "Invalid manifest".to_string(),
|
InstallError::InvalidManifest => "Invalid manifest".to_string(),
|
||||||
InstallError::Generic => "Install error".to_string(),
|
InstallError::Generic => "Install error".to_string(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,10 @@ impl PackageInstaller {
|
||||||
return Err(BinError::UnpackError("package has no data".to_string()));
|
return Err(BinError::UnpackError("package has no data".to_string()));
|
||||||
}
|
}
|
||||||
if std::path::Path::new(&path).exists() {
|
if std::path::Path::new(&path).exists() {
|
||||||
return Err(BinError::UnpackError("path already exists".to_string()));
|
return Err(BinError::UnpackError(format!(
|
||||||
|
"path already exists: {}",
|
||||||
|
path
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
tar::Archive::new(self.pkgfile.data.as_slice())
|
tar::Archive::new(self.pkgfile.data.as_slice())
|
||||||
.unpack(&path)
|
.unpack(&path)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use crate::CONFIG;
|
||||||
|
|
||||||
pub struct TempDir {
|
pub struct TempDir {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
@ -20,9 +21,11 @@ impl TempDir {
|
||||||
impl Default for TempDir {
|
impl Default for TempDir {
|
||||||
fn default() -> TempDir {
|
fn default() -> TempDir {
|
||||||
TempDir::new({
|
TempDir::new({
|
||||||
let mut t = std::env::temp_dir();
|
if let Some(d) = CONFIG.with(|c| c.tmp_dir.clone()) {
|
||||||
t.push("pkgr");
|
PathBuf::from(d)
|
||||||
t
|
} else {
|
||||||
|
PathBuf::from("/tmp/pkgr")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue