Implement the getSrc combinator
Allows the use of ${l.src ./foo ./bar} to generate a sparse source tree, used for the do script. This disects the source tree into those piece actually needed to build the target. - boosts clarity as all sources have to be explicitly specified - targets that don't use eachothers sources should be independent nowmaster
parent
d0d5b30f6a
commit
69bd805cc6
11
builder.nix
11
builder.nix
|
@ -1,6 +1,6 @@
|
||||||
buildArgs@{ lib ? import ./lib.nix {}, nixpkgs ? <nixpkgs>, pkgs ? import nixpkgs {}, root, cwd, filter ? [] }:
|
buildArgs@{ lib ? import ./lib.nix {}, nixpkgs ? <nixpkgs>, pkgs ? import nixpkgs {}, root, cwd, filter ? [] }:
|
||||||
let
|
let
|
||||||
inherit (lib) searchPath whichdo d1 d2;
|
inherit (lib) searchPath whichdo d1 d2 getSrc;
|
||||||
|
|
||||||
resolve = path: let
|
resolve = path: let
|
||||||
builder = (whichdo path);
|
builder = (whichdo path);
|
||||||
|
@ -11,15 +11,16 @@ let
|
||||||
with pkgs.lib;
|
with pkgs.lib;
|
||||||
with builtins;
|
with builtins;
|
||||||
let
|
let
|
||||||
# Funktionalise pkgs; our main entry point to resolve default*nix build scripts.
|
|
||||||
getSrc = filterSource
|
|
||||||
(path: type: baseNameOf path != ".git" && baseNameOf path != ".envrc" && (all (x: path != x) filter));
|
|
||||||
|
|
||||||
|
# CWD relative to source root
|
||||||
rcwd = dirOf (removePrefix (root + "/") builder);
|
rcwd = dirOf (removePrefix (root + "/") builder);
|
||||||
|
|
||||||
|
# Funktionalise pkgs; our main entry point to resolve default*nix build
|
||||||
|
# scripts.
|
||||||
funcPkgs = {
|
funcPkgs = {
|
||||||
__functor = self: arg: resolve arg;
|
__functor = self: arg: resolve arg;
|
||||||
inherit pkgs getSrc cwd rcwd;
|
src = getSrc root rcwd filter;
|
||||||
|
inherit pkgs cwd rcwd;
|
||||||
};
|
};
|
||||||
|
|
||||||
_builder = let
|
_builder = let
|
||||||
|
|
77
lib.nix
77
lib.nix
|
@ -1,8 +1,10 @@
|
||||||
{ lib ? import <nixpkgs/lib> }:
|
{ lib ? import <nixpkgs/lib> }:
|
||||||
let
|
let
|
||||||
inherit (builtins) baseNameOf dirOf length genList pathExists;
|
inherit (builtins) baseNameOf dirOf length genList pathExists filterSource
|
||||||
inherit (lib) take splitString concatStringsSep last foldl foldr head
|
isString match replaceStrings;
|
||||||
tail singleton removePrefix hasSuffix removeSuffix flatten crossLists reverseList;
|
inherit (lib) take splitString concatStringsSep last foldl foldr head tail
|
||||||
|
singleton removePrefix hasSuffix removeSuffix flatten crossLists reverseList
|
||||||
|
all any unique;
|
||||||
butlast = list: take (length list - 1) list;
|
butlast = list: take (length list - 1) list;
|
||||||
|
|
||||||
doFileSuffix = "do";
|
doFileSuffix = "do";
|
||||||
|
@ -14,16 +16,21 @@ let
|
||||||
[ doFileSuffix ]
|
[ doFileSuffix ]
|
||||||
(tail (splitString "." fn))));
|
(tail (splitString "." fn))));
|
||||||
|
|
||||||
|
genPathlist = path: let
|
||||||
|
pathlist = (splitString "/" path);
|
||||||
|
foldedpaths = foldr (a: b:
|
||||||
|
let
|
||||||
|
h = if length b == 0 then "" else head b;
|
||||||
|
in [ (h + a + "/") ] ++ b) [] (tail (reverseList pathlist));
|
||||||
|
in foldedpaths;
|
||||||
|
|
||||||
searchPath = path:
|
searchPath = path:
|
||||||
let
|
let
|
||||||
pathlist = (splitString "/" path);
|
pathlist = (splitString "/" path);
|
||||||
pat = (last pathlist);
|
pat = (last pathlist);
|
||||||
doFile = path + "." + doFileSuffix;
|
doFile = path + "." + doFileSuffix;
|
||||||
patlist = genPatterns pat;
|
patlist = genPatterns pat;
|
||||||
foldedpaths = foldr (a: b:
|
foldedpaths = genPathlist path;
|
||||||
let
|
|
||||||
h = if length b == 0 then "" else head b;
|
|
||||||
in [ (h + a + "/") ] ++ b) [] (tail (reverseList pathlist));
|
|
||||||
pths = crossLists (p: pat: p + pat) [ foldedpaths patlist ];
|
pths = crossLists (p: pat: p + pat) [ foldedpaths patlist ];
|
||||||
in [ doFile ] ++ pths;
|
in [ doFile ] ++ pths;
|
||||||
|
|
||||||
|
@ -31,10 +38,13 @@ let
|
||||||
pathlist = searchPath path;
|
pathlist = searchPath path;
|
||||||
in foldl (res: p: if res == "" then if pathExists p then p else res else res) "" pathlist;
|
in foldl (res: p: if res == "" then if pathExists p then p else res else res) "" pathlist;
|
||||||
|
|
||||||
|
# Redo's $1, the full name of the target
|
||||||
d1 = path: pat: let
|
d1 = path: pat: let
|
||||||
dir = (dirOf pat) + "/";
|
dir = (dirOf pat) + "/";
|
||||||
in removePrefix dir path;
|
in removePrefix dir path;
|
||||||
|
|
||||||
|
# Redo's $2, the full name of the target or the name stripped by a suffix for
|
||||||
|
# a default.* target.
|
||||||
d2 = path: pat: let
|
d2 = path: pat: let
|
||||||
dir = (dirOf pat) + "/";
|
dir = (dirOf pat) + "/";
|
||||||
_path = removePrefix dir path;
|
_path = removePrefix dir path;
|
||||||
|
@ -42,8 +52,59 @@ let
|
||||||
_out = removeSuffix _pat _path;
|
_out = removeSuffix _pat _path;
|
||||||
in if _out == "" then _path else _out;
|
in if _out == "" then _path else _out;
|
||||||
|
|
||||||
|
# The varargs capture combinator used by getSrc.
|
||||||
|
# Fuctions calling this are expected to supply a function treating one
|
||||||
|
# argument to the final function and a second function that operates on the
|
||||||
|
# whole list of arguments. Call the final function with literal null to
|
||||||
|
# trigger evaluation.
|
||||||
|
captureFunc = argFun: f: {
|
||||||
|
args = [];
|
||||||
|
__functor = self: a: let
|
||||||
|
_a = argFun a;
|
||||||
|
in if a == null
|
||||||
|
then f self.args
|
||||||
|
else self // { args = self.args ++ [ _a ]; };
|
||||||
|
__toString = self: f self.args;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Resolve a src given as string relative to cwd and root.
|
||||||
|
resolveSrc = root: rcwd: a: let
|
||||||
|
sanitize = s: let _s = replaceStrings [ "/./" ] ["/"] s; in if s != _s then sanitize _s else s;
|
||||||
|
_a = toString (/. + (root + "/" + rcwd + "/" + (sanitize a)));
|
||||||
|
in
|
||||||
|
if isString a then _a else toString a;
|
||||||
|
|
||||||
|
# Add all preceding paths to a src down to the root. Otherwise
|
||||||
|
# builtins.filterSource will reject it.
|
||||||
|
augmentedSrcs = root: srcs: let
|
||||||
|
aug = map (s: singleton s ++ (map (p: root + (removeSuffix "/" p)) (genPathlist (removePrefix root s)))) srcs;
|
||||||
|
in unique (flatten aug);
|
||||||
|
|
||||||
|
# The source tree resolver combinator.
|
||||||
|
# Takes the source root and cwd of the current builder and a list of paths
|
||||||
|
# that shall always be rejected.
|
||||||
|
#
|
||||||
|
# Returns a filter that accepts zero to n paths relative to cwd. Captures the
|
||||||
|
# whole source tree when called with zero arguments.
|
||||||
|
getSrc = root: rcwd: rejected:
|
||||||
|
captureFunc (resolveSrc root rcwd) (srcs: let
|
||||||
|
|
||||||
|
rejector = path: (all (x: path != x) rejected);
|
||||||
|
_srcs = (augmentedSrcs root srcs);
|
||||||
|
srcFilter = path: if srcs == []
|
||||||
|
then true # No explicit srcs means: Take the whole source tree!
|
||||||
|
else (any (x: path == x) _srcs);
|
||||||
|
filter = (path: type:
|
||||||
|
(baseNameOf path != ".git") &&
|
||||||
|
(baseNameOf path != ".envrc") &&
|
||||||
|
(rejector path) &&
|
||||||
|
(srcFilter path));
|
||||||
|
in (builtins.filterSource filter root));
|
||||||
|
|
||||||
self = {
|
self = {
|
||||||
inherit searchPath doFileSuffix whichdo d1 d2;
|
inherit doFileSuffix whichdo d1 d2 getSrc;
|
||||||
|
# For testing. To be removed.
|
||||||
|
inherit searchPath augmentedSrcs genPathlist captureFunc;
|
||||||
};
|
};
|
||||||
|
|
||||||
in self
|
in self
|
||||||
|
|
Loading…
Reference in New Issue