{lib}: with builtins; with lib; rec { ifelse = a: b: c: if a then b else c; fileContentsOr = a: b: (ifelse (pathIsRegularFile a) a b); cwd = builtins.getEnv "PWD"; # lst (string PATH) (string FILETYPE) (bool RETURNFULLPATH) lst = { p ? cwd, t ? "regular", b ? false, }: (lists.forEach (attrNames (filterAttrs (n: v: v == t) (readDir p))) (v: ((optionalString b "${p}/") + v))); lsf = p: (lst {p = p;}); lsd = p: (lst { p = p; t = "directory"; b = true; }); lsfRec = p: b: flatten ((map (np: lsfRec np b) (lsd p)) ++ (lst { p = p; b = b; })); hasAttrs = aList: d: (map (a: (ifelse (isList a) (hasAttrByPath a d) (hasAttr a d))) aList); # Not sure how list operations are implemented in Nix # This might be a tad bit inefficient. # TODO: look for better implementation (map is a builtin function so checking that probably won't help) # Sequentially checks elements of list (l) for condition (cond) and executes do on first match. meetsConDo = cond: do: l: ifelse (l == []) false (let h = head l; t = tail l; in ifelse (cond h) (do h) (meetsConDo cond do t)); deps = p: ifelse (isAttrs p) ( filter (p: isAttrs p) (p.buildInputs ++ p.nativeBuildInputs ++ p.propagatedBuildInputs ++ p.propagatedNativeBuildInputs) ) []; importFilter = l: p: filter (n: elem (nameFromURL (toString n) ".") l) p; depsRec = ld: ifelse (ld == []) [] ((toList ld) ++ (depsRec (lists.unique (lists.flatten (map (d: deps d) (toList ld)))))); isBroken = p: meetsConDo (s: ((hasAttrByPath s.path p) && (s.check (getAttrFromPath s.path p)))) (s: s.msg) [ { path = ["meta" "broken"]; msg = warn "Package ${p.name} is marked as broken." true; check = m: m; } { path = ["meta" "knownVulnerabilities"]; msg = warn "Package ${p.name} has known Vulnerabilities.." true; check = m: m != []; } { path = ["name"]; msg = warn "${p.name}: python2 is depricated." false; check = m: (strings.hasInfix "python2" m) || (strings.hasInfix "python-2" m); } # not sure if the following test creates false positives (AFAIK every derivation/package needs to have an outPath) # , definitely should catch all corner cases/everything that fails to evaluate. { path = ["outPath"]; msg = warn "Package ${p.name} has no outPath" true; check = m: !(tryEval m).success; } ]; depsBroken = p: lists.any (p: (isBroken p)) (deps p); # No more magic 🧙 here 😢 # But at least it now (hopefully) checks ONLY dependencies (and all of them at that). depsBrokenRec = p: ( meetsConDo (p: ifelse (depsBroken p) true (depsBrokenRec (deps p))) (p: true) (deps p) ); sopsHelper = template: names: options: let optionsIsFunction = (typeOf options) == "lambda"; in listToAttrs (map (name: { name = template name; value = ifelse optionsIsFunction (options name) options; }) names); pkgFilter = ld: (filter (p: ( ifelse (isBroken p) false (ifelse (depsBrokenRec p) (warn "Dependency of ${p.name} is marked as broken." false) true) )) ld); makeOptionTypeList = path: ( lists.forEach # get a list of all files ending in .nix in path (filter (filePath: hasSuffix ".nix" filePath) (lsfRec path true)) # remove leading path and trailing ".nix", replace every slash with "::" (replaceStrings ["${path}/" "/" ".nix"] ["" "::" ""]) ); }