diff --git a/Cargo.lock b/Cargo.lock index 7c85499..c944807 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,7 +148,10 @@ dependencies = [ "pacdef_macro", "path-absolutize", "regex", + "serde", + "serde_derive", "serde_json", + "serde_yaml", ] [[package]] @@ -231,6 +234,17 @@ version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_json" version = "1.0.91" @@ -242,6 +256,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "strsim" version = "0.10.0" @@ -280,6 +307,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unsafe-libyaml" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 9185285..6dc8388 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,9 @@ clap = "3.*" path-absolutize = "*" regex = "*" serde_json = "*" +serde_yaml = "*" +serde_derive = "*" +serde = "*" pacdef_macro = {path = "pacdef_macro/"} [profile.release] diff --git a/src/backend/actual/pacman.rs b/src/backend/actual/pacman.rs index fcffa77..e726a41 100644 --- a/src/backend/actual/pacman.rs +++ b/src/backend/actual/pacman.rs @@ -8,6 +8,7 @@ use crate::backend::backend_trait::*; use crate::{impl_backend_constants, Group, Package}; pub(crate) struct Pacman { + pub(crate) binary: String, pub(crate) packages: HashSet, } @@ -69,6 +70,7 @@ fn get_db_handle() -> Result { impl Pacman { pub(crate) fn new() -> Self { Self { + binary: BINARY.to_string(), packages: HashSet::new(), } } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..03a8fdc --- /dev/null +++ b/src/config.rs @@ -0,0 +1,61 @@ +use std::fs::{read_to_string, File}; +use std::io::{ErrorKind, Write}; +use std::path::PathBuf; + +use anyhow::{bail, Context, Result}; +use serde_derive::{Deserialize, Serialize}; + +use crate::path::get_pacdef_base_dir; + +const CONFIG_FILE_NAME: &str = "pacdef.yaml"; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Config { + pub aur_helper: String, + pub warn_not_symlinks: bool, +} + +impl Config { + pub fn load() -> Result { + let file = get_config_file()?; + let from_file = read_to_string(&file); + + if let Err(e) = from_file { + if e.kind() == ErrorKind::NotFound { + println!("creating default config under {file:?}"); + return Self::use_default_and_save_to(file); + } else { + bail!("unexpected error occured: {e:?}"); + }; + } + + let content = from_file.unwrap(); + + serde_yaml::from_str(&content).context("parsing yaml config") + } + + fn use_default_and_save_to(file: PathBuf) -> Result { + let result = Self::default(); + + let content = serde_yaml::to_string(&result).context("converting Config to yaml")?; + let mut output = File::create(file).context("creating default config file")?; + write!(output, "{content}").context("writing default config")?; + + Ok(result) + } +} + +fn get_config_file() -> Result { + let mut file = get_pacdef_base_dir().context("getting pacdef base dir for config file")?; + file.push(CONFIG_FILE_NAME); + Ok(file) +} + +impl Default for Config { + fn default() -> Self { + Self { + aur_helper: "paru".into(), + warn_not_symlinks: true, + } + } +} diff --git a/src/core.rs b/src/core.rs index 23dce67..3523959 100644 --- a/src/core.rs +++ b/src/core.rs @@ -14,18 +14,24 @@ use crate::env::get_single_var; use crate::path::get_pacdef_group_dir; use crate::search; use crate::ui::get_user_confirmation; +use crate::Config; use crate::Group; pub struct Pacdef { args: ArgMatches, + config: Config, groups: HashSet, } // TODO review impl Pacdef { #[must_use] - pub fn new(args: ArgMatches, groups: HashSet) -> Self { - Self { args, groups } + pub fn new(args: ArgMatches, config: Config, groups: HashSet) -> Self { + Self { + args, + config, + groups, + } } #[allow(clippy::unit_arg)] diff --git a/src/grouping/group.rs b/src/grouping/group.rs index a12e755..c0c8a2a 100644 --- a/src/grouping/group.rs +++ b/src/grouping/group.rs @@ -8,6 +8,8 @@ use anyhow::{Context, Result}; use super::Section; +use crate::Config; + #[derive(Debug)] pub struct Group { pub(crate) name: String, @@ -15,7 +17,7 @@ pub struct Group { } impl Group { - pub fn load_from_dir() -> Result> { + pub fn load(config: &Config) -> Result> { let mut result = HashSet::new(); let path = crate::path::get_pacdef_group_dir().context("getting pacdef group dir")?; @@ -23,8 +25,13 @@ impl Group { let file = entry.context("getting group file")?; let path = file.path(); + if config.warn_not_symlinks && !path.is_symlink() { + println!("WARNING: group file {path:?} is not a symlink"); + } + let group = Group::try_from(&path).with_context(|| format!("reading group file {path:?}"))?; + result.insert(group); } diff --git a/src/lib.rs b/src/lib.rs index b4c1340..f3cffe1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ mod action; pub mod args; mod backend; mod cmd; +mod config; mod core; mod env; mod grouping; @@ -9,6 +10,7 @@ mod path; mod search; mod ui; +pub use crate::config::Config; pub use crate::core::Pacdef; pub use crate::grouping::Group; pub(crate) use crate::grouping::Package; diff --git a/src/main.rs b/src/main.rs index 54539da..89624df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ use anyhow::{Context, Result}; -use pacdef::{args, Group, Pacdef}; +use pacdef::{args, Config, Group, Pacdef}; fn main() -> Result<()> { let args = args::get(); - let groups = Group::load_from_dir()?; - let pacdef = Pacdef::new(args, groups); + let config = Config::load().context("loading config file")?; + let groups = Group::load(&config).context("loading groups")?; + let pacdef = Pacdef::new(args, config, groups); pacdef.run_action_from_arg().context("running action") } diff --git a/src/path.rs b/src/path.rs index c8bda49..59e3eb6 100644 --- a/src/path.rs +++ b/src/path.rs @@ -8,7 +8,7 @@ pub(crate) fn get_pacdef_group_dir() -> Result { Ok(result) } -fn get_pacdef_base_dir() -> Result { +pub(crate) fn get_pacdef_base_dir() -> Result { let mut dir = get_xdg_config_home().context("getting XDG_CONFIG_HOME")?; dir.push("pacdef"); Ok(dir)