-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from ekala-project/init-manifest
feat: initial manifest parser
- Loading branch information
Showing
13 changed files
with
261 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.