diff --git a/modules/installer.nix b/modules/installer.nix index 9294c2f..a29c95b 100644 --- a/modules/installer.nix +++ b/modules/installer.nix @@ -13,6 +13,7 @@ let else "\${XDG_STATE_HOME:-$HOME/.local/state}/home-manager/gcroots"; stateFile = pkgs.writeText "flatpak-state.json" (builtins.toJSON { packages = map (builtins.getAttr "appId") cfg.packages; + overrides = cfg.overrides; }); statePath = "${gcroots}/${stateFile.name}"; @@ -42,6 +43,40 @@ let fi ''; + overridesDir = + if (installation == "system") + then "/var/lib/flatpak/overrides" + else "\${XDG_DATA_HOME:-$HOME/.local/share}/flatpak/overrides"; + flatpakOverridesCmd = installation: {}: '' + # Update overrides that are managed by this module (both old and new) + mkdir -p ${overridesDir} + ${pkgs.jq}/bin/jq -r -n \ + --argjson old "$OLD_STATE" \ + --argjson new "$NEW_STATE" \ + '$new.overrides + $old.overrides | keys[]' \ + | while read -r APP_ID; do + OVERRIDES_PATH=${overridesDir}/$APP_ID + + # Transform the INI-like Flatpak overrides file into a workable JSON + if [[ -f $OVERRIDES_PATH ]]; then + ACTIVE=$(cat $OVERRIDES_PATH \ + | ${pkgs.jc}/bin/jc --ini \ + | ${pkgs.jq}/bin/jq 'map_values(map_values(split(";") | select(. != []) // ""))') + else + ACTIVE={} + fi + + # Generate and save the updated overrides file + ${pkgs.jq}/bin/jq -r -n \ + --arg app_id "$APP_ID" \ + --argjson active "$ACTIVE" \ + --argjson old_state "$OLD_STATE" \ + --argjson new_state "$NEW_STATE" \ + --from-file ${./overrides.jq} \ + >$OVERRIDES_PATH + done + ''; + flatpakInstallCmd = installation: update: { appId, origin ? "flathub", commit ? null, ... }: '' ${pkgs.flatpak}/bin/flatpak --${installation} --noninteractive --no-auto-pin install \ ${if update && commit == null then ''--or-update'' else ''''} ${origin} ${appId} @@ -86,6 +121,9 @@ pkgs.writeShellScript "flatpak-managed-install" '' # Install packages ${mkFlatpakInstallCmd installation updateApplications cfg.packages} + # Configure overrides + ${flatpakOverridesCmd installation {}} + # Save state ln -sf ${stateFile} ${statePath} '' diff --git a/modules/options.nix b/modules/options.nix index e061b99..62fff40 100644 --- a/modules/options.nix +++ b/modules/options.nix @@ -119,6 +119,23 @@ in ''; }; + overrides = mkOption { + type = with types; attrsOf (attrsOf (attrsOf (either str (listOf str)))); + default = {}; + description = lib.mdDoc '' + Applies the provided attribute set into a Flatpak overrides file with the + same structure, keeping externally applied changes + ''; + example = literalExpression '' + { + # Array entries will be merged with externally applied values + "com.visualstudio.code".Context.sockets = ["wayland" "!x11" "!fallback-x11"]; + # String entries will override externally applied values + global.Environment.LC_ALL = "C.UTF-8"; + }; + ''; + }; + update = mkOption { type = with types; submodule updateOptions; default = { onActivation = false; auto = { enable = false; onCalendar = "weekly"; }; }; diff --git a/modules/overrides.jq b/modules/overrides.jq new file mode 100644 index 0000000..0da9f02 --- /dev/null +++ b/modules/overrides.jq @@ -0,0 +1,42 @@ +# Convert entry value into array +def values($value): if ($value | type) == "string" then [$value] else ($value // []) end; + +# State aliases + ($old_state.overrides[$app_id] // {}) as $old +| ($new_state.overrides[$app_id] // {}) as $new + +# Map sections that exist in either active or new state (ignore old) +| $active + $new | keys | map ( + . as $section | {"section_key": $section, "section_value": ( + + # Map entries that exist in either active or new state (ignore old) + ($active[$section] // {}) + ($new[$section] // {}) | keys | map ( + . as $entry | { "entry_key": $entry, "entry_value": ( + + # Entry value aliases + $active[$section][$entry] as $active_value + | $new[$section][$entry] as $new_value + | $old[$section][$entry] as $old_value + + # Use new value if it is a string + | if ($new_value | type) == "string" then $new_value + else + # Otherwise remove old values from the active ones, and add the new ones + values($active_value) - values($old_value) + values($new_value) + + # Remove empty arrays and duplicate values + | select(. != []) | unique + + # Convert array into Flatpak string array format + | join(";") + end + )} + ) + + # Remove empty arrays + | select(. != []) + )} + )[] + +# Generate the final overrides file +| "[\(.section_key)]", (.section_value[] | "\(.entry_key)=\(.entry_value)"), ""