-
-
Save grahamc/29cead72119d86c50ea43ea3746814ec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let | |
isDerivation = set: (set.type or "") == "derivation"; | |
callableWithEmptyAttrset = fn: | |
let | |
args = builtins.functionArgs fn; | |
defaultValueList = builtins.attrValues args; | |
in if args == { } | |
then false # plain lambda: «x: x» | |
else builtins.all (x: x) defaultValueList; | |
ofborgTypeOf = e: | |
let | |
nixType = builtins.typeOf e; | |
typeDescriptionHandler = { | |
# Primitive types first | |
int = _: "int"; | |
float = _: "float"; | |
bool = _: "bool"; | |
string = _: "string"; | |
path = _: "path"; | |
"null" = _: "null"; | |
# Fancy types | |
list = _: "list"; | |
set = set: | |
if isDerivation set | |
then "derivation" | |
else "set"; | |
lambda = fn: | |
if callableWithEmptyAttrset fn | |
then "callable" | |
else "lambda"; | |
mystery = x: assert builtins.trace "mystery type ${builtins.typeOf x}" false; null; | |
}; | |
in (typeDescriptionHandler."${nixType}" or typeDescriptionHandler.mystery) e; | |
makeReferrableAttrSet = e: | |
let | |
ofborgType = ofborgTypeOf e; | |
typeRecurser = let | |
id = x: x; | |
in { | |
int = id; | |
float = id; | |
bool = id; | |
string = id; | |
path = id; | |
"null" = id; | |
derivation = id; | |
lambda = id; | |
callable = lambda: lambda {}; | |
set = set: builtins.mapAttrs | |
(_: value: makeReferrableAttrSet value) | |
set; | |
list = list: (builtins.foldl' | |
({ counter, collector}: item: { | |
counter = counter + 1; | |
collector = collector // { | |
"${toString counter}" = makeReferrableAttrSet item; | |
}; | |
}) | |
{ counter = 0; collector = {};} | |
list).collector; | |
mystery = x: assert builtins.trace "mystery type ${ofborgType}" false; null; | |
}; | |
in (typeRecurser."${ofborgType}" or typeRecurser.mystery) e; | |
flattenReferrableAttrSet = attrs: let | |
withPrefix = prefix: attrset: | |
builtins.foldl' | |
(collector: name: | |
let | |
value = attrset."${name}"; | |
subPrefix = prefix ++ [name]; | |
in collector ++ (if (ofborgTypeOf value) == "set" | |
then withPrefix subPrefix value | |
else [[ subPrefix value ]] | |
)) | |
[] | |
(builtins.attrNames attrset); | |
labeledList = withPrefix [] attrs; | |
in builtins.foldl' | |
(collector: elem: let | |
nameElems = builtins.head elem; | |
value = builtins.head (builtins.tail elem); | |
name = builtins.concatStringsSep "." nameElems; | |
in collector // { "${name}" = value;}) | |
{} | |
labeledList; | |
flattenStructure = e: let | |
data = (makeReferrableAttrSet e); | |
in if (ofborgTypeOf data) == "set" | |
then flattenReferrableAttrSet data | |
else "bare"; | |
assertTrue = v: assert v; "ok"; | |
assertFalse = v: assert !v; "ok"; | |
assertEq = a: b: if a == b | |
then "ok" | |
else assert builtins.trace "a:" ( | |
builtins.trace (builtins.deepSeq a a) ( | |
builtins.trace "does not equal b:" ( | |
builtins.trace (builtins.deepSeq b b) false | |
) | |
) | |
); null; | |
in { | |
export = { | |
inherit flattenStructure; | |
}; | |
tests = let | |
drv = name: derivation { | |
inherit name; | |
builder = ./ofborg.lib.nix; | |
system = "bogus"; | |
}; | |
in { | |
is-derivation-int = assertFalse (isDerivation 1); | |
is-derivation = assertTrue (isDerivation (derivation { })); | |
is-derivation-attrset = assertFalse (isDerivation { }); | |
callable-attrset = assertFalse (callableWithEmptyAttrset ({ a }: a)); | |
callable-attrset-default = assertTrue (callableWithEmptyAttrset ({ a ? true }: a)); | |
callable-attrset-many = assertFalse (callableWithEmptyAttrset ({ a ? true, b }: a)); | |
callable-attrset-many-default = assertTrue (callableWithEmptyAttrset ({ a ? true, b ? true }: a)); | |
callable-attrset-hides-plain = assertTrue (callableWithEmptyAttrset ({ a ? true }: (x: a))); | |
callable-plain = assertFalse (callableWithEmptyAttrset (x: x)); | |
ofborgTypeOf-int = assertEq "int" (ofborgTypeOf 1); | |
ofborgTypeOf-float = assertEq "float" (ofborgTypeOf 1.1); | |
ofborgTypeOf-bool-true = assertEq "bool" (ofborgTypeOf true); | |
ofborgTypeOf-bool-false = assertEq "bool" (ofborgTypeOf false); | |
ofborgTypeOf-string = assertEq "string" (ofborgTypeOf "hello"); | |
ofborgTypeOf-string-path = assertEq "string" (ofborgTypeOf (builtins.toString ./.)); | |
ofborgTypeOf-path = assertEq "path" (ofborgTypeOf ./.); | |
#ofborgTypeOf-path-coerced = assertEq "path" (ofborgTypeOf (builtins.toPath "/")); | |
ofborgTypeOf-null = assertEq "null" (ofborgTypeOf null); | |
ofborgTypeOf-list = assertEq "list" (ofborgTypeOf [1 2 3]); | |
ofborgTypeOf-derivation = assertEq "derivation" (ofborgTypeOf (derivation { })); | |
ofborgTypeOf-set = assertEq "set" (ofborgTypeOf { }); | |
ofborgTypeOf-set-with-type = assertEq "set" (ofborgTypeOf { type = "hi"; }); | |
ofborgTypeOf-callable = assertEq "callable" (ofborgTypeOf ({ a ? true}: a)); | |
ofborgTypeOf-lambda = assertEq "lambda" (ofborgTypeOf ({ a }: a)); | |
ofborgTypeOf-lambda-plain = assertEq "lambda" (ofborgTypeOf (a: a)); | |
makeReferrableAttrSet-int = assertEq | |
1 | |
(makeReferrableAttrSet 1); | |
makeReferrableAttrSet-float = assertEq | |
1.1 | |
(makeReferrableAttrSet 1.1); | |
makeReferrableAttrSet-bool = assertEq | |
true | |
(makeReferrableAttrSet true); | |
makeReferrableAttrSet-string = assertEq | |
"hi" | |
(makeReferrableAttrSet "hi"); | |
makeReferrableAttrSet-path= assertEq | |
./. | |
(makeReferrableAttrSet ./.); | |
makeReferrableAttrSet-null= assertEq | |
null | |
(makeReferrableAttrSet null); | |
makeReferrableAttrSet-derivation = assertEq | |
(drv "bogus") | |
(makeReferrableAttrSet (drv "bogus")); | |
makeReferrableAttrSet-list = assertEq | |
{ | |
"0" = drv "bogus-0"; | |
"1" = drv "bogus-1"; | |
} | |
(makeReferrableAttrSet [ | |
(drv "bogus-0") | |
(drv "bogus-1") | |
]); | |
makeReferrableAttrSet-attrset = assertEq | |
{ a = "hi"; } | |
(makeReferrableAttrSet { a = "hi"; }); | |
/* lambdas aren't comparable :) | |
makeReferrableAttrSet-lambda-plain = let | |
lamb = x: x; | |
in assertEq | |
lamb | |
(makeReferrableAttrSet lamb); | |
*/ | |
makeReferrableAttrSet-lambda = let | |
lamb = { x ? true }: x; | |
in assertEq | |
true | |
(makeReferrableAttrSet lamb); | |
makeReferrableAttrSet-recursive = assertEq | |
{ | |
"a" = { | |
"0" = null; | |
"1" = { | |
"a" = { | |
"0" = "hello"; | |
"1" = { | |
"0" = "hi"; | |
"1" = "there"; | |
}; | |
}; | |
"b" = { | |
"2" = { | |
"foobar" = { | |
"baz" = "hello"; | |
}; | |
}; | |
}; | |
}; | |
}; | |
} | |
(makeReferrableAttrSet { | |
a = [ | |
null | |
{ | |
"a" = [ | |
"hello" | |
[ "hi" "there" ] | |
]; | |
"b" = { | |
"2" = { | |
"foobar" = { | |
"baz" = "hello"; | |
}; | |
}; | |
}; | |
} | |
]; | |
}); | |
flattenReferrableAttrSet-simple = assertEq | |
{ "a.b" = true; "a.c" = false; } | |
(flattenReferrableAttrSet { a = { b = true; c = false; }; }); | |
flattenReferrableAttrSet-recursive = assertEq | |
{ | |
"a.0" = null; | |
"a.1.a.0" = "hello"; | |
"a.1.a.1.0" = "hi"; | |
"a.1.a.1.1" = "there"; | |
"a.1.b.2.foobar.baz" = "hello"; | |
} | |
(flattenReferrableAttrSet | |
{ | |
"a" = { | |
"0" = null; | |
"1" = { | |
"a" = { | |
"0" = "hello"; | |
"1" = { | |
"0" = "hi"; | |
"1" = "there"; | |
}; | |
}; | |
"b" = { | |
"2" = { | |
"foobar" = { | |
"baz" = "hello"; | |
}; | |
}; | |
}; | |
}; | |
}; | |
} | |
); | |
flattenStructure-elaborate = assertEq | |
{ | |
"a.0" = null; | |
"a.1.a.0" = "hello"; | |
"a.1.a.1.0" = "hi"; | |
"a.1.a.1.1" = "there"; | |
"a.1.b.2.foobar.baz" = "hello"; | |
} | |
(flattenStructure { | |
a = [ | |
null | |
{ | |
"a" = [ | |
"hello" | |
[ "hi" "there" ] | |
]; | |
"b" = { | |
"2" = { x ? true}: { | |
"foobar" = { | |
"baz" = "hello"; | |
}; | |
}; | |
}; | |
} | |
]; | |
}); | |
flattenStructure-simple = assertEq | |
"bare" | |
(flattenStructure "hi"); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment