style: format entire depot with nixpkgs-fmt

This CL can be used to compare the style of nixpkgs-fmt against other
formatters (nixpkgs, alejandra).

Change-Id: I87c6abff6bcb546b02ead15ad0405f81e01b6d9e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/4397
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: lukegb <lukegb@tvl.fyi>
Reviewed-by: wpcarro <wpcarro@gmail.com>
Reviewed-by: Profpatsch <mail@profpatsch.de>
Reviewed-by: kanepyork <rikingcoding@gmail.com>
Reviewed-by: tazjin <tazjin@tvl.su>
Reviewed-by: cynthia <cynthia@tvl.fyi>
Reviewed-by: edef <edef@edef.eu>
Reviewed-by: eta <tvl@eta.st>
Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
Vincent Ambo 2022-01-30 19:06:58 +03:00 committed by tazjin
parent 2d10d60fac
commit aa122cbae7
310 changed files with 7278 additions and 5490 deletions

View file

@ -36,4 +36,4 @@ let
];
};
in
clhs-lookup
clhs-lookup

View file

@ -9,9 +9,9 @@ let
res = builtins.filter ({ username, ... }: username == user) depot.ops.users;
len = builtins.length res;
in
if len == 1
then (builtins.head res).email
else builtins.throw "findEmail: got ${toString len} results instead of 1";
if len == 1
then (builtins.head res).email
else builtins.throw "findEmail: got ${toString len} results instead of 1";
# dot-time(7) man page, ported from dotti.me
dot-time = rec {
@ -65,6 +65,6 @@ let
};
in
depot.nix.buildManPages "dot-time" {} [
dot-time
]
depot.nix.buildManPages "dot-time" { } [
dot-time
]

View file

