From ba94153c3bef8f91322029db7731aa3ab5f54dec Mon Sep 17 00:00:00 2001 From: Wroclaw Date: Mon, 17 Jun 2024 07:54:59 +0200 Subject: [PATCH] flakelike --- default.nix | 51 ++++++++++++++++++++ inputs.nix | 10 ++++ lib/overlays/version-info-fixup.nix | 8 ++++ lock.nix | 3 ++ outputs.nix | 53 +++++++++++++++++++++ pkgs/overlays/version-info-fixup.nix | 5 ++ pkgs/top-level/default.nix | 21 +++++++++ pkgs/top-level/impure.nix | 70 ++++++++++++++++++++++++++++ 8 files changed, 221 insertions(+) create mode 100644 default.nix create mode 100644 inputs.nix create mode 100644 lib/overlays/version-info-fixup.nix create mode 100644 lock.nix create mode 100644 outputs.nix create mode 100644 pkgs/overlays/version-info-fixup.nix create mode 100644 pkgs/top-level/default.nix create mode 100644 pkgs/top-level/impure.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..3ce80ff --- /dev/null +++ b/default.nix @@ -0,0 +1,51 @@ +# if evaluating outside of the store, copy the current directory to the store and import it +# filtering out .gitignore files and .git directories +# if evaluating inside the store, import the outputs.nix file + +let + contains = str: substr: let + str_length = builtins.stringLength str; + substr_length = builtins.stringLength substr; + listOfPossibleSubstrings = builtins.genList (i: builtins.substring i substr_length str) (str_length - substr_length + 1); + in if substr_length > str_length then false else builtins.any (x: x == substr) listOfPossibleSubstrings; + + endsWith = str: substr: let + str_length = builtins.stringLength str; + substr_length = builtins.stringLength substr; + in if substr_length > str_length then false else builtins.substring (str_length - substr_length) str_length str == substr; + + gitignore = builtins.filter (v: + # ignore comments and empty lines + if !(builtins.isString v) then false + else if !builtins.isNull(builtins.match "^#.*" v) then false + else if !builtins.isNull(builtins.match "^$" v) then false + else true + ) (builtins.split "\n" (builtins.readFile ./.gitignore)); + + # checks if a given path matches a gitignore pattern + # string -> bool + matchesGitIgnore = path: builtins.any (pattern: + let + patternLength = builtins.stringLength pattern; + unsupportedPatternMessage = "matchesGitIgnore: Unsupported pattern: ${pattern}"; + in + if pattern == "*" then true + else if pattern == ".*" then true + else if pattern == "*.*" then true + else if builtins.substring 0 2 pattern == "*." then endsWith path (builtins.substring 0 2 pattern) + else if contains pattern "*" then abort unsupportedPatternMessage + else if patternLength > 2 && builtins.substring 0 2 pattern == "./" then abort unsupportedPatternMessage + else if patternLength > 1 && builtins.substring 0 1 pattern == "/" then abort unsupportedPatternMessage + else contains path pattern + ) gitignore; + + currentFilePath = (builtins.unsafeGetAttrPos "any" { any = "any"; }).file; + storePathLength = builtins.stringLength (builtins.toString builtins.storeDir); + evaluatingInStore = (builtins.substring 0 storePathLength currentFilePath) == builtins.storeDir; + + selfInStore = builtins.filterSource (path: type: + type != "unknown" && builtins.baseNameOf path != ".git" && !matchesGitIgnore path + ) ./.; +in +if !(evaluatingInStore) then import selfInStore +else import ./outputs.nix diff --git a/inputs.nix b/inputs.nix new file mode 100644 index 0000000..9ad7d1e --- /dev/null +++ b/inputs.nix @@ -0,0 +1,10 @@ +let self = { + lock ? import ./lock.nix +, lib ? import "${(self {}).nixpkgs}/lib" +}: + +{ + inherit lock; + nixpkgs = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/${lock.nixpkgs}.tar.gz"; +}; +in self diff --git a/lib/overlays/version-info-fixup.nix b/lib/overlays/version-info-fixup.nix new file mode 100644 index 0000000..4d4cb9c --- /dev/null +++ b/lib/overlays/version-info-fixup.nix @@ -0,0 +1,8 @@ +{ inputs ? import ../../inputs.nix {} }: + +selfLib: superLib: { + trivial = superLib.trivial // { + versionSuffix = ".git.${builtins.substring 0 12 inputs.lock.nixpkgs}"; + revisionWithDefault = default: inputs.lock.nixpkgs or default; + }; +} diff --git a/lock.nix b/lock.nix new file mode 100644 index 0000000..cb24650 --- /dev/null +++ b/lock.nix @@ -0,0 +1,3 @@ +{ + nixpkgs = "2975732531b5fa6e728f837c6f090335cbef5285" /*git revision*/; +} diff --git a/outputs.nix b/outputs.nix new file mode 100644 index 0000000..9b268dd --- /dev/null +++ b/outputs.nix @@ -0,0 +1,53 @@ +{ inputs ? import ./inputs.nix {} +, selfPath ? builtins.toString ./. +}: + +let + +lib = (import "${inputs.nixpkgs}/lib").extend (import ./lib/overlays/version-info-fixup.nix { inherit inputs; }); + +self = { + inherit lib; + modifiedNixpkgs = import ./pkgs/top-level/impure.nix; + modifiedNixpkgsPure = import ./pkgs/top-level/default.nix; + overlays = { + selfExpr = import ./pkgs/overlays/selfExpr.nix { nixpkgsPath = inputs.nixpkgs; }; + unstable = import ./pkgs/overlays/unstable.nix; + versionInfoFixup = import ./pkgs/overlays/version-info-fixup.nix { inherit inputs; }; + }; + nixosConfigurations = let + dir = builtins.readDir ./hosts; + # list nix file paths in ./hosts to attributes in nixosConfigurations + filePaths = lib.mapAttrsToList (name: _: name) (lib.filterAttrs (name: type: + # filter out non-nix files + type == "regular" + # filter out files that don't end in .nix + && lib.hasSuffix ".nix" name + # filter out files that start with . + && ! lib.hasPrefix "." name + ) dir + ); + nixosSystem = import "${inputs.nixpkgs}/nixos/lib/eval-config.nix"; + in + # mapped list of nix file paths to attrSet with initialized NixOS configurations, + # whose names are derived from file names + builtins.listToAttrs (builtins.map (name: { + name = builtins.substring 0 (builtins.stringLength name - 4) name; + value = nixosSystem { + inherit lib; + modules = [ + ./hosts/${name} + { + config.nixpkgs.overlays = [ + ( import ./pkgs/overlays/selfExpr.nix { nixpkgsPath = ./pkgs/top-level/impure.nix; } ) + self.overlays.versionInfoFixup + ]; + } + ]; + specialArgs = { inherit self inputs; }; + }; + }) filePaths + ); +}; + +in self diff --git a/pkgs/overlays/version-info-fixup.nix b/pkgs/overlays/version-info-fixup.nix new file mode 100644 index 0000000..14d890e --- /dev/null +++ b/pkgs/overlays/version-info-fixup.nix @@ -0,0 +1,5 @@ +{ inputs ? import ../../inputs.nix {} }: + +self: super: { + lib = super.lib.extend (import ../../lib/overlays/version-info-fixup.nix { inherit inputs; }); +} diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix new file mode 100644 index 0000000..ab5307c --- /dev/null +++ b/pkgs/top-level/default.nix @@ -0,0 +1,21 @@ +{ inputs ? import ../../inputs.nix {} +, uninitializedNixpkgs ? import "${inputs.nixpkgs}/pkgs/top-level/default.nix" +, ... +} @ args: + +let + attrsToRemove = [ + "inputs" + "overlays" + "uninitializedNixpkgs" + ]; + + options = (builtins.removeAttrs args attrsToRemove) // { + overlays = (args.overlays or []) ++ [ + ( import ../overlays/selfExpr.nix { nixpkgsPath = ./impure.nix; } ) + ( import ../overlays/unstable.nix ) + ( import ../overlays/version-info-fixup.nix { inherit inputs; } ) + ]; + }; +in +uninitializedNixpkgs options diff --git a/pkgs/top-level/impure.nix b/pkgs/top-level/impure.nix new file mode 100644 index 0000000..20c7b42 --- /dev/null +++ b/pkgs/top-level/impure.nix @@ -0,0 +1,70 @@ +# Modified copy of github:NixOS/nixpkgs pkgs/top-level/impure.nix +# as of commit 242522b8fed8d63f262fd6e747ba1e4372b59a8e + +# I wish I could just import from nixpkgs and set different path to entry point. + +let + homeDir = builtins.getEnv "HOME"; + + # Return ‘x’ if it evaluates, or ‘def’ if it throws an exception. + try = x: def: let res = builtins.tryEval x; in if res.success then res.value else def; +in + +{ localSystem ? { system = args.system or builtins.currentSystem; } +, system ? localSystem.system +, crossSystem ? localSystem +, config ? let + configFile = builtins.getEnv "NIXPKGS_CONFIG"; + configFile2 = homeDir + "/.config/nixpkgs/config.nix"; + configFile3 = homeDir + "/.nixpkgs/config.nix"; # obsolete + in + if configFile != "" && builtins.pathExists configFile then import configFile + else if homeDir != "" && builtins.pathExists configFile2 then import configFile2 + else if homeDir != "" && builtins.pathExists configFile3 then import configFile3 + else {} +, overlays ? let + isDir = path: builtins.pathExists (path + "/."); + pathOverlays = try (toString ) ""; + homeOverlaysFile = homeDir + "/.config/nixpkgs/overlays.nix"; + homeOverlaysDir = homeDir + "/.config/nixpkgs/overlays"; + overlays = path: + # check if the path is a directory or a file + if isDir path then + # it's a directory, so the set of overlays from the directory, ordered lexicographically + let content = builtins.readDir path; in + map (n: import (path + ("/" + n))) + (builtins.filter + (n: + (builtins.match ".*\\.nix" n != null && + # ignore Emacs lock files (.#foo.nix) + builtins.match "\\.#.*" n == null) || + builtins.pathExists (path + ("/" + n + "/default.nix"))) + (builtins.attrNames content)) + else + # it's a file, so the result is the contents of the file itself + import path; + in + if pathOverlays != "" && builtins.pathExists pathOverlays then overlays pathOverlays + else if builtins.pathExists homeOverlaysFile && builtins.pathExists homeOverlaysDir then + throw '' + Nixpkgs overlays can be specified with ${homeOverlaysFile} or ${homeOverlaysDir}, but not both. + Please remove one of them and try again. + '' + else if builtins.pathExists homeOverlaysFile then + if isDir homeOverlaysFile then + throw (homeOverlaysFile + " should be a file") + else overlays homeOverlaysFile + else if builtins.pathExists homeOverlaysDir then + if !(isDir homeOverlaysDir) then + throw (homeOverlaysDir + " should be a directory") + else overlays homeOverlaysDir + else [] +, crossOverlays ? [] +, ... +} @ args: + +# Assertion checked in called nixpkgs upstream, thus removed here + +import ./. (builtins.removeAttrs args [ "system" ] // { + inherit config overlays localSystem; +})