···
cfg = config.programs.dconf;
+
# Compile keyfiles to dconf DB
+
compileDconfDb = dir: pkgs.runCommand "dconf-db"
+
nativeBuildInputs = [ (lib.getBin pkgs.dconf) ];
+
} "dconf compile $out ${dir}";
+
# Check if dconf keyfiles are valid
+
checkDconfKeyfiles = dir: pkgs.runCommand "check-dconf-keyfiles"
+
nativeBuildInputs = [ (lib.getBin pkgs.dconf) ];
+
if [[ -f ${dir} ]]; then
+
echo "dconf keyfiles should be a directory but a file is provided: ${dir}"
+
dconf compile db ${dir} || (
+
echo "The dconf keyfiles are invalid: ${dir}"
+
# Generate dconf DB from dconfDatabase and keyfiles
+
mkDconfDb = val: compileDconfDb (pkgs.symlinkJoin {
+
name = "nixos-generated-dconf-keyfiles";
+
(pkgs.writeTextDir "nixos-generated-dconf-keyfiles" (lib.generators.toDconfINI val.settings))
+
] ++ (map checkDconfKeyfiles val.keyfiles);
+
# Check if a dconf DB file is valid. The dconf cli doesn't return 1 when it can't
+
# open the database file so we have to check if the output is empty.
+
checkDconfDb = file: pkgs.runCommand "check-dconf-db"
+
nativeBuildInputs = [ (lib.getBin pkgs.dconf) ];
+
if [[ -d ${file} ]]; then
+
echo "dconf DB should be a file but a directory is provided: ${file}"
+
echo "file-db:${file}" > profile
+
DCONF_PROFILE=$(pwd)/profile dconf dump / > output 2> error
+
if [[ ! -s output ]] && [[ -s error ]]; then
+
echo "The dconf DB file is invalid: ${file}"
mkDconfProfile = name: value:
+
if lib.isDerivation value || lib.isPath value then
+
pkgs.runCommand "dconf-profile" { } ''
+
if [[ -d ${value} ]]; then
+
echo "Dconf profile should be a file but a directory is provided."
+
mkdir -p $out/etc/dconf/profile/
+
cp ${value} $out/etc/dconf/profile/${name}
+
pkgs.writeTextDir "etc/dconf/profile/${name}" (
+
lib.concatMapStrings (x: "${x}\n") ((
+
lib.optional value.enableUserDb "user-db:user"
+
db = if lib.isAttrs value && !lib.isDerivation value then mkDconfDb value else checkDconfDb value;
+
dconfDatabase = with lib.types; submodule {
+
keyfiles = lib.mkOption {
+
type = listOf (oneOf [ path package ]);
+
description = lib.mdDoc "A list of dconf keyfile directories.";
+
settings = lib.mkOption {
+
description = lib.mdDoc "An attrset used to generate dconf keyfile.";
+
example = literalExpression ''
+
"com/raggesilver/BlackBox" = {
+
scrollback-lines = mkUint32 10000;
+
theme-dark = "Tommorow Night";
+
dconfProfile = with lib.types; submodule {
+
enableUserDb = lib.mkOption {
+
description = lib.mdDoc "Add `user-db:user` at the beginning of the profile.";
+
databases = lib.mkOption {
+
type = with lib.types; listOf (oneOf [
+
description = lib.mdDoc ''
+
List of data sources for the profile. An element can be an attrset,
+
or the path of an already compiled database. Each element is converted
+
A key is searched from up to down and the first result takes the
+
priority. If a lock for a particular key is installed then the value from
+
the last database in the profile where the key is locked will be used.
+
This can be used to enforce mandatory settings.
···
type = with lib.types; attrsOf (oneOf [
+
description = lib.mdDoc ''
+
Attrset of dconf profiles. By default the `user` profile is used which
+
ends up in `/etc/dconf/profile/user`.
+
example = lib.literalExpression ''
+
# A "user" profile with a database
+
# A "bar" profile from a package
+
bar = pkgs.bar-dconf-profile;
+
# A "foo" profile from a path
packages = lib.mkOption {