From 60cb2b9474414b5101a9c13d8a74a56aaa1dd22a Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Tue, 26 Mar 2024 16:03:58 +0530 Subject: [PATCH 01/17] added functions for interfacing with plugins --- Cargo.toml | 4 +-- paxy-plugin/Cargo.toml | 16 ++++++++++++ paxy-plugin/src/main.rs | 3 +++ paxy/src/app/mod.rs | 1 + paxy/src/app/plugins.rs | 56 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 paxy-plugin/Cargo.toml create mode 100644 paxy-plugin/src/main.rs create mode 100644 paxy/src/app/plugins.rs diff --git a/Cargo.toml b/Cargo.toml index 31a423d..9fe582c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [ "paxy", "paxy-cli", - "paxy-gui", + "paxy-gui", "paxy-plugin", "tests", ] @@ -71,4 +71,4 @@ console = "0.15" # GUI relm4 = "0.6" -relm4-components = "0.6" \ No newline at end of file +relm4-components = "0.6" diff --git a/paxy-plugin/Cargo.toml b/paxy-plugin/Cargo.toml new file mode 100644 index 0000000..7322561 --- /dev/null +++ b/paxy-plugin/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "paxy-plugin" +version.workspace = true +description.workspace = true +repository.workspace = true +homepage.workspace = true +authors.workspace = true +keywords.workspace = true +exclude.workspace = true +categories.workspace = true +documentation.workspace = true +readme.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] diff --git a/paxy-plugin/src/main.rs b/paxy-plugin/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/paxy-plugin/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/paxy/src/app/mod.rs b/paxy/src/app/mod.rs index ddba724..fa48799 100644 --- a/paxy/src/app/mod.rs +++ b/paxy/src/app/mod.rs @@ -49,5 +49,6 @@ pub use config::*; pub use i18n::*; #[allow(unused_imports)] pub use logging::*; +mod plugins; // endregion: RE-EXPORTS diff --git a/paxy/src/app/plugins.rs b/paxy/src/app/plugins.rs new file mode 100644 index 0000000..7f7c3aa --- /dev/null +++ b/paxy/src/app/plugins.rs @@ -0,0 +1,56 @@ +use std::{ + fs::{write, File}, + path::{Path, PathBuf}, +}; + +use bson::{doc, Document}; +use extism::{Manifest, PluginBuilder, Wasm}; + +use crate::{actions::ensure_path, home}; + +#[allow(unused)] +pub(crate) fn plugin(manifest: Box) -> Wasm { + let mut file = home!(); + file.push(".paxy"); + file.push("plugins"); + ensure_path(Some(&file)); + file.push("plugins.bson"); + let plugins = if !file.is_file() { + let mut buf = vec![]; + let doc = doc! {"pax": "paxy.wasm"}; + doc.to_writer(&mut buf) + .unwrap(); + write(file, buf).unwrap(); + doc + } else { + Document::from_reader(File::open(file).unwrap()).unwrap() + }; + let plugin = plugins + .get( + manifest + .extension() + .expect("unknown manifest type") + .to_str() + .unwrap(), + ) + .unwrap() + .to_string(); + Wasm::file(plugin) +} + +pub fn call_plugin(wasm: Wasm, pkg: Box) { + let mut tmp = home!(); + tmp.push(".paxy"); + tmp.push("tmp"); + ensure_path(Some(&tmp)); + let manifest = Manifest::new([wasm]).with_allowed_paths( + [(tmp, PathBuf::from("/tmp")), (*pkg, PathBuf::from("/pkg"))] + .iter() + .cloned(), + ); + let plugin = PluginBuilder::new(manifest).with_wasi(true); + let mut plugin = plugin + .build() + .unwrap(); + plugin.call::<&str, &str>("process", "").unwrap(); +} From 517303c830fc8a5d3a8229b6a52cc49734132b3b Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Tue, 26 Mar 2024 16:22:55 +0530 Subject: [PATCH 02/17] fixed clippy issues --- paxy/src/actions/mod.rs | 21 ++++++++++----------- paxy/src/app/plugins.rs | 10 +++++++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/paxy/src/actions/mod.rs b/paxy/src/actions/mod.rs index ce4fff0..a89335c 100644 --- a/paxy/src/actions/mod.rs +++ b/paxy/src/actions/mod.rs @@ -74,6 +74,7 @@ macro_rules! home { } #[inline] +#[allow(clippy::unnecessary_unwrap)] pub fn ensure_path(path: Option<&PathBuf>) { if path.is_none() { let mut file = home!(); @@ -81,16 +82,14 @@ pub fn ensure_path(path: Option<&PathBuf>) { if !file.is_dir() { ::std::fs::create_dir_all(file).expect("Inufficient permissions"); } - } else { - if !path - .unwrap() - .is_dir() - { - ::std::fs::create_dir_all( - path.unwrap() - .clone(), - ) - .expect("Inufficient permissions"); - } + } else if !path + .unwrap() + .is_dir() + { + ::std::fs::create_dir_all( + path.unwrap() + .clone(), + ) + .expect("Inufficient permissions"); } } diff --git a/paxy/src/app/plugins.rs b/paxy/src/app/plugins.rs index 7f7c3aa..37340d4 100644 --- a/paxy/src/app/plugins.rs +++ b/paxy/src/app/plugins.rs @@ -9,6 +9,7 @@ use extism::{Manifest, PluginBuilder, Wasm}; use crate::{actions::ensure_path, home}; #[allow(unused)] +#[allow(clippy::boxed_local)] pub(crate) fn plugin(manifest: Box) -> Wasm { let mut file = home!(); file.push(".paxy"); @@ -38,13 +39,14 @@ pub(crate) fn plugin(manifest: Box) -> Wasm { Wasm::file(plugin) } -pub fn call_plugin(wasm: Wasm, pkg: Box) { +#[allow(unused)] +pub fn call_plugin(wasm: Wasm, pkg: PathBuf) { let mut tmp = home!(); tmp.push(".paxy"); tmp.push("tmp"); ensure_path(Some(&tmp)); let manifest = Manifest::new([wasm]).with_allowed_paths( - [(tmp, PathBuf::from("/tmp")), (*pkg, PathBuf::from("/pkg"))] + [(tmp, PathBuf::from("/tmp")), (pkg, PathBuf::from("/pkg"))] .iter() .cloned(), ); @@ -52,5 +54,7 @@ pub fn call_plugin(wasm: Wasm, pkg: Box) { let mut plugin = plugin .build() .unwrap(); - plugin.call::<&str, &str>("process", "").unwrap(); + plugin + .call::<&str, &str>("process", "") + .unwrap(); } From ddcc2f2fc521376910faf7ba07ae79006b555231 Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Thu, 11 Apr 2024 11:24:51 -0500 Subject: [PATCH 03/17] feat: :construction: Integrating configuration from various sources --- paxy/src/app/config.rs | 30 +++++++++++++++++++++--------- paxy/src/ui/mod.rs | 16 ++++++++++++++-- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 0a59e0c..7c47720 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -3,7 +3,11 @@ /// local paths. overridden by environment variables starting with `PAXY_`, /// overridden by the configuration file specified by the commandline. /// Values from only files with supported file extensions would be merged. -pub fn init_config(config_filepath: Option<&Path>) -> Result<(Config, Vec), Error> { +pub fn init_config(cli_modifier: C) -> Result<(Config, Vec), Error> +where + C: clap::Parser + ui::CliModifier + fmt::Debug, + ::L: LogLevel, +{ let mut candidate_config_filepath_stubs: Vec = Vec::new(); // Global directories @@ -41,10 +45,11 @@ pub fn init_config(config_filepath: Option<&Path>) -> Result<(Config, Vec) -> Result<(Config, Vec &Option; - fn is_json(&self) -> bool; + fn is_json(&self) -> &Option; fn is_plain(&self) -> bool; @@ -237,6 +248,7 @@ use owo_colors::OwoColorize; use snafu::{ResultExt, Snafu}; use tracing_appender::non_blocking::WorkerGuard; use tracing_subscriber::filter::LevelFilter; +use figment; use crate::app::{self, config, logging}; From 5b373336a1283964f56b05baaeeb2c06d2ebb5a8 Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Thu, 11 Apr 2024 22:30:39 -0500 Subject: [PATCH 04/17] Initial attempt --- Cargo.toml | 2 +- paxy/src/app/config.rs | 34 +++++------ paxy/src/app/logging.rs | 17 +++++- paxy/src/ui/mod.rs | 132 ++++++++++++++++++---------------------- 4 files changed, 92 insertions(+), 93 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0688588..fe7a04c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ paxy = { path = "paxy" } # Logging tracing = "0.1" tracing-appender = "0.2" -tracing-subscriber = "0.3" +tracing-subscriber = { version = "0.3", features = ["serde", "tracing-serde"] } # Configuration figment = "0.10" diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 7c47720..69cb553 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -3,10 +3,10 @@ /// local paths. overridden by environment variables starting with `PAXY_`, /// overridden by the configuration file specified by the commandline. /// Values from only files with supported file extensions would be merged. -pub fn init_config(cli_modifier: C) -> Result<(Config, Vec), Error> +pub fn init_config(cli_modifier: &C) -> Result<(Config, Vec), Error> where - C: clap::Parser + ui::CliModifier + fmt::Debug, - ::L: LogLevel, + C: ui::CliModifier, + ::L: clap_verbosity_flag::LogLevel, { let mut candidate_config_filepath_stubs: Vec = Vec::new(); @@ -35,17 +35,14 @@ where // Merge configuration values from global and local filepaths figment = candidate_config_filepath_stubs .iter() - .fold( - figment, - move |figment, candidate_config_filepath_stub| { - admerge_from_stub(candidate_config_filepath_stub, figment) - }, - ); + .fold(figment, move |figment, candidate_config_filepath_stub| { + admerge_from_stub(candidate_config_filepath_stub, figment) + }); // Merge configuration values from environment variables figment = figment.admerge(Env::prefixed(&format!("{}_", *app::APP_NAME))); - // Merge configuration values from additional config filepaths (usually + // Merge configuration values from additional config filepaths (usually // specified through CLI) if let Some(additional_config_filepath) = cli_modifier.config_file() { if let Some(parent) = additional_config_filepath.parent() { @@ -62,17 +59,17 @@ where // These are not set to be optional, so only action-required states are // merged with the configuration if cli_modifier.is_uncolored() { - figment.admerge(("no_color", true)); + figment = figment.admerge(("no_color", true)); } - if let Some(log_level_filter) = cli_input.verbosity_filter() { - figment.admerge(("log_level_filter", log_level_filter)); + if let Some(log_level_filter) = cli_modifier.verbosity_filter() { + figment = figment.admerge(("log_level_filter", log_level_filter)); } Ok(( figment .extract() .context(ExtractConfigSnafu {})?, - candidate_config_filepath_stubs + candidate_config_filepath_stubs, )) } @@ -96,7 +93,7 @@ fn admerge_from_stub(candidate_config_filepath_stub: &PathBuf, mut figment: Figm pub struct Config { pub log_directory: Option, - pub log_level_filter: Option, + pub log_level_filter: Option, pub no_color: Option, } @@ -111,7 +108,7 @@ impl Default for Config { fn default() -> Self { Config { log_directory: None, - log_level_filter: Some(log::LevelFilter::Info), + log_level_filter: Some(LevelFilter::Info), no_color: Some(false), } } @@ -151,7 +148,7 @@ pub enum Error { // region: IMPORTS -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use figment::{ providers::{Env, Format, Json, Toml, Yaml}, @@ -163,7 +160,8 @@ use figment::{ }; use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; +use log::LevelFilter; -use crate::{ui, app}; +use crate::{app, ui}; // endregion: IMPORTS diff --git a/paxy/src/app/logging.rs b/paxy/src/app/logging.rs index c7a6478..4b96c57 100644 --- a/paxy/src/app/logging.rs +++ b/paxy/src/app/logging.rs @@ -1,12 +1,14 @@ pub fn init_log( preferred_log_dirpath: Option, - preferred_log_level_filter: Option, + preferred_log_level_filter: Option, ) -> Result<(Handle, PathBuf), Error> { let log_filename = format!("{}.log", *app::APP_NAME); let log_dirpath = obtain_log_dirpath(preferred_log_dirpath)?; let log_file_appender = tracing_appender::rolling::daily(log_dirpath.clone(), log_filename.clone()); - let log_level_filter = preferred_log_level_filter.unwrap_or(LevelFilter::INFO); + let log_level_filter = tracing_level_filter_from_log_level_filter( + preferred_log_level_filter.unwrap_or(log::LevelFilter::Info), + ); // Obtain writers to various logging destinations and worker guards (for // keeping the streams alive) @@ -188,6 +190,17 @@ fn obtain_log_dirpath(preferred_log_dirpath: Option) -> Result LevelFilter { + match level_filter { + log::LevelFilter::Off => LevelFilter::OFF, + log::LevelFilter::Error => LevelFilter::ERROR, + log::LevelFilter::Warn => LevelFilter::WARN, + log::LevelFilter::Info => LevelFilter::INFO, + log::LevelFilter::Debug => LevelFilter::DEBUG, + log::LevelFilter::Trace => LevelFilter::TRACE, + } +} + type OutputModeSwitchFunction = Box Result<(), Error>>; pub struct Handle { diff --git a/paxy/src/ui/mod.rs b/paxy/src/ui/mod.rs index 736512e..21af28b 100644 --- a/paxy/src/ui/mod.rs +++ b/paxy/src/ui/mod.rs @@ -8,37 +8,17 @@ where let cli_input = C::parse(); // Obtain user configuration - let (figment, config_filepaths) = config::init_config( - cli_input - .config_file() - .as_ref() - .map(|f| PathBuf::as_path(&f)), - ) - .context(app::ConfigSnafu {}) - .context(crate::AppSnafu)?; - - if cli_input.is_uncolored() { - figment.admerge(("no_color", true)); - anstream::ColorChoice::Never.write_global(); - owo_colors::set_override(false); - } - if let Some(log_level_filter) = cli_input.verbosity_filter() { - figment.admerge(("log_level_filter", log_level_filter)); - } - - + let (config, config_filepaths) = config::init_config(&cli_input) + .context(app::ConfigSnafu {}) + .context(crate::AppSnafu)?; // Turn off colors if needed - let mut is_cli_uncolored = cli_input.is_uncolored(); - if !is_cli_uncolored { - if let Some(no_color) = config.no_color { - is_cli_uncolored = no_color; + if let Some(no_color) = config.no_color { + if no_color { + anstream::ColorChoice::Never.write_global(); + owo_colors::set_override(false); } } - if is_cli_uncolored { - anstream::ColorChoice::Never.write_global(); - owo_colors::set_override(false); - } // Begin logging with preferred log directory and preferred verbosity let config_log_dirpath = config @@ -52,10 +32,7 @@ where .parse() .ok() }); - let verbosity_filter = cli_input - .verbosity_filter() - .or(config_verbosity_filter); - let (mut handle, log_filepath) = logging::init_log(config_log_dirpath, verbosity_filter) + let (mut handle, log_filepath) = logging::init_log(config_log_dirpath, config_verbosity_filter.into()) .context(app::LoggingSnafu {}) .context(crate::AppSnafu {})?; @@ -77,7 +54,15 @@ where .context(crate::AppSnafu {})?; } - // Welcome message + emit_welcome_messages(); + emit_diagnostic_messages(config_filepaths, log_filepath, &cli_input); + emit_test_messages(); + + Ok((cli_input, handle.worker_guards)) +} + +fn emit_welcome_messages() { + // Welcome messages tracing::debug!( "{} - {}", "Paxy".bold(), @@ -89,41 +74,13 @@ where "shivanandvp".italic(), "".italic() ); - tracing::debug!( - target:"TEST", "{}{}{}{}{}{}{}{}", - "███".black(), - "███".red(), - "███".green(), - "███".yellow(), - "███".blue(), - "███".purple(), - "███".cyan(), - "███".white() - ); - tracing::debug!( - target:"TEST", "{}{}{}{}{}{}{}{}", - "███".bright_black(), - "███".bright_red(), - "███".bright_green(), - "███".bright_yellow(), - "███".bright_blue(), - "███".bright_purple(), - "███".bright_cyan(), - "███".bright_white() - ); - - if cli_input.is_test() { - // Test messages - tracing::trace!(target:"TEST", "{} Testing trace!...", console::Emoji("🧪", "")); - tracing::debug!(target:"TEST", "{} Testing debug!...", console::Emoji("🧪", "")); - tracing::info!(target:"TEST", "{} Testing info!...", console::Emoji("🧪", "")); - tracing::warn!(target:"TEST", "{} Testing warn!...", console::Emoji("🧪", "")); - tracing::error!(target:"TEST", "{} Testing error!...", console::Emoji("🧪", "")); - - tracing::info!(target:"JSON", "{} Testing: {}", console::Emoji("🧪", ""), "{\"JSON\": \"Target\"}"); - tracing::info!(target:"PLAIN", "{} Testing: Plain Target", console::Emoji("🧪", "")); - } +} +fn emit_diagnostic_messages(config_filepaths: Vec, log_filepath: PathBuf, cli_input: &C) +where + C: clap::Parser + CliModifier + fmt::Debug, + ::L: LogLevel, +{ tracing::debug!( "{} The {} is {}... {}", console::Emoji("⚙️", ""), @@ -160,8 +117,40 @@ where .dimmed(), cli_input.dimmed() ); +} - Ok((cli_input, handle.worker_guards)) +fn emit_test_messages() { + tracing::debug!( + target:"TEST", "{}{}{}{}{}{}{}{}", + "███".black(), + "███".red(), + "███".green(), + "███".yellow(), + "███".blue(), + "███".purple(), + "███".cyan(), + "███".white() + ); + tracing::debug!( + target:"TEST", "{}{}{}{}{}{}{}{}", + "███".bright_black(), + "███".bright_red(), + "███".bright_green(), + "███".bright_yellow(), + "███".bright_blue(), + "███".bright_purple(), + "███".bright_cyan(), + "███".bright_white() + ); + + tracing::trace!(target:"TEST", "{} Testing trace!...", console::Emoji("🧪", "")); + tracing::debug!(target:"TEST", "{} Testing debug!...", console::Emoji("🧪", "")); + tracing::info!(target:"TEST", "{} Testing info!...", console::Emoji("🧪", "")); + tracing::warn!(target:"TEST", "{} Testing warn!...", console::Emoji("🧪", "")); + tracing::error!(target:"TEST", "{} Testing error!...", console::Emoji("🧪", "")); + + tracing::info!(target:"JSON", "{} Testing: {}", console::Emoji("🧪", ""), "{\"JSON\": \"Target\"}"); + tracing::info!(target:"PLAIN", "{} Testing: Plain Target", console::Emoji("🧪", "")); } impl CliModifier for T @@ -177,7 +166,7 @@ where { fn verbosity_filter(&self) -> Option { if self.is_plain() || self.is_json() { - return Some(LevelFilter::INFO); + return Some(LevelFilter::Info); } let verbosity_flag_filter = self @@ -185,7 +174,7 @@ where .log_level_filter(); if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug && self.is_debug() { - return Some(LevelFilter::DEBUG); + return Some(LevelFilter::Debug); } verbosity_flag_filter @@ -215,7 +204,7 @@ pub trait GlobalArguments { fn config_file(&self) -> &Option; - fn is_json(&self) -> &Option; + fn is_json(&self) -> bool; fn is_plain(&self) -> bool; @@ -247,8 +236,7 @@ use clap_verbosity_flag::LogLevel; use owo_colors::OwoColorize; use snafu::{ResultExt, Snafu}; use tracing_appender::non_blocking::WorkerGuard; -use tracing_subscriber::filter::LevelFilter; -use figment; +use log::LevelFilter; use crate::app::{self, config, logging}; From 35dfc5f280eaa0aaed9d705d5fd6303963fc6dde Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Fri, 12 Apr 2024 02:56:15 -0500 Subject: [PATCH 05/17] . --- Cargo.toml | 2 +- paxy/src/app/config.rs | 45 +++++++++++-------- paxy/src/app/i18n.rs | 16 ++++--- paxy/src/app/mod.rs | 47 +++++++++++-------- paxy/src/{ui/mod.rs => app/ui.rs} | 75 +++++++++++++++++++++++++------ paxy/src/lib.rs | 30 ++++++------- requirements.txt | 0 7 files changed, 141 insertions(+), 74 deletions(-) rename paxy/src/{ui/mod.rs => app/ui.rs} (83%) delete mode 100644 requirements.txt diff --git a/Cargo.toml b/Cargo.toml index fe7a04c..0688588 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ paxy = { path = "paxy" } # Logging tracing = "0.1" tracing-appender = "0.2" -tracing-subscriber = { version = "0.3", features = ["serde", "tracing-serde"] } +tracing-subscriber = "0.3" # Configuration figment = "0.10" diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 69cb553..b66ffe8 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -91,6 +91,8 @@ fn admerge_from_stub(candidate_config_filepath_stub: &PathBuf, mut figment: Figm #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Config { + pub paths: app::Paths, + pub log_directory: Option, pub log_level_filter: Option, @@ -128,6 +130,29 @@ impl Provider for Config { } } +// region: IMPORTS + +use std::path::PathBuf; + +use figment::{ + providers::{Env, Format, Json, Toml, Yaml}, + value::{Dict, Map}, + Figment, + Metadata, + Profile, + Provider, +}; +use log::LevelFilter; +use serde::{Deserialize, Serialize}; +use snafu::{OptionExt, ResultExt, Snafu}; + +use crate::app; +use crate::app::ui; + +// endregion: IMPORTS + +// region: ERRORS + #[derive(Debug, Snafu)] #[non_exhaustive] pub enum Error { @@ -146,22 +171,4 @@ pub enum Error { ExtractConfig { source: figment::Error }, } -// region: IMPORTS - -use std::path::PathBuf; - -use figment::{ - providers::{Env, Format, Json, Toml, Yaml}, - value::{Dict, Map}, - Figment, - Metadata, - Profile, - Provider, -}; -use serde::{Deserialize, Serialize}; -use snafu::{OptionExt, ResultExt, Snafu}; -use log::LevelFilter; - -use crate::{app, ui}; - -// endregion: IMPORTS +// endregion: ERRORS diff --git a/paxy/src/app/i18n.rs b/paxy/src/app/i18n.rs index 5a5f554..13d5087 100644 --- a/paxy/src/app/i18n.rs +++ b/paxy/src/app/i18n.rs @@ -1,3 +1,13 @@ +// TODO: The module code goes here + +// region: IMPORTS + +use snafu::Snafu; + +// endregion: IMPORTS + +// region: ERRORS + #[derive(Debug, Snafu)] #[non_exhaustive] pub enum Error { @@ -6,8 +16,4 @@ pub enum Error { I18nDummy {}, } -// region: IMPORTS - -use snafu::Snafu; - -// endregion: IMPORTS +// endregion: ERRORS \ No newline at end of file diff --git a/paxy/src/app/mod.rs b/paxy/src/app/mod.rs index ddba724..6d367b8 100644 --- a/paxy/src/app/mod.rs +++ b/paxy/src/app/mod.rs @@ -2,6 +2,24 @@ lazy_static! { pub static ref APP_NAME: &'static str = "paxy"; } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Paths { + pub config_dirpaths: Vec, + pub log_dirpath: PathBuf, +} + +// region: IMPORTS + +use std::path::PathBuf; + +use lazy_static::lazy_static; +use serde::{Deserialize, Serialize}; +use snafu::Snafu; + +// endregion: IMPORTS + +// region: ERRORS + #[derive(Debug, Snafu)] #[non_exhaustive] pub enum Error { @@ -19,6 +37,13 @@ pub enum Error { source: config::Error, }, + #[non_exhaustive] + #[snafu(display("in the UI: {source}"), visibility(pub))] + Ui { + #[snafu(backtrace)] + source: ui::Error, + }, + #[non_exhaustive] #[snafu(display("in internationalization: {source}"), visibility(pub))] Internationalization { @@ -27,27 +52,13 @@ pub enum Error { }, } -// region: IMPORTS -use lazy_static::lazy_static; -use snafu::Snafu; +// endregion: ERRORS -// endregion: IMPORTS - -// region: MODULES +// region: EXTERNAL-SUBMODULES pub mod config; pub mod i18n; pub mod logging; +pub mod ui; -// endregion: MODULES - -// region: RE-EXPORTS - -#[allow(unused_imports)] -pub use config::*; -#[allow(unused_imports)] -pub use i18n::*; -#[allow(unused_imports)] -pub use logging::*; - -// endregion: RE-EXPORTS +// endregion: EXTERNAL-SUBMODULES diff --git a/paxy/src/ui/mod.rs b/paxy/src/app/ui.rs similarity index 83% rename from paxy/src/ui/mod.rs rename to paxy/src/app/ui.rs index 21af28b..c5aae31 100644 --- a/paxy/src/ui/mod.rs +++ b/paxy/src/app/ui.rs @@ -32,9 +32,10 @@ where .parse() .ok() }); - let (mut handle, log_filepath) = logging::init_log(config_log_dirpath, config_verbosity_filter.into()) - .context(app::LoggingSnafu {}) - .context(crate::AppSnafu {})?; + let (mut handle, log_filepath) = + logging::init_log(config_log_dirpath, config_verbosity_filter.into()) + .context(app::LoggingSnafu {}) + .context(crate::AppSnafu {})?; // Modify logging behavior if Plain or Json output is desired if cli_input.is_json() { @@ -153,6 +154,51 @@ fn emit_test_messages() { tracing::info!(target:"PLAIN", "{} Testing: Plain Target", console::Emoji("🧪", "")); } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CliFormat { + pub output_mode: Option, + verbosity_level_filter: log::LevelFilter, + pub is_colored: Option, +} + +impl CliFormat { + pub fn try_set_max_verbosity_level(suggested_max_verbosity_level: log::LevelFilter) -> Result<(),> { + return match self.output_mode.unwrap_or_default() { + CliOutputMode::Regular => suggested_max_verbosity_level.as_str().parse().unwrap(), + CliOutputMode::Plain => todo!(), + CliOutputMode::Json => todo!(), + CliOutputMode::Test => todo!(), + }; + } + pub fn max_verbosity_level(&self) -> log::LevelFilter { + return verbosity_level_filter; + } +} + +impl Default for CliFormat { + fn default() -> Self { + Self { + output_mode: Default::default(), + verbosity_level_filter: log::LevelFilter::Info, + is_colored: Some(true), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum CliOutputMode { + Regular, + Plain, + Json, + Test, +} + +impl Default for CliOutputMode { + fn default() -> Self { + CliOutputMode::Regular + } +} + impl CliModifier for T where T: GlobalArguments, @@ -165,22 +211,21 @@ where ::L: LogLevel, { fn verbosity_filter(&self) -> Option { - if self.is_plain() || self.is_json() { - return Some(LevelFilter::Info); - } - let verbosity_flag_filter = self .verbosity() .log_level_filter(); - if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug && self.is_debug() { + if self.is_plain() || self.is_json() { + return Some(LevelFilter::Info); + } else if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug && self.is_debug() + { return Some(LevelFilter::Debug); + } else { + return verbosity_flag_filter + .as_str() + .parse() + .ok(); } - - verbosity_flag_filter - .as_str() - .parse() - .ok() } fn is_uncolored(&self) -> bool { @@ -233,10 +278,12 @@ use core::fmt; use std::{env, path::PathBuf}; use clap_verbosity_flag::LogLevel; +use log::LevelFilter; use owo_colors::OwoColorize; +use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; +use tracing::Level; use tracing_appender::non_blocking::WorkerGuard; -use log::LevelFilter; use crate::app::{self, config, logging}; diff --git a/paxy/src/lib.rs b/paxy/src/lib.rs index 0f1bfa9..0790bf0 100644 --- a/paxy/src/lib.rs +++ b/paxy/src/lib.rs @@ -2,6 +2,16 @@ pub fn type_of(_: &T) -> &str { any::type_name::() } +// region: IMPORTS + +use std::any; + +use snafu::Snafu; + +// endregion: IMPORTS + +// region: ERRORS + #[derive(Debug, Snafu)] #[non_exhaustive] pub enum Error { @@ -12,13 +22,6 @@ pub enum Error { source: app::Error, }, - #[non_exhaustive] - #[snafu(display("in the UI: {source}"), visibility(pub))] - Ui { - #[snafu(backtrace)] - source: ui::Error, - }, - #[non_exhaustive] #[snafu(display("in an action:{source}"), visibility(pub))] Actions { @@ -27,19 +30,12 @@ pub enum Error { }, } -// region: IMPORTS - -use std::any; - -use snafu::Snafu; - -// endregion: IMPORTS +// endregion: ERRORS -// region: MODULES +// region: EXTERNAL-SUBMODULES pub mod actions; pub mod app; pub mod data; -pub mod ui; -// endregion: MODULES +// endregion: EXTERNAL-SUBMODULES diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index e69de29..0000000 From 1be564e9674dd97f47e87ff3a91adf46805d847a Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Mon, 22 Apr 2024 19:16:05 -0500 Subject: [PATCH 06/17] . --- paxy/src/app/ui.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/paxy/src/app/ui.rs b/paxy/src/app/ui.rs index c5aae31..dc6d514 100644 --- a/paxy/src/app/ui.rs +++ b/paxy/src/app/ui.rs @@ -157,21 +157,16 @@ fn emit_test_messages() { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CliFormat { pub output_mode: Option, - verbosity_level_filter: log::LevelFilter, + pub requested_verbosity: Option, pub is_colored: Option, } impl CliFormat { - pub fn try_set_max_verbosity_level(suggested_max_verbosity_level: log::LevelFilter) -> Result<(),> { - return match self.output_mode.unwrap_or_default() { - CliOutputMode::Regular => suggested_max_verbosity_level.as_str().parse().unwrap(), - CliOutputMode::Plain => todo!(), - CliOutputMode::Json => todo!(), - CliOutputMode::Test => todo!(), - }; - } - pub fn max_verbosity_level(&self) -> log::LevelFilter { - return verbosity_level_filter; + pub fn resolve_max_verbosity_level() -> LevelFilter { + match self.output_mode { + Some(CliOutputMode::Plain) | Some(CliOutputMode::Json) => return Some(LevelFilter::Info), + _ => return verbosity_level_filter, + } } } From 270c274c9082db4e230cf6bf3aca0f8f09856d94 Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Sun, 5 May 2024 10:30:28 +0530 Subject: [PATCH 07/17] added semver to workspace --- .gitignore | 4 ---- Cargo.toml | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 7e9708a..6100424 100644 --- a/.gitignore +++ b/.gitignore @@ -16,16 +16,12 @@ Cargo.lock # Visual Studio Code *.code-workspace -/.vscode -.vscode/* -!.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json !.vscode/*.code-snippets .history/ *.vsix -.vscode # Packaging /packaging/**/pkg diff --git a/Cargo.toml b/Cargo.toml index 9fe582c..6b9753d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,7 @@ members = [ "paxy", "paxy-cli", "paxy-gui", "paxy-plugin", - - "tests", + "tests", "semver" ] resolver = "2" From f3a8a9cd3d905d58c6a6371d81c2359bcf708a52 Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Sun, 5 May 2024 17:27:44 -0500 Subject: [PATCH 08/17] fix: :construction: WIP fixing configuration --- paxy-cli/src/lib.rs | 11 ++- paxy-cli/src/main.rs | 7 ++ paxy-gui/src/lib.rs | 19 +++++- paxy-gui/src/main.rs | 7 ++ paxy/Cargo.toml | 2 +- paxy/src/app/config.rs | 29 ++++---- paxy/src/app/i18n.rs | 2 +- paxy/src/app/logging.rs | 9 +-- paxy/src/app/mod.rs | 6 -- paxy/src/app/ui.rs | 147 +++++++++++++++++++++++++--------------- 10 files changed, 150 insertions(+), 89 deletions(-) diff --git a/paxy-cli/src/lib.rs b/paxy-cli/src/lib.rs index a0883de..e81535e 100644 --- a/paxy-cli/src/lib.rs +++ b/paxy-cli/src/lib.rs @@ -1,5 +1,12 @@ +//! Has the [`run_cli`] function and the commandline interface template +//! [`cli_template::CliTemplate`] + +/// Calls the [`ui::run_common::`] function supplying it with the commandline +/// interface template as a type. Any errors are thrown back to the calling +/// function. A debug message is then displayed conveying that the program is +/// being run in the CLI mode. pub fn run_cli() -> Result<(), paxy::Error> { - let (_cli_input, _worker_guards) = ui::run_common::()?; + let (_cli_input, _logging_worker_guards) = ui::run_common::()?; tracing::debug!( "Running in {} mode... {}", @@ -408,6 +415,6 @@ mod cli_template { // region: RE-EXPORTS -pub use cli_template::*; +pub use cli_template::*; // Flatten the module heirarchy for easier access // endregion: RE-EXPORTS diff --git a/paxy-cli/src/main.rs b/paxy-cli/src/main.rs index 7a7b4c3..73509b7 100644 --- a/paxy-cli/src/main.rs +++ b/paxy-cli/src/main.rs @@ -1,3 +1,10 @@ +//! Starts execution at the [`main`] function. Offloads the implemenation +//! details to its corresponding library crate. + +/// Calls the [`paxy_cli::run_cli`] function and captures the returned +/// [`Result`]. If there was an error, the error message chain is printed to the +/// standard error stream (`stderr`). The program then returns an `0` or `1` +/// corresponding to "no error" or "error" based on the result. fn main() -> process::ExitCode { let return_value = paxy_cli::run_cli(); match return_value { diff --git a/paxy-gui/src/lib.rs b/paxy-gui/src/lib.rs index 7fb4393..dd71737 100644 --- a/paxy-gui/src/lib.rs +++ b/paxy-gui/src/lib.rs @@ -1,5 +1,12 @@ +//! Has the [`run_gui`] function and the commandline interface template +//! [`gui_cli_template::CliTemplate`] + +/// Calls the [`ui::run_common::`] function supplying it with the commandline +/// interface template as a type. Any errors are thrown back to the calling +/// function. A debug message is then displayed conveying that the program is +/// being run in the GUI mode. pub fn run_gui() -> Result<(), paxy::Error> { - let (_cli_input, _worker_guards) = ui::run_common::()?; + let (_cli_input, _logging_worker_guards) = ui::run_common::()?; tracing::debug!( "Running in {} mode... {}", @@ -15,7 +22,7 @@ pub fn run_gui() -> Result<(), paxy::Error> { pub enum Error { #[non_exhaustive] #[snafu(display(""), visibility(pub))] - GuiDummy {}, + GuiDummy {}, // No errors implemented yet } // region: IMPORTS @@ -28,7 +35,11 @@ use snafu::Snafu; // region: MODULES +/// The commandline interface for the GUI program. Allows one to specify flags +/// that control output on a console. mod gui_cli_template { + + /// The base commandline template consists of global arguments #[derive(Parser, Debug)] #[command(version, author, about, args_conflicts_with_subcommands = true)] pub struct CliTemplate { @@ -36,6 +47,8 @@ mod gui_cli_template { pub global_args: ui::cli_template::GlobalArgs, } + /// Implement a trait that can extract standard global arguments from our + /// own CLI template impl ui::GlobalArguments for CliTemplate { type L = clap_verbosity_flag::InfoLevel; @@ -91,6 +104,6 @@ mod gui_cli_template { // region: RE-EXPORTS -pub use gui_cli_template::*; +pub use gui_cli_template::*; // Flatten the module heirarchy for easier access // endregion: RE-EXPORTS diff --git a/paxy-gui/src/main.rs b/paxy-gui/src/main.rs index edf4ea4..f96597b 100644 --- a/paxy-gui/src/main.rs +++ b/paxy-gui/src/main.rs @@ -1,3 +1,10 @@ +//! Starts execution at the [`main`] function. Offloads the implemenation +//! details to its corresponding library crate. + +/// Calls the [`paxy_gui::run_gui`] function and captures the returned +/// [`Result`]. If there was an error, the error message chain is printed to the +/// standard error stream (`stderr`). The program then returns an `0` or `1` +/// corresponding to "no error" or "error" based on the result. fn main() -> process::ExitCode { let return_value = paxy_gui::run_gui(); match return_value { diff --git a/paxy/Cargo.toml b/paxy/Cargo.toml index 1af4864..949f1fe 100644 --- a/paxy/Cargo.toml +++ b/paxy/Cargo.toml @@ -53,7 +53,7 @@ console = { workspace = true } home = "0.5.9" toml = "0.8.10" pollster = "0.3" -reqwest = "0.11" +reqwest = "0.12" url = { version = "2.3", features = ["serde"] } extism = "1.2.0" bson = "2.9.0" diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index b66ffe8..1623935 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -3,10 +3,10 @@ /// local paths. overridden by environment variables starting with `PAXY_`, /// overridden by the configuration file specified by the commandline. /// Values from only files with supported file extensions would be merged. -pub fn init_config(cli_modifier: &C) -> Result<(Config, Vec), Error> +pub fn init_config(cli_global_arguments: G) -> Result<(Config, Vec), Error> where - C: ui::CliModifier, - ::L: clap_verbosity_flag::LogLevel, + G: ui::GlobalArguments, + ::L: clap_verbosity_flag::LogLevel, { let mut candidate_config_filepath_stubs: Vec = Vec::new(); @@ -44,7 +44,7 @@ where // Merge configuration values from additional config filepaths (usually // specified through CLI) - if let Some(additional_config_filepath) = cli_modifier.config_file() { + if let Some(additional_config_filepath) = preferred_config_filepath { if let Some(parent) = additional_config_filepath.parent() { if let Some(stem) = additional_config_filepath.file_stem() { let mut stub = PathBuf::from(parent); @@ -58,10 +58,10 @@ where // Merge configuration values from the CLI // These are not set to be optional, so only action-required states are // merged with the configuration - if cli_modifier.is_uncolored() { + if cli_global_arguments.is_uncolored() { figment = figment.admerge(("no_color", true)); } - if let Some(log_level_filter) = cli_modifier.verbosity_filter() { + if let Some(log_level_filter) = cli_global_arguments.verbosity_filter() { figment = figment.admerge(("log_level_filter", log_level_filter)); } @@ -91,13 +91,11 @@ fn admerge_from_stub(candidate_config_filepath_stub: &PathBuf, mut figment: Figm #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Config { - pub paths: app::Paths, + pub config_dirpaths: Vec, - pub log_directory: Option, + pub log_dirpath: PathBuf, - pub log_level_filter: Option, - - pub no_color: Option, + pub cli_output_format: ui::CliOutputFormat, } impl Config { @@ -108,10 +106,11 @@ impl Config { impl Default for Config { fn default() -> Self { - Config { - log_directory: None, - log_level_filter: Some(LevelFilter::Info), - no_color: Some(false), + Self { + config_dirpaths: None, + log_dirpath: None, + log_directory: todo!(), + cli_output_format: todo!(), } } } diff --git a/paxy/src/app/i18n.rs b/paxy/src/app/i18n.rs index 13d5087..ef0eadc 100644 --- a/paxy/src/app/i18n.rs +++ b/paxy/src/app/i18n.rs @@ -16,4 +16,4 @@ pub enum Error { I18nDummy {}, } -// endregion: ERRORS \ No newline at end of file +// endregion: ERRORS diff --git a/paxy/src/app/logging.rs b/paxy/src/app/logging.rs index 4b96c57..86f27f4 100644 --- a/paxy/src/app/logging.rs +++ b/paxy/src/app/logging.rs @@ -1,14 +1,9 @@ -pub fn init_log( - preferred_log_dirpath: Option, - preferred_log_level_filter: Option, -) -> Result<(Handle, PathBuf), Error> { +pub fn init_log(max_output_verbosity: log::LevelFilter) -> Result<(Handle, PathBuf), Error> { let log_filename = format!("{}.log", *app::APP_NAME); let log_dirpath = obtain_log_dirpath(preferred_log_dirpath)?; let log_file_appender = tracing_appender::rolling::daily(log_dirpath.clone(), log_filename.clone()); - let log_level_filter = tracing_level_filter_from_log_level_filter( - preferred_log_level_filter.unwrap_or(log::LevelFilter::Info), - ); + let log_level_filter = tracing_level_filter_from_log_level_filter(max_output_verbosity); // Obtain writers to various logging destinations and worker guards (for // keeping the streams alive) diff --git a/paxy/src/app/mod.rs b/paxy/src/app/mod.rs index 6d367b8..9e7e534 100644 --- a/paxy/src/app/mod.rs +++ b/paxy/src/app/mod.rs @@ -2,12 +2,6 @@ lazy_static! { pub static ref APP_NAME: &'static str = "paxy"; } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Paths { - pub config_dirpaths: Vec, - pub log_dirpath: PathBuf, -} - // region: IMPORTS use std::path::PathBuf; diff --git a/paxy/src/app/ui.rs b/paxy/src/app/ui.rs index dc6d514..199464c 100644 --- a/paxy/src/app/ui.rs +++ b/paxy/src/app/ui.rs @@ -1,65 +1,94 @@ #[tracing::instrument(level = "trace")] pub fn run_common() -> Result<(C, Vec), crate::Error> where - C: clap::Parser + CliModifier + fmt::Debug, + C: clap::Parser + GlobalArguments + fmt::Debug, ::L: LogLevel, { // Obtain CLI arguments let cli_input = C::parse(); // Obtain user configuration - let (config, config_filepaths) = config::init_config(&cli_input) + let (config, config_filepath_stubs) = config::init_config(&cli_input.config_file()) .context(app::ConfigSnafu {}) .context(crate::AppSnafu)?; - // Turn off colors if needed - if let Some(no_color) = config.no_color { - if no_color { - anstream::ColorChoice::Never.write_global(); - owo_colors::set_override(false); - } + // Begin logging + let (mut logging_handle, log_filepath) = logging::init_log(&config.) + .context(app::LoggingSnafu {}) + .context(crate::AppSnafu {})?; + + // Adjust output formatting if requested + adjust_output_formatting(&config.cli_output_format, &logging_handle); + + emit_welcome_messages(); + + emit_diagnostic_messages(config_filepath_stubs, log_filepath, &cli_input); + + emit_test_messages(); + + Ok((cli_input, logging_handle.worker_guards)) +} + +fn resolve_max_output_verbosity(cli_output_format: &CliOutputFormat, cli_global_arguments: G) { + let verbosity_flag_filter = cli_output_format + .verbosity() + .log_level_filter(); + + if matches!( + cli_output_format.output_mode, + CliOutputMode::Plain | CliOutputMode::Json + ){ + return Some(LevelFilter::Info); + } else if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug && cli_global_arguments.is_debug() + { + return Some(LevelFilter::Debug); + } else { + return verbosity_flag_filter + .as_str() + .parse() + .ok(); } +} - // Begin logging with preferred log directory and preferred verbosity - let config_log_dirpath = config - .log_directory - .as_ref() - .map(PathBuf::from); - let config_verbosity_filter: Option = config - .log_level_filter - .and_then(|lf| { - lf.as_str() - .parse() - .ok() - }); - let (mut handle, log_filepath) = - logging::init_log(config_log_dirpath, config_verbosity_filter.into()) - .context(app::LoggingSnafu {}) - .context(crate::AppSnafu {})?; +fn adjust_output_formatting( + cli_output_format: &CliOutputFormat, + mut logging_handle: &logging::Handle, +) { + // Turn off colors if requested + if matches!( + cli_output_format.output_mode, + CliOutputMode::Plain | CliOutputMode::Json + ) || cli_output_format.no_color + || is_env_variable_set("NO_COLOR") + || is_env_variable_set(format!( + "{}_NO_COLOR", + String::from(*app::APP_NAME).to_uppercase() + )) + { + anstream::ColorChoice::Never.write_global(); + owo_colors::set_override(false); + } - // Modify logging behavior if Plain or Json output is desired - if cli_input.is_json() { - handle - .switch_to_json() - .context(app::LoggingSnafu {}) - .context(crate::AppSnafu {})?; - } else if cli_input.is_plain() { - handle + // Change output mode if requested + match cli_output_format.output_mode { + CliOutputMode::Plain => logging_handle .switch_to_plain() .context(app::LoggingSnafu {}) - .context(crate::AppSnafu {})?; - } else if cli_input.is_test() { - handle + .context(crate::AppSnafu {})?, + CliOutputMode::Json => logging_handle + .switch_to_json() + .context(app::LoggingSnafu {}) + .context(crate::AppSnafu {})?, + CliOutputMode::Test => logging_handle .switch_to_test() .context(app::LoggingSnafu {}) - .context(crate::AppSnafu {})?; + .context(crate::AppSnafu {})?, + _ => {} } +} - emit_welcome_messages(); - emit_diagnostic_messages(config_filepaths, log_filepath, &cli_input); - emit_test_messages(); - - Ok((cli_input, handle.worker_guards)) +fn is_env_variable_set>(env_variable_name: S) -> bool { + env::var(env_variable_name.as_ref()).map_or(false, |value| !value.is_empty()) } fn emit_welcome_messages() { @@ -77,8 +106,11 @@ fn emit_welcome_messages() { ); } -fn emit_diagnostic_messages(config_filepaths: Vec, log_filepath: PathBuf, cli_input: &C) -where +fn emit_diagnostic_messages( + config_filepath_stubs: Vec, + log_filepath: PathBuf, + cli_input: &C, +) where C: clap::Parser + CliModifier + fmt::Debug, ::L: LogLevel, { @@ -101,8 +133,9 @@ where "{} {} {:?}", console::Emoji("📂", ""), "Config Filepath(s) (without file extensions):".magenta(), - config_filepaths, + config_dirpaths, ); + tracing::debug!( "{} {} {:?}", console::Emoji("📂", ""), @@ -155,27 +188,31 @@ fn emit_test_messages() { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CliFormat { - pub output_mode: Option, - pub requested_verbosity: Option, - pub is_colored: Option, +pub struct CliOutputFormat { + pub output_mode: CliOutputMode, + + pub requested_verbosity: log::LevelFilter, + + pub no_color: bool, } -impl CliFormat { +impl CliOutputFormat { pub fn resolve_max_verbosity_level() -> LevelFilter { match self.output_mode { - Some(CliOutputMode::Plain) | Some(CliOutputMode::Json) => return Some(LevelFilter::Info), + Some(CliOutputMode::Plain) | Some(CliOutputMode::Json) => { + return Some(LevelFilter::Info) + } _ => return verbosity_level_filter, } } } -impl Default for CliFormat { +impl Default for CliOutputFormat { fn default() -> Self { Self { output_mode: Default::default(), - verbosity_level_filter: log::LevelFilter::Info, - is_colored: Some(true), + requested_verbosity: Some(log::LevelFilter::Info), + is_colored: Some(true), } } } @@ -286,6 +323,8 @@ use crate::app::{self, config, logging}; // region: MODULES +/// Common commandline interface template for global arguments, intended to be +/// shared between the GUI and CLI programs. pub mod cli_template { #[derive(Clone, Debug, Args)] #[command(next_display_order = usize::MAX - 100)] @@ -360,6 +399,6 @@ pub mod cli_template { // region: RE-EXPORTS #[allow(unused_imports)] -pub use cli_template::*; +pub use cli_template::*; // Flatten the module heirarchy for easier access // endregion: RE-EXPORTS From dcd64e0cb06c2608e45739108735145c09b5f1ed Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Mon, 6 May 2024 16:09:42 -0500 Subject: [PATCH 09/17] WIP --- paxy-cli/src/lib.rs | 42 ++++++------ paxy-gui/src/lib.rs | 30 ++++----- paxy/src/app/config.rs | 106 +++++++++++++++++++++++------- paxy/src/app/ui.rs | 142 ++++++++++++++++++++++++++++------------- 4 files changed, 213 insertions(+), 107 deletions(-) diff --git a/paxy-cli/src/lib.rs b/paxy-cli/src/lib.rs index e81535e..3402db6 100644 --- a/paxy-cli/src/lib.rs +++ b/paxy-cli/src/lib.rs @@ -58,7 +58,7 @@ mod cli_template { )] pub struct CliTemplate { #[command(flatten)] - pub global_arguments: ui::cli_template::GlobalArgs, + pub global_args: ui::cli_template::GlobalArgs, #[command(subcommand)] pub entity: Option, @@ -67,43 +67,39 @@ mod cli_template { /// Implement a trait that can extract standard global arguments from our /// own CLI template impl ui::GlobalArguments for CliTemplate { - type L = clap_verbosity_flag::InfoLevel; - - fn config_file(&self) -> &Option { - &self - .global_arguments - .config_file + fn config_filepath(&self) -> &Option { + self.global_args + .config_filepath() } fn is_json(&self) -> bool { - self.global_arguments - .json_flag + self.global_args + .is_json() } fn is_plain(&self) -> bool { - self.global_arguments - .plain_flag + self.global_args + .is_plain() } fn is_debug(&self) -> bool { - self.global_arguments - .debug_flag + self.global_args + .is_debug() } - fn is_no_color(&self) -> bool { - self.global_arguments - .no_color_flag + fn is_test(&self) -> bool { + self.global_args + .is_test() } - fn is_test(&self) -> bool { - self.global_arguments - .test_flag + fn is_no_color(&self) -> bool { + self.global_args + .is_no_color() } - fn verbosity(&self) -> &clap_verbosity_flag::Verbosity { - &self - .global_arguments - .verbose + fn verbosity_filter(&self) -> &log::LevelFilter { + self.global_args + .verbosity_filter() } } diff --git a/paxy-gui/src/lib.rs b/paxy-gui/src/lib.rs index dd71737..b110471 100644 --- a/paxy-gui/src/lib.rs +++ b/paxy-gui/src/lib.rs @@ -50,43 +50,39 @@ mod gui_cli_template { /// Implement a trait that can extract standard global arguments from our /// own CLI template impl ui::GlobalArguments for CliTemplate { - type L = clap_verbosity_flag::InfoLevel; - - fn config_file(&self) -> &Option { - &self - .global_args - .config_file + fn config_filepath(&self) -> &Option { + self.global_args + .config_filepath() } fn is_json(&self) -> bool { self.global_args - .json_flag + .is_json() } fn is_plain(&self) -> bool { self.global_args - .plain_flag + .is_plain() } fn is_debug(&self) -> bool { self.global_args - .debug_flag + .is_debug() } - fn is_no_color(&self) -> bool { + fn is_test(&self) -> bool { self.global_args - .no_color_flag + .is_test() } - fn is_test(&self) -> bool { + fn is_no_color(&self) -> bool { self.global_args - .test_flag + .is_no_color() } - fn verbosity(&self) -> &clap_verbosity_flag::Verbosity { - &self - .global_args - .verbose + fn verbosity_filter(&self) -> &log::LevelFilter { + self.global_args + .verbosity_filter() } } diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 1623935..3820579 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -89,43 +89,102 @@ fn admerge_from_stub(candidate_config_filepath_stub: &PathBuf, mut figment: Figm figment } -#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Config { - pub config_dirpaths: Vec, - - pub log_dirpath: PathBuf, - - pub cli_output_format: ui::CliOutputFormat, + pub figment: Figment, } impl Config { pub fn new() -> Self { - Self::default() + Self { + figment: Figment::from(ConfigTemplate::default()), + } } -} -impl Default for Config { - fn default() -> Self { - Self { - config_dirpaths: None, - log_dirpath: None, - log_directory: todo!(), - cli_output_format: todo!(), + pub fn with_overriding_file>(&mut self, filepath: P) -> &mut Self { + let filepath: &Path = filepath.as_ref(); + if let Some(file_extension) = filepath.extension() { + file_extension = file_extension + .to_string_lossy() + .to_lowercase(); + match (file_extension) { + "toml" => { + self.figment = self + .figment + .admerge(Toml::file(filepath)); + } + "json" => { + self.figment = self + .figment + .admerge(Json::file(filepath)); + } + "yaml" | "yml" => { + self.figment = self + .figment + .admerge(Yaml::file(filepath)); + } + } } + + self } -} -impl Provider for Config { - fn metadata(&self) -> Metadata { - Metadata::named("Library Config") + pub fn with_overriding_files(&mut self, filepaths: I) -> &mut Self + where + P: AsRef, + I: Iterator, + { + filepaths.for_each(|filepath| self.with_overriding_file(filepath)); + + self + } + + pub fn with_overriding_env>(prefix: S) -> &mut Self { + let prefix = prefix.as_ref(); + self.figment = self + .figment + .admerge(Env::prefixed(prefix)); + + self } - fn data(&self) -> Result, figment::Error> { - figment::providers::Serialized::defaults(Config::default()).data() + pub fn with_overriding_env_var>(env_var_name: S) -> &mut Self { + let env_var_name = env_var_name.as_ref(); + self.figment = self + .figment + .admerge(Env::raw().only(&[env_var_name])); + + self + } + + pub fn with_overriding_args(&mut self, arguments: A) -> &mut Self { + if let Some(path) = arguments.config_filepath() { + self.figment = self.figment.admerge(("config_filepaths", path)); + } + + self } - fn profile(&self) -> Option { - None + pub fn object(&self) -> Result { + self.figment + .extract() + .context(ExtractConfigSnafu {})? + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ConfigTemplate { + pub config_filepaths: Vec, + pub log_filepath_stub: PathBuf, + pub console_output_format: ConsoleOutputFormat, +} + +impl Default for ConfigTemplate { + fn default() -> Self { + Self { + config_filepaths: Vec::new(), + log_filepath_stub: PathBuf::default(), + console_output_format: ConsoleOutputFormat::default(), + } } } @@ -145,6 +204,7 @@ use log::LevelFilter; use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; +use super::ui::GlobalArguments; use crate::app; use crate::app::ui; diff --git a/paxy/src/app/ui.rs b/paxy/src/app/ui.rs index 199464c..00d1fad 100644 --- a/paxy/src/app/ui.rs +++ b/paxy/src/app/ui.rs @@ -13,9 +13,13 @@ where .context(crate::AppSnafu)?; // Begin logging - let (mut logging_handle, log_filepath) = logging::init_log(&config.) - .context(app::LoggingSnafu {}) - .context(crate::AppSnafu {})?; + let (mut logging_handle, log_filepath) = logging::init_log( + &config + .cli_output_format + .requested_verbosity, + ) + .context(app::LoggingSnafu {}) + .context(crate::AppSnafu {})?; // Adjust output formatting if requested adjust_output_formatting(&config.cli_output_format, &logging_handle); @@ -29,17 +33,19 @@ where Ok((cli_input, logging_handle.worker_guards)) } -fn resolve_max_output_verbosity(cli_output_format: &CliOutputFormat, cli_global_arguments: G) { - let verbosity_flag_filter = cli_output_format - .verbosity() - .log_level_filter(); +fn resolve_max_output_verbosity( + cli_output_format: &CliOutputFormat, + cli_global_arguments: G, +) -> log::LevelFilter { + let verbosity_flag_filter = cli_output_format.requested_verbosity; if matches!( cli_output_format.output_mode, CliOutputMode::Plain | CliOutputMode::Json - ){ + ) { return Some(LevelFilter::Info); - } else if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug && cli_global_arguments.is_debug() + } else if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug + && cli_global_arguments.is_debug() { return Some(LevelFilter::Debug); } else { @@ -188,56 +194,38 @@ fn emit_test_messages() { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CliOutputFormat { - pub output_mode: CliOutputMode, +pub struct ConsoleOutputFormat { + pub output_mode: ConsoleOutputMode, - pub requested_verbosity: log::LevelFilter, + pub max_verbosity: log::LevelFilter, pub no_color: bool, } -impl CliOutputFormat { - pub fn resolve_max_verbosity_level() -> LevelFilter { - match self.output_mode { - Some(CliOutputMode::Plain) | Some(CliOutputMode::Json) => { - return Some(LevelFilter::Info) - } - _ => return verbosity_level_filter, - } - } -} - -impl Default for CliOutputFormat { +impl Default for ConsoleOutputFormat { fn default() -> Self { Self { - output_mode: Default::default(), - requested_verbosity: Some(log::LevelFilter::Info), - is_colored: Some(true), + output_mode: ConsoleOutputMode::default(), + max_verbosity: log::LevelFilter::Info, + no_color: false, } } } #[derive(Debug, Clone, Serialize, Deserialize)] -pub enum CliOutputMode { +pub enum ConsoleOutputMode { Regular, Plain, Json, Test, } -impl Default for CliOutputMode { +impl Default for ConsoleOutputMode { fn default() -> Self { CliOutputMode::Regular } } -impl CliModifier for T -where - T: GlobalArguments, - ::L: LogLevel, -{ -} - pub trait CliModifier: GlobalArguments where ::L: LogLevel, @@ -277,9 +265,7 @@ where } pub trait GlobalArguments { - type L; - - fn config_file(&self) -> &Option; + fn config_filepath(&self) -> &Option; fn is_json(&self) -> bool; @@ -291,9 +277,38 @@ pub trait GlobalArguments { fn is_test(&self) -> bool; - fn verbosity(&self) -> &clap_verbosity_flag::Verbosity - where - Self::L: LogLevel; + fn verbosity_filter(&self) -> &log::LevelFilter; + + fn console_output_mode(&self) -> ConsoleOutputMode { + if self.is_json() { + ConsoleOutputMode::Json + } else if self.is_plain() { + ConsoleOutputMode::Plain + } else if self.is_test() { + ConsoleOutputMode::Test + } else { + ConsoleOutputMode::Regular + } + } + + fn max_output_verbosity(&self) -> log::LevelFilter { + let verbosity_flag_filter = cli_output_format.requested_verbosity; + if matches!( + cli_output_format.output_mode, + CliOutputMode::Plain | CliOutputMode::Json + ) { + return Some(LevelFilter::Info); + } else if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug + && cli_global_arguments.is_debug() + { + return Some(LevelFilter::Debug); + } else { + return verbosity_flag_filter + .as_str() + .parse() + .ok(); + } + } } #[derive(Debug, Snafu)] @@ -309,7 +324,6 @@ pub enum Error { use core::fmt; use std::{env, path::PathBuf}; -use clap_verbosity_flag::LogLevel; use log::LevelFilter; use owo_colors::OwoColorize; use serde::{Deserialize, Serialize}; @@ -382,7 +396,45 @@ pub mod cli_template { pub test_flag: bool, #[command(flatten)] - pub verbose: clap_verbosity_flag::Verbosity, + pub verbosity: clap_verbosity_flag::Verbosity, + } + + impl GlobalArguments for GlobalArgs { + fn config_filepath(&self) -> &Option { + self.config_filepath + } + + fn is_json(&self) -> bool { + self.json_flag + } + + fn is_plain(&self) -> bool { + self.plain_flag + } + + fn is_debug(&self) -> bool { + self.debug_flag + } + + fn is_test(&self) -> bool { + self.test_flag + } + + fn is_no_color(&self) -> bool { + self.no_color_flag + } + + fn verbosity_filter(&self) -> &log::LevelFilter { + self.verbosity + .log_level_filter() + .and_then(|log_level_filter| { + log_level_filter + .as_str() + .parse() + .ok() + }) + .unwrap_or(log::LevelFilter::Info) + } } // region: IMPORTS @@ -391,6 +443,8 @@ pub mod cli_template { use clap::Args; + use super::GlobalArguments; + // endregion: IMPORTS } From d4cfd3b1a59cee3e6f1d52ae0929c62283a04941 Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Mon, 6 May 2024 19:19:59 -0500 Subject: [PATCH 10/17] WIP --- paxy-cli/src/lib.rs | 2 +- paxy-gui/src/lib.rs | 2 +- paxy/src/app/config.rs | 89 +++++++++++++++++++++++++++++------------- paxy/src/app/ui.rs | 33 ++++++---------- 4 files changed, 75 insertions(+), 51 deletions(-) diff --git a/paxy-cli/src/lib.rs b/paxy-cli/src/lib.rs index 3402db6..7784a8d 100644 --- a/paxy-cli/src/lib.rs +++ b/paxy-cli/src/lib.rs @@ -97,7 +97,7 @@ mod cli_template { .is_no_color() } - fn verbosity_filter(&self) -> &log::LevelFilter { + fn verbosity_filter(&self) -> log::LevelFilter { self.global_args .verbosity_filter() } diff --git a/paxy-gui/src/lib.rs b/paxy-gui/src/lib.rs index b110471..4f97089 100644 --- a/paxy-gui/src/lib.rs +++ b/paxy-gui/src/lib.rs @@ -80,7 +80,7 @@ mod gui_cli_template { .is_no_color() } - fn verbosity_filter(&self) -> &log::LevelFilter { + fn verbosity_filter(&self) -> log::LevelFilter { self.global_args .verbosity_filter() } diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 3820579..052a72c 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -89,6 +89,23 @@ fn admerge_from_stub(candidate_config_filepath_stub: &PathBuf, mut figment: Figm figment } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ConfigTemplate { + pub config_filepaths: Vec, + pub log_filepath_stub: PathBuf, + pub console_output_format: ConsoleOutputFormat, +} + +impl Default for ConfigTemplate { + fn default() -> Self { + Self { + config_filepaths: Vec::new(), + log_filepath_stub: PathBuf::default(), + console_output_format: ConsoleOutputFormat::default(), + } + } +} + pub struct Config { pub figment: Figment, } @@ -147,18 +164,51 @@ impl Config { self } - pub fn with_overriding_env_var>(env_var_name: S) -> &mut Self { - let env_var_name = env_var_name.as_ref(); - self.figment = self - .figment - .admerge(Env::raw().only(&[env_var_name])); + pub fn with_overriding_args(&mut self, cli_arguments: A) -> &mut Self { + if let Some(path) = cli_arguments.config_filepath() { + self.figment = self + .figment + .admerge(("config_filepaths", path)); + } - self - } + let console_output_mode = cli_arguments.console_output_mode(); + if console_output_mode != ConsoleOutputMode::Regular { + self.figment = self + .figment + .admerge(("console_output_format.mode", console_output_mode)); + } - pub fn with_overriding_args(&mut self, arguments: A) -> &mut Self { - if let Some(path) = arguments.config_filepath() { - self.figment = self.figment.admerge(("config_filepaths", path)); + let current_max_verbosity = self + .figment + .extract_inner::("console_output_format.max_verbosity"); + let requested_max_verbosity = cli_arguments.max_output_verbosity(); + if let Ok(current_max_verbosity) = current_max_verbosity { + if cli_requested_max_verbosity > current_max_verbosity { + self.figment = self + .figment + .admerge(( + "console_output_format.max_verbosity", + requested_max_verbosity, + )) + } + } + + let current_no_color = self + .figment + .extract_inner::("console_output_format.no_color"); + let requested_no_color = + cli_arguments.is_no_color() || cli_arguments.is_plain() || cli_arguments.is_json(); + let env_no_color = env::var("NO_COLOR").is_ok() + || env::var(format!( + "{}_NO_COLOR", + String::from(*app::APP_NAME).to_uppercase() + )) + .is_ok() + || env::var("TERM").is_ok_and(|env_term_value| env_term_value.to_lowercase == "dumb"); + if !current_no_color && (requested_no_color || env_no_color) { + self.figment = self + .figment + .admerge(("console_output_format.no_color", true)); } self @@ -171,23 +221,6 @@ impl Config { } } -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ConfigTemplate { - pub config_filepaths: Vec, - pub log_filepath_stub: PathBuf, - pub console_output_format: ConsoleOutputFormat, -} - -impl Default for ConfigTemplate { - fn default() -> Self { - Self { - config_filepaths: Vec::new(), - log_filepath_stub: PathBuf::default(), - console_output_format: ConsoleOutputFormat::default(), - } - } -} - // region: IMPORTS use std::path::PathBuf; @@ -204,7 +237,7 @@ use log::LevelFilter; use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; -use super::ui::GlobalArguments; +use super::ui::{ConsoleOutputMode, GlobalArguments}; use crate::app; use crate::app::ui; diff --git a/paxy/src/app/ui.rs b/paxy/src/app/ui.rs index 00d1fad..0aa279f 100644 --- a/paxy/src/app/ui.rs +++ b/paxy/src/app/ui.rs @@ -40,7 +40,7 @@ fn resolve_max_output_verbosity( let verbosity_flag_filter = cli_output_format.requested_verbosity; if matches!( - cli_output_format.output_mode, + cli_output_format.mode, CliOutputMode::Plain | CliOutputMode::Json ) { return Some(LevelFilter::Info); @@ -62,7 +62,7 @@ fn adjust_output_formatting( ) { // Turn off colors if requested if matches!( - cli_output_format.output_mode, + cli_output_format.mode, CliOutputMode::Plain | CliOutputMode::Json ) || cli_output_format.no_color || is_env_variable_set("NO_COLOR") @@ -76,7 +76,7 @@ fn adjust_output_formatting( } // Change output mode if requested - match cli_output_format.output_mode { + match cli_output_format.mode { CliOutputMode::Plain => logging_handle .switch_to_plain() .context(app::LoggingSnafu {}) @@ -195,7 +195,7 @@ fn emit_test_messages() { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ConsoleOutputFormat { - pub output_mode: ConsoleOutputMode, + pub mode: ConsoleOutputMode, pub max_verbosity: log::LevelFilter, @@ -205,7 +205,7 @@ pub struct ConsoleOutputFormat { impl Default for ConsoleOutputFormat { fn default() -> Self { Self { - output_mode: ConsoleOutputMode::default(), + mode: ConsoleOutputMode::default(), max_verbosity: log::LevelFilter::Info, no_color: false, } @@ -277,7 +277,7 @@ pub trait GlobalArguments { fn is_test(&self) -> bool; - fn verbosity_filter(&self) -> &log::LevelFilter; + fn verbosity_filter(&self) -> log::LevelFilter; fn console_output_mode(&self) -> ConsoleOutputMode { if self.is_json() { @@ -292,21 +292,12 @@ pub trait GlobalArguments { } fn max_output_verbosity(&self) -> log::LevelFilter { - let verbosity_flag_filter = cli_output_format.requested_verbosity; - if matches!( - cli_output_format.output_mode, - CliOutputMode::Plain | CliOutputMode::Json - ) { - return Some(LevelFilter::Info); - } else if verbosity_flag_filter < clap_verbosity_flag::LevelFilter::Debug - && cli_global_arguments.is_debug() - { - return Some(LevelFilter::Debug); + if self.is_plain() || self.is_json() { + log::LevelFilter::Info + } else if self.is_debug() && log::LevelFilter::Debug > self.verbosity_filter() { + log::LevelFilter::Debug } else { - return verbosity_flag_filter - .as_str() - .parse() - .ok(); + self.verbosity_filter() } } } @@ -424,7 +415,7 @@ pub mod cli_template { self.no_color_flag } - fn verbosity_filter(&self) -> &log::LevelFilter { + fn verbosity_filter(&self) -> log::LevelFilter { self.verbosity .log_level_filter() .and_then(|log_level_filter| { From 41987d44125c185e9f87ed903a3433e41cce249d Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Tue, 7 May 2024 09:09:15 +0530 Subject: [PATCH 11/17] working on the plugin --- .gitmodules | 3 ++ .vscode/settings.json | 6 ++++ Cargo.toml | 13 +++++--- Containerfile | 4 +++ Makefile.toml | 2 ++ paxy-plugin/Cargo.toml | 10 ++++++ paxy-plugin/examples/paxy.px | 13 ++++++++ paxy-plugin/src/lib.rs | 65 ++++++++++++++++++++++++++++++++++++ paxy-plugin/src/main.rs | 3 -- paxy/src/actions/add_repo.rs | 7 ++-- paxy/src/actions/rm_repo.rs | 1 - paxy/src/app/plugins.rs | 20 +++++++---- rust-toolchain.toml | 2 ++ semver | 1 + 14 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 .gitmodules create mode 100644 .vscode/settings.json create mode 100644 Makefile.toml create mode 100644 paxy-plugin/examples/paxy.px create mode 100644 paxy-plugin/src/lib.rs delete mode 100644 paxy-plugin/src/main.rs create mode 160000 semver diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1e726f9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "semver"] + path = semver + url = git@github.com:FerrisWasTaken/semver.git diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d61fbe1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "rust-analyzer.showUnlinkedFileNotification": false, + "rust-analyzer.cargo.features": [ + "extism_support" + ] +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 6b9753d..06e1e8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,17 @@ [workspace] - members = [ "paxy", "paxy-cli", "paxy-gui", "paxy-plugin", "tests", "semver" ] - -resolver = "2" - +default-members = [ + "paxy", + "paxy-cli", + "paxy-gui", + "tests", "semver" +] +resolver = "1" [workspace.package] @@ -19,7 +22,7 @@ homepage = "https://pax-hub.github.io/" authors = [ "shivanandvp ", "lylythechosenone", - "ferriswastaken", + "Ishaan S ", "flyingcakes85", ] keywords = ["package", "package-manager", "paxy", "packager"] diff --git a/Containerfile b/Containerfile index 43d5c99..217c45d 100644 --- a/Containerfile +++ b/Containerfile @@ -3,6 +3,7 @@ FROM archlinux:latest ENV RUSTC_WRAPPER=sccache ENV CARGO_INCREMENTAL=0 ENV CARGO_TARGET_DIR=/paxy/podman-target +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.cargo/bin # Install Rust RUN pacman -Sy --noconfirm rustup cargo @@ -13,3 +14,6 @@ RUN rustup default nightly-2024-03-17 RUN pacman -Sy --noconfirm gdk-pixbuf2 pango gtk4 pkg-config # Extras RUN pacman -S --noconfirm sccache +RUN cargo install cargo-make +RUN cargo install cargo-binstall +RUN cargo binstall --no-confirm wasmer-cli \ No newline at end of file diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 0000000..1e92228 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,2 @@ +[tasks.build] +args = ["build"] \ No newline at end of file diff --git a/paxy-plugin/Cargo.toml b/paxy-plugin/Cargo.toml index 7322561..c5df3bd 100644 --- a/paxy-plugin/Cargo.toml +++ b/paxy-plugin/Cargo.toml @@ -1,3 +1,4 @@ +cargo-features = ["per-package-target"] [package] name = "paxy-plugin" version.workspace = true @@ -12,5 +13,14 @@ documentation.workspace = true readme.workspace = true edition.workspace = true license.workspace = true +default-target = "wasm32-wasi" [dependencies] +extism-pdk = "1.1.0" +semver = {version = "1.0.22", features = ["serde"]} +serde = { workspace = true, features = ["derive"] } +toml = "0.8.12" +reqwest = { version = "0.11", features = ["blocking", "json"] } + +[lib] +crate_type = ["cdylib"] diff --git a/paxy-plugin/examples/paxy.px b/paxy-plugin/examples/paxy.px new file mode 100644 index 0000000..e7113db --- /dev/null +++ b/paxy-plugin/examples/paxy.px @@ -0,0 +1,13 @@ +name = "Paxy" +repo = "https://github.com/Pax-Hub/paxy" + +[[version]] +ver = "0.1.0" +src = "https://github.com/Pax-hub/paxy/releases/tag/0.1.0" +dependencies = ["rust >= 1.72.0"] +install_inst = "mv pkg/paxy /usr/bin" + +[[version]] +ver = "0.1.1" +src = "https://github.com/Pax-hub/paxy/releases/tag/0.1.1" +install_inst = "mv /pkg/paxy /usr/bin" \ No newline at end of file diff --git a/paxy-plugin/src/lib.rs b/paxy-plugin/src/lib.rs new file mode 100644 index 0000000..56ec9cf --- /dev/null +++ b/paxy-plugin/src/lib.rs @@ -0,0 +1,65 @@ +use std::{ + fs, + process::Command, +}; + +use extism_pdk::{plugin_fn, FnResult, Json}; +use semver::{Version, VersionReq}; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +struct Pkg { + name: String, + repo: String, + version: Vec, +} + +#[derive(Debug, Deserialize)] +struct Ver { + ver: Version, + dependencies: Vec, + src: String, + install_inst: String, +} + +fn parse_file() -> Pkg { + toml::from_str( + fs::read_to_string("/pkg") + .unwrap() + .as_str(), + ) + .expect("invalid file") +} + +fn exec_inst(commands: String) { + for stmt in commands.split(';') { + let mut args = stmt + .split(' ') + .collect::>(); + let mut cmd = Command::new( + args.get(0) + .expect("malformed command"), + ); + args.remove(0); + cmd.args(args); + let mut handle = match cmd.spawn() { + Ok(c) => c, + Err(_) => panic!("Illegal expression: {stmt}") + }; + handle.wait().unwrap(); + } +} + +#[plugin_fn] +pub fn prep(req: Json) -> FnResult { + let pkg = parse_file(); + let ver; + let req = req.0; + for version in pkg.version { + if version.ver == req { + ver = version; + break; + } + } + todo!() +} \ No newline at end of file diff --git a/paxy-plugin/src/main.rs b/paxy-plugin/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/paxy-plugin/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/paxy/src/actions/add_repo.rs b/paxy/src/actions/add_repo.rs index 4e28462..fc0841f 100644 --- a/paxy/src/actions/add_repo.rs +++ b/paxy/src/actions/add_repo.rs @@ -1,4 +1,4 @@ -use std::fs::{write, File}; +use std::fs::{remove_dir_all, write, File}; use bson::{doc, Document}; use git2::Repository; @@ -33,7 +33,10 @@ fn add_repo(repo: &str, name: &str) { file.push("repos"); file.push(name); ensure_path(Some(&file)); - Repository::clone(repo, file).unwrap(); + if Repository::clone(repo, file.clone()).is_err() { + remove_dir_all(file.clone()).unwrap(); + Repository::clone(repo, file); + } } #[cfg(test)] diff --git a/paxy/src/actions/rm_repo.rs b/paxy/src/actions/rm_repo.rs index 8b13789..e69de29 100644 --- a/paxy/src/actions/rm_repo.rs +++ b/paxy/src/actions/rm_repo.rs @@ -1 +0,0 @@ - diff --git a/paxy/src/app/plugins.rs b/paxy/src/app/plugins.rs index 37340d4..4420397 100644 --- a/paxy/src/app/plugins.rs +++ b/paxy/src/app/plugins.rs @@ -1,6 +1,7 @@ use std::{ fs::{write, File}, path::{Path, PathBuf}, + str::FromStr, }; use bson::{doc, Document}; @@ -10,7 +11,7 @@ use crate::{actions::ensure_path, home}; #[allow(unused)] #[allow(clippy::boxed_local)] -pub(crate) fn plugin(manifest: Box) -> Wasm { +pub(crate) fn plugin(manifest: Box) -> (Wasm, PathBuf) { let mut file = home!(); file.push(".paxy"); file.push("plugins"); @@ -18,7 +19,7 @@ pub(crate) fn plugin(manifest: Box) -> Wasm { file.push("plugins.bson"); let plugins = if !file.is_file() { let mut buf = vec![]; - let doc = doc! {"pax": "paxy.wasm"}; + let doc = doc! {"px": "paxy.wasm"}; doc.to_writer(&mut buf) .unwrap(); write(file, buf).unwrap(); @@ -36,7 +37,7 @@ pub(crate) fn plugin(manifest: Box) -> Wasm { ) .unwrap() .to_string(); - Wasm::file(plugin) + (Wasm::file(&plugin), PathBuf::from_str(&plugin).unwrap()) } #[allow(unused)] @@ -45,10 +46,17 @@ pub fn call_plugin(wasm: Wasm, pkg: PathBuf) { tmp.push(".paxy"); tmp.push("tmp"); ensure_path(Some(&tmp)); + tmp.pop(); + tmp.push("fakeroot"); + ensure_path(Some(&tmp)); let manifest = Manifest::new([wasm]).with_allowed_paths( - [(tmp, PathBuf::from("/tmp")), (pkg, PathBuf::from("/pkg"))] - .iter() - .cloned(), + [ + (tmp.clone(), PathBuf::from("/tmp")), + (pkg, PathBuf::from("/pkg")), + (tmp, PathBuf::from("/")), + ] + .iter() + .cloned(), ); let plugin = PluginBuilder::new(manifest).with_wasi(true); let mut plugin = plugin diff --git a/rust-toolchain.toml b/rust-toolchain.toml index af42841..d6e5acf 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -8,4 +8,6 @@ targets = [ "aarch64-unknown-linux-gnu", "aarch64-pc-windows-msvc", "aarch64-apple-darwin", + "wasm32-wasi", + "wasm32-unknown-unknown" ] \ No newline at end of file diff --git a/semver b/semver new file mode 160000 index 0000000..5aabf8f --- /dev/null +++ b/semver @@ -0,0 +1 @@ +Subproject commit 5aabf8fec173feacb73bb91f124482607eb0e56a From ff600c23f6fca505b6945df86f83609a24c2fe9e Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Tue, 7 May 2024 09:30:44 +0530 Subject: [PATCH 12/17] fmt --- paxy-plugin/src/lib.rs | 13 ++++++------- paxy/src/actions/mod.rs | 3 ++- paxy/src/actions/repository/install.rs | 2 +- paxy/src/app/config.rs | 9 +++------ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/paxy-plugin/src/lib.rs b/paxy-plugin/src/lib.rs index 56ec9cf..51a0a03 100644 --- a/paxy-plugin/src/lib.rs +++ b/paxy-plugin/src/lib.rs @@ -1,7 +1,4 @@ -use std::{ - fs, - process::Command, -}; +use std::{fs, process::Command}; use extism_pdk::{plugin_fn, FnResult, Json}; use semver::{Version, VersionReq}; @@ -44,9 +41,11 @@ fn exec_inst(commands: String) { cmd.args(args); let mut handle = match cmd.spawn() { Ok(c) => c, - Err(_) => panic!("Illegal expression: {stmt}") + Err(_) => panic!("Illegal expression: {stmt}"), }; - handle.wait().unwrap(); + handle + .wait() + .unwrap(); } } @@ -62,4 +61,4 @@ pub fn prep(req: Json) -> FnResult { } } todo!() -} \ No newline at end of file +} diff --git a/paxy/src/actions/mod.rs b/paxy/src/actions/mod.rs index 79dd83f..4eecafd 100644 --- a/paxy/src/actions/mod.rs +++ b/paxy/src/actions/mod.rs @@ -44,9 +44,10 @@ pub fn ensure_path(path: Option<&PathBuf>) { // region: IMPORTS -use snafu::Snafu; use std::path::PathBuf; +use snafu::Snafu; + // endregion: IMPORTS // region: MODULES diff --git a/paxy/src/actions/repository/install.rs b/paxy/src/actions/repository/install.rs index 5bf4f98..11d9fba 100644 --- a/paxy/src/actions/repository/install.rs +++ b/paxy/src/actions/repository/install.rs @@ -48,7 +48,7 @@ pub enum Error { // region: IMPORTS use std::{ - fs::{write, File, remove_dir_all}, + fs::{remove_dir_all, write, File}, path::PathBuf, }; diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 0a59e0c..73b9042 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -31,12 +31,9 @@ pub fn init_config(config_filepath: Option<&Path>) -> Result<(Config, Vec Date: Tue, 7 May 2024 10:47:48 +0530 Subject: [PATCH 13/17] set the name for the repository to paxy-pkgs and refactored config to use bson --- paxy/Cargo.toml | 3 + paxy/src/actions/mod.rs | 9 ++- paxy/src/actions/repository/install.rs | 21 ++++--- paxy/src/data/config.rs | 80 ++++++++++++++++++-------- 4 files changed, 82 insertions(+), 31 deletions(-) diff --git a/paxy/Cargo.toml b/paxy/Cargo.toml index 1af4864..1860e88 100644 --- a/paxy/Cargo.toml +++ b/paxy/Cargo.toml @@ -58,3 +58,6 @@ url = { version = "2.3", features = ["serde"] } extism = "1.2.0" bson = "2.9.0" git2 = {version = "0.18.3", default-features = false, features = ["https"]} + +[dev-dependencies] +serial_test = "3.1.1" \ No newline at end of file diff --git a/paxy/src/actions/mod.rs b/paxy/src/actions/mod.rs index 4eecafd..f7b164e 100644 --- a/paxy/src/actions/mod.rs +++ b/paxy/src/actions/mod.rs @@ -42,9 +42,16 @@ pub fn ensure_path(path: Option<&PathBuf>) { } } +#[inline] +pub(crate) fn ensure_file(file: &PathBuf, f: F) { + if !file.is_file() { + f(File::create(file).unwrap()) + } +} + // region: IMPORTS -use std::path::PathBuf; +use std::{fs::File, path::{Path, PathBuf}}; use snafu::Snafu; diff --git a/paxy/src/actions/repository/install.rs b/paxy/src/actions/repository/install.rs index 11d9fba..34fbfcc 100644 --- a/paxy/src/actions/repository/install.rs +++ b/paxy/src/actions/repository/install.rs @@ -6,7 +6,7 @@ fn add_repo(repo: &str, name: &str) { file.push("repos.bson"); let mut doc = if !file.is_file() { warn!("file not found. Creating"); - let doc = doc! {"paxy-official": "https://github.com/Pax-Hub/paxy-pkg-repository.git"}; + let doc = doc! {"paxy-pkgs": "https://github.com/Pax-Hub/paxy-pkg-repository.git"}; let mut buf = vec![]; doc.to_writer(&mut buf) .unwrap(); @@ -65,18 +65,25 @@ use crate::actions::ensure_path; #[cfg(test)] mod tests { + use std::fs; + use super::*; + use serial_test::serial; #[test] - fn add_repo_norm_test() { + #[serial] + fn repo_add_norm() { + let mut repo_file = home!(); + repo_file.push(".paxy"); + repo_file.push("repos.bson"); + if repo_file.is_file() { + fs::remove_file(&repo_file).unwrap(); + } add_repo("https://github.com/Pax-Hub/paxy-pkg-repository.git", "paxy"); - let mut file = home!(); - file.push(".paxy"); - file.push("repos.bson"); - let doc = Document::from_reader(File::open(file.clone()).unwrap()).unwrap(); + let doc = Document::from_reader(File::open(repo_file.clone()).unwrap()).unwrap(); assert_eq!( doc, - doc! {"paxy-official": "https://github.com/Pax-Hub/paxy-pkg-repository.git", "paxy": "https://github.com/Pax-Hub/paxy-pkg-repository.git"} + doc! {"paxy-pkgs": "https://github.com/Pax-Hub/paxy-pkg-repository.git", "paxy": "https://github.com/Pax-Hub/paxy-pkg-repository.git"} ); } } diff --git a/paxy/src/data/config.rs b/paxy/src/data/config.rs index 6fa649a..94a6912 100644 --- a/paxy/src/data/config.rs +++ b/paxy/src/data/config.rs @@ -4,12 +4,15 @@ use std::{ path::PathBuf, }; +use bson::{doc, Document}; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Serialize, Deserialize)] +use crate::{actions::ensure_file, home}; + +#[derive(Serialize, Deserialize, PartialEq, Debug)] pub struct Config { - pub repositories: Option>, + pub repositories: Document, pub system_install_location: PathBuf, pub user_install_location: PathBuf, pub default_install_type: InstallType, @@ -17,10 +20,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { - let mut user: PathBuf = match home::home_dir() { - Some(path) => path, - None => panic!("Impossible to get your home dir!"), - }; + let mut user: PathBuf = home!(); user.push(".paxy"); user.push("pkgs"); let system = if cfg!(linux) { @@ -28,11 +28,23 @@ impl Default for Config { } else { PathBuf::from("") }; + let mut repo_file = home!(); + repo_file.push(".paxy"); + repo_file.push("repos.bson"); + + ensure_file(&repo_file, |mut f: File| { + let mut buf = Vec::new(); + doc! {"paxy-pkgs": "https://github.com/Pax-Hub/paxy-pkg-repository.git"} + .to_writer(&mut buf) + .unwrap(); + f.write_all(&buf) + .unwrap(); + }); + let repo_file = File::open(repo_file).unwrap(); + let doc = Document::from_reader(repo_file).unwrap(); let conf = Config { - repositories: Some(vec![ - Url::parse("https://github.com/Pax-Hub/Packages.git").unwrap() - ]), + repositories: doc, user_install_location: user.clone(), /* Not harmful since the value is dropped in the * very next line */ system_install_location: system, @@ -41,7 +53,7 @@ impl Default for Config { if !user.is_dir() { create_dir_all(user.clone()).expect("No permission"); // Not harmful since the value is dropped in the soon user.pop(); - user.push("config.ini"); + user.push("config.toml"); if user.is_file() { fs::remove_file(user.clone()).unwrap(); } @@ -59,7 +71,7 @@ impl Default for Config { } } -#[derive(Serialize, Deserialize, Default)] +#[derive(Serialize, Deserialize, Default, PartialEq, Debug)] pub enum InstallType { User, #[default] @@ -68,18 +80,40 @@ pub enum InstallType { #[allow(dead_code)] fn load_conf() -> Config { - let mut conf_path: PathBuf = match home::home_dir() { - Some(path) => path, - None => panic!("Impossible to get your home dir!"), - }; + let mut conf_path: PathBuf = home!(); conf_path.push(".paxy"); - conf_path.push("config.ini"); - match toml::from_str::( - fs::read_to_string(&conf_path) - .unwrap() - .as_str(), - ) { - Ok(val) => val, - Err(_) => Config::default(), + conf_path.push("config.toml"); + match fs::read_to_string(&conf_path) { + Ok(val) => match toml::from_str(&val) { + Ok(toml) => toml, + Err(_) => panic!("invalid config file"), + }, + Err(_) => { + let val = Config::default(); + let toml = toml::to_string_pretty::(&val).unwrap(); + let mut file = File::create(conf_path).unwrap(); + file.write_all(toml.as_bytes()) + .unwrap(); + val + } + } +} + +#[cfg(test)] +mod tests { + use serial_test::serial; + + use super::*; + + #[test] + #[serial] + fn load_conf_test_noexist() { + let mut repo_file = home!(); + repo_file.push(".paxy"); + repo_file.push("repos.bson"); + if repo_file.is_file() { + fs::remove_file(repo_file).unwrap(); + } + assert_eq!(load_conf(), Config::default()) } } From a5167872998abb22064596b306a34dccd86362ef Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Tue, 7 May 2024 21:57:23 +0530 Subject: [PATCH 14/17] removed semver --- .gitmodules | 3 --- Cargo.toml | 7 ++++--- paxy-plugin/Cargo.toml | 5 ++--- semver | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 .gitmodules delete mode 160000 semver diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 1e726f9..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "semver"] - path = semver - url = git@github.com:FerrisWasTaken/semver.git diff --git a/Cargo.toml b/Cargo.toml index 949ae8a..c614c9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,13 +3,13 @@ members = [ "paxy", "paxy-cli", "paxy-gui", "paxy-plugin", - "tests", "semver" + "tests" ] default-members = [ "paxy", "paxy-cli", "paxy-gui", - "tests", "semver" + "tests" ] resolver = "1" @@ -54,7 +54,8 @@ snafu = "0.8" # Data lazy_static = "1.4" -serde = { version = "1.0", features = ["derive"] } +semver = {git = "https://github.com/FerrisWasTaken/semver.git", features = ["extism_support"]} +serde = { version = "1.0.200", features = ["derive"] } serde-aux = "4.5" serde_yaml = "0.9" tracing-serde = "0.1" diff --git a/paxy-plugin/Cargo.toml b/paxy-plugin/Cargo.toml index c5df3bd..66c7056 100644 --- a/paxy-plugin/Cargo.toml +++ b/paxy-plugin/Cargo.toml @@ -17,10 +17,9 @@ default-target = "wasm32-wasi" [dependencies] extism-pdk = "1.1.0" -semver = {version = "1.0.22", features = ["serde"]} -serde = { workspace = true, features = ["derive"] } toml = "0.8.12" +semver = { workspace = true, features = ["extism_support"]} reqwest = { version = "0.11", features = ["blocking", "json"] } [lib] -crate_type = ["cdylib"] +crate-type = ["cdylib"] diff --git a/semver b/semver deleted file mode 160000 index 5aabf8f..0000000 --- a/semver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5aabf8fec173feacb73bb91f124482607eb0e56a From 298cba284ef88b26be66c8d7168a7268246c06c2 Mon Sep 17 00:00:00 2001 From: pvshvp-oss Date: Wed, 8 May 2024 12:06:24 -0500 Subject: [PATCH 15/17] WIP --- Cargo.toml | 3 ++- paxy/Cargo.toml | 3 ++- paxy/src/app/config.rs | 32 ++++++++++++++++++++------------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0688588..bf04a50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ paxy = { path = "paxy" } tracing = "0.1" tracing-appender = "0.2" tracing-subscriber = "0.3" +log = "0.4" # Configuration figment = "0.10" @@ -57,7 +58,7 @@ serde-aux = "4.5" serde_yaml = "0.9" tracing-serde = "0.1" speedy = "0.8" -log = "0.4" +itertools = "0.12" # Internationalization fluent = "0.16" diff --git a/paxy/Cargo.toml b/paxy/Cargo.toml index 949f1fe..479ba7b 100644 --- a/paxy/Cargo.toml +++ b/paxy/Cargo.toml @@ -20,6 +20,7 @@ edition.workspace = true tracing = { workspace = true } tracing-appender = { workspace = true } tracing-subscriber = { workspace = true } +log = { workspace = true, features = ["serde"] } # Configuration figment = { workspace = true, features = ["toml", "json", "yaml", "env"] } @@ -37,7 +38,7 @@ serde-aux = { workspace = true } serde_yaml = { workspace = true } tracing-serde = { workspace = true } speedy = { workspace = true } -log = { workspace = true, features = ["serde"] } +itertools = { workspace = true } # Internationalization fluent = { workspace = true } diff --git a/paxy/src/app/config.rs b/paxy/src/app/config.rs index 052a72c..ff512e3 100644 --- a/paxy/src/app/config.rs +++ b/paxy/src/app/config.rs @@ -8,16 +8,16 @@ where G: ui::GlobalArguments, ::L: clap_verbosity_flag::LogLevel, { - let mut candidate_config_filepath_stubs: Vec = Vec::new(); + let mut candidate_config_filepaths: Vec = Vec::new(); // Global directories #[cfg(target_family = "unix")] - candidate_config_filepath_stubs.extend(["/etc/xdg".into(), "/etc".into()]); + candidate_config_filepaths.extend(["/etc/xdg".into(), "/etc".into()]); #[cfg(target_os = "windows")] candidate_config_filepath_stubs.extend([""]); // Local directories - candidate_config_filepath_stubs.push( + candidate_config_filepaths.push( directories::BaseDirs::new() .context(RetreiveConfigUserAppBaseDirectoriesSnafu {})? .config_dir() @@ -25,22 +25,22 @@ where ); // Append filename to create filepath stubs - candidate_config_filepath_stubs + candidate_config_filepaths .iter_mut() .for_each(|f| f.push(*app::APP_NAME)); + candidate_config_filepaths = candidate_config_filepaths + .iter() + .cartesian_product(["toml", "TOML", "json", "JSON", "yaml", "YAML", "yml", "YML"]); + // Initialize configuration with app-wide defaults - let mut figment = Figment::from(Config::default()); + let mut config = Config::new(); // Merge configuration values from global and local filepaths - figment = candidate_config_filepath_stubs - .iter() - .fold(figment, move |figment, candidate_config_filepath_stub| { - admerge_from_stub(candidate_config_filepath_stub, figment) - }); + config = config.with_overriding_files(candidate_config_filepaths); // Merge configuration values from environment variables - figment = figment.admerge(Env::prefixed(&format!("{}_", *app::APP_NAME))); + config = config.with_overriding_env(&format!("{}_", *app::APP_NAME)); // Merge configuration values from additional config filepaths (usually // specified through CLI) @@ -145,6 +145,13 @@ impl Config { self } + pub fn with_overriding_filepath_stub>(&mut self, filepath_stub: P) -> &mut Self { + let filepath_stub: PathBuf = filepath_stub.into(); + + + self + } + pub fn with_overriding_files(&mut self, filepaths: I) -> &mut Self where P: AsRef, @@ -155,7 +162,7 @@ impl Config { self } - pub fn with_overriding_env>(prefix: S) -> &mut Self { + pub fn with_overriding_env>(&mut self, prefix: S) -> &mut Self { let prefix = prefix.as_ref(); self.figment = self .figment @@ -233,6 +240,7 @@ use figment::{ Profile, Provider, }; +use itertools::Itertools; use log::LevelFilter; use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; From ca62b9d8d8b5d6c8697c90cb9854e4f1412dbaba Mon Sep 17 00:00:00 2001 From: Ishaan Subramanya Date: Thu, 9 May 2024 11:17:09 +0530 Subject: [PATCH 16/17] stop tracking vscode and add semver as a dependency --- .gitignore | 1 + .vscode/settings.json | 6 ------ Cargo.toml | 1 - paxy-plugin/Cargo.toml | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 6100424..fe8042d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ Cargo.lock !.vscode/*.code-snippets .history/ *.vsix +.vscode/ # Packaging /packaging/**/pkg diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index d61fbe1..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rust-analyzer.showUnlinkedFileNotification": false, - "rust-analyzer.cargo.features": [ - "extism_support" - ] -} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c614c9f..823b0ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,6 @@ snafu = "0.8" # Data lazy_static = "1.4" -semver = {git = "https://github.com/FerrisWasTaken/semver.git", features = ["extism_support"]} serde = { version = "1.0.200", features = ["derive"] } serde-aux = "4.5" serde_yaml = "0.9" diff --git a/paxy-plugin/Cargo.toml b/paxy-plugin/Cargo.toml index 66c7056..3b075c7 100644 --- a/paxy-plugin/Cargo.toml +++ b/paxy-plugin/Cargo.toml @@ -18,7 +18,7 @@ default-target = "wasm32-wasi" [dependencies] extism-pdk = "1.1.0" toml = "0.8.12" -semver = { workspace = true, features = ["extism_support"]} +semver = {git = "https://github.com/FerrisWasTaken/semver.git", features = ["extism_support"]} reqwest = { version = "0.11", features = ["blocking", "json"] } [lib] From e59df2f36465ec086d1be5e7876ce84a45debef5 Mon Sep 17 00:00:00 2001 From: Kamal Abbas <83987394+0x177@users.noreply.github.com> Date: Thu, 9 May 2024 17:24:03 +0300 Subject: [PATCH 17/17] add rm_repo.rs (#16) * added basic remove repo function * cleaner error reporting * semver submodule to dependency * merge bug * refactroed to use macro --------- Co-authored-by: Ishaan Subramanya --- .gitignore | 2 +- Cargo.toml | 2 +- paxy/src/actions/repository/mod.rs | 7 +++ paxy/src/actions/repository/rm_repo.rs | 71 ++++++++++++++++++++++++++ paxy/src/data/config.rs | 2 +- paxy/src/data/mod.rs | 2 +- 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 paxy/src/actions/repository/rm_repo.rs diff --git a/.gitignore b/.gitignore index fe8042d..4a45cf4 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ Cargo.lock !.vscode/*.code-snippets .history/ *.vsix -.vscode/ +/.vscode/ # Packaging /packaging/**/pkg diff --git a/Cargo.toml b/Cargo.toml index 83bae38..1fd9e5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,4 +74,4 @@ console = "0.15" # GUI relm4 = "0.8" -relm4-components = "0.8" \ No newline at end of file +relm4-components = "0.8" diff --git a/paxy/src/actions/repository/mod.rs b/paxy/src/actions/repository/mod.rs index 7b2228e..1a2231f 100644 --- a/paxy/src/actions/repository/mod.rs +++ b/paxy/src/actions/repository/mod.rs @@ -24,6 +24,10 @@ pub enum Error { #[non_exhaustive] #[snafu(display("Could not downgrade:\n {source}"))] CouldNotDowngrade { source: downgrade::Error }, + + #[non_exhaustive] + #[snafu(display("Could not remove:\n {source}"))] + CouldNotRemove { source: rm_repo::Error } } // region: IMPORTS @@ -42,6 +46,7 @@ pub mod list; pub mod search; pub mod uninstall; pub mod update; +pub mod rm_repo; // endregion: MODULES @@ -60,5 +65,7 @@ pub use search::*; pub use uninstall::*; #[allow(unused_imports)] pub use update::*; +#[allow(unused_imports)] +pub use rm_repo::*; // endregion: RE-EXPORTS diff --git a/paxy/src/actions/repository/rm_repo.rs b/paxy/src/actions/repository/rm_repo.rs new file mode 100644 index 0000000..96fa649 --- /dev/null +++ b/paxy/src/actions/repository/rm_repo.rs @@ -0,0 +1,71 @@ +//region: IMPORTS +use bson::Document; +use crate::data::config::{Config,load_conf}; +use std::{ + path::PathBuf, + io::Write, +}; +use snafu::{Snafu,ensure,OptionExt,ResultExt}; +//endregion: IMPORTS + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("failed to serialize repo data into byte stream {source}"))] + FailedToSerialize {source: bson::ser::Error}, + + #[snafu(display("failed to write to repo data file {source}"))] + FailedToWriteData {source: std::io::Error}, + + #[snafu(display("repo not found"))] + FailedToFindRepo {}, +} + +#[allow(dead_code)] +fn delete_repo(repo_name: &str) -> Result<(),Error> { + let mut config = load_conf(); + let mut readable_data = config.repositories; + + readable_data.get(repo_name).context(FailedToFindRepoSnafu{})?; + readable_data.remove(repo_name); + let mut buf = vec![]; + let rbd_result = readable_data.to_writer(&mut buf); + + rbd_result.context(FailedToSerializeSnafu{})?; + + let mut repos_file_path: PathBuf = home!(); + repos_file_path.push(".paxy"); + repos_file_path.push("repos.bson"); + let mut file = std::fs::OpenOptions::new().write(true).truncate(true).open(repos_file_path).unwrap(); + let ftw_result = file.write_all(&buf); + + ftw_result.context(FailedToWriteDataSnafu{})?; + + config.repositories = readable_data; + + let mut config_toml_path: PathBuf = home!(); + + config_toml_path.push(".paxy"); + config_toml_path.push("config.toml"); + + let mut config_toml_file = std::fs::OpenOptions::new().write(true).truncate(true).open(config_toml_path).unwrap(); + config_toml_file.write_all( + toml::to_string(&config) + .unwrap() + .as_bytes(), + ) + .expect("Permission error"); + + Ok(()) +} + +//region: TESTS +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn delete_repo_test() { + Config::default(); + assert_eq!(delete_repo("paxy-pkgs").is_ok(),true); + } +} +//endregion: TESTS diff --git a/paxy/src/data/config.rs b/paxy/src/data/config.rs index 94a6912..db6b54e 100644 --- a/paxy/src/data/config.rs +++ b/paxy/src/data/config.rs @@ -79,7 +79,7 @@ pub enum InstallType { } #[allow(dead_code)] -fn load_conf() -> Config { +pub fn load_conf() -> Config { let mut conf_path: PathBuf = home!(); conf_path.push(".paxy"); conf_path.push("config.toml"); diff --git a/paxy/src/data/mod.rs b/paxy/src/data/mod.rs index 68a6538..2b894b4 100644 --- a/paxy/src/data/mod.rs +++ b/paxy/src/data/mod.rs @@ -35,4 +35,4 @@ use snafu::Snafu; // pub use some_module::*; // endregion: RE-EXPORTS -mod config; +pub mod config;