Skip to content

Commit

Permalink
Merge pull request #12 from ekala-project/init-manifest
Browse files Browse the repository at this point in the history
feat: initial manifest parser
  • Loading branch information
nrdxp authored Aug 6, 2024
2 parents 933ee30 + 505b59e commit 398f00e
Show file tree
Hide file tree
Showing 13 changed files with 261 additions and 158 deletions.
147 changes: 147 additions & 0 deletions compose.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
let
l = builtins;
src = import ./src;
in
{
extern ? { },
features ? [ ],
# internal features of the composer function
stdFeatures ? src.stdToml.features.default or [ ],
composeFeatures ? src.composeToml.features.default,
# enable testing code paths
__internal__test ? false,
__isStd__ ? false,
}:
dir':
let
dir = src.prepDir dir';

std = src.readStd {
features = stdFeatures;
inherit __internal__test;
} ./std.toml;

composeFeatures' = src.features.parse src.composeToml.features composeFeatures;

meta = {
features = {
mod = features;
compose = composeFeatures';
std = stdFeatures;
};
};

f =
f: pre: dir:
let
contents = l.readDir dir;

preOpt = {
_if = pre != null;
inherit pre;
};

scope =
let
scope' = with src; {
mod = self';
builtins = errors.builtins;
import = errors.import;
scopedImport = errors.import;
__fetchurl = errors.fetch;
__currentSystem = errors.system;
__currentTime = errors.time;
__nixPath = errors.nixPath;
__storePath = errors.storePath;
__getEnv = errors.getEnv;
__getFlake = errors.import;
};

scope'' = src.set.inject scope' [
preOpt
{
_if = !__isStd__ && l.elem "std" composeFeatures';
inherit std;
}
{
_if = !__isStd__;
atom = atom' // {
inherit meta;
};
}
{
_if = __isStd__;
std = l.removeAttrs (extern // atom // { inherit meta; }) [ "std" ];
}
{
_if = __internal__test;
# information about the internal module system itself
# available to tests
__internal = {
# a copy of the global scope, for testing if values exist
# mostly for our internal testing functions
scope = scope'';
};
}
];
in
scope'';

Import = scopedImport scope;

g =
name: type:
let
path = dir + "/${name}";
file = src.file.parse name;
in
if type == "directory" then
{ ${name} = f ((src.lowerKeys self) // src.set.cond preOpt) path; }
else if type == "regular" && file.ext or null == "nix" && name != "mod.nix" then
{ ${file.name} = Import "${path}"; }
else
null # Ignore other file types
;

self' = src.lowerKeys (l.removeAttrs self [ "mod" ] // { outPath = src.rmNixSrcs dir; });

self =
let
mod = Import "${dir + "/mod.nix"}";
in
assert src.modIsValid mod dir;
src.filterMap g contents // mod;

in
if src.hasMod contents then
src.collectPublic self
else
# Base case: no module
{ };

atom' = l.removeAttrs (extern // atom // { inherit extern; }) [
"atom"
(baseNameOf dir)
];

atom =
let
fixed = src.fix f null dir;
in
src.set.inject fixed [
({ _if = __isStd__; } // src.pureBuiltins)
{
_if = l.elem "pkg_lib" meta.features.mod;
lib = extern.lib;
}
];
in
assert
!__internal__test
# older versions of Nix don't have the `warn` builtin
|| l.warn or l.trace ''
in ${toString ./default.nix}:
Internal testing functionality is enabled via the `__test` boolean.
This should never be `true` except in internal test runs.
'' true;
atom
184 changes: 57 additions & 127 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,143 +1,73 @@
let
l = builtins;
src = import ./src;
in
{
extern ? { },
features ? [ ],
# internal features of the composer function
stdFeatures ? src.stdToml.features.default or [ ],
composeFeatures ? src.composeToml.features.default,
# enable testing code paths
features ? null,
__internal__test ? false,
__isStd__ ? false,
}:
dir':
path':
let
dir = src.prepDir dir';

std = src.composeStd {
features = stdFeatures;
inherit __internal__test;
} ./std;

composeFeatures' = src.features.parse src.composeToml.features composeFeatures;

meta = {
features = {
mod = features;
compose = composeFeatures';
std = stdFeatures;
};
};

f =
f: pre: dir:
src = import ./src;
path = src.prepDir path';
config = builtins.fromTOML (builtins.readFile path);
features' =
let
contents = l.readDir dir;

preOpt = {
_if = pre != null;
inherit pre;
};

scope =
let
scope' = with src; {
mod = self';
builtins = errors.builtins;
import = errors.import;
scopedImport = errors.import;
__fetchurl = errors.fetch;
__currentSystem = errors.system;
__currentTime = errors.time;
__nixPath = errors.nixPath;
__storePath = errors.storePath;
__getEnv = errors.getEnv;
__getFlake = errors.import;
};

scope'' = src.set.inject scope' [
preOpt
{
_if = !__isStd__ && l.elem "std" composeFeatures';
inherit std;
}
{
_if = !__isStd__;
atom = atom' // {
inherit meta;
};
}
{
_if = __isStd__;
std = atom // {
inherit meta;
};
}
{
_if = __internal__test;
# information about the internal module system itself
# available to tests
__internal = {
# a copy of the global scope, for testing if values exist
# mostly for our internal testing functions
scope = scope'';
};
}
];
in
scope'';
featSet = config.features or { };
featIn = if features == null then featSet.default or [ ] else features;
in
src.features.parse featSet featIn;

