diff --git a/README.md b/README.md index 7476029..8cec75c 100644 --- a/README.md +++ b/README.md @@ -344,12 +344,14 @@ locked = false binstall = false [flatpak] -# If this is `true` then flatpak packages default to using the `--system` -# option. -# If this is `false` then flatpak packages default to using the `--user` -# option. -# Default: true -systemwide = true +# The default installation to use for flatpak packages. If equal to "user" +# then the --user option is passed when installing packages, if it is equal +# to "system" then the "--system" option is passed, and if it is equal to +# anything else then "--installation={installation}" is passed. If this is +# not set then nothing is passed. This config can be overridden on a +# per-package basis. +# Default: None +installation = "system" [vscode] # Since VSCode and VSCodium both operate on the same package database @@ -492,7 +494,15 @@ flatpak = { "package1", { name = "package2", - options = { remote = "flathub", systemwide = false } + options = { remote = "flathub", installation = "user" }, + }, + { + name = "package3", + options = { remote = "flathub", installation = "system" }, + }, + { + name = "package4", + options = { remote = "flathub", installation = "my_custom_installation" }, }, ] } diff --git a/src/backends/brew.rs b/src/backends/brew.rs index 4bfd53a..8f973c4 100644 --- a/src/backends/brew.rs +++ b/src/backends/brew.rs @@ -14,7 +14,7 @@ pub struct Brew; #[derive(Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct BrewConfig { - #[serde_inline_default(FlatpakConfig::default().systemwide)] + #[serde_inline_default(BrewConfig::default().quarantine)] quarantine: bool, } impl Default for BrewConfig { diff --git a/src/backends/flatpak.rs b/src/backends/flatpak.rs index 91fc76a..904b3a4 100644 --- a/src/backends/flatpak.rs +++ b/src/backends/flatpak.rs @@ -11,22 +11,16 @@ use serde_inline_default::serde_inline_default; pub struct Flatpak; #[serde_inline_default] -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Default)] #[serde(deny_unknown_fields)] pub struct FlatpakConfig { - #[serde_inline_default(FlatpakConfig::default().systemwide)] - pub systemwide: bool, -} -impl Default for FlatpakConfig { - fn default() -> Self { - Self { systemwide: true } - } + installation: Option, } #[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct FlatpakPackageOptions { - pub systemwide: Option, + pub installation: Option, pub remote: Option, } @@ -58,49 +52,30 @@ impl Backend for Flatpak { return Ok(BTreeMap::new()); } - let system_apps = run_command_for_stdout( + let apps = run_command_for_stdout( [ "flatpak", "list", - "--system", "--app", - "--columns=application", + "--columns=application,installation", ], Perms::Same, false, )?; - let system_apps = system_apps.lines().map(|x| { - ( - x.trim().to_owned(), - Self::PackageOptions { - systemwide: Some(true), - remote: None, - }, - ) - }); - let user_apps = run_command_for_stdout( - [ - "flatpak", - "list", - "--user", - "--app", - "--columns=application", - ], - Perms::Same, - false, - )?; - let user_apps = user_apps.lines().map(|x| { + let apps = apps.lines().map(|line| { + let parts = line.split_whitespace().collect::>(); + ( - x.trim().to_owned(), + parts[0].to_string(), Self::PackageOptions { - systemwide: Some(false), + installation: Some(parts[1].to_string()), remote: None, }, ) }); - Ok(system_apps.chain(user_apps).collect()) + Ok(apps.collect()) } fn install_packages( @@ -108,21 +83,30 @@ impl Backend for Flatpak { no_confirm: bool, config: &Self::Config, ) -> Result<()> { + let mut groups = BTreeMap::new(); for (package, options) in packages { + let installation = options.installation.clone().or(config.installation.clone()); + let remote = options.remote.clone(); + groups + .entry((installation, remote)) + .or_insert_with(Vec::new) + .push(package.clone()); + } + + for ((installation, remote), packages) in groups { run_command( - [ - "flatpak", - "install", - if options.systemwide.unwrap_or(config.systemwide) { - "--system" - } else { - "--user" - }, - ] - .into_iter() - .chain(Some("--assumeyes").filter(|_| no_confirm)) - .chain(options.remote.as_deref()) - .chain([package.as_str()]), + ["flatpak", "install"] + .into_iter() + .chain(Some("--assumeyes").filter(|_| no_confirm)) + .map(|x| x.to_string()) + .chain(match installation.as_deref() { + Some("user") => Some("--user".to_string()), + Some("system") => Some("--system".to_string()), + Some(x) => Some(format!("--installation={x}")), + None => None, + }) + .chain(remote) + .chain(packages), Perms::Same, )?; }