Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allowUnfree and overlays #383

Merged
merged 8 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions docs/reference/yaml-options.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@

| Key | Value |
| -------------------------- | ----------------------------------------------------------------------------- |
| inputs | Defaults to `inputs.nixpkgs.url: github:NixOS/nixpkgs/nixpkgs-unstable`. |
| inputs.<name> | Identifier name used when passing the input in your ``devenv.nix`` function. |
| inputs.<name>.url | URI specification of the input, see below for possible values. |
| inputs.<name>.flake | Does the input contain ``flake.nix`` or ``devenv.nix``. Defaults to ``true``. |
| imports | A list of relative paths or references to inputs to import ``devenv.nix``. |
| Key | Value |
| ----------------------------- | ----------------------------------------------------------------------------- |
| allowUnfree | Allow unfree packages. Defaults to `false`. |
| inputs | Defaults to `inputs.nixpkgs.url: github:NixOS/nixpkgs/nixpkgs-unstable`. |
| inputs.<name> | Identifier name used when passing the input in your ``devenv.nix`` function. |
| inputs.<name>.url | URI specification of the input, see below for possible values. |
| inputs.<name>.flake | Does the input contain ``flake.nix`` or ``devenv.nix``. Defaults to ``true``. |
| inputs.<name>.overlays | A list of overlays to include from the input. |
| imports | A list of relative paths or references to inputs to import ``devenv.nix``. |


## inputs.<name>.url

Expand All @@ -24,6 +27,7 @@
## An extensive example

```yaml
allowUnfree: true
inputs:
nixpkgs:
url: github:NixOS/nixpkgs/nixpkgs-unstable
Expand All @@ -35,4 +39,7 @@ imports:
- ./backend
- myproject
- myproject/relative/path
overlays:
myproject:
- default
```
5 changes: 5 additions & 0 deletions examples/overlays/devenv.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{ pkgs, ... }:

{
packages = [ pkgs.rust-bin.stable.latest.default ];
}
8 changes: 8 additions & 0 deletions examples/overlays/devenv.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
allowUnfree: true
inputs:
nixpkgs:
url: github:NixOS/nixpkgs/nixpkgs-unstable
rust-overlay:
url: github:oxalica/rust-overlay
overlays:
- default
46 changes: 46 additions & 0 deletions src/devenv-yaml.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{ pkgs }:

pkgs.writers.writePython3Bin "devenv-yaml" { libraries = with pkgs.python3Packages; [ strictyaml path ]; } ''
from strictyaml import Map, MapPattern, Str, Seq
from strictyaml import load, Bool, Any, Optional, YAMLError
import json
import sys
import os
from path import Path

inputsSchema = MapPattern(Str(), Map({
"url": Str(),
Optional("flake", default=None): Bool(),
Optional("inputs", default=None): Any(),
Optional("overlays", default=None): Seq(Str())
}))

schema = Map({
Optional("inputs", default=None): inputsSchema,
Optional("allowUnfree", default=False): Bool(),
Optional("imports", default=None): Seq(Str())
})

filename = Path("devenv.yaml").bytes().decode('utf8')
try:
devenv = load(filename, schema, label="devenv.yaml").data
except YAMLError as error:
print("Error in `devenv.yaml`", error)
sys.exit(1)

inputs = {}
for input, attrs in devenv.get('inputs', {}).items():
inputs[input] = {k: attrs[k] for k in ('url', 'inputs', 'flake')
if k in attrs}

devenv_dir = sys.argv[1]

with open(os.path.join(devenv_dir, "flake.json"), 'w') as f:
f.write(json.dumps(inputs))

with open(os.path.join(devenv_dir, "devenv.json"), 'w') as f:
f.write(json.dumps(devenv))

