diff --git a/modules/programs/git.nix b/modules/programs/git.nix index 2ab84b5a1..16db07d9a 100644 --- a/modules/programs/git.nix +++ b/modules/programs/git.nix @@ -6,6 +6,19 @@ let cfg = config.programs.git; + # create [section "subsection"] keys from "section.subsection" attrset names + mkSectionName = name: + let + containsQuote = strings.hasInfix ''"'' name; + sections = splitString "." name; + section = head sections; + subsections = tail sections; + subsection = concatStringsSep "." subsections; + in + if containsQuote || subsections == [] + then name + else "${section} \"${subsection}\""; + # generation for multiple ini values mkKeyValue = k: v: let @@ -13,15 +26,33 @@ let in concatStringsSep "\n" (map mkKeyValue (toList v)); - gitToIni = generators.toINI { inherit mkKeyValue; }; + # converts { a.b.c = 5; } to { "a.b".c = 5; } for toINI + gitFlattenAttrs = + let + recurse = path: value: + if isAttrs value then + mapAttrsToList (name: value: recurse ([name] ++ path) value) value + else if length path > 1 then + { ${concatStringsSep "." (reverseList (tail path))}.${head path} = value; } + else + { ${head path} = value; }; + in + attrs: foldl recursiveUpdate {} (flatten (recurse [] attrs)); + + gitToIni = attrs: + let + toIni = generators.toINI { inherit mkKeyValue mkSectionName; }; + in + toIni (gitFlattenAttrs attrs); gitIniType = with types; let primitiveType = either str (either bool int); multipleType = either primitiveType (listOf primitiveType); sectionType = attrsOf multipleType; + supersectionType = attrsOf (either multipleType sectionType); in - attrsOf sectionType; + attrsOf supersectionType; signModule = types.submodule { options = { @@ -128,6 +159,7 @@ in default = {}; example = { core = { whitespace = "trailing-space,space-before-tab"; }; + url."ssh://git@host".insteadOf = "otherhost"; }; description = "Additional configuration to add."; }; @@ -200,7 +232,7 @@ in hasSmtp = name: account: account.smtp != null; genIdentity = name: account: with account; - nameValuePair "sendemail \"${name}\"" ({ + nameValuePair "sendemail.${name}" ({ smtpEncryption = if smtp.tls.enable then "tls" else ""; smtpServer = smtp.host; smtpUser = userName; @@ -235,19 +267,23 @@ in }) (mkIf (cfg.includes != []) { - xdg.configFile."git/config".text = mkAfter - (concatMapStringsSep "\n" - (i: with i; '' - [${if (condition == null) then "include" else "includeIf \"${condition}\""}] - path = ${path} - '') - cfg.includes); + xdg.configFile."git/config".text = + let + include = i: with i; + if condition != null + then { includeIf.${condition}.path = "${path}"; } + else { include.path = "${path}"; }; + in + mkAfter + (concatStringsSep "\n" + (map gitToIni + (map include cfg.includes))); }) (mkIf cfg.lfs.enable { home.packages = [ pkgs.git-lfs ]; - programs.git.iniContent."filter \"lfs\"" = + programs.git.iniContent.filter.lfs = let skipArg = optional cfg.lfs.skipSmudge "--skip"; in diff --git a/tests/modules/programs/git-expected.conf b/tests/modules/programs/git-expected.conf index ba4a362e4..d02ebf316 100644 --- a/tests/modules/programs/git-expected.conf +++ b/tests/modules/programs/git-expected.conf @@ -12,6 +12,12 @@ multiple=1 multiple=2 name=value +[extra "backcompat.with.dots"] +previously=worked + +[extra "subsection"] +value=test + [filter "lfs"] clean=git-lfs clean -- %f process=git-lfs filter-process @@ -27,10 +33,10 @@ name=John Doe signingKey=00112233445566778899AABBCCDDEEFF [include] -path = ~/path/to/config.inc +path=~/path/to/config.inc [includeIf "gitdir:~/src/dir"] -path = ~/path/to/conditional.inc +path=~/path/to/conditional.inc [includeIf "gitdir:~/src/dir"] -path = @git_include_path@ +path=@git_include_path@ diff --git a/tests/modules/programs/git.nix b/tests/modules/programs/git.nix index 771c909a5..c5203e417 100644 --- a/tests/modules/programs/git.nix +++ b/tests/modules/programs/git.nix @@ -58,9 +58,11 @@ in { aliases.a2 = mkForce "baz"; + extraConfig."extra \"backcompat.with.dots\"".previously = "worked"; extraConfig.extra.boolean = true; extraConfig.extra.integer = 38; extraConfig.extra.multiple = [2]; + extraConfig.extra.subsection.value = "test"; } ];