diff --git a/CHANGELOG.md b/CHANGELOG.md index f69a063..ad464a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## Unreleased +### Added + +- Added the HomeBrew Package Manager (#41) + ### Fixed - Fixed the optional dependencies Install Option in Arch packages being diff --git a/README.md b/README.md index d29b4c1..236a38a 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ additional backends are welcome! | ------------------------------ | ----------- | ------------------------------------- | | `pacman`/`paru`/`pikaur`/`yay` | `[arch]` | see the `arch_package_manager` config | | `apt` | `[apt]` | | +| `brew` | `[brew]` | | | `dnf` | `[dnf]` | | | `flatpak` | `[flatpak]` | | | `pipx` | `[pipx]` | | @@ -137,37 +138,41 @@ arch = [ # optional_deps: additional packages to install with this package, short-form syntax only { package = "metapac", optional_deps = ["git"] } ] -cargo = [ +apt = [ "metapac", - # see cargo docs for info on the options - { package = "metapac", git = "https://github.com/ripytide/metapac", all_features = true, no_default_features = false, features = [ "feature1", ] }, + { package = "metapac" } ] -pipx = [ +brew = [ "metapac", { package = "metapac" } ] -apt = [ +cargo = [ "metapac", - { package = "metapac" } + # see cargo docs for info on the options + { package = "metapac", git = "https://github.com/ripytide/metapac", all_features = true, no_default_features = false, features = [ "feature1", ] }, ] -xbps = [ +dnf = [ "metapac", - { package = "metapac" } + # see dnf docs for more info on these options + { package = "metapac", repo = "/etc/yum.repos.d/fedora_extras.repo" }, ] flatpak = [ "metapac", { package = "metapac" } ] -dnf = [ +pipx = [ "metapac", - # see dnf docs for more info on these options - { package = "metapac", repo = "/etc/yum.repos.d/fedora_extras.repo" }, + { package = "metapac" } ] rustup = [ "stable", # components: extra non-default components to install with this toolchain { package = "stable", components = ["rust-analyzer"] } ] +xbps = [ + "metapac", + { package = "metapac" } +] ``` # Credits diff --git a/config.toml b/config.toml index 4256b80..7cf287e 100644 --- a/config.toml +++ b/config.toml @@ -9,7 +9,7 @@ # Since pacman, paru, pikaur and yay all operate on the same package database # they are mutually exclusive and so you must pick which one you want # metapac to use. -# Must be one of: ["pacman", "paru", "pikaur", yay"] +# Must be one of: ["pacman", "paru", "pikaur", "yay"] # Default: "pacman" arch_package_manager = "paru" diff --git a/groups/example_group.toml b/groups/example_group.toml index d7e07f7..133dddc 100644 --- a/groups/example_group.toml +++ b/groups/example_group.toml @@ -22,34 +22,38 @@ arch = [ # optional_deps: additional packages to install with this package, short-form syntax only { package = "metapac", optional_deps = ["git"] } ] -cargo = [ +apt = [ "metapac", - # see cargo docs for info on the options - { package = "metapac", git = "https://github.com/ripytide/metapac", all_features = true, no_default_features = false, features = [ "feature1", ] }, + { package = "metapac" } ] -pipx = [ +brew = [ "metapac", { package = "metapac" } ] -apt = [ +cargo = [ "metapac", - { package = "metapac" } + # see cargo docs for info on the options + { package = "metapac", git = "https://github.com/ripytide/metapac", all_features = true, no_default_features = false, features = [ "feature1", ] }, ] -xbps = [ +dnf = [ "metapac", - { package = "metapac" } + # see dnf docs for more info on these options + { package = "metapac", repo = "/etc/yum.repos.d/fedora_extras.repo" }, ] flatpak = [ "metapac", { package = "metapac" } ] -dnf = [ +pipx = [ "metapac", - # see dnf docs for more info on these options - { package = "metapac", repo = "/etc/yum.repos.d/fedora_extras.repo" }, + { package = "metapac" } ] rustup = [ "stable", # components: extra non-default components to install with this toolchain { package = "stable", components = ["rust-analyzer"] } ] +xbps = [ + "metapac", + { package = "metapac" } +] diff --git a/src/backends/brew.rs b/src/backends/brew.rs new file mode 100644 index 0000000..1e047a1 --- /dev/null +++ b/src/backends/brew.rs @@ -0,0 +1,74 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use color_eyre::Result; +use serde::{Deserialize, Serialize}; + +use crate::cmd::{command_found, run_command, run_command_for_stdout}; +use crate::prelude::*; + +#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] +pub struct Brew; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct BrewQueryInfo {} + +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct BrewInstallOptions {} + +impl Backend for Brew { + type QueryInfo = BrewQueryInfo; + type InstallOptions = BrewInstallOptions; + + fn map_managed_packages( + packages: BTreeMap, + _: &Config, + ) -> Result> { + Ok(packages) + } + + fn query_installed_packages(_: &Config) -> Result> { + if !command_found("brew") { + return Ok(BTreeMap::new()); + } + + let explicit = run_command_for_stdout( + ["brew", "list", "-1", "--quiet", "--installed-on-request"], + Perms::Same, + )?; + + Ok(explicit + .lines() + .map(|x| (x.to_string(), BrewQueryInfo {})) + .collect()) + } + + fn install_packages( + packages: &BTreeMap, + _: bool, + _: &Config, + ) -> Result<()> { + if !packages.is_empty() { + run_command( + ["brew", "install"] + .into_iter() + .chain(packages.keys().map(String::as_str)), + Perms::Same, + )?; + } + + Ok(()) + } + + fn remove_packages(packages: &BTreeSet, _: bool, _: &Config) -> Result<()> { + if !packages.is_empty() { + run_command( + ["brew", "remove"] + .into_iter() + .chain(packages.iter().map(String::as_str)), + Perms::Same, + )?; + } + + Ok(()) + } +} diff --git a/src/backends/mod.rs b/src/backends/mod.rs index 58862be..a4b2124 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -1,6 +1,7 @@ pub mod all; pub mod apt; pub mod arch; +pub mod brew; pub mod cargo; pub mod dnf; pub mod flatpak; @@ -16,7 +17,7 @@ use serde::{Deserialize, Serialize}; macro_rules! apply_public_backends { ($macro:ident) => { - $macro! { Arch, Apt, Cargo, Dnf, Flatpak, Pipx, Rustup, Xbps } + $macro! { Arch, Apt, Brew, Cargo, Dnf, Flatpak, Pipx, Rustup, Xbps } }; } pub(crate) use apply_public_backends; diff --git a/src/prelude.rs b/src/prelude.rs index 2cbc457..c91a802 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -2,23 +2,20 @@ pub use crate::backends::all::{ AnyBackend, InstallOptions, PackageIds, QueryInfos, RawInstallOptions, RawPackageIds, }; pub(crate) use crate::backends::apply_public_backends; -pub use crate::backends::apt::{Apt, AptQueryInfo}; +pub use crate::backends::apt::{Apt, AptInstallOptions, AptQueryInfo}; pub use crate::backends::arch::{Arch, ArchInstallOptions, ArchQueryInfo}; -pub use crate::backends::cargo::Cargo; +pub use crate::backends::brew::{Brew, BrewInstallOptions, BrewQueryInfo}; +pub use crate::backends::cargo::{Cargo, CargoInstallOptions, CargoQueryInfo}; pub use crate::backends::dnf::{Dnf, DnfInstallOptions, DnfQueryInfo}; -pub use crate::backends::flatpak::{Flatpak, FlatpakQueryInfo}; -pub use crate::backends::pipx::Pipx; +pub use crate::backends::flatpak::{Flatpak, FlatpakInstallOptions, FlatpakQueryInfo}; +pub use crate::backends::pipx::{Pipx, PipxInstallOptions, PipxQueryOptions}; pub use crate::backends::rustup::{Rustup, RustupInstallOptions, RustupQueryInfo}; -pub use crate::backends::xbps::Xbps; -pub use crate::backends::Backend; -pub use crate::backends::StringPackageStruct; -pub use crate::cli::AddCommand; -pub use crate::cli::CleanCommand; -pub use crate::cli::MainArguments; -pub use crate::cli::MainSubcommand; -pub use crate::cli::ReviewCommand; -pub use crate::cli::SyncCommand; -pub use crate::cli::UnmanagedCommand; +pub use crate::backends::xbps::{Xbps, XbpsInstallOptions, XbpsQueryInfo}; +pub use crate::backends::{Backend, StringPackageStruct}; +pub use crate::cli::{ + AddCommand, CleanCommand, MainArguments, MainSubcommand, ReviewCommand, SyncCommand, + UnmanagedCommand, +}; pub use crate::cmd::Perms; pub use crate::config::{ArchPackageManager, Config}; pub use crate::groups::Groups;