Skip to content

Commit

Permalink
feat: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jakehamilton committed Dec 25, 2021
0 parents commit 45f03d7
Show file tree
Hide file tree
Showing 36 changed files with 639 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
result
.DS_Store
136 changes: 136 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
description = "Plus Ultra";

inputs = {
# NixPkgs
nixpkgs.url = "nixpkgs/nixos-21.11";
nixpkgs-unstable.url = "nixpkgs/nixos-unstable";

# Home Manager
home-manager.url = "github:nix-community/home-manager/release-21.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";

# macOS Support
darwin.url = "github:lnl7/nix-darwin/master";
darwin.inputs.nixpkgs.follows = "nixpkgs";

# Utils
utils.url = "github:gytis-ivaskevicius/flake-utils-plus";

# Extras
nixos-hardware.url = "github:nixos/nixos-hardware";
nixos-hardware.inputs.nixpkgs.follows = "nixpkgs";
};

outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, home-manager, utils
, nixos-hardware, darwin, ... }:
let lib = import ./lib inputs;
in utils.lib.mkFlake {
inherit self inputs lib;

channelsConfig = { allowUnfree = true; };

hosts = lib.mkHosts { src = ./machines; };
# hosts.jasper.modules = builtins.trace (lib.getFiles ./machines)
# (lib.getFiles ./machines);
};
}
6 changes: 6 additions & 0 deletions lib/bool.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
inputs@{ lib, ... }:

{
is = x: y: x == y;
not = x: y: x != y;
}
54 changes: 54 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
inputs@{ nixpkgs, home-manager, darwin, utils, nixos-hardware, ... }:

let
# This file is the entrypoint for the lib system and
# needs to define a few functions itself since we can't
# yet import the full lib.

# Compose two functions.
compose = f: g: x: f (g x);

# The flipped version of `builtins.getAttr`. This function
# gets passed the set *first* and then the attribute to access.
getAttr' = set: attr: set.${attr};

# Inputs comes from `flake.nix` and has a `self` property.
# We can't use `self` in lib code since it will cause infinite
# recursion.
inputModules = builtins.removeAttrs inputs [ "self" ];

# Merge two sets.
merge = a: b: a // b;

# Construct a new lib set given an array of sets to merge with.
mkLib =
(libs: nixpkgs.lib.extend (final: prev: nixpkgs.lib.foldl merge prev libs));

