Skip to content

Commit

Permalink
chore: refactor for readability & tracability
Browse files Browse the repository at this point in the history
The default.nix logic should now be easier to follow with core concerns
factored out into a seperate `src` directory. Also, a better error is
reported to the user in the event a module is not in a valid format,
showing the exact location on disk where the failed module resides.
  • Loading branch information
nrdxp committed Aug 4, 2024
1 parent 46bace4 commit b6fc1de
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 89 deletions.
129 changes: 40 additions & 89 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,94 +1,40 @@
let
fix = import ./std/fix.nix;
filterMap = scopedImport { std = builtins; } ./std/set/filterMap.nix;
parse = scopedImport { std = builtins; } ./std/file/parse.nix;
strToPath = scopedImport { std = builtins; } ./std/path/strToPath.nix;
toLowerCase = scopedImport rec {
std = builtins;
mod = scopedImport { inherit std mod; } ./std/string/mod.nix;
} ./std/string/toLowerCase.nix;
cond = import ./std/set/cond.nix;
compose = import ./.;

lowerKeys = filterMap (k: v: { ${toLowerCase k} = v; });
filterMod = builtins.filterSource (
path: type:
let
file = parse (baseNameOf path);
in
(type == "regular" && file.ext or null != "nix")
|| (type == "directory" && !builtins.pathExists "${path}/mod.nix")
);

src = import ./src;
l = builtins;
in
{
extern ? { },
}:
dir:
with src;
let
std =
compose { } ./std
// filterMap (
k: v:
if
builtins.match "^import|^scopedImport|^builtins|^fetch.*|^current.*|^nixPath|^storePath" k != null
then
null
else
{ ${k} = v; }
) builtins;
atom' = builtins.removeAttrs (extern // atom // { inherit extern; }) [
"atom"
(baseNameOf dir)
];

filterPub = filterMap (
k: v:
let
s = toLowerCase k;
in
if s == k then null else { ${s} = v; }
);
std = composeStd ./std;

atom = fix (
f =
f: pre: dir':
let
# It is crucial that the directory is a path literal, not a string
# since the implicit copy to the /nix/store, which provides isolation,
# only happens for path literals.
dir = strToPath dir';

contents = builtins.readDir dir;

hasMod = contents."mod.nix" or null == "regular";

mod = if hasMod then scope "${dir + "/mod.nix"}" else { };
contents = l.readDir dir;

scope =
let
importErr = "Importing arbitrary Nix files is forbidden. Declare your dependencies via the module system instead.";
in
scopedImport (
{
inherit std;
atom = atom';
mod = lowerKeys (builtins.removeAttrs self [ "mod" ] // { outPath = filterMod dir; });
# override builtins, so they can only be accessed via `std`
builtins = abort "Please access builtins uniformly via the `std` scope.";
import = abort importErr;
scopedImport = abort importErr;
__fetchurl = abort "Ad hoc fetching is illegal. Declare dependencies statically in the manifest instead.";
__currentSystem = abort "Accessing the current system is impure. Declare supported systems in the manifest.";
__currentTime = abort "Accessing the current time is impure & illegal.";
__nixPath = abort "The NIX_PATH is an impure feature, and therefore illegal.";
__storePath = abort "Making explicit dependencies on store paths is illegal.";
scope = injectPrevious pre {
inherit std;
atom = atom';
mod = lowerKeys (l.removeAttrs self [ "mod" ] // { outPath = filterMod dir; });
builtins = errors.builtins;
import = errors.import;
scopedImport = errors.import;
__fetchurl = errors.fetch;
__currentSystem = errors.system;
__currentTime = errors.time;
__nixPath = errors.nixPath;
__storePath = errors.storePath;
};

}
// cond {
_if = pre != null;
inherit pre;
}
);
Import = scopedImport scope;

g =
name: type:
Expand All @@ -97,27 +43,32 @@ let
file = parse name;
in
if type == "directory" then
{
${name} = f (
(lowerKeys self)
// cond {
_if = pre != null;
inherit pre;
}
) path;
}
{ ${name} = f (injectPrevious pre (lowerKeys self)) path; }
else if type == "regular" && file.ext or null == "nix" && name != "mod.nix" then
{ ${file.name} = scope "${path}"; }
{ ${file.name} = Import "${path}"; }
else
null # Ignore other file types
;

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

in
if !hasMod then
{ } # Base case: no module
else
if hasMod contents then
filterPub self
) null dir;
else
# Base case: no module
{ };

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

atom = fix f null dir;
in
atom
62 changes: 62 additions & 0 deletions src/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# to avoid excessive recursion that can lead to inefficiency or errors
# we cannot compose the individual pieces of the module composer as a regular module
# so instead we abstract them out here, into a manually specified "psuedo-module"
# to keep the core impelementation clean
let
compose = import ../.;
fix = import ../std/fix.nix;
cond = import ../std/set/cond.nix;
filterMap = scopedImport { std = builtins; } ../std/set/filterMap.nix;
strToPath = scopedImport { std = builtins; } ../std/path/strToPath.nix;
parse = scopedImport { std = builtins; } ../std/file/parse.nix;
toLowerCase = scopedImport rec {
std = builtins;
mod = scopedImport { inherit std mod; } ../std/string/mod.nix;
} ../std/string/toLowerCase.nix;
stdFilter = import ./stdFilter.nix;
in
{
inherit
parse
fix
filterMap
strToPath
cond
;
lowerKeys = filterMap (k: v: { ${toLowerCase k} = v; });
filterPub = filterMap (
k: v:
let
s = toLowerCase k;
in
if s == k then null else { ${s} = v; }
);
filterMod = builtins.filterSource (
path: type:
let
file = parse (baseNameOf path);
in
(type == "regular" && file.ext or null != "nix")
|| (type == "directory" && !builtins.pathExists "${path}/mod.nix")
);
errors = import ./errors.nix;
composeStd = path: compose { } path // filterMap stdFilter builtins;

modIsValid =
mod: dir:
builtins.isAttrs mod
|| throw ''
The following module does not evaluate to a valid attribute set:
${toString dir}/mod.nix
'';

injectPrevious =
pre: set:
set
// cond {
_if = pre != null;
inherit pre;
};

hasMod = contents: contents."mod.nix" or null == "regular";
}
9 changes: 9 additions & 0 deletions src/errors.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
import = abort "Importing arbitrary Nix files is forbidden. Declare your dependencies via the module system instead.";
builtins = abort "Please access builtins uniformly via the `std` scope.";
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.";
time = abort "Accessing the current time is impure & illegal.";
nixPath = abort "The NIX_PATH is an impure feature, and therefore illegal.";
storePath = abort "Making explicit dependencies on store paths is illegal.";
}
7 changes: 7 additions & 0 deletions src/stdFilter.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
k: v:
if
builtins.match "^import|^scopedImport|^builtins|^fetch.*|^current.*|^nixPath|^storePath" k != null
then
null
else
{ ${k} = v; }

0 comments on commit b6fc1de

Please sign in to comment.