Monorepo for Tangled tangled.org
11

Configure Feed

Select the types of activity you want to include in your feed.

1{ 2 pkgs, 3 lib, 4 options, 5 config, 6 ... 7} @ args: let 8 configPath = /run/spindle/user-config/config.json; 9 userConfig = 10 args.userConfig 11 or ( 12 if builtins.pathExists configPath 13 then lib.importJSON configPath 14 else {} 15 ); 16 17 registry = userConfig.registry or {}; 18 19 # registry targets may be structured attrs or flake ref strings; strings are 20 # parsed by nix itself in getFlake. flakeRefToString rejects unforced attr 21 # values, hence the toJSON round-trip 22 toRefString = target: 23 if builtins.isAttrs target 24 then builtins.flakeRefToString (builtins.fromJSON (builtins.toJSON target)) 25 else target; 26 27 # user registry entries shadow the system registry (which pins nixpkgs) 28 getFlake = ref: builtins.getFlake (toRefString (registry.${ref} or ref)); 29 30 # "flakeref#attr" or a bare attr looked up in nixpkgs. nixpkgs refs use the 31 # already-evaluated pkgs directly instead of re-evaluating via getFlake, 32 # unless the user remapped nixpkgs in their registry 33 resolvePackage = ref: let 34 parts = lib.splitString "#" ref; 35 hasAttr = lib.length parts > 1; 36 flakeRef = 37 if hasAttr 38 then lib.head parts 39 else "nixpkgs"; 40 pkgName = 41 if hasAttr 42 then lib.elemAt parts 1 43 else ref; 44 system = pkgs.stdenv.hostPlatform.system; 45 flake = getFlake flakeRef; 46 notFound = throw "Package ${pkgName} not found in ${flakeRef}"; 47 in 48 if flakeRef == "nixpkgs" && !(registry ? nixpkgs) 49 then pkgs.${pkgName} or notFound 50 else flake.legacyPackages.${system}.${pkgName} or flake.packages.${system}.${pkgName} or notFound; 51 52 # strings are resolved as package references only where the option type 53 # actually expects packages; everything else passes through untouched 54 resolveForType = type: v: 55 if type.name == "package" && builtins.isString v 56 then resolvePackage v 57 # path-typed options (e.g. services.udev.packages) accept derivations via 58 # coercion; "#" disambiguates flake refs from actual paths, which are 59 # always absolute 60 else if type.name == "path" && builtins.isString v && lib.hasInfix "#" v && !lib.hasPrefix "/" v 61 then resolvePackage v 62 else if type.name == "nullOr" && v != null 63 then resolveForType type.nestedTypes.elemType v 64 else if type.name == "listOf" && builtins.isList v 65 then map (resolveForType type.nestedTypes.elemType) v 66 else if (type.name == "attrsOf" || type.name == "lazyAttrsOf") && builtins.isAttrs v 67 then builtins.mapAttrs (_: resolveForType type.nestedTypes.elemType) v 68 else if type.name == "submodule" && builtins.isAttrs v 69 then resolveOptions (type.getSubOptions []) v 70 else v; 71 72 resolveOptions = opts: builtins.mapAttrs (name: resolveValue (opts.${name} or null)); 73 74 resolveValue = opt: v: 75 if !builtins.isAttrs opt 76 then v 77 else if lib.isOption opt 78 then resolveForType opt.type v 79 else if builtins.isAttrs v 80 then resolveOptions opt v 81 else v; 82 83 # `foo = true` is shorthand for `foo.enable = true`, but only when an 84 # enable option actually exists under foo 85 hasEnableOption = opt: 86 builtins.isAttrs opt 87 && ( 88 if lib.isOption opt 89 then (opt.type.getSubOptions opt.loc) ? enable 90 else opt ? enable && lib.isOption opt.enable 91 ); 92 93 normalize = opts: name: v: let 94 opt = opts.${name} or null; 95 in 96 if builtins.isBool v && hasEnableOption opt 97 then {enable = v;} 98 else resolveValue opt v; 99 100 # dependencies go into a devshell so we can make use of stdenv setup hooks 101 # (e.g. for pkg-config and such) 102 dependencies = userConfig.dependencies or []; 103 spindleDevShell = pkgs.mkShellNoCC { 104 name = "spindle-deps"; 105 packages = map resolvePackage dependencies; 106 }; 107 spindleDevEnv = spindleDevShell.overrideAttrs (_: { 108 name = "spindle-deps-env"; 109 # materialize the devshell like how nix print-dev-env does internally 110 args = ["${config.nix.package.src}/src/nix/get-env.sh"]; 111 }); 112in { 113 nix.registry = builtins.mapAttrs (name: _: 114 lib.mkForce { 115 to = { 116 type = "path"; 117 path = (getFlake name).outPath; 118 }; 119 }) 120 registry; 121 environment.etc = lib.mkIf (dependencies != []) { 122 "spindle/devshell-drv".text = "${spindleDevEnv}"; 123 }; 124 services = builtins.mapAttrs (normalize (options.services or {})) (userConfig.services or {}); 125 virtualisation = builtins.mapAttrs (normalize (options.virtualisation or {})) (userConfig.virtualisation or {}); 126}