# A helper for pulling out libs from flake inputs. This way we
# can construct a single `lib` set with all of the functions from
# any input's `lib` attribute.
getLibs = inputs:
(builtins.filter (builtins.hasAttr "lib")
(builtins.map (getAttr' inputs) (builtins.attrNames inputs)));

# Get a list of files in a directory.
getFiles = path: (builtins.attrNames (builtins.readDir path));

# Get a list of files in a directory that are *not* "default.nix".
getModuleFiles =
compose (builtins.filter (name: name != "default.nix")) getFiles;

# Merge together libs from flake inputs.
baseLib = mkLib (getLibs inputModules);

# Construct our lib instance using a fixed point for self-referencing.
# This makes it so each lib module can reference `lib` itself to get
# access to other modules.
lib = nixpkgs.lib.fix (self:
let attrs = inputModules // { lib = self // baseLib; };
in builtins.foldl' merge { }
(builtins.map (file: import (./. + "/${file}") attrs)
(getModuleFiles ./.)));

# Export our lib merged with the base lib we created.
in baseLib.extend (final: prev: prev // lib)
32 changes: 32 additions & 0 deletions lib/fp.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
inputs@{ lib, ... }:

rec {
# Identity. Does nothing but return its argument.
id = x: x;

# Creates a function that returns the given value.
only = x: _: x;

# Compose two functions.
compose = f: g: x: f (g x);

# Compose functions from left to right.
pipeAll = lib.foldl compose id;

# Compose functions from right to left.
composeAll = lib.foldr compose id;

# Invert a function with two arguments.
flip2 = f: a: b: f b a;
# Invert a function with three arguments.
flip3 = f: a: b: c: f c b a;
# Invert a function with three arguments.
flip4 = f: a: b: c: d: f d c b a;

# Call a function with an argument.
call = f: x: f x;

# The inverse of `call`. Given an argument, call the next
# function provided with it.
apply = flip2 call;
}
51 changes: 51 additions & 0 deletions lib/fs.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
inputs@{ lib, ... }:

let
# Matches a file's name and its file extension (after the last period).
fileNameRegex = "(.*)\\.(.*)$";
in rec {
# Common assertions for files.
isFileKind = lib.is "regular";
isSymLinkKind = lib.is "symlink";
isDirectoryKind = lib.is "directory";
isUnknownKind = lib.is "unknown";

hasFileExtension = file:
lib.not null (builtins.match fileNameRegex (builtins.toString file));

splitFileExtension = file:
let match = (builtins.match fileNameRegex (builtins.toString file));
in assert lib.assertMsg (lib.not null match)
"File name must match file regex.";
match;

getFileName = file:
if hasFileExtension file then
builtins.concatStringsSep "" (lib.init (splitFileExtension file))
else
file;

getFileExtension = file:
if hasFileExtension file then lib.last (splitFileExtension file) else "";

# Test whether or not a path refers to a *.nix file.
isNixFile = path: lib.is "nix" (getFileExtension path);

# Get a list of directory paths in a directory.
getDirs = path:
lib.mapAttrNames (name: path + "/${name}")
(lib.filterAttrs (lib.only isDirectoryKind) (builtins.readDir path));

# Get a list of file paths in a directory.
getFiles = path:
lib.mapAttrNames (name: path + "/${name}")
(lib.filterAttrs (lib.only isFileKind) (builtins.readDir path));

# Get a list of *.nix files in a directory.
getModuleFiles = path: builtins.filter (isNixFile) (getFiles path);

# Get a list of *.nix files in a directory *excluding* "default.nix".
getModuleFilesWithoutDefault = path:
builtins.filter (file: lib.not "default.nix" (builtins.baseNameOf file))
(getModuleFiles path);
}
46 changes: 46 additions & 0 deletions lib/machine.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
inputs@{ lib, darwin, ... }:

rec {
isDarwin = lib.hasInfix "darwin";

getDynamicConfig = system:
(lib.optionalAttrs (lib.isDarwin system) {
output = "darwinConfigurations";
builder = args:
darwin.lib.darwinSystem (builtins.removeAttrs args [ "system" ]);
});

withDynamicConfig = lib.composeAll [ lib.merge getDynamicConfig ];

# Pass through all inputs except `self` and `utils` due to them breaking
# the module system or causing recursion.
mkSpecialArgs = args:
(builtins.removeAttrs inputs [ "self" "utils" ]) // {
inherit lib;
};

mkHost = { system, path, name ? lib.getFileName (builtins.baseNameOf path)
, modules ? [ ], specialArgs ? { } }: {
"${name}" = withDynamicConfig system {
inherit system;
modules = [ path ] ++ modules;
specialArgs = mkSpecialArgs specialArgs;
};
};

mkHosts = { src, hostOptions ? { } }:
let
systems = lib.getDirs src;
hosts = builtins.concatMap (systemPath:
let
system = builtins.baseNameOf systemPath;
modules = lib.getDirs systemPath;
in builtins.map (path:
let
name = lib.getFileName (builtins.baseNameOf path);
options = lib.optionalAttrs (builtins.hasAttr name hostOptions)
hostOptions.${name};
host = mkHost ({ inherit system path name; } // options);
in host) modules) systems;
in lib.foldl lib.merge { } hosts;
}
16 changes: 16 additions & 0 deletions lib/set.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
inputs@{ lib, ... }:

{
# Merge two sets.
merge = x: y: x // y;

# This comes directly from `builtins` to make it easier to refer to.
getAttr = builtins.getAttr;

# The flipped version of `builtins.getAttr`. This function
# gets passed the set *first* and then the attribute to access.
getAttr' = lib.flip2 builtins.getAttr;

# Map the attribute names of a set. Returns a list of the results.
mapAttrNames = fn: attrs: builtins.map fn (builtins.attrNames attrs);
}
Loading

0 comments on commit 45f03d7

Please sign in to comment.