diff --git a/src/backends/mod.rs b/src/backends/mod.rs index 11b5ebf..8754947 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -7,6 +7,7 @@ pub mod dnf; pub mod flatpak; pub mod pipx; pub mod rustup; +pub mod snap; pub mod winget; pub mod xbps; @@ -27,6 +28,7 @@ macro_rules! apply_public_backends { (Flatpak, flatpak), (Pipx, pipx), (Rustup, rustup), + (Snap, snap), (WinGet, winget), (Xbps, xbps) } }; diff --git a/src/backends/snap.rs b/src/backends/snap.rs new file mode 100644 index 0000000..eee5aec --- /dev/null +++ b/src/backends/snap.rs @@ -0,0 +1,89 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use color_eyre::Result; +use serde::{Deserialize, Serialize}; + +use crate::cmd::{run_command, run_command_for_stdout}; +use crate::prelude::*; + +#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] +pub struct Snap; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct SnapQueryInfo {} + +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct SnapInstallOptions {} + +impl Backend for Snap { + type QueryInfo = SnapQueryInfo; + type InstallOptions = SnapInstallOptions; + + fn map_managed_packages( + packages: BTreeMap, + _: &Config, + ) -> Result> { + Ok(packages) + } + + fn query_installed_packages(config: &Config) -> Result> { + if Self::version(config).is_err() { + return Ok(BTreeMap::new()); + } + + let output = run_command_for_stdout(["snap", "list"], Perms::Same, false)?; + + // Skip the first line which is the header + Ok(output + .lines() + .skip(1) + .filter_map(|line| line.split_whitespace().next()) + .map(|name| (name.to_string(), SnapQueryInfo {})) + .collect()) + } + + fn install_packages( + packages: &BTreeMap, + no_confirm: bool, + _: &Config, + ) -> Result<()> { + if !packages.is_empty() { + run_command( + ["snap", "install"] + .into_iter() + .chain(Some("--assume-yes").filter(|_| no_confirm)) + .chain(packages.keys().map(String::as_str)), + Perms::Sudo, + )?; + } + + Ok(()) + } + + fn remove_packages(packages: &BTreeSet, no_confirm: bool, _: &Config) -> Result<()> { + if !packages.is_empty() { + run_command( + ["snap", "remove"] + .into_iter() + .chain(Some("--assume-yes").filter(|_| no_confirm)) + .chain(packages.iter().map(String::as_str)), + Perms::Sudo, + )?; + } + + Ok(()) + } + + fn version(_: &Config) -> Result { + run_command_for_stdout(["snap", "--version"], Perms::Same, false) + .map(|output| { + output + .lines() + .next() + .unwrap_or_default() + .split_whitespace() + .collect::>() + .join(" ") + }) + } +} diff --git a/src/prelude.rs b/src/prelude.rs index bae83f0..13b793c 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,6 +10,7 @@ pub use crate::backends::dnf::{Dnf, DnfInstallOptions, DnfQueryInfo}; 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::snap::{Snap, SnapInstallOptions, SnapQueryInfo}; pub use crate::backends::winget::{WinGet, WinGetInstallOptions, WinGetQueryInfo}; pub use crate::backends::xbps::{Xbps, XbpsInstallOptions, XbpsQueryInfo}; pub use crate::backends::{Backend, StringPackageStruct};