@ -1,4 +1,4 @@
{ depot ? import ../../../../.. {}
{ depot ? import ../../../../.. { }
, pkgs ? depot.third_party.nixpkgs
, ...
}:

View file

@ -19,9 +19,9 @@ let
;
bins = getBins cheddar [ "cheddar" ]
// getBins mandoc [ "mandoc" ]
// getBins coreutils [ "cat" "mv" "mkdir" ]
;
// getBins mandoc [ "mandoc" ]
// getBins coreutils [ "cat" "mv" "mkdir" ]
;
normalizeDrv = fetchurl {
url = "https://necolas.github.io/normalize.css/8.0.1/normalize.css";
@ -29,7 +29,10 @@ let
};
execlineStdoutInto = target: line: [
"redirfd" "-w" "1" target
"redirfd"
"-w"
"1"
target
] ++ line;
# I will not write a pure nix markdown renderer
@ -39,16 +42,24 @@ let
# I will not write a pure nix markdown renderer
markdown = md:
let
html = runExecline.local "rendered-markdown" {
stdin = md;
} ([
"importas" "-iu" "out" "out"
] ++ execlineStdoutInto "$out" [
bins.cheddar "--about-filter" "description.md"
]);
in builtins.readFile html;
html = runExecline.local "rendered-markdown"
{
stdin = md;
}
([
"importas"
"-iu"
"out"
"out"
] ++ execlineStdoutInto "$out" [
bins.cheddar
"--about-filter"
"description.md"
]);
in
builtins.readFile html;
indexTemplate = { title, description, pages ? [] }: ''
indexTemplate = { title, description, pages ? [ ] }: ''
<!doctype html>
<html>
<head>
@ -137,40 +148,40 @@ let
htmlman =
{ title
# title of the index page
# title of the index page
, description ? ""
# description which is displayed after
# the main heading on the index page
, pages ? []
# man pages of the following structure:
# {
# name : string;
# section : int;
# path : either path string;
# }
# path is optional, if it is not given,
# the man page source must be located at
# "${manDir}/${name}.${toString section}"
# description which is displayed after
# the main heading on the index page
, pages ? [ ]
# man pages of the following structure:
# {
# name : string;
# section : int;
# path : either path string;
# }
# path is optional, if it is not given,
# the man page source must be located at
# "${manDir}/${name}.${toString section}"
, manDir ? null
# directory in which man page sources are located
# directory in which man page sources are located
, style ? defaultStyle
# CSS to use as a string
# CSS to use as a string
, normalizeCss ? true
# whether to include normalize.css before the custom CSS
# whether to include normalize.css before the custom CSS
, linkXr ? "all"
# How to handle cross references in the html output:
#
# * none: don't convert cross references into hyperlinks
# * all: link all cross references as if they were
# rendered into $out by htmlman
# * inManDir: link to all man pages which have their source
# in `manDir` and use the format string defined
# in linkXrFallback for all other cross references.
# How to handle cross references in the html output:
#
# * none: don't convert cross references into hyperlinks
# * all: link all cross references as if they were
# rendered into $out by htmlman
# * inManDir: link to all man pages which have their source
# in `manDir` and use the format string defined
# in linkXrFallback for all other cross references.
, linkXrFallback ? "https://manpages.debian.org/unstable/%N.%S.en.html"
# fallback link to use if linkXr == "inManDir" and the man
# page is not in ${manDir}. Placeholders %N (name of page)
# and %S (section of page) can be used. See mandoc(1) for
# more information.
# fallback link to use if linkXr == "inManDir" and the man
# page is not in ${manDir}. Placeholders %N (name of page)
# and %S (section of page) can be used. See mandoc(1) for
# more information.
}:
let
@ -188,47 +199,70 @@ let
mandocOpts = lib.concatStringsSep "," ([
"style=style.css"
] ++ linkXrEnum.match linkXr {
all = [ "man=./%N.%S.html" ];
all = [ "man=./%N.%S.html" ];
inManDir = [ "man=./%N.%S.html;${linkXrFallback}" ];
none = [ ];
none = [ ];
});
html =
runExecline.local "htmlman-${title}" {
derivationArgs = {
inherit index style;
passAsFile = [ "index" "style" ];
};
} ([
"multisubstitute" [
"importas" "-iu" "out" "out"
"importas" "-iu" "index" "indexPath"
"importas" "-iu" "style" "stylePath"
]
"if" [ bins.mkdir "-p" "$out" ]
"if" [ bins.mv "$index" "\${out}/index.html" ]
"if" (execlineStdoutInto "\${out}/style.css" [
"if" ([
bins.cat
] ++ lib.optional normalizeCss normalizeDrv
runExecline.local "htmlman-${title}"
{
derivationArgs = {
inherit index style;
passAsFile = [ "index" "style" ];
};
}
([
"multisubstitute"
[
"importas"
"-iu"
"out"
"out"
"importas"
"-iu"
"index"
"indexPath"
"importas"
"-iu"
"style"
"stylePath"
]
"if"
[ bins.mkdir "-p" "$out" ]
"if"
[ bins.mv "$index" "\${out}/index.html" ]
"if"
(execlineStdoutInto "\${out}/style.css" [
"if"
([
bins.cat
] ++ lib.optional normalizeCss normalizeDrv
++ [
"$style"
"$style"
])
])
])
# let mandoc check for available man pages
"execline-cd" "${manDir}"
] ++ lib.concatMap ({ name, section, ... }@p:
execlineStdoutInto "\${out}/${name}.${toString section}.html" [
"if" [
bins.mandoc
"-mdoc"
"-T" "html"
"-O" mandocOpts
(resolvePath p)
]
]) pages);
in html // {
# let mandoc check for available man pages
"execline-cd"
"${manDir}"
] ++ lib.concatMap
({ name, section, ... }@p:
execlineStdoutInto "\${out}/${name}.${toString section}.html" [
"if"
[
bins.mandoc
"-mdoc"
"-T"
"html"
"-O"
mandocOpts
(resolvePath p)
]
])
pages);
in
html // {
deploy = deployScript title html;
};
in
htmlman
htmlman

View file

@ -53,17 +53,20 @@ let
asciiAlpha = c:
let
v = ord c;
in (v >= 65 && v <= 90)
in
(v >= 65 && v <= 90)
|| (v >= 97 && v <= 122);
asciiNum = c:
let
v = ord c;
in v >= 48 && v <= 57;
in
v >= 48 && v <= 57;
asciiAlphaNum = c: asciiAlpha c || asciiNum c;
in {
in
{
inherit
allChars
char
@ -78,18 +81,19 @@ in {
# originally I generated a nix file containing a list of
# characters, but infinisil uses a better way which I adapt
# which is using builtins.readFile instead of import.
__generateAllChars = pkgs.runCommandCC "generate-all-chars" {
source = ''
#include <stdio.h>
__generateAllChars = pkgs.runCommandCC "generate-all-chars"
{
source = ''
#include <stdio.h>
int main(void) {
for(int i = 1; i <= 0xff; i++) {
putchar(i);
int main(void) {
for(int i = 1; i <= 0xff; i++) {
putchar(i);
}
}
}
'';
passAsFile = [ "source" ];
} ''
'';
passAsFile = [ "source" ];
} ''
$CC -o "$out" -x c "$sourcePath"
'';
}

View file

@ -26,6 +26,6 @@ let
];
in
runTestsuite "char" [
testAllCharConversion
]
runTestsuite "char" [
testAllCharConversion
]

View file

@ -68,13 +68,14 @@ let
then s x
else x == s;
in
if b
then builtins.elemAt c 1
else switch x (builtins.tail conds);
if b
then builtins.elemAt c 1
else switch x (builtins.tail conds);
in {
in
{
inherit
cond
switch

View file

@ -21,7 +21,7 @@ let
(cond [ [ true 1 2 ] [ false 1 ] ]))
(assertEq "last is true" "last"
(cond [
[ false dontEval]
[ false dontEval ]
[ false dontEval ]
[ true "last" ]
]))
@ -34,6 +34,6 @@ let
];
in
runTestsuite "nix.flow" [
testCond
]
runTestsuite "nix.flow" [
testCond
]

View file

@ -24,6 +24,6 @@ let
(fun.hasEllipsis ({ depot, pkgs, ... }: 42)))
];
in
runTestsuite "nix.fun" [
hasEllipsisTests
]
runTestsuite "nix.fun" [
hasEllipsisTests
]

View file

@ -20,7 +20,7 @@ let
=> "&lt;hello&gt;"
*/
escapeMinimal = builtins.replaceStrings
[ "<" ">" "&" "\"" "'" ]
[ "<" ">" "&" "\"" "'" ]
[ "&lt;" "&gt;" "&amp;" "&quot;" "&#039;" ];
/* Return a string with a correctly rendered tag of the given name,
@ -87,18 +87,20 @@ let
renderTag = tag: attrs: content:
let
attrs' = builtins.concatStringsSep "" (
builtins.map (n:
" ${escapeMinimal n}=\"${escapeMinimal (toString attrs.${n})}\""
) (builtins.attrNames attrs)
builtins.map
(n:
" ${escapeMinimal n}=\"${escapeMinimal (toString attrs.${n})}\""
)
(builtins.attrNames attrs)
);
content' =
if builtins.isList content
then builtins.concatStringsSep "" content
else content;
in
if content == null
then "<${tag}${attrs'}/>"
else "<${tag}${attrs'}>${content'}</${tag}>";
if content == null
then "<${tag}${attrs'}/>"
else "<${tag}${attrs'}>${content'}</${tag}>";
/* Prepend "<!DOCTYPE html>" to a string.
@ -111,7 +113,8 @@ let
*/
withDoctype = doc: "<!DOCTYPE html>" + doc;
in {
in
{
inherit escapeMinimal renderTag withDoctype;
__findFile = _: renderTag;

View file

@ -8,15 +8,17 @@ let
;
exampleDocument = withDoctype (<html> { lang = "en"; } [
(<head> {} [
(<head> { } [
(<meta> { charset = "utf-8"; } null)
(<title> {} "html.nix example document")
(<link> {
rel = "license";
href = "https://code.tvl.fyi/about/LICENSE";
type = "text/html";
} null)
(<style> {} (esc ''
(<title> { } "html.nix example document")
(<link>
{
rel = "license";
href = "https://code.tvl.fyi/about/LICENSE";
type = "text/html";
}
null)
(<style> { } (esc ''
hgroup h2 {
font-weight: normal;
}
@ -26,39 +28,45 @@ let
}
''))
])
(<body> {} [
(<main> {} [
(<hgroup> {} [
(<h1> {} (esc "html.nix"))
(<h2> {} [
(<em> {} "the")
(<body> { } [
(<main> { } [
(<hgroup> { } [
(<h1> { } (esc "html.nix"))
(<h2> { } [
(<em> { } "the")
(esc " most cursed HTML DSL ever!")
])
])
(<dl> {} [
(<dt> {} [
(<dl> { } [
(<dt> { } [
(esc "Q: Wait, it's all ")
(<a> {
href = "https://cl.tvl.fyi/q/hashtag:cursed";
} (esc "cursed"))
(<a>
{
href = "https://cl.tvl.fyi/q/hashtag:cursed";
}
(esc "cursed"))
(esc " nix hacks?")
])
(<dd> {} (esc "A: Always has been. 🔫"))
(<dt> {} (esc "Q: Why does this work?"))
(<dd> {} [
(<dd> { } (esc "A: Always has been. 🔫"))
(<dt> { } (esc "Q: Why does this work?"))
(<dd> { } [
(esc "Because nix ")
(<a> {
href = "https://github.com/NixOS/nix/blob/293220bed5a75efc963e33c183787e87e55e28d9/src/libexpr/parser.y#L410-L416";
} (esc "translates "))
(<a> {
href = "https://github.com/NixOS/nix/blob/293220bed5a75efc963e33c183787e87e55e28d9/src/libexpr/lexer.l#L100";
} (esc "SPATH tokens"))
(<a>
{
href = "https://github.com/NixOS/nix/blob/293220bed5a75efc963e33c183787e87e55e28d9/src/libexpr/parser.y#L410-L416";
}
(esc "translates "))
(<a>
{
href = "https://github.com/NixOS/nix/blob/293220bed5a75efc963e33c183787e87e55e28d9/src/libexpr/lexer.l#L100";
}
(esc "SPATH tokens"))
(esc " like ")
(<code> {} (esc "<nixpkgs>"))
(<code> { } (esc "<nixpkgs>"))
(esc " into calls to ")
(<code> {} (esc "__findFile"))
(<code> { } (esc "__findFile"))
(esc " in the ")
(<em> {} (esc "current"))
(<em> { } (esc "current"))
(esc " scope.")
])
])
@ -67,7 +75,8 @@ let
]);
in
pkgs.runCommandNoCC "html.nix.html" {
pkgs.runCommandNoCC "html.nix.html"
{
passAsFile = [ "exampleDocument" ];
inherit exampleDocument;
nativeBuildInputs = [ pkgs.html5validator ];

View file

@ -47,12 +47,12 @@ let
if i == 0
then ""
else go (bitShiftR i 4)
+ string.charAt (bitAnd i 15) hexdigits;
+ string.charAt (bitAnd i 15) hexdigits;
sign = lib.optionalString (int < 0) "-";
in
if int == 0
then "0"
else "${sign}${go (abs int)}";
if int == 0
then "0"
else "${sign}${go (abs int)}";
fromHexMap = builtins.listToAttrs
(lib.imap0 (i: c: { name = c; value = i; })
@ -72,11 +72,12 @@ let
val = v.val + (fromHexMap."${d}" * v.mul);
mul = v.mul * 16;
})
{ val = 0; mul = 1; } digits;
{ val = 0; mul = 1; }
digits;
in
if negative
then -parsed.val
else parsed.val;
if negative
then -parsed.val
else parsed.val;
# A nix integer is a 64bit signed integer
maxBound = 9223372036854775807;
@ -99,7 +100,8 @@ let
inRange = a: b: x: x >= a && x <= b;
in {
in
{
inherit
maxBound
minBound

View file

@ -31,22 +31,262 @@ let
];
expectedBytes = [
"00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "0A" "0B" "0C" "0D" "0E" "0F"
"10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "1A" "1B" "1C" "1D" "1E" "1F"
"20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "2A" "2B" "2C" "2D" "2E" "2F"
"30" "31" "32" "33" "34" "35" "36" "37" "38" "39" "3A" "3B" "3C" "3D" "3E" "3F"
"40" "41" "42" "43" "44" "45" "46" "47" "48" "49" "4A" "4B" "4C" "4D" "4E" "4F"
"50" "51" "52" "53" "54" "55" "56" "57" "58" "59" "5A" "5B" "5C" "5D" "5E" "5F"
"60" "61" "62" "63" "64" "65" "66" "67" "68" "69" "6A" "6B" "6C" "6D" "6E" "6F"
"70" "71" "72" "73" "74" "75" "76" "77" "78" "79" "7A" "7B" "7C" "7D" "7E" "7F"
"80" "81" "82" "83" "84" "85" "86" "87" "88" "89" "8A" "8B" "8C" "8D" "8E" "8F"
"90" "91" "92" "93" "94" "95" "96" "97" "98" "99" "9A" "9B" "9C" "9D" "9E" "9F"
"A0" "A1" "A2" "A3" "A4" "A5" "A6" "A7" "A8" "A9" "AA" "AB" "AC" "AD" "AE" "AF"
"B0" "B1" "B2" "B3" "B4" "B5" "B6" "B7" "B8" "B9" "BA" "BB" "BC" "BD" "BE" "BF"
"C0" "C1" "C2" "C3" "C4" "C5" "C6" "C7" "C8" "C9" "CA" "CB" "CC" "CD" "CE" "CF"
"D0" "D1" "D2" "D3" "D4" "D5" "D6" "D7" "D8" "D9" "DA" "DB" "DC" "DD" "DE" "DF"
"E0" "E1" "E2" "E3" "E4" "E5" "E6" "E7" "E8" "E9" "EA" "EB" "EC" "ED" "EE" "EF"
"F0" "F1" "F2" "F3" "F4" "F5" "F6" "F7" "F8" "F9" "FA" "FB" "FC" "FD" "FE" "FF"
"00"
"01"
"02"
"03"
"04"
"05"
"06"
"07"
"08"
"09"
"0A"
"0B"
"0C"
"0D"
"0E"
"0F"
"10"
"11"
"12"
"13"
"14"
"15"
"16"
"17"
"18"
"19"
"1A"
"1B"
"1C"
"1D"
"1E"
"1F"
"20"
"21"
"22"
"23"
"24"
"25"
"26"
"27"
"28"
"29"
"2A"
"2B"
"2C"
"2D"
"2E"
"2F"
"30"
"31"
"32"
"33"
"34"
"35"
"36"
"37"
"38"
"39"
"3A"
"3B"
"3C"
"3D"
"3E"
"3F"
"40"
"41"
"42"
"43"
"44"
"45"
"46"
"47"
"48"
"49"
"4A"
"4B"
"4C"
"4D"
"4E"
"4F"
"50"
"51"
"52"
"53"
"54"
"55"
"56"
"57"
"58"
"59"
"5A"
"5B"
"5C"
"5D"
"5E"
"5F"
"60"
"61"
"62"
"63"
"64"
"65"
"66"
"67"
"68"
"69"
"6A"
"6B"
"6C"
"6D"
"6E"
"6F"
"70"
"71"
"72"
"73"
"74"
"75"
"76"
"77"
"78"
"79"
"7A"
"7B"
"7C"
"7D"
"7E"
"7F"
"80"
"81"
"82"
"83"
"84"
"85"
"86"
"87"
"88"
"89"
"8A"
"8B"
"8C"
"8D"
"8E"
"8F"
"90"
"91"
"92"
"93"
"94"
"95"
"96"
"97"
"98"
"99"
"9A"
"9B"
"9C"
"9D"
"9E"
"9F"
"A0"
"A1"
"A2"
"A3"
"A4"
"A5"
"A6"
"A7"
"A8"
"A9"
"AA"
"AB"
"AC"
"AD"
"AE"
"AF"
"B0"
"B1"
"B2"
"B3"
"B4"
"B5"
"B6"
"B7"
"B8"
"B9"
"BA"
"BB"
"BC"
"BD"
"BE"
"BF"
"C0"
"C1"
"C2"
"C3"
"C4"
"C5"
"C6"
"C7"
"C8"
"C9"
"CA"
"CB"
"CC"
"CD"
"CE"
"CF"
"D0"
"D1"
"D2"
"D3"
"D4"
"D5"
"D6"
"D7"
"D8"
"D9"
"DA"
"DB"
"DC"
"DD"
"DE"
"DF"
"E0"
"E1"
"E2"
"E3"
"E4"
"E5"
"E6"
"E7"
"E8"
"E9"
"EA"
"EB"
"EC"
"ED"
"EE"
"EF"
"F0"
"F1"
"F2"
"F3"
"F4"
"F5"
"F6"
"F7"
"F8"
"F9"
"FA"
"FB"
"FC"
"FD"
"FE"
"FF"
];
hexByte = i: string.fit { width = 2; char = "0"; } (int.toHex i);
@ -64,14 +304,18 @@ let
];
testHex = it "checks conversion to hex" (lib.flatten [
(lib.imap0 (i: hex: [
(assertEq "hexByte ${toString i} == ${hex}" (hexByte i) hex)
(assertEq "${toString i} == fromHex ${hex}" i (int.fromHex hex))
]) expectedBytes)
(builtins.map ({ left, right }: [
(assertEq "toHex ${toString left} == ${right}" (int.toHex left) right)
(assertEq "${toString left} == fromHex ${right}" left (int.fromHex right))
]) hexInts)
(lib.imap0
(i: hex: [
(assertEq "hexByte ${toString i} == ${hex}" (hexByte i) hex)
(assertEq "${toString i} == fromHex ${hex}" i (int.fromHex hex))
])
expectedBytes)
(builtins.map
({ left, right }: [
(assertEq "toHex ${toString left} == ${right}" (int.toHex left) right)
(assertEq "${toString left} == fromHex ${right}" left (int.fromHex right))
])
hexInts)
]);
testBasic = it "checks basic int operations" [
@ -94,20 +338,23 @@ let
];
testExp = it "checks exponentiation"
(builtins.map ({ left, right }:
assertEq
"2 ^ ${toString left} == ${toString right}"
(int.exp 2 left) right) expNumbers);
(builtins.map
({ left, right }:
assertEq
"2 ^ ${toString left} == ${toString right}"
(int.exp 2 left)
right)
expNumbers);
shifts = [
{ a = 2; b = 5; c = 64; op = "<<"; }
{ a = -2; b = 5; c = -64; op = "<<"; }
{ a = 2; b = 5; c = 64; op = "<<"; }
{ a = -2; b = 5; c = -64; op = "<<"; }
{ a = 123; b = 4; c = 1968; op = "<<"; }
{ a = 1; b = 8; c = 256; op = "<<"; }
{ a = 256; b = 8; c = 1; op = ">>"; }
{ a = 374; b = 2; c = 93; op = ">>"; }
{ a = 2; b = 2; c = 0; op = ">>"; }
{ a = 99; b = 9; c = 0; op = ">>"; }
{ a = 1; b = 8; c = 256; op = "<<"; }
{ a = 256; b = 8; c = 1; op = ">>"; }
{ a = 374; b = 2; c = 93; op = ">>"; }
{ a = 2; b = 2; c = 0; op = ">>"; }
{ a = 99; b = 9; c = 0; op = ">>"; }
];
checkShift = { a, b, c, op }@args:
@ -116,15 +363,18 @@ let
"<<" = int.bitShiftL;
">>" = int.bitShiftR;
};
in assertEq "${toString a} ${op} ${toString b} == ${toString c}" (f a b) c;
in
assertEq "${toString a} ${op} ${toString b} == ${toString c}" (f a b) c;
checkShiftRDivExp = n:
assertEq "${toString n} >> 5 == ${toString n} / 2 ^ 5"
(int.bitShiftR n 5) (int.div n (int.exp 2 5));
(int.bitShiftR n 5)
(int.div n (int.exp 2 5));
checkShiftLMulExp = n:
assertEq "${toString n} >> 6 == ${toString n} * 2 ^ 6"
(int.bitShiftL n 5) (int.mul n (int.exp 2 5));
(int.bitShiftL n 5)
(int.mul n (int.exp 2 5));
testBit = it "checks bitwise operations" (lib.flatten [
(builtins.map checkShift shifts)
@ -160,11 +410,11 @@ let
]);
divisions = [
{ a = 2; b = 1; c = 2; mod = 0;}
{ a = 2; b = 2; c = 1; mod = 0;}
{ a = 20; b = 10; c = 2; mod = 0;}
{ a = 12; b = 5; c = 2; mod = 2;}
{ a = 23; b = 4; c = 5; mod = 3;}
{ a = 2; b = 1; c = 2; mod = 0; }
{ a = 2; b = 2; c = 1; mod = 0; }
{ a = 20; b = 10; c = 2; mod = 0; }
{ a = 12; b = 5; c = 2; mod = 2; }
{ a = 23; b = 4; c = 5; mod = 3; }
];
checkDiv = n: { a, b, c, mod }: [
@ -176,28 +426,34 @@ let
testDivMod = it "checks integer division and modulo"
(lib.flatten [
(builtins.map (checkDiv "+a / +b") divisions)
(builtins.map (fun.rl (checkDiv "-a / +b") (x: x // {
a = -x.a;
c = -x.c;
mod = -x.mod;
})) divisions)
(builtins.map (fun.rl (checkDiv "+a / -b") (x: x // {
b = -x.b;
c = -x.c;
})) divisions)
(builtins.map (fun.rl (checkDiv "-a / -b") (x: x // {
a = -x.a;
b = -x.b;
mod = -x.mod;
})) divisions)
(builtins.map
(fun.rl (checkDiv "-a / +b") (x: x // {
a = -x.a;
c = -x.c;
mod = -x.mod;
}))
divisions)
(builtins.map
(fun.rl (checkDiv "+a / -b") (x: x // {
b = -x.b;
c = -x.c;
}))
divisions)
(builtins.map
(fun.rl (checkDiv "-a / -b") (x: x // {
a = -x.a;
b = -x.b;
mod = -x.mod;
}))
divisions)
]);
in
runTestsuite "nix.int" [
testBounds
testHex
testBasic
testExp
testBit
testDivMod
]
runTestsuite "nix.int" [
testBounds
testHex
testBasic
testExp
testBit
testDivMod
]

View file

@ -21,7 +21,8 @@ let
charAt = i: s:
let
r = builtins.substring i 1 s;
in if r == "" then null else r;
in
if r == "" then null else r;
charIndex = char: s:
let
@ -32,7 +33,8 @@ let
[ (charAt i s == char) i ]
[ true (go (i + 1)) ]
];
in go 0;
in
go 0;
toChars = lib.stringToCharacters;
fromChars = lib.concatStrings;
@ -46,15 +48,16 @@ let
let
leftS = fromChars (builtins.genList (_: char) left);
rightS = fromChars (builtins.genList (_: char) right);
in "${leftS}${s}${rightS}";
in
"${leftS}${s}${rightS}";
fit = { char ? " ", width, side ? "left" }: s:
let
diff = width - builtins.stringLength s;
in
if diff <= 0
then s
else pad { inherit char; "${side}" = diff; } s;
if diff <= 0
then s
else pad { inherit char; "${side}" = diff; } s;
# pattern matching for strings only
match = val: matcher: matcher."${val}";
@ -80,23 +83,28 @@ let
tokens = lib.flatten (builtins.split "(%.)" formatString);
argsNeeded = builtins.length (builtins.filter specifierWithArg tokens);
format = args: (builtins.foldl' ({ out ? "", argIndex ? 0 }: token: {
argIndex = argIndex + (if specifierWithArg token then 1 else 0);
out =
/**/ if token == "%s" then out + builtins.elemAt args argIndex
else if token == "%%" then out + "%"
else if isSpecifier token then throw "Unsupported format specifier ${token}"
else out + token;
}) {} tokens).out;
format = args: (builtins.foldl'
({ out ? "", argIndex ? 0 }: token: {
argIndex = argIndex + (if specifierWithArg token then 1 else 0);
out =
/**/
if token == "%s" then out + builtins.elemAt args argIndex
else if token == "%%" then out + "%"
else if isSpecifier token then throw "Unsupported format specifier ${token}"
else out + token;
})
{ }
tokens).out;
accumulateArgs = argCount: args:
if argCount > 0
then arg: accumulateArgs (argCount - 1) (args ++ [ arg ])
else format args;
in
accumulateArgs argsNeeded [];
accumulateArgs argsNeeded [ ];
in {
in
{
inherit
take
drop

View file

@ -63,10 +63,10 @@ let
];
in
runTestsuite "nix.string" [
testTakeDrop
testIndexing
testFinding
testMatch
testPrintf
]
runTestsuite "nix.string" [
testTakeDrop
testIndexing
testFinding
testMatch
testPrintf
]

View file

@ -10,9 +10,24 @@ let
;
reserved = c: builtins.elem c [
"!" "#" "$" "&" "'" "(" ")"
"*" "+" "," "/" ":" ";" "="
"?" "@" "[" "]"
"!"
"#"
"$"
"&"
"'"
"("
")"
"*"
"+"
","
"/"
":"
";"
"="
"?"
"@"
"["
"]"
];
unreserved = c: char.asciiAlphaNum c
@ -21,11 +36,13 @@ let
percentEncode = c:
if unreserved c
then c
else "%" + (string.fit {
width = 2;
char = "0";
side = "left";
} (int.toHex (char.ord c)));
else "%" + (string.fit
{
width = 2;
char = "0";
side = "left";
}
(int.toHex (char.ord c)));
encode = { leaveReserved ? false }: s:
let
@ -34,7 +51,8 @@ let
if leaveReserved && reserved c
then c
else percentEncode c;
in lib.concatStrings (builtins.map tr chars);
in
lib.concatStrings (builtins.map tr chars);
decode = s:
let
@ -71,9 +89,10 @@ let
];
in
(builtins.foldl' decodeStep {} tokens).result;
(builtins.foldl' decodeStep { } tokens).result;
in {
in
{
inherit
encode
decode

View file

@ -14,11 +14,13 @@ let
checkEncoding = args: { left, right }:
assertEq "encode ${builtins.toJSON left} == ${builtins.toJSON right}"
(url.encode args left) right;
(url.encode args left)
right;
checkDecoding = { left, right }:
assertEq "${builtins.toJSON left} == decode ${builtins.toJSON right}"
(url.decode left) right;
assertEq "${builtins.toJSON left} == decode ${builtins.toJSON right}"
(url.decode left)
right;
unreserved = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_~";
@ -33,7 +35,7 @@ let
];
testEncode = it "checks url.encode"
(builtins.map (checkEncoding {}) encodeExpected);
(builtins.map (checkEncoding { }) encodeExpected);
testDecode = it "checks url.decode"
(builtins.map checkDecoding encodeExpected);
@ -50,7 +52,7 @@ let
"urn:oasis:names:specification:docbook:dtd:xml:4.1.2"
]);
in
runTestsuite "nix.url" [
testEncode
testLeaveReserved
]
runTestsuite "nix.url" [
testEncode
testLeaveReserved
]

View file

@ -25,7 +25,7 @@ let
Type: integer -> integer
*/
byteCount = i: flow.cond [
[ (int.bitAnd i 128 == 0) 1 ]
[ (int.bitAnd i 128 == 0) 1 ]
[ (int.bitAnd i 224 == 192) 2 ]
[ (int.bitAnd i 240 == 224) 3 ]
[ (int.bitAnd i 248 == 240) 4 ]
@ -45,30 +45,30 @@ let
first:
# byte position as an index starting with 0
pos:
let
defaultRange = int.inRange 128 191;
let
defaultRange = int.inRange 128 191;
secondBytePredicate = flow.switch first [
[ (int.inRange 194 223) defaultRange ] # C2..DF
[ 224 (int.inRange 160 191) ] # E0
[ (int.inRange 225 236) defaultRange ] # E1..EC
[ 237 (int.inRange 128 159) ] # ED
[ (int.inRange 238 239) defaultRange ] # EE..EF
[ 240 (int.inRange 144 191) ] # F0
[ (int.inRange 241 243) defaultRange ] # F1..F3
[ 244 (int.inRange 128 143) ] # F4
[ (fun.const true) null ]
];
secondBytePredicate = flow.switch first [
[ (int.inRange 194 223) defaultRange ] # C2..DF
[ 224 (int.inRange 160 191) ] # E0
[ (int.inRange 225 236) defaultRange ] # E1..EC
[ 237 (int.inRange 128 159) ] # ED
[ (int.inRange 238 239) defaultRange ] # EE..EF
[ 240 (int.inRange 144 191) ] # F0
[ (int.inRange 241 243) defaultRange ] # F1..F3
[ 244 (int.inRange 128 143) ] # F4
[ (fun.const true) null ]
];
firstBytePredicate = byte: assert first == byte;
first < 128 || secondBytePredicate != null;
in
# Either ASCII or in one of the byte ranges of Table 3-6.
if pos == 0 then firstBytePredicate
# return predicate according to Table 3-6.
else if pos == 1 then assert secondBytePredicate != null; secondBytePredicate
# 3rd and 4th byte have only one validity rule
else defaultRange;
firstBytePredicate = byte: assert first == byte;
first < 128 || secondBytePredicate != null;
in
# Either ASCII or in one of the byte ranges of Table 3-6.
if pos == 0 then firstBytePredicate
# return predicate according to Table 3-6.
else if pos == 1 then assert secondBytePredicate != null; secondBytePredicate
# 3rd and 4th byte have only one validity rule
else defaultRange;
/* Iteration step for decoding an UTF-8 byte sequence.
It decodes incrementally, i. e. it has to be fed
@ -128,23 +128,24 @@ let
# the current value by the amount of bytes left.
offset = (count - (pos + 1)) * 6;
in
code + (int.bitShiftL (int.bitAnd mask value) offset);
code + (int.bitShiftL (int.bitAnd mask value) offset);
illFormedMsg =
"Ill-formed byte ${int.toHex value} at position ${toString pos} in ${toString count} byte UTF-8 sequence";
in
if !(wellFormedByte first pos value) then builtins.throw illFormedMsg
else if pos + 1 == count
then (builtins.removeAttrs args [ # allow extra state being passed through
"count"
"code"
"pos"
"first"
]) // { result = newCode; }
else (builtins.removeAttrs args [ "result" ]) // {
inherit count first;
code = newCode;
pos = pos + 1;
};
if !(wellFormedByte first pos value) then builtins.throw illFormedMsg
else if pos + 1 == count
then (builtins.removeAttrs args [
# allow extra state being passed through
"count"
"code"
"pos"
"first"
]) // { result = newCode; }
else (builtins.removeAttrs args [ "result" ]) // {
inherit count first;
code = newCode;
pos = pos + 1;
};
/* Decode an UTF-8 string into a list of codepoints.
@ -161,7 +162,7 @@ let
{
key = "start";
stringIndex = -1;
state = {};
state = { };
codepoint = null;
}
];
@ -170,7 +171,8 @@ let
# updated values for current iteration step
newIndex = stringIndex + 1;
newState = step state (builtins.substring newIndex 1 s);
in lib.optional (newIndex < stringLength) {
in
lib.optional (newIndex < stringLength) {
# unique keys to make genericClosure happy
key = toString newIndex;
# carryover state for the next step
@ -183,35 +185,39 @@ let
in
# extract all steps that yield a code point into a list
builtins.map (v: v.codepoint) (
builtins.filter (
{ codepoint, stringIndex, state, ... }:
builtins.filter
(
{ codepoint, stringIndex, state, ... }:
let
# error message in case we are missing bytes at the end of input
earlyEndMsg =
if state ? count && state ? pos
then "Missing ${toString (with state; count - pos)} bytes at end of input"
else "Unexpected end of input";
in
let
# error message in case we are missing bytes at the end of input
earlyEndMsg =
if state ? count && state ? pos
then "Missing ${toString (with state; count - pos)} bytes at end of input"
else "Unexpected end of input";
in
# filter out all iteration steps without a codepoint value
codepoint != null
# filter out all iteration steps without a codepoint value
codepoint != null
# if we are at the iteration step of a non-empty input string, throw
# an error if no codepoint was returned, as it indicates an incomplete
# UTF-8 sequence.
|| (stringLength > 0 && stringIndex == stringLength - 1 && throw earlyEndMsg)
) iterResult
)
iterResult
);
/* Pretty prints a Unicode codepoint in the U+<HEX> notation.
Type: integer -> string
*/
formatCodepoint = cp: "U+" + string.fit {
width = 4;
char = "0";
} (int.toHex cp);
formatCodepoint = cp: "U+" + string.fit
{
width = 4;
char = "0";
}
(int.toHex cp);
encodeCodepoint = cp:
let
@ -219,11 +225,11 @@ let
# Note that this doesn't check if the Unicode codepoint is allowed,
# but rather allows all theoretically UTF-8-encodeable ones.
count = flow.switch cp [
[ (int.inRange 0 127) 1 ] # 00000000 0xxxxxxx
[ (int.inRange 128 2047) 2 ] # 00000yyy yyxxxxxx
[ (int.inRange 2048 65535) 3 ] # zzzzyyyy yyxxxxxx
[ (int.inRange 0 127) 1 ] # 00000000 0xxxxxxx
[ (int.inRange 128 2047) 2 ] # 00000yyy yyxxxxxx
[ (int.inRange 2048 65535) 3 ] # zzzzyyyy yyxxxxxx
[ (int.inRange 65536 1114111) 4 ] # 000uuuuu zzzzyyyy yyxxxxxx,
# capped at U+10FFFF
# capped at U+10FFFF
[ (fun.const true) (builtins.throw invalidCodepointMsg) ]
];
@ -234,32 +240,34 @@ let
# according to Table 3-6. from The Unicode Standard, Version 13.0,
# section 3.9. u is split into uh and ul since they are used in
# different bytes in the end.
components = lib.mapAttrs (_: { mask, offset }:
int.bitAnd (int.bitShiftR cp offset) mask
) {
x = {
mask = if count > 1 then 63 else 127;
offset = 0;
components = lib.mapAttrs
(_: { mask, offset }:
int.bitAnd (int.bitShiftR cp offset) mask
)
{
x = {
mask = if count > 1 then 63 else 127;
offset = 0;
};
y = {
mask = if count > 2 then 63 else 31;
offset = 6;
};
z = {
mask = 15;
offset = 12;
};
# u which belongs into the second byte
ul = {
mask = 3;
offset = 16;
};
# u which belongs into the first byte
uh = {
mask = 7;
offset = 18;
};
};
y = {
mask = if count > 2 then 63 else 31;
offset = 6;
};
z = {
mask = 15;
offset = 12;
};
# u which belongs into the second byte
ul = {
mask = 3;
offset = 16;
};
# u which belongs into the first byte
uh = {
mask = 7;
offset = 18;
};
};
inherit (components) x y z ul uh;
# Finally construct the byte sequence for the given codepoint. This is
@ -286,15 +294,18 @@ let
unableToEncodeMessage = "Can't encode ${formatCodepoint cp} as UTF-8";
in string.fromBytes (
builtins.genList (i:
let
byte = builtins.elemAt bytes i;
in
in
string.fromBytes (
builtins.genList
(i:
let
byte = builtins.elemAt bytes i;
in
if wellFormedByte firstByte i byte
then byte
else builtins.throw unableToEncodeMessage
) count
)
count
);
/* Encode a list of Unicode codepoints into an UTF-8 string.
@ -303,7 +314,8 @@ let
*/
encode = lib.concatMapStrings encodeCodepoint;
in {
in
{
inherit
encode
decode

View file

@ -25,9 +25,10 @@ let
char
;
rustDecoder = rustSimple {
name = "utf8-decode";
} ''
rustDecoder = rustSimple
{
name = "utf8-decode";
} ''
use std::io::{self, Read};
fn main() -> std::io::Result<()> {
let mut buffer = String::new();
@ -47,10 +48,11 @@ let
rustDecode = s:
let
expr = runCommandLocal "${s}-decoded" {} ''
expr = runCommandLocal "${s}-decoded" { } ''
printf '%s' ${lib.escapeShellArg s} | ${rustDecoder} > $out
'';
in import expr;
in
import expr;
hexDecode = l:
utf8.decode (string.fromBytes (builtins.map int.fromHex l));
@ -65,23 +67,27 @@ let
(assertEq "well-formed: F4 80 83 92" (hexDecode [ "F4" "80" "83" "92" ]) [ 1048786 ])
(assertThrows "Codepoint out of range: 0xFFFFFF" (hexEncode [ "FFFFFF" ]))
(assertThrows "Codepoint out of range: -0x02" (hexEncode [ "-02" ]))
] ++ builtins.genList (i:
let
cp = i + int.fromHex "D800";
in
] ++ builtins.genList
(i:
let
cp = i + int.fromHex "D800";
in
assertThrows "Can't encode UTF-16 reserved characters: ${utf8.formatCodepoint cp}"
(utf8.encode [ cp ])
) (int.fromHex "07FF"));
)
(int.fromHex "07FF"));
testAscii = it "checks decoding of ascii strings"
(builtins.map (s: assertEq "ASCII decoding is equal to UTF-8 decoding for \"${s}\""
(string.toBytes s) (utf8.decode s)) [
"foo bar"
"hello\nworld"
"carriage\r\nreturn"
"1238398494829304 []<><>({})[]!!)"
(string.take 127 char.allChars)
]);
(builtins.map
(s: assertEq "ASCII decoding is equal to UTF-8 decoding for \"${s}\""
(string.toBytes s)
(utf8.decode s)) [
"foo bar"
"hello\nworld"
"carriage\r\nreturn"
"1238398494829304 []<><>({})[]!!)"
(string.take 127 char.allChars)
]);
randomUnicode = [
"" # empty string should yield empty list
@ -126,16 +132,17 @@ let
testDecodingEncoding = it "checks that decoding and then encoding forms an identity"
(builtins.map
(s: assertEq "Decoding and then encoding ${s} yields itself"
(utf8.encode (utf8.decode s)) s)
(utf8.encode (utf8.decode s))
s)
(lib.flatten [
glassSentences
randomUnicode
]));
in
runTestsuite "nix.utf8" [
testFailures
testAscii
testDecoding
testDecodingEncoding
]
runTestsuite "nix.utf8" [
testFailures
testAscii
testDecoding
testDecodingEncoding
]

View file

@ -33,7 +33,7 @@ let
symphorien
erictapen
expipiplus1
;
;
};
# buildRustPackage handling
@ -55,24 +55,25 @@ let
extractCargoLock = drv:
if !(drv ? cargoDeps.outPath)
then null
else pkgs.runCommandNoCC "${drv.name}-Cargo.lock" {} ''
if test -d "${drv.cargoDeps}"; then
cp "${drv.cargoDeps}/Cargo.lock" "$out"
fi
else
pkgs.runCommandNoCC "${drv.name}-Cargo.lock" { } ''
if test -d "${drv.cargoDeps}"; then
cp "${drv.cargoDeps}/Cargo.lock" "$out"
fi
if test -f "${drv.cargoDeps}"; then
tar -xO \
--no-wildcards-match-slash --wildcards \
-f "${drv.cargoDeps}" \
'*/Cargo.lock' \
> "$out"
fi
'';
if test -f "${drv.cargoDeps}"; then
tar -xO \
--no-wildcards-match-slash --wildcards \
-f "${drv.cargoDeps}" \
'*/Cargo.lock' \
> "$out"
fi
'';
# nixpkgs traversal
# Condition for us to recurse: Either at top-level or recurseForDerivation.
recurseInto = path: x: path == [] ||
recurseInto = path: x: path == [ ] ||
(lib.isAttrs x && (x.recurseForDerivations or false));
# Returns the value or false if an eval error occurs.
@ -97,46 +98,69 @@ let
doRec = tryEvalOrFalse (recurseInto path x);
isRust = tryEvalOrFalse (isRustPackage x);
in
if doRec then lib.concatLists (
lib.mapAttrsToList (n: go (path ++ [ n ])) x
) else if isDrv && isRust then [
{
attr = path;
lock = extractCargoLock x;
maintainers = x.meta.maintainers or [];
}
] else [];
in go [];
if doRec then
lib.concatLists
(
lib.mapAttrsToList (n: go (path ++ [ n ])) x
) else if isDrv && isRust then [
{
attr = path;
lock = extractCargoLock x;
maintainers = x.meta.maintainers or [ ];
}
] else [ ];
in
go [ ];
# Report generation and formatting
reportFor = { attr, lock, maintainers ? [] }: let
# naïve attribute path to Nix syntax conversion
strAttr = lib.concatStringsSep "." attr;
strMaintainers = lib.concatMapStringsSep " " (m: "@${m.github}") (
builtins.filter (x: builtins.elem x maintainerWhitelist) maintainers
);
in
reportFor = { attr, lock, maintainers ? [ ] }:
let
# naïve attribute path to Nix syntax conversion
strAttr = lib.concatStringsSep "." attr;
strMaintainers = lib.concatMapStringsSep " " (m: "@${m.github}") (
builtins.filter (x: builtins.elem x maintainerWhitelist) maintainers
);
in
if lock == null
then pkgs.emptyFile
else depot.nix.runExecline "${strAttr}-vulnerability-report" {} [
"pipeline" [
bins.cargo-audit
"audit" "--json"
"-n" "--db" rustsec-advisory-db
"-f" lock
]
"importas" "out" "out"
"redirfd" "-w" "1" "$out"
bins.jq "-rj" "-f" ./format-audit-result.jq
"--arg" "attr" strAttr
"--arg" "maintainers" strMaintainers
];
else
depot.nix.runExecline "${strAttr}-vulnerability-report" { } [
"pipeline"
[
bins.cargo-audit
"audit"
"--json"
"-n"
"--db"
rustsec-advisory-db
"-f"
lock
]
"importas"
"out"
"out"
"redirfd"
"-w"
"1"
"$out"
bins.jq
"-rj"
"-f"
./format-audit-result.jq
"--arg"
"attr"
strAttr
"--arg"
"maintainers"
strMaintainers
];
# GHMF in issues splits paragraphs on newlines
description = lib.concatMapStringsSep "\n\n" (
builtins.replaceStrings [ "\n" ] [ " " ]
) [
description = lib.concatMapStringsSep "\n\n"
(
builtins.replaceStrings [ "\n" ] [ " " ]
) [
''
The vulnerability report below was generated by
[nixpkgs-crate-holes](https://code.tvl.fyi/tree/users/sterni/nixpkgs-crate-holes)
@ -194,39 +218,63 @@ let
);
in
depot.nix.runExecline "nixpkgs-rust-pkgs-vulnerability-report.md" {
stdin = lib.concatMapStrings (report: "${report}\n") reports;
} [
"importas" "out" "out"
"redirfd" "-w" "1" "$out"
depot.nix.runExecline "nixpkgs-rust-pkgs-vulnerability-report.md"
{
stdin = lib.concatMapStrings (report: "${report}\n") reports;
} [
"importas"
"out"
"out"
"redirfd"
"-w"
"1"
"$out"
# Print introduction paragraph for the issue
"if" [ bins.printf "%s\n\n" description ]
"if"
[ bins.printf "%s\n\n" description ]
# Print all reports
"foreground" [
"forstdin" "-E" "report" bins.cat "$report"
"foreground"
[
"forstdin"
"-E"
"report"
bins.cat
"$report"
]
# Print stats at the end (mostly as a gimmick), we already know how many
# attributes there are and count the attributes with vulnerability by
# finding the number of checkable list entries in the output.
"backtick" "-E" "vulnerableCount" [
"pipeline" [
bins.grep "^- \\[ \\]" "$out"
"backtick"
"-E"
"vulnerableCount"
[
"pipeline"
[
bins.grep
"^- \\[ \\]"
"$out"
]
bins.wc "-l"
bins.wc
"-l"
]
"if" [
"if"
[
bins.printf
"\n%s of %s checked attributes have vulnerable dependencies.\n\n"
"$vulnerableCount"
(toString (builtins.length reports))
]
"if" [
bins.printf "%s\n\n" runInstructions
"if"
[
bins.printf
"%s\n\n"
runInstructions
]
];
singleReport =
{ # Attribute to check: string or list of strings (attr path)
{
# Attribute to check: string or list of strings (attr path)
attr
# Path to importable nixpkgs checkout
, nixpkgsPath
@ -241,37 +289,63 @@ let
strAttr = lib.concatStringsSep "." attr';
in
depot.nix.runExecline "${strAttr}-report.html" {} [
"importas" "out" "out"
"backtick" "-I" "-E" "-N" "report" [
bins.cargo-audit "audit"
depot.nix.runExecline "${strAttr}-report.html" { } [
"importas"
"out"
"out"
"backtick"
"-I"
"-E"
"-N"
"report"
[
bins.cargo-audit
"audit"
"--quiet"
"-n" "--db" rustsec-advisory-db
"-f" lockFile
"-n"
"--db"
rustsec-advisory-db
"-f"
lockFile
]
"pipeline" [
"ifte" [
bins.printf "%s" "$report"
] [
bins.printf "%s\n" "No vulnerabilities found"
"pipeline"
[
"ifte"
[
bins.printf
"%s"
"$report"
]
bins.test "-n" "$report"
[
bins.printf
"%s\n"
"No vulnerabilities found"
]
bins.test
"-n"
"$report"
]
"pipeline" [
bins.tee "/dev/stderr"
"pipeline"
[
bins.tee
"/dev/stderr"
]
"redirfd" "-w" "1" "$out"
"redirfd"
"-w"
"1"
"$out"
bins.ansi2html
];
in {
in
{
full = reportForNixpkgs;
single = singleReport;
inherit
extractCargoLock
allLockFiles
;
;
# simple sanity check, doesn't cover everything, but testing the full report
# is quite expensive in terms of evaluation.