with open(os.path.join(devenv_dir, "imports.txt"), 'w') as f:
f.write("\n".join(devenv.get('imports', [])))
''
5 changes: 3 additions & 2 deletions src/devenv.nix
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ pkgs.writeScriptBin "devenv" ''
export DEVENV_DIR="$(pwd)/.devenv"
export DEVENV_GC="$DEVENV_DIR/gc"
mkdir -p "$DEVENV_GC"
# TODO: validate devenv.yaml using jsonschema
if [[ -f devenv.yaml ]]; then
cat devenv.yaml | ${pkgs.yaml2json}/bin/yaml2json > "$DEVENV_DIR/devenv.json"
${import ./devenv-yaml.nix { inherit pkgs; }}/bin/devenv-yaml "$DEVENV_DIR"
else
[[ -f "$DEVENV_DIR/devenv.json" ]] && rm "$DEVENV_DIR/devenv.json"
[[ -f "$DEVENV_DIR/flake.json" ]] && rm "$DEVENV_DIR/flake.json"
[[ -f "$DEVENV_DIR/imports.txt" ]] && rm "$DEVENV_DIR/imports.txt"
fi
cp -f ${import ./flake.nix { inherit pkgs version; }} "$FLAKE_FILE"
chmod +w "$FLAKE_FILE"
Expand Down
42 changes: 26 additions & 16 deletions src/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,47 @@
pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
devenv.url = "github:cachix/devenv?dir=src/modules";
} // (if builtins.pathExists ./.devenv/devenv.json
then (builtins.fromJSON (builtins.readFile ./.devenv/devenv.json)).inputs
} // (if builtins.pathExists ./.devenv/flake.json
then builtins.fromJSON (builtins.readFile ./.devenv/flake.json)
else {});

outputs = { nixpkgs, ... }@inputs:
let
pkgs = import nixpkgs { system = "${pkgs.system}"; };
lib = pkgs.lib;
devenv = if builtins.pathExists ./.devenv/devenv.json
then builtins.fromJSON (builtins.readFile ./.devenv/devenv.json)
else {};
toModule = path:
getOverlays = inputName: inputAttrs:
map (overlay: let
input = inputs.''${inputName} or (throw "No such input `''${inputName}` while trying to configure overlays.");
in input.overlays.''${overlay} or (throw "Input `''${inputName}` has no overlay called `''${overlay}`. Supported overlays: ''${nixpkgs.lib.concatStringsSep ", " (builtins.attrNames input.overlays)}"))
inputAttrs.overlays or [];
overlays = nixpkgs.lib.flatten (nixpkgs.lib.mapAttrsToList getOverlays (devenv.inputs or {}));
pkgs = import nixpkgs {
system = "${pkgs.system}";
allowUnfree = devenv.allowUnfree or false;
inherit overlays;
};
lib = pkgs.lib;
importModule = path:
if lib.hasPrefix "./" path
then ./. + (builtins.substring 1 255 path) + "/devenv.nix"
else if lib.hasPrefix "../" path
then throw "devenv: ../ is not supported for imports"
else let
paths = lib.splitString "/" path;
name = builtins.head paths;
input = inputs.''${name} or (throw "Unknown input ''${name}");
subpath = "/''${lib.concatStringsSep "/" (builtins.tail paths)}";
devenvpath = "''${input}" + subpath + "/devenv.nix";
in if builtins.pathExists devenvpath
then devenvpath
else throw (devenvpath + " file does not exist for input ''${name}.");
then throw "devenv: ../ is not supported for imports"
else let
paths = lib.splitString "/" path;
name = builtins.head paths;
input = inputs.''${name} or (throw "Unknown input ''${name}");
subpath = "/''${lib.concatStringsSep "/" (builtins.tail paths)}";
devenvpath = "''${input}" + subpath + "/devenv.nix";
in if builtins.pathExists devenvpath
then devenvpath
else throw (devenvpath + " file does not exist for input ''${name}.");
project = pkgs.lib.evalModules {
specialArgs = inputs // { inherit inputs pkgs; };
modules = [
(inputs.devenv.modules + /top-level.nix)
{ devenv.cliVersion = "${version}"; }
] ++ (map toModule (devenv.imports or [])) ++ [
] ++ (map importModule (devenv.imports or [])) ++ [
./devenv.nix
(devenv.devenv or {})
(if builtins.pathExists ./devenv.local.nix then ./devenv.local.nix else {})
Expand Down