Including an override.xml file in shared-mime-info

I’m looking to include an shared-mime-info override.xml file in a nixos system, something that would be placed in

/usr/share/mime/packages

in a conventional structure.

I have

xdg.mime.enable = true

and see that

/run/current-system/sw/share/mime/packages

exists and contains symlinks to xml files (such as the freedesktop.org.xml). The override.xml should be in the same folder as the freedesktop.org.xml.

I see options in

https://github.com/NixOS/nixpkgs/blob/147d81d15594cd73f3ad38ae36dae09c1004292f/nixos/modules/config/xdg/mime.nix

to handle added/removed associations and feel that if there was an option to define an override.xml, it would be here. Also there’s:

https://github.com/NixOS/nixpkgs/blob/147d81d15594cd73f3ad38ae36dae09c1004292f/pkgs/data/misc/shared-mime-info/default.nix

but I’m not seeing where it says “Put freedesktop.org.xml in …/share/mime/packages”

I won’t be offended if you ELI5, I expect it might be needed :slight_smile:

The file gets linked there thanks to the following two options:

Simple way to insert your own file there is creating a single file package using writeTextFile and passing the result to environment.systemPackages.

Note that this method only works for packages that look for files in /run/current-system/sw like update-mime-database does. Most packages will search their own store paths so this is not a generally applicable technique.

So what I’ve ended up with is:

{ config, pkgs, ... }:

let
  overrideXml = pkgs.writeTextFile {
    name = "override.xml";
    destination = "/share/mime/packages/override.xml";
    text = ''
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
... all your override data ...
</mime-info>
'';
};

in {
  environment.systemPackages = [
    overrideXml
  ];
}

Which works for me. Very many thanks!

For completeness, and as it is perhaps a bit counterintuitive, you do need the leading slash in the:

destination = "/share/mime/packages/override.xml";

If you have:

destination = "share/mime/packages/override.xml";

you get an obtuse error:

error: builder for '/nix/store/q99l4nmyrinaf2nbvvwpa94r5kcgyndi-override.xml.drv' failed to produce output path for output 'out' at '/nix/store/q99l4nmyrinaf2nbvvwpa94r5kcgyndi-override.xml.drv.chroot/nix/store/spyiqabfk2rbzkl6nbpd3dpl9a8f5zyd-override.xml'

Most packages will search their own store paths so this is not a generally applicable technique.

Is there general way of doing this?

I notice you can create a file in /etc with “environment.etc”, and you get the file in /etc. You’ve got this method for /usr and the files appear under /run/current-system/sw. What happens, say, if you want a config file under /var/lib?

You can use systemd.tmpfiles option.

Just note that unlike stuff linked to /run/current-system/sw, it will not be changed atomically and it is no longer congruent management we love about NixOS – systemd.tmpfiles option delegates the file creation to systemd which will do it divergently at its leisure. If you later remove the option from your configuration and switch to system built from it, the file will not be removed because systemd loses track of it.

For completeness, environment.etc also modifies the file system outside of build (at activation time) but, thanks to its limited scope, it can do it somewhat congruently and mostly atomically.