Import = scopedImport scope;
backends = config.backends or { };
nix = backends.nix or { };
composer = config.composer or { };

g =
name: type:
root = nix.root or "nix";
extern =
let
fetcher = nix.fetcher or "native"; # native doesn't exist yet
conf = config.fetcher or { };
f = conf.${fetcher} or { };
root = f.root or "npins";
in
if fetcher == "npins" then
let
pins = import (dirOf path + "/${root}");
in
src.filterMap (
k: v:
let
path = dir + "/${name}";
file = src.file.parse name;
src = "${pins.${v.name or k}}/${v.sub or ""}";
val =
if v.import or false then
if v.args or [ ] != [ ] then builtins.foldl' (f: x: f x) (import src) v.args else import src
else
src;
in
if type == "directory" then
{ ${name} = f ((src.lowerKeys self) // src.set.cond preOpt) path; }
else if type == "regular" && file.ext or null == "nix" && name != "mod.nix" then
{ ${file.name} = Import "${path}"; }
if (v.optional or false && builtins.elem k features') || (!v.optional or false) then
{ "${k}" = val; }
else
null # Ignore other file types
;

self' = src.lowerKeys (l.removeAttrs self [ "mod" ] // { outPath = src.rmNixSrcs dir; });

self =
let
mod = Import "${dir + "/mod.nix"}";
in
assert src.modIsValid mod dir;
src.filterMap g contents // mod;

in
if src.hasMod contents then
src.collectPublic self
null
) config.fetch or { }
# else if fetcher = "native", etc
else
# Base case: no module
{ };

atom' = l.removeAttrs (extern // atom // { inherit extern; }) [
"atom"
(baseNameOf dir)
];
project = config.project or { };
meta = project.meta or { };

atom =
in
(import ./compose.nix) {
inherit extern __internal__test;
features = features';
composeFeatures =
let
fixed = src.fix f null dir;
features = composer.features or src.composeToml.features.default;
in
src.set.inject fixed [ ({ _if = __isStd__; } // src.pureBuiltins) ];
in
assert
!__internal__test
# older versions of Nix don't have the `warn` builtin
|| l.warn or l.trace ''
in ${toString ./default.nix}:
Internal testing functionality is enabled via the `__test` boolean.
This should never be `true` except in internal test runs.
'' true;
atom
src.features.parse src.composeToml.features features;
stdFeatures =
let
std = composer.std or { };
features = std.features or src.stdToml.features.default;
in
src.features.parse src.stdToml.features features;

__isStd__ = meta.__is_std__ or false;

} (dirOf path + "/${root}")
20 changes: 20 additions & 0 deletions dev.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[project]
name = "dev-tools"

[fetch.pkgs]
name = "nixpkgs"
import = true
args = [{}]

[composer]
features = ["std"]
std.features = ["pkg_lib"]

[backends.nix]
root = "dev"
# default when `eka` cli is ready
# fetcher = "native"
fetcher = "npins"

[fetcher.npins]
root = "npins"
8 changes: 1 addition & 7 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
let
compose = import ./.;
dev = compose {
extern = rec {
pins = import ./npins;
pkgs = import pins.nixpkgs { };
};
} ./dev;
dev = (import ./.) { } ./dev.toml;
in
dev.shell
Loading

0 comments on commit 398f00e

Please sign in to comment.