|
-## Features
+### Features
- Flake definition aggregated from Nix modules.
- [Input](https://github.com/vic/flake-file/blob/main/modules/options/default.nix) and Output schemas based on Nix types.
@@ -39,7 +39,7 @@ This means
- Incrementally add [flake-parts-builder](#parts_templates) templates.
- Pick flakeModules for different feature sets.
- [Dendritic](https://vic.github.io/dendrix/Dendritic.html) flake template.
-- Works on stable Nix, [npins](templates/npins) and [unflake](templates/unflake) environments.
+- Works on stable Nix, [npins](templates/npins), [unflake](templates/unflake), [nixlock](templates/nixlock) environments.
|
diff --git a/dev/_bootstrap-tests.nix b/dev/_bootstrap-tests.nix
index 41f50d4..569ea67 100644
--- a/dev/_bootstrap-tests.nix
+++ b/dev/_bootstrap-tests.nix
@@ -106,6 +106,17 @@ let
'';
};
+ test-nixlock = pkgs.writeShellApplication {
+ name = "test-nixlock";
+ runtimeInputs = [
+ (empty.flake-file.apps.write-nixlock pkgs)
+ ];
+ text = ''
+ write-nixlock
+ grep vic/empty-flake/archive ${outdir}/nixlock.lock.nix
+ '';
+ };
+
in
pkgs.mkShell {
buildInputs = [
@@ -115,5 +126,6 @@ pkgs.mkShell {
test-npins
test-npins-follows
test-npins-transitive
+ test-nixlock
];
}
diff --git a/docs/src/content/docs/explanation/what-is-flake-file.mdx b/docs/src/content/docs/explanation/what-is-flake-file.mdx
index a255d8b..1c4f7da 100644
--- a/docs/src/content/docs/explanation/what-is-flake-file.mdx
+++ b/docs/src/content/docs/explanation/what-is-flake-file.mdx
@@ -36,7 +36,7 @@ move your outputs function into `outputs.nix` and use something like:
Even if some people use unstable flakes, others should not be forced out of stable Nix.
Each module defines inputs and flake-file can extract to whatever input-locking backend you need.
-Be it `flake.nix`, `unflake.nix`, `npins`.
+Be it `flake.nix`, `unflake.nix`, `nixlock`, `npins`.
## Everybody `.follows`
@@ -66,7 +66,7 @@ Running `nix run .#write-flake` materialises all declared inputs into `flake.nix
- **Modular:** Each module declares only its own dependencies.
- **Composable:** Modules can be shared across projects — including their input declarations.
-- **Backend-agnostic:** The same module options generate `flake.nix`, `unflake.nix`, or `npins/` depending on the chosen backend.
+- **Backend-agnostic:** The same module options generate `flake.nix`, `unflake.nix`, `nixlock` or `npins/` depending on the chosen backend.
- **Standard Nix:** Uses the Nix module system — `lib.mkDefault`, priority overrides, conditional inputs — all work as expected.
## Real-world Usage
diff --git a/docs/src/content/docs/guides/flake-modules.mdx b/docs/src/content/docs/guides/flake-modules.mdx
index e03ef46..8f39ecd 100644
--- a/docs/src/content/docs/guides/flake-modules.mdx
+++ b/docs/src/content/docs/guides/flake-modules.mdx
@@ -78,10 +78,16 @@ Source: [`modules/prune-lock/nix-auto-follow.nix`](https://github.com/vic/flake-
Defines `flake-file` options for [npins](https://github.com/andir/npins)-based environments. Exposes `write-npins`. Supports `github`, `gitlab`, `channel`, `tarball`, and `git` schemes. Respects `follows` for deduplication. Prunes stale pins automatically.
-Source: [`modules/npins.nix`](https://github.com/vic/flake-file/tree/main/modules/npins.nix)
+Source: [`modules/npins`](https://github.com/vic/flake-file/tree/main/modules/npins)
## `flakeModules.unflake`
Defines `flake-file` options for [unflake](https://codeberg.org/goldstein/unflake)-based environments. Exposes `write-unflake`.
-Source: [`modules/unflake.nix`](https://github.com/vic/flake-file/tree/main/modules/unflake.nix)
+Source: [`modules/unflake`](https://github.com/vic/flake-file/tree/main/modules/unflake)
+
+## `flakeModules.nixlock`
+
+Defines `flake-file` options for [nixlock](https://codeberg.org/FrdrCkII/nixlock)-based environments. Exposes `write-nixlock`.
+
+Source: [`modules/nixlock`](https://github.com/vic/flake-file/tree/main/modules/nixlock)
diff --git a/docs/src/content/docs/guides/templates.mdx b/docs/src/content/docs/guides/templates.mdx
index f873375..84f4238 100644
--- a/docs/src/content/docs/guides/templates.mdx
+++ b/docs/src/content/docs/guides/templates.mdx
@@ -60,6 +60,14 @@ For **non-flake** (stable Nix) environments. Uses [goldstein/unflake](https://co
nix flake init -t github:vic/flake-file#unflake
```
+## `nixlock`
+
+For **non-flake** (stable Nix) environments. Uses [FrdrCkII/nixlock](https://codeberg.org/FrdrCkII/nixlock) to pin inputs.
+
+```shell
+nix flake init -t github:vic/flake-file#unflake
+```
+
## Tips
> **Tip:** You can use the `write-flake` app as part of a devshell command or a git pre-commit hook to keep `flake.nix` always up to date.
diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx
index af603d9..0fa4e5e 100644
--- a/docs/src/content/docs/index.mdx
+++ b/docs/src/content/docs/index.mdx
@@ -55,6 +55,6 @@ Ever wanted to interpolate a string just to discover inputs are **NOT REAL** Nix
Built-in support for automatic `flake.lock` flattening via `allfollow` or `nix-auto-follow`.
- Generate `flake.nix`, `unflake.nix`, or `npins/` from the same module options. Switch backends without rewriting your modules.
+ Generate `flake.nix`, `unflake.nix`, `nixlock`, or `npins/` from the same module options. Switch backends without rewriting your modules.
diff --git a/docs/src/content/docs/overview.mdx b/docs/src/content/docs/overview.mdx
index d2db7db..01a049a 100644
--- a/docs/src/content/docs/overview.mdx
+++ b/docs/src/content/docs/overview.mdx
@@ -44,7 +44,7 @@ flake-file treats `flake.nix` as a generated artifact. You declare inputs and se
Learn More
- Adopt flake-file in a non-flake project using npins or unflake.
+ Adopt flake-file in a non-flake project using npins, nixlock or unflake.
Learn More
diff --git a/docs/src/content/docs/reference/bootstrap.mdx b/docs/src/content/docs/reference/bootstrap.mdx
index ec4f1e6..ffc27d5 100644
--- a/docs/src/content/docs/reference/bootstrap.mdx
+++ b/docs/src/content/docs/reference/bootstrap.mdx
@@ -5,7 +5,7 @@ description: All options for the flake-file bootstrap command.
import { Aside } from '@astrojs/starlight/components';
-The bootstrap command lets you generate `flake.nix`, `unflake.nix`, or `npins/` from scratch — without being inside an existing flake.
+The bootstrap command lets you generate `flake.nix`, `unflake.nix`, `nixlock.lock.nix`, or `npins/` from scratch — without being inside an existing flake.
```shell
nix-shell https://github.com/vic/flake-file/archive/refs/heads/main.zip \
@@ -21,6 +21,7 @@ The `flake-file.sh` shell provides these commands:
| `write-flake` | Generate a `flake.nix` file |
| `write-inputs` | Generate an `inputs.nix` expression (for debugging) |
| `write-unflake` | Generate `unflake.nix` via [unflake](https://codeberg.org/goldstein/unflake) |
+| `write-nixlock` | Generate `nixlock.lock.nix` via [nixlock](https://codeberg.org/FrdrCkII/nixlock) |
| `write-npins` | Generate/update `npins/` directory via [npins](https://github.com/andir/npins) |
## Arguments
diff --git a/docs/src/content/docs/tutorials/bootstrap.mdx b/docs/src/content/docs/tutorials/bootstrap.mdx
index f09454f..7e76d97 100644
--- a/docs/src/content/docs/tutorials/bootstrap.mdx
+++ b/docs/src/content/docs/tutorials/bootstrap.mdx
@@ -21,14 +21,14 @@ You can create a `flake.nix` from scratch — without running inside an existing
# Write a minimal flake-file.nix file (or copy a flake.nix of yours)
echo '{ inputs.flake-file.url = "github:vic/flake-file"; }' > flake-file.nix
-# Generate flake.nix or unflake.nix or npins from flake-file.nix
+# Generate flake.nix or unflake.nix or npins or nixlock from flake-file.nix
nix-shell https://github.com/vic/flake-file/archive/refs/heads/main.zip \
-A flake-file.sh --run write-flake --arg modules ./flake-file.nix
```
> See also: all [bootstrap command args](/reference/bootstrap)
-Replace `write-flake` with `write-inputs`, `write-unflake`, or `write-npins` to target a different backend.
+Replace `write-flake` with `write-inputs`, `write-unflake`, `write-nixlock`, or `write-npins` to target a different backend.
## Using a modules directory
diff --git a/docs/src/content/docs/tutorials/migrate-no-flakes.mdx b/docs/src/content/docs/tutorials/migrate-no-flakes.mdx
index 6c9aad1..14e8e5c 100644
--- a/docs/src/content/docs/tutorials/migrate-no-flakes.mdx
+++ b/docs/src/content/docs/tutorials/migrate-no-flakes.mdx
@@ -12,6 +12,7 @@ of tools for that in the ecosystem.
flake-file has support
for [`unflake`](https://codeberg.org/goldstein/unflake)
+and [`nixlock`](https://codeberg.org/FrdrCkII/nixlock)
and [`npins`](https://github.com/andir/npins)
send PR for others.
diff --git a/modules/bootstrap/default.nix b/modules/bootstrap/default.nix
index 6e75ab3..2152892 100644
--- a/modules/bootstrap/default.nix
+++ b/modules/bootstrap/default.nix
@@ -40,6 +40,7 @@ let
./../options
./../npins
./../unflake
+ ./../nixlock
./../write-inputs.nix
./../write-flake.nix
./../flake-options.nix
diff --git a/modules/default.nix b/modules/default.nix
index 146bca0..7ddea51 100644
--- a/modules/default.nix
+++ b/modules/default.nix
@@ -8,6 +8,7 @@ let
import-tree
npins
unflake
+ nixlock
flake-options
;
};
@@ -29,6 +30,11 @@ let
./unflake
];
+ nixlock.imports = [
+ base
+ ./nixlock
+ ];
+
default.imports = [
base
./write-flake.nix
@@ -67,6 +73,11 @@ let
path = ./../templates/unflake;
};
+ templates.nixlock = {
+ description = "nixlock template";
+ path = ./../templates/nixlock;
+ };
+
templates.dendritic = {
description = "dendritic template";
path = ./../templates/dendritic;
diff --git a/modules/nixlock/default.nix b/modules/nixlock/default.nix
new file mode 100644
index 0000000..df888e2
--- /dev/null
+++ b/modules/nixlock/default.nix
@@ -0,0 +1,155 @@
+{ lib, config, ... }:
+let
+ inherit (config) flake-file;
+ inherit (import ../lib.nix lib) inputsExpr;
+
+ inputs = inputsExpr flake-file.inputs;
+
+ nixlock-source = fetchTarball {
+ url = flake-file.nixlock.url;
+ sha256 = flake-file.nixlock.sha256;
+ };
+
+ nlLibs = (import "${nixlock-source}/${flake-file.nixlock.version}").libs;
+
+ parseGithub =
+ path:
+ let
+ parts = lib.splitString "/" path;
+ owner = builtins.elemAt parts 0;
+ repo = builtins.elemAt parts 1;
+ ref = if builtins.length parts > 2 then builtins.elemAt parts 2 else "HEAD";
+ in
+ {
+ type = "gitArchive";
+ url = "https://github.com/${owner}/${repo}";
+ inherit ref;
+ };
+
+ parseGitlab =
+ path:
+ let
+ parts = lib.splitString "/" path;
+ owner = builtins.elemAt parts 0;
+ repo = builtins.elemAt parts 1;
+ ref = if builtins.length parts > 2 then builtins.elemAt parts 2 else "HEAD";
+ in
+ {
+ type = "gitArchive";
+ url = "https://gitlab.com/${owner}/${repo}";
+ inherit ref;
+ };
+
+ flakeUrlToNixlock =
+ url:
+ let
+ scheme = builtins.head (lib.splitString ":" url);
+ rest = lib.concatStringsSep ":" (builtins.tail (lib.splitString ":" url));
+ in
+ if scheme == "github" then
+ parseGithub rest
+ else if scheme == "gitlab" then
+ parseGitlab rest
+ else if lib.hasPrefix "git+" url then
+ {
+ type = "git";
+ url = lib.removePrefix "git+" url;
+ ref = "HEAD";
+ }
+ else if lib.hasPrefix "http" url then
+ {
+ type = "archive";
+ inherit url;
+ }
+ else
+ null;
+
+ toNixlockInput = _name: input: if input ? url then flakeUrlToNixlock input.url else null;
+
+ inputsFile = lib.filterAttrs (_: v: v != null) (lib.mapAttrs toNixlockInput inputs);
+
+ lockListFor =
+ upType: lockFile:
+ lib.filterAttrs (
+ name: value:
+ !(lockFile ? ${name})
+ || value != lockFile.${name}.meta or { }
+ || (if upType == "update" then !(value.isFreeze or false) else false)
+ ) inputsFile;
+
+ shellFor =
+ upType: lockFile: lockFileName:
+ let
+ entries = lockListFor upType lockFile;
+ in
+ nlLibs.toLockShell {
+ inherit lockFile lockFileName;
+ inputsFile = entries;
+ cmds = lib.concatStringsSep "\n" (
+ lib.mapAttrsToList (n: v: nlLibs.types.${v.type}.fresh n v) entries
+ );
+ };
+
+ write-nixlock =
+ pkgs:
+ let
+ rootPath = flake-file.intoPath;
+ lockFileName = flake-file.nixlock.lockFileName;
+ lockScript = shellFor "lock" { } lockFileName;
+ updateScript = shellFor "update" { } lockFileName;
+ in
+ pkgs.writeShellApplication {
+ name = "write-nixlock";
+ excludeShellChecks = [
+ "SC2016"
+ "SC2086"
+ "SC2089"
+ "SC2090"
+ ];
+ runtimeInputs = with pkgs; [
+ nix
+ nixfmt
+ git
+ nix-prefetch-git
+ curl
+ coreutils
+ gnugrep
+ gnused
+ gawk
+ jq
+ ];
+ text = ''
+ cd ${rootPath}
+ case "''${1:-lock}" in
+ lock) ${lockScript} ;;
+ update) ${updateScript} ;;
+ *) echo "usage: write-nixlock [lock|update]" >&2; exit 1 ;;
+ esac
+ '';
+ };
+in
+{
+ config.flake-file.apps = { inherit write-nixlock; };
+ options.flake-file.nixlock = {
+ url = lib.mkOption {
+ type = lib.types.str;
+ description = "nixlock archive url";
+ default = "https://codeberg.org/FrdrCkII/nixlock/archive/dad9155634ce5d5183429daaeef2bbf6de9afcbf.tar.gz";
+ };
+ sha256 = lib.mkOption {
+ type = lib.types.str;
+ description = "nixlock archive sha256";
+ default = "sha256:0bycgfdar1xcxgbp75r7bpmfvm2qh8206q2h2vsx5qn8fr39x0li";
+ };
+ version = lib.mkOption {
+ type = lib.types.str;
+ description = "nixlock version to load";
+ default = "v3";
+ };
+ lockFileName = lib.mkOption {
+ type = lib.types.str;
+ description = "nixlock lockfile name";
+ default = "nixlock.lock.nix";
+ };
+ };
+}
diff --git a/templates/nixlock/README.md b/templates/nixlock/README.md
new file mode 100644
index 0000000..05e3d29
--- /dev/null
+++ b/templates/nixlock/README.md
@@ -0,0 +1,19 @@
+# Nixlock
+
+This template is an example of using `flake-file.inputs` in a non-flakes project.
+
+It uses [nixlock](https://codeberg.org/FrdrCkII/nixlock) to pin and fetch inputs defined as options inside `./modules`.
+
+## Generate nixlock
+
+The following command is a convenience for generating `nixlock.lock.nix`:
+
+```shell
+nix-shell . -A flake-file.sh --run write-nixlock
+```
+
+You can also the `update` command.
+
+```shell
+nix-shell . -A flake-file.sh --run 'write-nixlock update'
+```
diff --git a/templates/nixlock/default.nix b/templates/nixlock/default.nix
new file mode 100644
index 0000000..d16c6f0
--- /dev/null
+++ b/templates/nixlock/default.nix
@@ -0,0 +1,30 @@
+let
+ outputs =
+ inputs:
+ (inputs.nixpkgs.lib.evalModules {
+ modules = [ (inputs.import-tree ./modules) ];
+ specialArgs = { inherit inputs; };
+ }).config;
+
+ input-overrides = {
+ # uncomment for local checkout on CI
+ # flake-file = import ./../../modules;
+ };
+
+ with-inputs = import (fetchTarball {
+ url = "https://github.com/vic/with-inputs/archive/f19ccc093928f4987ab56534e0de37b25d8f5817.zip";
+ sha256 = "sha256:0bcfic6myy2qmyj40kxpxv04hp925l9b0wkd507v69d070qsg285";
+ });
+
+ nixlock-inputs = builtins.mapAttrs (
+ _n: v:
+ v
+ // {
+ outPath = fetchTarball {
+ url = v.lock.url;
+ sha256 = v.lock.hash;
+ };
+ }
+ ) (import ./nixlock.lock.nix);
+in
+with-inputs nixlock-inputs input-overrides outputs
diff --git a/templates/nixlock/modules/default.nix b/templates/nixlock/modules/default.nix
new file mode 100644
index 0000000..5e8a931
--- /dev/null
+++ b/templates/nixlock/modules/default.nix
@@ -0,0 +1,10 @@
+{ inputs, ... }:
+{
+ imports = [ inputs.flake-file.flakeModules.nixlock ];
+
+ flake-file.inputs = {
+ flake-file.url = "github:vic/flake-file";
+ import-tree.url = "github:vic/import-tree";
+ nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
+ };
+}
diff --git a/templates/nixlock/nixlock.lock.nix b/templates/nixlock/nixlock.lock.nix
new file mode 100644
index 0000000..aed91b6
--- /dev/null
+++ b/templates/nixlock/nixlock.lock.nix
@@ -0,0 +1,35 @@
+{
+ "flake-file" = {
+ "lock" = {
+ "hash" = "sha256-qIpm5BtK3EkqlGXBG0jCZ3sg3gdxyPxI10iubZwMGFk=";
+ "url" = "https://github.com/vic/flake-file/archive/8a5c8771ac5be1af11192bcd88e6a1cdabd038a5.tar.gz";
+ };
+ "meta" = {
+ "ref" = "HEAD";
+ "type" = "gitArchive";
+ "url" = "https://github.com/vic/flake-file";
+ };
+ };
+ "import-tree" = {
+ "lock" = {
+ "hash" = "sha256-AkfVgWWxt1pa1SlfKzcL1oQpMzgP70U3fBtzXqEGOms=";
+ "url" =
+ "https://github.com/vic/import-tree/archive/78c35e32f2b499c25e0671e41662537a6b1edbf0.tar.gz";
+ };
+ "meta" = {
+ "ref" = "HEAD";
+ "type" = "gitArchive";
+ "url" = "https://github.com/vic/import-tree";
+ };
+ };
+ "nixpkgs" = {
+ "lock" = {
+ "hash" = "sha256-OgUF+EoJ36hz3jo8qBuizb8suT0mu1n7mzmcGdeOjWE=";
+ "url" = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
+ };
+ "meta" = {
+ "type" = "archive";
+ "url" = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
+ };
+ };
+}
diff --git a/templates/npins/default.nix b/templates/npins/default.nix
index 9c14086..e7161d6 100644
--- a/templates/npins/default.nix
+++ b/templates/npins/default.nix
@@ -1,26 +1,24 @@
let
outputs =
inputs:
- let
- nixpkgs = inputs.nixpkgs or (import { });
- import-tree = inputs.import-tree or (import );
- in
- (nixpkgs.lib.evalModules {
- modules = [ (import-tree ./modules) ];
+ (inputs.nixpkgs.lib.evalModules {
+ modules = [ (inputs.import-tree ./modules) ];
specialArgs = {
inherit inputs;
- self = inputs.self or { };
+ self = inputs.self;
};
}).config;
- withInputs =
- inputs: outputs:
- outputs (
- inputs
- // {
- # uncomment on CI for local checkout
- # flake-file = import ./../../modules;
- }
- );
+ with-inputs = import (builtins.fetchTarball {
+ url = "https://github.com/vic/with-inputs/archive/f19ccc093928f4987ab56534e0de37b25d8f5817.zip";
+ sha256 = "sha256:0bcfic6myy2qmyj40kxpxv04hp925l9b0wkd507v69d070qsg285";
+ });
+
+ inputs-overrides ={
+ # uncomment on CI for local checkout
+ # flake-file = import ./../../modules;
+ };
+
+ sources = import ./npins;
in
-import ./with-inputs.nix withInputs outputs
+with-inputs sources inputs-overrides outputs
diff --git a/templates/npins/with-inputs.nix b/templates/npins/with-inputs.nix
deleted file mode 100644
index 193ae03..0000000
--- a/templates/npins/with-inputs.nix
+++ /dev/null
@@ -1,40 +0,0 @@
-let
- hasSources = builtins.pathExists ./npins;
- sources = if hasSources then import ./npins else { };
- selfInputs = builtins.mapAttrs (name: value: mkInputs name value) sources;
- # from Nixlock: https://codeberg.org/FrdrCkII/nixlock/src/branch/main/default.nix
- mkInputs =
- name: sourceInfo:
- let
- flakePath = sourceInfo.outPath + "/flake.nix";
- isFlake = sources.${name}.flake or true;
- in
- if isFlake && builtins.pathExists flakePath then
- let
- flake = import (sourceInfo.outPath + "/flake.nix");
- inputs = builtins.mapAttrs (name: _value: selfInputs.${name}) (flake.inputs or { });
- outputs = flake.outputs (inputs // { inherit self; });
- self =
- sourceInfo
- // outputs
- // {
- _type = "flake";
- inherit inputs outputs sourceInfo;
- };
- in
- self
- else
- sourceInfo
- // {
- inherit sourceInfo;
- };
-in
-selfInputs
-// {
- __functor =
- selfInputs: outputs:
- let
- self = outputs (selfInputs // { inherit self; });
- in
- self;
-}
|