From 557d20ccaca3d46bf232a9203e821a2fef6ba0be Mon Sep 17 00:00:00 2001
From: li
Date: Wed, 18 Dec 2024 13:16:09 +0100
Subject: [PATCH 1/4] feat: implement minimal `use` scope for external deps
---
src/core/compose.nix | 6 +++++-
src/dev/shell.nix | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/core/compose.nix b/src/core/compose.nix
index 55b957d..2a149dc 100644
--- a/src/core/compose.nix
+++ b/src/core/compose.nix
@@ -134,6 +134,10 @@ let
_if = __isStd__;
std = l.removeAttrs (extern // atom) [ "std" ];
}
+ {
+ _if = !__isStd__;
+ use = l.removeAttrs extern [ "std" ];
+ }
{
_if = __internal__test;
# information about the internal module system itself
@@ -197,7 +201,7 @@ let
# Base case: no module
{ };
- atomScope = l.removeAttrs (extern // atom // { inherit extern; }) [
+ atomScope = l.removeAttrs atom [
"atom"
(baseNameOf par)
];
diff --git a/src/dev/shell.nix b/src/dev/shell.nix
index 8c77a8f..e22c625 100644
--- a/src/dev/shell.nix
+++ b/src/dev/shell.nix
@@ -1,5 +1,5 @@
{
- pkgs ? atom.pkgs,
+ pkgs ? use.pkgs,
}:
pkgs.mkShell {
packages = with pkgs; [
From 7baf1561e39446c89d9fa61d1d229daff6f45415 Mon Sep 17 00:00:00 2001
From: li
Date: Mon, 16 Dec 2024 14:49:39 +0100
Subject: [PATCH 2/4] style: self-documenting code for importAtom
---
src/core/importAtom.nix | 73 ++++++++++++++++++++++++-----------------
1 file changed, 43 insertions(+), 30 deletions(-)
diff --git a/src/core/importAtom.nix b/src/core/importAtom.nix
index f86ed6f..1d8a0cb 100644
--- a/src/core/importAtom.nix
+++ b/src/core/importAtom.nix
@@ -45,6 +45,7 @@ let
nix = backend.nix or { };
root = mod.prepDir (dirOf path);
+
src = builtins.seq id (
let
file = mod.parse (baseNameOf path);
@@ -52,42 +53,54 @@ let
in
builtins.substring 0 (len - 1) file.name
);
+
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
- mod.filterMap (
- k: v:
+ # TODO native doesn't exist yet
+ fetcher = nix.fetcher or "native";
+ throwMissingNativeFetcher = abort "Native fetcher isn't implemented yet";
+
+ fetcherConfig = config.fetcher or { };
+ npinRoot = fetcherConfig.npin.root or "npins";
+ pins = import (dirOf path + "/${npinRoot}");
+
+ fetchEnabledNpinsDep =
+ depName: depConfig:
let
- src = "${pins.${v.name or k}}/${v.subdir or ""}";
- val =
- if v.import or false then
- if v.args or [ ] != [ ] then
- builtins.foldl' (
- f: x:
- let
- intersect = x // (builtins.intersectAttrs x extern);
- in
- if builtins.isAttrs x then f intersect else f x
- ) (import src) v.args
+ depIsEnabled =
+ (depConfig.optional or false && builtins.elem depName features') || (!depConfig.optional or false);
+
+ npinSrc = "${pins.${depConfig.name or depName}}/${depConfig.subdir or ""}";
+
+ applyArguments =
+ appliedFunction: nextArgument:
+ let
+ argsFromDeps = depConfig.argsFromDeps or true && builtins.isAttrs nextArgument;
+ argIntersectedwithDeps = nextArgument // (builtins.intersectAttrs nextArgument extern);
+ in
+ if argsFromDeps nextArgument then
+ appliedFunction argIntersectedwithDeps
+ else
+ appliedFunction nextArgument;
+
+ dependency =
+ if depConfig.import or false then
+ if depConfig.args or [ ] != [ ] then
+ builtins.foldl' applyArguments (import npinSrc) depConfig.args
else
- import src
+ import npinSrc
else
- src;
+ npinSrc;
in
- if (v.optional or false && builtins.elem k features') || (!v.optional or false) then
- { "${k}" = val; }
- else
- null
- ) config.fetch or { }
- # else if fetcher = "native", etc
+ if depIsEnabled then { "${depName}" = dependency; } else null;
+
+ npinsDeps = mod.filterMap fetchEnabledNpinsDep config.fetch or { };
+
+ in
+ if fetcher == "npins" then
+ npinsDeps
+ else if fetcher == "native" then
+ throwMissingNativeFetcher
else
{ };
From d307f75ffbaf74554f3301f88684466c8b802f57 Mon Sep 17 00:00:00 2001
From: li
Date: Thu, 19 Dec 2024 15:33:01 +0100
Subject: [PATCH 3/4] feat: added optional top-level `system`
---
src/core/compose.nix | 12 ++++++++++--
src/core/errors.nix | 3 ++-
src/core/importAtom.nix | 8 +++++---
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/src/core/compose.nix b/src/core/compose.nix
index 2a149dc..de475a5 100644
--- a/src/core/compose.nix
+++ b/src/core/compose.nix
@@ -56,11 +56,13 @@
let
l = builtins;
core = import ./mod.nix;
+
in
-{
+input@{
src,
root,
config,
+ system ? null,
extern ? { },
features ? [ ],
# internal features of the composer function
@@ -78,6 +80,8 @@ let
inherit __internal__test;
} (../. + "/std@.toml");
+ systemIsDefinedAndEnabled = system != null && l.elem "system" features;
+
coreFeatures' = core.features.resolve core.coreToml.features coreFeatures;
stdFeatures' = core.features.resolve core.stdToml.features stdFeatures;
@@ -112,7 +116,7 @@ let
import = errors.import;
scopedImport = errors.import;
__fetchurl = errors.fetch;
- __currentSystem = errors.system;
+ __currentSystem = errors.currentSystem;
__currentTime = errors.time 0;
__nixPath = errors.nixPath [ ];
__storePath = errors.storePath;
@@ -134,6 +138,10 @@ let
_if = __isStd__;
std = l.removeAttrs (extern // atom) [ "std" ];
}
+ {
+ _if = !__isStd__;
+ system = if systemIsDefinedAndEnabled then input.system else core.errors.system;
+ }
{
_if = !__isStd__;
use = l.removeAttrs extern [ "std" ];
diff --git a/src/core/errors.nix b/src/core/errors.nix
index b7e3f42..f86b92c 100644
--- a/src/core/errors.nix
+++ b/src/core/errors.nix
@@ -44,7 +44,8 @@ in
modFromDir (stripParentDir par path);
import = abort "Importing arbitrary Nix files is forbidden. Declare your dependencies via the module system instead.";
fetch = abort "Ad hoc fetching is illegal. Declare dependencies statically in the manifest instead.";
- system = abort "Accessing the current system is impure. Declare supported systems in the manifest.";
+ currentSystem = abort "Accessing the current system is impure. Declare system in the manifest.";
+ system = abort "`system` has been accessed and is undefined";
time = _: warn "currentTime: Ignoring request for current time, returning: 0";
nixPath = _: warn "nixPath: ignoring impure NIX_PATH request, returning: []";
storePath = abort "Making explicit dependencies on store paths is illegal.";
diff --git a/src/core/importAtom.nix b/src/core/importAtom.nix
index 1d8a0cb..8dfb366 100644
--- a/src/core/importAtom.nix
+++ b/src/core/importAtom.nix
@@ -16,6 +16,7 @@
valid input (and the CLI should type check on it's end)
*/
{
+ system ? null,
features ? null,
__internal__test ? false,
}:
@@ -109,11 +110,12 @@ let
in
mod.compose {
inherit
+ src
+ root
+ config
+ system
extern
__internal__test
- config
- root
- src
;
features = features';
coreFeatures =
From e63ee646693196efaf80351231207f3d17c48143 Mon Sep 17 00:00:00 2001
From: li
Date: Thu, 19 Dec 2024 22:14:04 +0100
Subject: [PATCH 4/4] feat: importAtom: implemented local dependencies
---
src/core/importAtom.nix | 218 +++++++++++++++++++++++-----------------
1 file changed, 124 insertions(+), 94 deletions(-)
diff --git a/src/core/importAtom.nix b/src/core/importAtom.nix
index 8dfb366..c85aa80 100644
--- a/src/core/importAtom.nix
+++ b/src/core/importAtom.nix
@@ -15,119 +15,149 @@
revalidating on the Nix side as an extra precaution, but initially, we just assume we have a
valid input (and the CLI should type check on it's end)
*/
-{
- system ? null,
- features ? null,
- __internal__test ? false,
-}:
-path':
let
- mod = import ./mod.nix;
+ importAtom =
+ importAtomArgs@{
+ system ? null,
+ features ? null,
+ __internal__test ? false,
+ }:
+ path':
+ let
+ mod = import ./mod.nix;
- path = mod.prepDir path';
+ path = mod.prepDir path';
+ root = mod.prepDir (dirOf path); # TODO Is prepDir required twice?
- file = builtins.readFile path;
- config = builtins.fromTOML file;
- atom = config.atom or { };
- id = builtins.seq version (atom.id or (mod.errors.missingAtom path' "id"));
- version = atom.version or (mod.errors.missingAtom path' "version");
+ file = builtins.readFile path;
+ config = builtins.fromTOML file;
+ atom = config.atom or { };
+ id = builtins.seq version (atom.id or (mod.errors.missingAtom path' "id"));
+ version = atom.version or (mod.errors.missingAtom path' "version");
+ core = config.core or { };
+ std = config.std or { };
+ meta = atom.meta or { };
- core = config.core or { };
- std = config.std or { };
+ features =
+ let
+ atomFeatures = importAtomArgs.features or null;
+ featSet = config.features or { };
+ default = featSet.default or [ ];
+ argsHaveNoFeatures = atomFeatures == null;
+ featIn = if argsHaveNoFeatures then default else atomFeatures;
+ in
+ mod.features.resolve featSet featIn;
- features' =
- let
- featSet = config.features or { };
- featIn = if features == null then featSet.default or [ ] else features;
- in
- mod.features.resolve featSet featIn;
+ backend = config.backend or { };
+ nix = backend.nix or { };
- backend = config.backend or { };
- nix = backend.nix or { };
+ src = builtins.seq id (
+ let
+ file = mod.parse (baseNameOf path);
+ len = builtins.stringLength file.name;
+ in
+ builtins.substring 0 (len - 1) file.name
+ );
- root = mod.prepDir (dirOf path);
+ extern =
+ let
+ # TODO native doesn't exist yet
+ fetcher = nix.fetcher or "native";
+ throwMissingNativeFetcher = abort "Native fetcher isn't implemented yet";
- src = builtins.seq id (
- let
- file = mod.parse (baseNameOf path);
- len = builtins.stringLength file.name;
- in
- builtins.substring 0 (len - 1) file.name
- );
+ fetcherConfig = config.fetcher or { };
+ npinRoot = fetcherConfig.npin.root or "npins";
+ pins = import (dirOf path + "/${npinRoot}");
- extern =
- let
- # TODO native doesn't exist yet
- fetcher = nix.fetcher or "native";
- throwMissingNativeFetcher = abort "Native fetcher isn't implemented yet";
+ local = config.local or { };
- fetcherConfig = config.fetcher or { };
- npinRoot = fetcherConfig.npin.root or "npins";
- pins = import (dirOf path + "/${npinRoot}");
+ isDepEnabled =
+ depName: depConfig:
+ let
+ optional = depConfig.optional or false;
+ featureIsEnabled = builtins.elem depName features;
+ in
+ (optional && featureIsEnabled) || (!optional);
- fetchEnabledNpinsDep =
- depName: depConfig:
- let
- depIsEnabled =
- (depConfig.optional or false && builtins.elem depName features') || (!depConfig.optional or false);
+ obtainLocalDep =
+ depName: depConfig:
+ let
+ depManifest = "${root}/${depConfig.path}";
+ depIsEnabled = isDepEnabled depName depConfig;
+ dependency = importAtom { inherit system; } depManifest;
+ in
+ if depIsEnabled then { "${depName}" = dependency; } else null;
- npinSrc = "${pins.${depConfig.name or depName}}/${depConfig.subdir or ""}";
+ obtainedLocalDeps = mod.filterMap obtainLocalDep local;
- applyArguments =
- appliedFunction: nextArgument:
+ localDeps = if local != { } then obtainedLocalDeps else { };
+
+ fetchEnabledNpinsDep =
+ depName: depConfig:
let
- argsFromDeps = depConfig.argsFromDeps or true && builtins.isAttrs nextArgument;
- argIntersectedwithDeps = nextArgument // (builtins.intersectAttrs nextArgument extern);
+ importDep = depConfig.import or false;
+ depArgs = depConfig.args or [ ];
+ depHasArgs = depArgs != [ ];
+ depIsEnabled = isDepEnabled depName depConfig;
+
+ npinSrc = "${pins.${depConfig.name or depName}}/${depConfig.subdir or ""}";
+
+ applyArguments =
+ appliedFunction: nextArgument:
+ let
+ argsFromDeps = depConfig.argsFromDeps or true && builtins.isAttrs nextArgument;
+ argIntersectedwithDeps = nextArgument // (builtins.intersectAttrs nextArgument extern);
+ in
+ if argsFromDeps nextArgument then
+ appliedFunction argIntersectedwithDeps
+ else
+ appliedFunction nextArgument;
+
+ importedSrcWithArgs = builtins.foldl' applyArguments (import npinSrc) depArgs;
+
+ importedSrc = if depHasArgs then importedSrcWithArgs else import npinSrc;
+
+ dependency = if importDep then importedSrc else npinSrc;
in
- if argsFromDeps nextArgument then
- appliedFunction argIntersectedwithDeps
- else
- appliedFunction nextArgument;
-
- dependency =
- if depConfig.import or false then
- if depConfig.args or [ ] != [ ] then
- builtins.foldl' applyArguments (import npinSrc) depConfig.args
- else
- import npinSrc
+ if depIsEnabled then { "${depName}" = dependency; } else null;
+
+ npinsDeps = mod.filterMap fetchEnabledNpinsDep config.fetch or { };
+
+ externalDeps =
+ if fetcher == "npins" then
+ npinsDeps
+ else if fetcher == "native" then
+ throwMissingNativeFetcher
else
- npinSrc;
- in
- if depIsEnabled then { "${depName}" = dependency; } else null;
+ { };
- npinsDeps = mod.filterMap fetchEnabledNpinsDep config.fetch or { };
+ in
+ localDeps // externalDeps;
in
- if fetcher == "npins" then
- npinsDeps
- else if fetcher == "native" then
- throwMissingNativeFetcher
- else
- { };
+ mod.compose {
+ inherit
+ src
+ root
+ config
+ system
+ extern
+ features
+ __internal__test
+ ;
+ coreFeatures =
+ let
+ feat = core.features or mod.coreToml.features.default;
+ in
+ mod.features.resolve mod.coreToml.features feat;
+ stdFeatures =
+ let
+ feat = std.features or mod.stdToml.features.default;
+ in
+ mod.features.resolve mod.stdToml.features feat;
- meta = atom.meta or { };
+ __isStd__ = meta.__is_std__ or false;
+ };
in
-mod.compose {
- inherit
- src
- root
- config
- system
- extern
- __internal__test
- ;
- features = features';
- coreFeatures =
- let
- feat = core.features or mod.coreToml.features.default;
- in
- mod.features.resolve mod.coreToml.features feat;
- stdFeatures =
- let
- feat = std.features or mod.stdToml.features.default;
- in
- mod.features.resolve mod.stdToml.features feat;
-
- __isStd__ = meta.__is_std__ or false;
-}
+importAtom