GermanBread / declarative-flatpak

126 stars 4 forks source link

Refactor `overrides.nix` using `pkgs.formats` #23

Closed PJungkamp closed 2 weeks ago

PJungkamp commented 10 months ago

I'd like to see a more flexible overrides mechanism using pkgs.formats. The current implementation only supports the bare minimum of overrides. The format of the overrides file is, according to flatpak-metadata(5), just plain ini with list that are concatenated with ';'.

Here is an example of how one might use the upstream nixpkgs ini format:

{ pkgs ? import <nixpkgs> {}, lib ? pkgs.lib }:
let
  ini = pkgs.formats.ini {
    listToValue = lib.concatMapStringsSep ";" (lib.generators.mkValueStringDefault {});
  };
in ini.generate "flatpak-override" {
  "Context" = {
    "filesystems" = ["~/Games/Heroic" "/media/Data"];
    "sockets" = "!x11";
  };
}

I'll give it a try myself when I get around to tweaking my NixOS configuration again (might take some time), I just wanted to drop it here for anyone who's interested in improving the override mechanism. :D

It shouldn't be hard to make this as flexible as the upstream nixpkgs systemd service configuration, which I'd take as inspiration and design guideline.

@GermanBread Danke für dieses NixOS Modul! Ein Hoch auf das deutsche Brot!

GermanBread commented 9 months ago

Now I get it. But the issue remains that I cannot implement the type checks properly.

I have no idea how to tell Nix that the overrride attribute can support different submodules (types.oneOf [ <list of submodules> ] for example). It just errors out in a weird way.

Thanks for the tip though.

PJungkamp commented 9 months ago

I'd suggest something like the following for the options. (Just from the top of my head, not actually tested. I'm pretty much guaranteed to miss some semicolon)

  overrides = mkOption {
    type = types.attrsOf (types.submodule ({config, ...}: {
      options = {
        source = mkOption {
          type = types.path;
          internal = true;
        };
        metadata = mkOption {
          type = with types; attrsOf (attrsOf anything);
          internal = true;
        };
        filesystems = mkOption {
          type = with types; listOf str;
          default = [];
        };
        sockets = mkOption {
          type = with types; listOf str;
          default = [];
        };
        environment = mkOption {
          type = with types; attrsOf str;
          default = {};
        };
      };

      config.metadata = {
        "Context" = {
          inherit (config) filesystems sockets;
        };
        "Environment" = config.environment;
      };

      config.source = ini.generate config.metadata;
    });
    default = {};
  };

Note that I changed the type of overrides.<name>.environment and removed some unnecessary nullOr types. You can then pretty much generate the INI file using the ini.generate from above.


The nice thing here is that it also supports overriding the generated metadata file with another one which might also resolve issue #14. He'd be able to use builtins.readDir and map in combination with the internal overrides.<name>.source attribute to realize his wish.


I also quite like using internal options in NixOS modules since they can be inspected easily using nix eval and nix build.

# here's how I'd format my laptops global flatpak overrides as nice json using `jq`
$ nix eval --json .#nixosConfigurations.yoga9.config.services.flatpak.overrides.global.metadata | jq

# here's how I'd build and inpect the generated metadata file
$ nix build .#nixosConfigurations.yoga9.config.services.flatpak.overrides.global.source | cat ./result

It makes working with generated files so much easier.


I'm currently not using the declarative-flatpak module, I tried to refactor a bit so that it won't touch my system flatpak installation and uses a custom one instead, but I haven't got it working yet. See e.g. https://blogs.gnome.org/mclasen/2018/08/26/about-flatpak-installations/


Just some thoughts!

I hoffe du bist gut ins neue Jahr gekommen! :D

EDIT: I did miss a semicolon.