lib.generators.toGitINI: performance improvements (#522818)

This commit is contained in:
adisbladis
2026-05-28 06:27:54 +00:00
committed by GitHub

View File

@@ -23,9 +23,12 @@
let
inherit (lib)
addErrorContext
any
assertMsg
attrNames
attrValues
concatLists
concatMap
concatMapStringsSep
concatStrings
concatStringsSep
@@ -52,6 +55,7 @@ let
isString
last
length
genAttrs
mapAttrs
mapAttrsToList
optionals
@@ -379,55 +383,69 @@ rec {
See the [git-config documentation](https://git-scm.com/docs/git-config#_variables) for possible values.
*/
toGitINI =
attrs:
let
mkSectionName =
let
containsQuote = hasInfix ''"'';
in
name:
let
containsQuote = hasInfix ''"'' name;
sections = splitString "." name;
section = head sections;
subsections = tail sections;
subsection = concatStringsSep "." subsections;
in
if containsQuote || subsections == [ ] then name else ''${section} "${subsection}"'';
if containsQuote name || length sections == 1 then
name
else
''${head sections} "${concatStringsSep "." (tail sections)}"'';
mkValueString =
v:
let
escapedV = ''"${replaceStrings [ "\n" " " ''"'' "\\" ] [ "\\n" "\\t" ''\"'' "\\\\" ] v}"'';
escape = replaceStrings [ "\n" " " ''"'' "\\" ] [ "\\n" "\\t" ''\"'' "\\\\" ];
in
mkValueStringDefault { } (if isString v then escapedV else v);
v: mkValueStringDefault { } (if isString v then ''"${escape v}"'' else v);
# generation for multiple ini values
mkKeyValue =
k: v:
let
mkKeyValue = mkKeyValueDefault { inherit mkValueString; } " = " k;
mkKeyValue = mkKeyValueDefault { inherit mkValueString; } " = ";
attrToString = k: v: "\t" + mkKeyValue k v;
in
concatStringsSep "\n" (map (kv: "\t" + mkKeyValue kv) (toList v));
k: v: if isList v then concatStringsSep "\n" (map (attrToString k) v) else attrToString k v;
# converts { a.b.c = 5; } to { "a.b".c = 5; } for toINI
gitFlattenAttrs =
let
isNonDrvAttrs = value: isAttrs value && !isDerivation value;
recurse =
path: value:
if isAttrs value && !isDerivation value then
mapAttrsToList (name: value: recurse ([ name ] ++ path) value) value
if isNonDrvAttrs value then
concatMap (name: recurse ([ name ] ++ path) value.${name}) (attrNames value)
else if length path > 1 then
{
${concatStringsSep "." (reverseList (tail path))}.${head path} = value;
}
[
{
${concatStringsSep "." (reverseList (tail path))}.${head path} = value;
}
]
else
{
${head path} = value;
};
[
{
${head path} = value;
}
];
in
attrs: foldl recursiveUpdate { } (flatten (recurse [ ] attrs));
attrs:
let
# Filter the names for any that contain nested attrsets. attrs that
# don't contain nested attrsets can stay the same =
namesToRewrite = filter (
name: isAttrs attrs.${name} && any isNonDrvAttrs (attrValues attrs.${name})
) (attrNames attrs);
attrsToRewrite = genAttrs namesToRewrite (name: attrs.${name});
in
removeAttrs attrs namesToRewrite // foldl recursiveUpdate { } (recurse [ ] attrsToRewrite);
toINI_ = toINI { inherit mkKeyValue mkSectionName; };
in
toINI_ (gitFlattenAttrs attrs);
attrs: toINI_ (gitFlattenAttrs attrs);
/**
`mkKeyValueDefault` wrapper that handles dconf INI quirks.