diff --git a/flake.nix b/flake.nix index 7bcd35b..4a21110 100644 --- a/flake.nix +++ b/flake.nix @@ -12,8 +12,6 @@ outputs = { self - , nixpkgs - , nix-darwin , flake-parts , ... }@inputs: @@ -26,7 +24,7 @@ perSystem = { pkgs, system, ... }: let tests = import ./tests/setup.nix { - inherit pkgs inputs system; + inherit self pkgs inputs system; }; docs = import ./docs { diff --git a/modules/_impl.nix b/modules/_impl.nix index e3c86ff..f581770 100644 --- a/modules/_impl.nix +++ b/modules/_impl.nix @@ -1,58 +1,28 @@ -{ pkgs, lib, ... }: +{ config, lib, ... }: let - writePlist = configuration: with lib; + purgePlist = defaults: let - # We can only serialize values that are not null to *.plist files - # The rest will be mapped to deletion commands - writable = conf: - filterAttrs - (domain: attrs: attrs != { }) - (mapAttrs - (domain: attrs: - (filterAttrs (n: v: v != null) attrs)) - conf); - deletable = conf: - mapAttrs + lib.mapAttrs (domain: attrs: - (filterAttrs (n: v: v == null) attrs)) - conf; - - toPlist = domain: attrs: - pkgs.writeText "${domain}.plist" (generators.toPlist { } attrs); - - importAttrs = conf: - mapAttrsToList - (domain: attrs: '' - /usr/bin/defaults import '${ - escapeShellArg domain - }' ${toPlist domain attrs} - '') + (lib.filterAttrs (n: v: v == null) attrs)) conf; deleteAttrs = conf: - flatten ( - mapAttrsToList + lib.flatten ( + lib.mapAttrsToList (domain: attrs: - mapAttrsToList + lib.mapAttrsToList (key: _value: '' /usr/bin/defaults delete '${ - escapeShellArg domain - }' '${escapeShellArg key}' &> /dev/null || true + lib.escapeShellArg domain + }' '${lib.escapeShellArg key}' &> /dev/null || true '') attrs) conf); in - concatLines ( - (importAttrs (writable configuration)) ++ - (deleteAttrs (deletable configuration)) - ); - - reload = '' - # Reload settings - /System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u - ''; + lib.concatLines (deleteAttrs (deletable defaults)); in { @@ -67,15 +37,29 @@ in str ])) ); + description = '' + Holds all user defaults assignment made by plist-manager. Its value gets + assigned to either nix-darwin's `system.defaults.*` or home-manager's + `targets.darwin.default.*`. + ''; default = { }; internal = true; visible = false; - apply = value: '' - set -e + }; - ${writePlist value} - ${reload} + purgeScript = mkOption { + type = types.lines; + description = '' + A script to purge all the unset user defaults. This won't be taken care + of by default by either nix-darwin or home-manager ''; + default = ""; + internal = true; + visible = false; }; }; + + config = { + plist.purgeScript = purgePlist config.plist.out; + }; } diff --git a/targets/darwin.nix b/targets/darwin.nix index fe18b2a..8b8dce8 100644 --- a/targets/darwin.nix +++ b/targets/darwin.nix @@ -1,18 +1,18 @@ -{ config, pkgs, ... }: - -let - script = pkgs.writeShellScript "plist-darwin-activate" config.plist.out; - fail = msg: "(printf '\\033[0;31m${msg}\\033[0m\n' && exit 1)"; -in +{ config, ... }: { imports = [ ../modules ]; + system.defaults.CustomUserPreferences = config.plist.out; + system.activationScripts.postActivation.text = '' echo "Activating plistManager" - echo "└── Using ${script}" - ${script} || ${fail "Failed to run ${script}"} + + ${config.plist.purgeScript} + + # Reload settings + /System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u ''; } diff --git a/targets/home-manager.nix b/targets/home-manager.nix index 7fdadd9..f7ad0b6 100644 --- a/targets/home-manager.nix +++ b/targets/home-manager.nix @@ -1,17 +1,17 @@ -{ config, pkgs, lib, ... }: - -let - script = pkgs.writeShellScript "plist-home-activate" config.plist.out; - fail = msg: "(printf '\\033[0;31m${msg}\\033[0m\n' && exit 1)"; -in +{ config, lib, ... }: { imports = [ ../modules ]; + targets.darwin.defaults = config.plist.out; + home.activation.plistManager = lib.hm.dag.entryAfter [ "setDarwinDefaults" ] '' - echo "└── Using ${script}" - run ${script} || ${fail "Failed to run ${script}"} + set -e + ${config.plist.purgeScript} + + # Reload settings + /System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u ''; } diff --git a/tests/setup.nix b/tests/setup.nix index 1b30064..e54f1d4 100644 --- a/tests/setup.nix +++ b/tests/setup.nix @@ -1,11 +1,12 @@ -{ pkgs +{ self +, pkgs , inputs , system }: -let - lib = pkgs.lib; +with pkgs.lib; +let buildFromConfig = configuration: sel: sel (import inputs.nix-darwin { inherit (inputs) nixpkgs; @@ -19,15 +20,23 @@ let makeTest = name: test: let configuration = - { config, pkgs, lib, ... }: + { config, pkgs, ... }: + + let + defaults = builtins.toJSON + config.system.defaults.CustomUserPreferences; + + purgeScript = config.plist.purgeScript; + in + { imports = [ - ../modules/_impl.nix + self.darwinModules.default test ]; - options.test = lib.mkOption { - type = lib.types.lines; + options.test = mkOption { + type = types.lines; }; config = { @@ -37,20 +46,17 @@ let { nativeBuildInputs = with pkgs; [ jq - jc - ripgrep ]; } '' set -e - echo ${lib.escapeShellArg config.plist.out} > $out + mkdir -p $out + echo ${escapeShellArg defaults} > $out/defaults.json + echo ${escapeShellArg purgeScript} > $out/purge.sh # Holds domain context d="" - # Holds path to the plist file for the domain (if any) - f="" - function Domain { if [[ -n "$d" ]]; then echo "Domain end" @@ -60,20 +66,10 @@ let echo "" echo "Domain start: '$d'" - - f=$(rg -PNo "'$d' (/nix/.*plist)" $out -r '$1' || echo None) - echo "Imports -> $f" } function Set { - if ! test -e "$f"; then - echo "" - echo "Assertion failed for '$1'. No imports to domain '$d'" - echo "" - exit 1 - fi - - v=$(cat $f | jc --plist | jq ".\"$1\"") + v=$(cat $out/defaults.json | jq ".\"$d\".\"$1\"") if [[ "$v" != "$2" ]]; then echo "" @@ -87,20 +83,20 @@ let echo "" echo "Full output:" echo "" - cat $out | sed 's/^/ /' + jq . $out/defaults.json | sed 's/^/ /' echo "" exit 1 fi } function Del { - if ! grep -q "defaults delete '$d' '$1'" $out; then + if ! grep -q "defaults delete '$d' '$1'" $out/purge.sh; then echo "" echo "Expected attribute '$d'.'$1' to be deleted." echo "" echo "Actual output:" echo "" - cat $out | sed 's/^/ /' + cat $out/purge.sh | sed 's/^/ /' echo "" exit 1 fi @@ -115,10 +111,10 @@ let buildFromConfig configuration (config: config.system.build.run-test); in -lib.listToAttrs (map +listToAttrs (map (file: rec { name = testName file; value = makeTest name file; }) - (lib.fileset.toList - (lib.fileset.fileFilter (file: lib.hasPrefix "test-" file.name) ./.))) + (fileset.toList + (fileset.fileFilter (file: hasPrefix "test-" file.name) ./.)))