Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
dermetfan committed Sep 30, 2022
1 parent bda93c6 commit 1ac9aa1
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 9 deletions.
130 changes: 127 additions & 3 deletions nix/lib.nix
@@ -1,9 +1,9 @@
inputs: let
inherit (inputs.nixpkgs.lib) evalModules filterAttrs;
inherit (inputs.nixpkgs.lib) evalModules filterAttrs collect isDerivation nameValuePair getAttrFromPath imap0 optional showAttrPath;
inherit (builtins) mapAttrs;

augmentPkgs = import ./augmentPkgs.nix inputs;

in rec {
evalAction = {
tasks,
rootDir ? null,
Expand Down Expand Up @@ -92,7 +92,7 @@ inputs: let
];
})
.config;
in rec {

ciceroFromStd = {
actions,
tasks,
Expand Down Expand Up @@ -143,4 +143,128 @@ in rec {
tullia = tulliaStd.tullia.${system};
cicero = tulliaStd.cicero.${system};
};

/*
Like `mapAttrsRecursiveCond` from nixpkgs
but the condition and mapping functions
take the attribute path as their first parameter.
*/
mapAttrsRecursiveCondWithPath = cond: f:
let
recurse = path: __mapAttrs (name: value:
let
newPath = path ++ [name];
g =
if __isAttrs value && cond newPath value
then recurse
else f;
in g newPath value
);
in recurse [];

/*
Returns the paths to values that satisfy the given predicate in the given attrset.
The predicate and recursion predicate functions take path and value as their parameters.
If the recursion prediate function is null, it defaults to the negated predicate.
*/
findAttrsRecursiveCond = cond: pred: attrs:
collect __isList (
mapAttrsRecursiveCondWithPath
(
if cond == null
then p: v: !pred p v
else cond
)
(p: v:
if pred p v
then p
else null
)
attrs
);

findAttrsRecursive = findAttrsRecursiveCond null;

# Returns a new attrset from the result of `findAttrsRecursiveCond` using the given naming function.
findFlattenAttrsRecursiveCond = cond: pred: mkName: attrs:
__listToAttrs (
map
(path: nameValuePair
(mkName path)
(getAttrFromPath path attrs)
)
(findAttrsRecursiveCond cond pred attrs)
);

drvToTaskRecursiveCond = cond: mkName: attrs:
__listToAttrs (
map
(path: nameValuePair
(mkName path)
(let
v = getAttrFromPath path attrs;
in {config, lib, ...}: {
preset.nix.enable = true;

drvToTask = with lib; {
attrPath = mkOption {
type = with types; listOf str;
default = path;
readOnly = true;
};

installable = mkOption {
type = types.str;
};
};

command.text = ''
attr=${lib.escapeShellArg config.drvToTask.installable}
echo Building "$attr"…
echo -e '\tdrv: '${lib.escapeShellArg (__unsafeDiscardStringContext v.drvPath)}
echo -e '\tout: '${lib.escapeShellArg (__unsafeDiscardStringContext v.outPath)}
nix build -L "$attr"
'';
})
)
(findAttrsRecursiveCond cond (_: isDerivation) attrs)
);

drvToTaskRecursive = drvToTaskRecursiveCond null;

flakeOutputTasks = path: flake: flakeUrl:
let
mkFlakeFragement = p: showAttrPath (path ++ p);
in __mapAttrs
(_: task: {config, lib, ...}: {
imports = [task];

options.flakeOutputTask.flakeUrl = with lib; mkOption {
type = types.str;
};

config.drvToTask.installable =
"${config.flakeOutputTask.flakeUrl}#${mkFlakeFragement config.drvToTask.attrPath}";
})
(
drvToTaskRecursive
mkFlakeFragement
(getAttrFromPath path flake.outputs)
);

/*
Returns attrset of tullia tasks named with the given prefix
that run the corresponding task and depend on each other in the order given.
*/
taskSequence = prefix: tasks: taskNames: __listToAttrs (
imap0 (i: taskName: nameValuePair
(prefix + taskName)
({...}: {
imports = [tasks.${taskName}];
after = optional (i > 0) (
prefix + __elemAt taskNames (i - 1)
);
})
) taskNames
);
}
16 changes: 10 additions & 6 deletions nix/module.nix
Expand Up @@ -48,16 +48,16 @@
pred
(
let
o = options.${k};
o = options.${k} or null;
in
if lib.isOption options.${k}
then options.${k}.type.getSubOptions []
else options.${k}
if lib.isOption o
then o.type.getSubOptions []
else o
)
)
(
lib.filterAttrs
(k: pred (p ++ [k]) options.${k})
(k: pred (p ++ [k]) options.${k} or null)
values
);
in
Expand Down Expand Up @@ -1261,7 +1261,11 @@ in {
(
# Remove read-only options to avoid an evaluation error.
filterOptionValues
(path: option: value: !option.readOnly or false)
(path: option: value:
if option == null
then false
else !option.readOnly or false
)
(taskType.getSubOptions [])
task
)
Expand Down

0 comments on commit 1ac9aa1

Please sign in to comment.