lol

nixos.minetest-server: Add option for generating config file and ability to add extra command line flags

This adds two main features:

1. `services.minetest-server.config` is an options object that is automatically serialized into a minetest config file.
2. `services.minetest-server.extraArgs` provides an escape hatch to pass extra arguments.

+63 -8
+63 -8
nixos/modules/services/games/minetest-server.nix
··· 3 3 with lib; 4 4 5 5 let 6 + CONTAINS_NEWLINE_RE = ".*\n.*"; 7 + # The following values are reserved as complete option values: 8 + # { - start of a group. 9 + # """ - start of a multi-line string. 10 + RESERVED_VALUE_RE = "[[:space:]]*(\"\"\"|\\{)[[:space:]]*"; 11 + NEEDS_MULTILINE_RE = "${CONTAINS_NEWLINE_RE}|${RESERVED_VALUE_RE}"; 12 + 13 + # There is no way to encode """ on its own line in a Minetest config. 14 + UNESCAPABLE_RE = ".*\n\"\"\"\n.*"; 15 + 16 + toConfMultiline = name: value: 17 + assert lib.assertMsg 18 + ((builtins.match UNESCAPABLE_RE value) == null) 19 + ''""" can't be on its own line in a minetest config.''; 20 + "${name} = \"\"\"\n${value}\n\"\"\"\n"; 21 + 22 + toConf = values: 23 + lib.concatStrings 24 + (lib.mapAttrsToList 25 + (name: value: { 26 + bool = "${name} = ${toString value}\n"; 27 + int = "${name} = ${toString value}\n"; 28 + null = ""; 29 + set = "${name} = {\n${toConf value}}\n"; 30 + string = 31 + if (builtins.match NEEDS_MULTILINE_RE value) != null 32 + then toConfMultiline name value 33 + else "${name} = ${value}\n"; 34 + }.${builtins.typeOf value}) 35 + values); 36 + 6 37 cfg = config.services.minetest-server; 7 - flag = val: name: optionalString (val != null) "--${name} ${toString val} "; 38 + flag = val: name: lib.optionals (val != null) ["--${name}" "${toString val}"]; 39 + 8 40 flags = [ 9 - (flag cfg.gameId "gameid") 10 - (flag cfg.world "world") 11 - (flag cfg.configPath "config") 12 - (flag cfg.logPath "logfile") 13 - (flag cfg.port "port") 14 - ]; 41 + "--server" 42 + ] 43 + ++ ( 44 + if cfg.configPath != null 45 + then ["--config" cfg.configPath] 46 + else ["--config" (builtins.toFile "minetest.conf" (toConf cfg.config))]) 47 + ++ (flag cfg.gameId "gameid") 48 + ++ (flag cfg.world "world") 49 + ++ (flag cfg.logPath "logfile") 50 + ++ (flag cfg.port "port") 51 + ++ cfg.extraArgs; 15 52 in 16 53 { 17 54 options = { ··· 55 92 ''; 56 93 }; 57 94 95 + config = mkOption { 96 + type = types.attrsOf types.anything; 97 + default = {}; 98 + description = lib.mdDoc '' 99 + Settings to add to the minetest config file. 100 + 101 + This option is ignored if `configPath` is set. 102 + ''; 103 + }; 104 + 58 105 logPath = mkOption { 59 106 type = types.nullOr types.path; 60 107 default = null; ··· 75 122 If set to null, the default 30000 will be used. 76 123 ''; 77 124 }; 125 + 126 + extraArgs = mkOption { 127 + type = types.listOf types.str; 128 + default = []; 129 + description = lib.mdDoc '' 130 + Additional command line flags to pass to the minetest executable. 131 + ''; 132 + }; 78 133 }; 79 134 }; 80 135 ··· 100 155 script = '' 101 156 cd /var/lib/minetest 102 157 103 - exec ${pkgs.minetest}/bin/minetest --server ${concatStrings flags} 158 + exec ${pkgs.minetest}/bin/minetest ${lib.escapeShellArgs flags} 104 159 ''; 105 160 }; 106 161 };