mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 21:50:33 +03:00
nixos/dconf: add settings support
This commit is contained in:
parent
cce75fa51e
commit
fb52d5df86
2 changed files with 158 additions and 5 deletions
|
@ -230,6 +230,14 @@ rec {
|
||||||
in
|
in
|
||||||
toINI_ (gitFlattenAttrs attrs);
|
toINI_ (gitFlattenAttrs attrs);
|
||||||
|
|
||||||
|
# mkKeyValueDefault wrapper that handles dconf INI quirks.
|
||||||
|
# The main differences of the format is that it requires strings to be quoted.
|
||||||
|
mkDconfKeyValue = mkKeyValueDefault { mkValueString = v: toString (lib.gvariant.mkValue v); } "=";
|
||||||
|
|
||||||
|
# Generates INI in dconf keyfile style. See https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en
|
||||||
|
# for details.
|
||||||
|
toDconfINI = toINI { mkKeyValue = mkDconfKeyValue; };
|
||||||
|
|
||||||
/* Generates JSON from an arbitrary (non-function) value.
|
/* Generates JSON from an arbitrary (non-function) value.
|
||||||
* For more information see the documentation of the builtin.
|
* For more information see the documentation of the builtin.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,12 +3,138 @@
|
||||||
let
|
let
|
||||||
cfg = config.programs.dconf;
|
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}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dconf compile db ${dir} || (
|
||||||
|
echo "The dconf keyfiles are invalid: ${dir}"
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
cp -R ${dir} $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Generate dconf DB from dconfDatabase and keyfiles
|
||||||
|
mkDconfDb = val: compileDconfDb (pkgs.symlinkJoin {
|
||||||
|
name = "nixos-generated-dconf-keyfiles";
|
||||||
|
paths = [
|
||||||
|
(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}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "file-db:${file}" > profile
|
||||||
|
DCONF_PROFILE=$(pwd)/profile dconf dump / > output 2> error
|
||||||
|
if [[ ! -s output ]] && [[ -s error ]]; then
|
||||||
|
cat error
|
||||||
|
echo "The dconf DB file is invalid: ${file}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp ${file} $out
|
||||||
|
'';
|
||||||
|
|
||||||
# Generate dconf profile
|
# Generate dconf profile
|
||||||
mkDconfProfile = name: value:
|
mkDconfProfile = name: value:
|
||||||
pkgs.runCommand "dconf-profile" { } ''
|
if lib.isDerivation value || lib.isPath value then
|
||||||
mkdir -p $out/etc/dconf/profile/
|
pkgs.runCommand "dconf-profile" { } ''
|
||||||
cp ${value} $out/etc/dconf/profile/${name}
|
if [[ -d ${value} ]]; then
|
||||||
'';
|
echo "Dconf profile should be a file but a directory is provided."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p $out/etc/dconf/profile/
|
||||||
|
cp ${value} $out/etc/dconf/profile/${name}
|
||||||
|
''
|
||||||
|
else
|
||||||
|
pkgs.writeTextDir "etc/dconf/profile/${name}" (
|
||||||
|
lib.concatMapStrings (x: "${x}\n") ((
|
||||||
|
lib.optional value.enableUserDb "user-db:user"
|
||||||
|
) ++ (
|
||||||
|
map
|
||||||
|
(value:
|
||||||
|
let
|
||||||
|
db = if lib.isAttrs value && !lib.isDerivation value then mkDconfDb value else checkDconfDb value;
|
||||||
|
in
|
||||||
|
"file-db:${db}")
|
||||||
|
value.databases
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
dconfDatabase = with lib.types; submodule {
|
||||||
|
options = {
|
||||||
|
keyfiles = lib.mkOption {
|
||||||
|
type = listOf (oneOf [ path package ]);
|
||||||
|
default = [ ];
|
||||||
|
description = lib.mdDoc "A list of dconf keyfile directories.";
|
||||||
|
};
|
||||||
|
settings = lib.mkOption {
|
||||||
|
type = attrs;
|
||||||
|
default = { };
|
||||||
|
description = lib.mdDoc "An attrset used to generate dconf keyfile.";
|
||||||
|
example = literalExpression ''
|
||||||
|
with lib.gvariant;
|
||||||
|
{
|
||||||
|
"com/raggesilver/BlackBox" = {
|
||||||
|
scrollback-lines = mkUint32 10000;
|
||||||
|
theme-dark = "Tommorow Night";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dconfProfile = with lib.types; submodule {
|
||||||
|
options = {
|
||||||
|
enableUserDb = lib.mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = lib.mdDoc "Add `user-db:user` at the beginning of the profile.";
|
||||||
|
};
|
||||||
|
|
||||||
|
databases = lib.mkOption {
|
||||||
|
type = with lib.types; listOf (oneOf [
|
||||||
|
path
|
||||||
|
package
|
||||||
|
dconfDatabase
|
||||||
|
]);
|
||||||
|
default = [ ];
|
||||||
|
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
|
||||||
|
to a file-db.
|
||||||
|
|
||||||
|
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.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
|
@ -19,8 +145,27 @@ in
|
||||||
type = with lib.types; attrsOf (oneOf [
|
type = with lib.types; attrsOf (oneOf [
|
||||||
path
|
path
|
||||||
package
|
package
|
||||||
|
dconfProfile
|
||||||
]);
|
]);
|
||||||
description = lib.mdDoc "Attrset of dconf profiles.";
|
default = { };
|
||||||
|
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
|
||||||
|
user.databases = [
|
||||||
|
{
|
||||||
|
settings = { };
|
||||||
|
}
|
||||||
|
];
|
||||||
|
# A "bar" profile from a package
|
||||||
|
bar = pkgs.bar-dconf-profile;
|
||||||
|
# A "foo" profile from a path
|
||||||
|
foo = ''${./foo}
|
||||||
|
};
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = lib.mkOption {
|
packages = lib.mkOption {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue