Merge remote-tracking branch 'upstream/main' into patch-1
This commit is contained in:
commit
11647f17dc
18 changed files with 604 additions and 63 deletions
|
|
@ -10,6 +10,10 @@ Opinionated features are provided by an ecosystem of modules that you can import
|
|||
`flake-parts` _itself_ has the goal to be a minimal mirror of the Nix flake schema.
|
||||
Used by itself, it is very lightweight.
|
||||
|
||||
> It is definitely the best Flake framework and it is simply out of this world!
|
||||
|
||||
—Pol Dellaiera ([source](https://not-a-number.io/2025/refactoring-my-infrastructure-as-code-configurations/#trade-offs))
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: [flake.parts](https://flake.parts)
|
||||
|
|
|
|||
|
|
@ -15,32 +15,6 @@
|
|||
"." = { };
|
||||
"dev" = { };
|
||||
};
|
||||
effect.settings = {
|
||||
# Only fetch the `lib` subtree.
|
||||
# NOTE: Users don't have to do this. They are recommended to use follows
|
||||
# and just use the `nixpkgs` they're already fetching anyway.
|
||||
# It doesn't have to be `lib/` only!
|
||||
git.update.script = lib.mkBefore ''
|
||||
echo 'Fetching nixpkgs-lib tree'
|
||||
branch="nixos-unstable"
|
||||
mkdir ~/nixpkgs
|
||||
git -C ~/nixpkgs init
|
||||
git -C ~/nixpkgs remote add origin https://github.com/NixOS/nixpkgs.git
|
||||
git -C ~/nixpkgs fetch origin --filter=blob:none --depth=1 "$branch"
|
||||
commit="$(git -C ~/nixpkgs rev-parse FETCH_HEAD)"
|
||||
tree="$(git -C ~/nixpkgs rev-parse FETCH_HEAD:lib)"
|
||||
|
||||
echo 'Adjusting nixpkgs-lib.url'
|
||||
sed -i flake.nix -e \
|
||||
's^ nixpkgs-lib\.url = ".*^ nixpkgs-lib\.url = "https://github.com/NixOS/nixpkgs/archive/'$tree'.tar.gz"; # '$commit' /lib from '$branch'^'
|
||||
git diff
|
||||
grep -F "$tree" flake.nix >/dev/null || {
|
||||
echo 'failed to write new tree to flake.nix'
|
||||
exit 1
|
||||
}
|
||||
git commit flake.nix -m 'flake.nix: Update nixpkgs-lib tree'
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
perSystem = { config, pkgs, ... }: {
|
||||
|
|
|
|||
36
dev/flake.lock
generated
36
dev/flake.lock
generated
|
|
@ -3,11 +3,11 @@
|
|||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"lastModified": 1747046372,
|
||||
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -24,11 +24,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1736143030,
|
||||
"narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=",
|
||||
"lastModified": 1759362264,
|
||||
"narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de",
|
||||
"rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -63,11 +63,11 @@
|
|||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1738237977,
|
||||
"narHash": "sha256-oJN/yvRL7G0WlR/hTkQIjFbPkzCV+sFnNB/38Tb9RL4=",
|
||||
"lastModified": 1761230615,
|
||||
"narHash": "sha256-pLE7U5gOtlA/2wbKCsVRYf5DqMQ5TWBCrCfZGytDDeo=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "hercules-ci-effects",
|
||||
"rev": "6d1b6d5d59758b4f5f05745f774fc13cdc59da43",
|
||||
"rev": "7db2b867219a26781437d840ce457b75b7645154",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -78,11 +78,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1736798957,
|
||||
"narHash": "sha256-qwpCtZhSsSNQtK4xYGzMiyEDhkNzOCz/Vfu4oL2ETsQ=",
|
||||
"lastModified": 1760284886,
|
||||
"narHash": "sha256-TK9Kr0BYBQ/1P5kAsnNQhmWWKgmZXwUQr4ZMjCzWf2c=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9abb87b552b7f55ac8916b6fc9e5cb486656a2f3",
|
||||
"rev": "cf3f5c4def3c7b5f1fc012b3d839575dbe552d43",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -94,11 +94,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1738452225,
|
||||
"narHash": "sha256-Qmwx3FXM0x0pdjibwTk/uRbayqDrs3EwmRJe7tQWu48=",
|
||||
"lastModified": 1762038587,
|
||||
"narHash": "sha256-jGt23EE/KEkLpTtFJfh9LgH2Kga13VIQUCB4ElpTFKQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6c4e0724e0a785a20679b1bca3a46bfce60f05b6",
|
||||
"rev": "ac6d58bb8b60e0835eb24af588e36bedb0f492ea",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -116,11 +116,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737465171,
|
||||
"narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=",
|
||||
"lastModified": 1760663237,
|
||||
"narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
|
||||
"rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,18 @@ rec {
|
|||
};
|
||||
};
|
||||
|
||||
bundlersExample = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
{
|
||||
imports = [ flake-parts.flakeModules.bundlers ];
|
||||
systems = [ "a" "b" ];
|
||||
perSystem = { system, ... }: {
|
||||
packages.hello = pkg system "hello";
|
||||
bundlers.toTarball = drv: pkg system "tarball-${drv.name}";
|
||||
bundlers.toAppImage = drv: pkg system "appimage-${drv.name}";
|
||||
};
|
||||
};
|
||||
|
||||
modulesFlake = mkFlake
|
||||
{
|
||||
inputs.self = { };
|
||||
|
|
@ -180,6 +192,44 @@ rec {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
This one is for manual testing. Should look like:
|
||||
|
||||
```
|
||||
nix-repl> checks.x86_64-linux.eval-tests.internals.printSystem.withSystem "foo" ({ config, ... }: null)
|
||||
trace: Evaluating perSystem for foo
|
||||
null
|
||||
|
||||
nix-repl> checks.x86_64-linux.eval-tests.internals.printSystem.withSystem "foo" ({ config, ... }: null)
|
||||
null
|
||||
|
||||
```
|
||||
*/
|
||||
printSystem = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
({ withSystem, ... }: {
|
||||
systems = [ ];
|
||||
perSystem = { config, system, ... }:
|
||||
builtins.trace "Evaluating perSystem for ${system}" { };
|
||||
flake.withSystem = withSystem;
|
||||
});
|
||||
|
||||
dogfoodProvider = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
({ flake-parts-lib, ... }: {
|
||||
imports = [
|
||||
(flake-parts-lib.importAndPublish "dogfood" { flake.marker = "dogfood"; })
|
||||
];
|
||||
});
|
||||
|
||||
dogfoodConsumer = mkFlake
|
||||
{ inputs.self = { }; }
|
||||
({ flake-parts-lib, ... }: {
|
||||
imports = [
|
||||
dogfoodProvider.modules.flake.dogfood
|
||||
];
|
||||
});
|
||||
|
||||
runTests = ok:
|
||||
|
||||
assert empty == {
|
||||
|
|
@ -224,6 +274,9 @@ rec {
|
|||
};
|
||||
};
|
||||
|
||||
assert bundlersExample.bundlers.a.toTarball (pkg "a" "hello") == pkg "a" "tarball-hello";
|
||||
assert bundlersExample.bundlers.b.toAppImage (pkg "b" "hello") == pkg "b" "appimage-hello";
|
||||
|
||||
# - exported package becomes part of overlay.
|
||||
# - perSystem is invoked for the right system, when system is non-memoized
|
||||
assert nixpkgsWithEasyOverlay.hello == pkg "x86_64-linux" "hello";
|
||||
|
|
@ -277,6 +330,9 @@ rec {
|
|||
];
|
||||
}).config.test.option == "nixos-test";
|
||||
|
||||
assert dogfoodProvider.marker == "dogfood";
|
||||
assert dogfoodConsumer.marker == "dogfood";
|
||||
|
||||
ok;
|
||||
|
||||
result = runTests "ok";
|
||||
|
|
|
|||
28
extras/bundlers.nix
Normal file
28
extras/bundlers.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{ lib
|
||||
, flake-parts-lib
|
||||
, ...
|
||||
}:
|
||||
let
|
||||
inherit
|
||||
(lib)
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
inherit
|
||||
(flake-parts-lib)
|
||||
mkTransposedPerSystemModule
|
||||
;
|
||||
in
|
||||
mkTransposedPerSystemModule {
|
||||
name = "bundlers";
|
||||
option = mkOption {
|
||||
type = types.lazyAttrsOf (types.functionTo types.package);
|
||||
default = { };
|
||||
description = ''
|
||||
An attribute set of bundlers to be used by [`nix bundle`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-bundle.html).
|
||||
|
||||
`nix bundle --bundler .#<name>` <derivation> will bundle <derivation> using the bundler `bundlers.<name>`.
|
||||
'';
|
||||
};
|
||||
file = ./bundlers.nix;
|
||||
}
|
||||
|
|
@ -85,11 +85,7 @@ let
|
|||
# addressed store path is a pure input, so we have to fetch and wire it
|
||||
# manually with flake-compat.
|
||||
get-flake = src: (flake-compat { inherit src; system = throw "operating flake-compat in pure mode; system not allowed to be used"; }).outputs;
|
||||
# TODO: update
|
||||
flake-compat = import (builtins.fetchTarball {
|
||||
url = "https://github.com/edolstra/flake-compat/archive/9ed2ac151eada2306ca8c418ebd97807bb08f6ac.tar.gz";
|
||||
sha256 = "sha256:063slk1np1g1dkh21a82x655kpja7p4pc74rb3lqankyrbbpy4hx";
|
||||
});
|
||||
flake-compat = import ../vendor/flake-compat;
|
||||
|
||||
in
|
||||
{
|
||||
|
|
@ -105,6 +101,10 @@ in
|
|||
The flake attributes are overridden with `lib.mkForce` priority.
|
||||
|
||||
See the `partitions` options to understand the purpose.
|
||||
|
||||
Example: `partitionedAttrs.devShells = "dev";`
|
||||
|
||||
Equivalent: `flake.devShells = lib.mkForce config.partitions.dev.module.flake.devShells;`
|
||||
'';
|
||||
example = {
|
||||
"devShells" = "dev";
|
||||
|
|
|
|||
15
flake.lock
generated
15
flake.lock
generated
|
|
@ -2,14 +2,17 @@
|
|||
"nodes": {
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1738452942,
|
||||
"narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
||||
"lastModified": 1761765539,
|
||||
"narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "719359f4562934ae99f5443f20aa06c2ffff91fc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
description = "Flake basics described using the module system";
|
||||
|
||||
inputs = {
|
||||
nixpkgs-lib.url = "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"; # 3a228057f5b619feb3186e986dbe76278d707b6e /lib from nixos-unstable
|
||||
nixpkgs-lib.url = "github:nix-community/nixpkgs.lib";
|
||||
};
|
||||
|
||||
outputs = inputs@{ nixpkgs-lib, ... }:
|
||||
|
|
@ -50,6 +50,7 @@
|
|||
flakeModules = ./extras/flakeModules.nix;
|
||||
modules = ./extras/modules.nix;
|
||||
partitions = ./extras/partitions.nix;
|
||||
bundlers = ./extras/bundlers.nix;
|
||||
};
|
||||
in
|
||||
lib.mkFlake { inherit inputs; } {
|
||||
|
|
|
|||
24
lib.nix
24
lib.nix
|
|
@ -174,7 +174,11 @@ let
|
|||
options = {
|
||||
flake = flake-parts-lib.mkSubmoduleOptions {
|
||||
${name} = mkOption {
|
||||
type = types.lazyAttrsOf option.type;
|
||||
type = types.attrsWith {
|
||||
elemType = option.type;
|
||||
lazy = true;
|
||||
placeholder = "system";
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
See {option}`perSystem.${name}` for description and examples.
|
||||
|
|
@ -221,6 +225,24 @@ let
|
|||
importApply =
|
||||
modulePath: staticArgs:
|
||||
lib.setDefaultModuleLocation modulePath (import modulePath staticArgs);
|
||||
|
||||
inherit (import ./lib/memoize/memoize.nix {
|
||||
inherit lib;
|
||||
}) memoizeStr;
|
||||
|
||||
/**
|
||||
`importAndPublish name module` returns a module that both imports the `module`, and exposes it as flake attribute `modules.flake.${name}`.
|
||||
|
||||
This also imports the optional [`modules`](https://flake.parts/options/flake-parts-modules.html) module to support that.
|
||||
*/
|
||||
importAndPublish = name: module: { lib, ... }: {
|
||||
_class = "flake";
|
||||
imports = [
|
||||
module
|
||||
./extras/modules.nix
|
||||
];
|
||||
flake.modules.flake.${name} = module;
|
||||
};
|
||||
};
|
||||
|
||||
# A best effort, lenient estimate. Please use a recent nixpkgs lib if you
|
||||
|
|
|
|||
2
lib/memoize/bytes.dat
Normal file
2
lib/memoize/bytes.dat
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<D096><E29486><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<E8B28A><E9BCAC><EFBFBD><EFBFBD>
|
||||
23
lib/memoize/measure-bytes-per-char.nix
Normal file
23
lib/memoize/measure-bytes-per-char.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Run with:
|
||||
# NIX_SHOW_STATS=1 nix eval --expr 'import ./measure-bytes-per-char.nix { control = false; size = 10; }' --impure
|
||||
# NIX_SHOW_STATS=1 nix eval --expr 'import ./measure-bytes-per-char.nix { control = true; size = 10; }' --impure
|
||||
|
||||
{ control ? false, size ? 10 }:
|
||||
|
||||
let
|
||||
lib = import <nixpkgs/lib>;
|
||||
inherit (import ./memoize.nix { inherit lib; }) memoizeStr;
|
||||
|
||||
# Create a string of the specified size
|
||||
key = lib.concatStrings (lib.genList (i: "a") size);
|
||||
|
||||
# Memoized identity function
|
||||
memoId = memoizeStr (x: x);
|
||||
|
||||
# Prime the trie with a minimal query to force its construction
|
||||
prime = memoId "";
|
||||
|
||||
in
|
||||
if control
|
||||
then builtins.seq prime key # Return key after priming
|
||||
else builtins.seq prime (memoId key) # Pass through memoization after priming
|
||||
50
lib/memoize/memoize.nix
Normal file
50
lib/memoize/memoize.nix
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{ lib, ... }:
|
||||
let
|
||||
keys =
|
||||
let
|
||||
nonNullBytesStr =
|
||||
builtins.readFile ./bytes.dat;
|
||||
nonNullItems =
|
||||
lib.stringToCharacters nonNullBytesStr;
|
||||
|
||||
keysList = [ "" ] ++ nonNullItems;
|
||||
|
||||
byteNames = lib.genAttrs keysList (k: null);
|
||||
in
|
||||
byteNames;
|
||||
|
||||
/**
|
||||
Produce an infinite trie for memoizing a function with a string input.
|
||||
|
||||
This uses memory in terms of a large factor of the number of unique string suffixes passed to the memoizeStr / queryTrie functions.
|
||||
*/
|
||||
makeTrie = prefix: f:
|
||||
lib.mapAttrs
|
||||
(k: v: if k == "" then f prefix else makeTrie (prefix + k) f)
|
||||
keys;
|
||||
|
||||
queryTrie =
|
||||
trie: needle:
|
||||
let
|
||||
needleList = lib.stringToCharacters needle;
|
||||
destination = lib.foldl'
|
||||
(subtrie: c: subtrie.${c})
|
||||
trie
|
||||
needleList;
|
||||
in
|
||||
destination."";
|
||||
|
||||
in
|
||||
{
|
||||
/**
|
||||
Turn a function that accepts a string input into one that memoizes the results.
|
||||
Make sure to partially apply it and use it over and over in e.g. the same let binding.
|
||||
Otherwise, you're wasting kilobytes of memory allocations *for each letter in each call*.
|
||||
That's 12+ KB per input byte on Nix 2.31, and more on older versions.
|
||||
Yes, this function is surprisingly EXPENSIVE, but cheaper than e.g. reinvoking Nixpkgs.
|
||||
Its memory cost is comparable to that of loading a small Nix file.
|
||||
*/
|
||||
memoizeStr = f:
|
||||
let trie = makeTrie "" f;
|
||||
in queryTrie trie;
|
||||
}
|
||||
10
lib/memoize/test.nix
Normal file
10
lib/memoize/test.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Ad hoc manual test dependent on observing side effects
|
||||
let
|
||||
lib = import ~/src/nixpkgs-master/lib;
|
||||
inherit (import ./memoize.nix { inherit lib; }) memoizeStr;
|
||||
# Don't use this in the wild, it's too expensive!
|
||||
printOnce = memoizeStr (x: builtins.trace "computing f ${lib.strings.escapeNixString x}" x);
|
||||
in
|
||||
{
|
||||
inherit printOnce memoizeStr lib;
|
||||
}
|
||||
|
|
@ -59,6 +59,14 @@ let
|
|||
}
|
||||
'';
|
||||
|
||||
/**
|
||||
We primarily use `systems` to help memoize the per system context, but that
|
||||
doesn't extend to arbitrary `system`s.
|
||||
For that, we use the slightly less efficient, but perfectly acceptable
|
||||
`memoizeStr` function.
|
||||
*/
|
||||
otherMemoizedSystems = flake-parts-lib.memoizeStr config.perSystem;
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
|
@ -139,8 +147,7 @@ in
|
|||
|
||||
config = {
|
||||
allSystems = genAttrs config.systems config.perSystem;
|
||||
# TODO: Sub-optimal error message. Get Nix to support a memoization primop, or get Nix Flakes to support systems properly or get Nix Flakes to add a name to flakes.
|
||||
_module.args.getSystem = system: config.allSystems.${system} or (builtins.trace "using non-memoized system ${system}" config.perSystem system);
|
||||
_module.args.getSystem = system: config.allSystems.${system} or (otherMemoizedSystems system);
|
||||
|
||||
# The warning is there for a reason. Only use this in situations where the
|
||||
# performance cost has already been incurred, such as in `flakeModules.easyOverlay`,
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@
|
|||
outputs = inputs@{ flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [
|
||||
# To import a flake module
|
||||
# 1. Add foo to inputs
|
||||
# 2. Add foo as a parameter to the outputs function
|
||||
# 3. Add here: foo.flakeModule
|
||||
# To import an internal flake module: ./other.nix
|
||||
# To import an external flake module:
|
||||
# 1. Add foo to inputs
|
||||
# 2. Add foo as a parameter to the outputs function
|
||||
# 3. Add here: foo.flakeModule
|
||||
|
||||
];
|
||||
systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
|
||||
|
|
|
|||
20
vendor/flake-compat/COPYING
vendored
Normal file
20
vendor/flake-compat/COPYING
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Copyright (c) 2020-2021 Eelco Dolstra and the flake-compat contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
21
vendor/flake-compat/README.md
vendored
Normal file
21
vendor/flake-compat/README.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# `vendor/flake-compat`
|
||||
|
||||
Flake-parts uses [flake-compat] in the partitions module.
|
||||
|
||||
Revision: f387cd2afec9419c8ee37694406ca490c3f34ee5
|
||||
|
||||
Non-essential files were omitted: `flake.nix`, CI configuration.
|
||||
|
||||
## Why vendor?
|
||||
|
||||
Vendoring is generally not recommended, but for flake-parts we make a different trade-off.
|
||||
|
||||
- Dependency is tiny
|
||||
- Fetching latency is significant compared to size
|
||||
- Cost gets multiplied by the high number of users/callers and flake-parts occurrences (when follows isn't used)
|
||||
- Some users care about the size of their lock file
|
||||
- Nix has some overhead for each lock node when updating a lock file
|
||||
- Hard to provide input in the Nix sandbox (for those who have evaluation tests in derivations)
|
||||
- Most users are unaffected (only impacts users of `partitions`)
|
||||
|
||||
[flake-compat]: https://github.com/NixOS/flake-compat
|
||||
319
vendor/flake-compat/default.nix
vendored
Normal file
319
vendor/flake-compat/default.nix
vendored
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
# Compatibility function to allow flakes to be used by
|
||||
# non-flake-enabled Nix versions. Given a source tree containing a
|
||||
# 'flake.nix' and 'flake.lock' file, it fetches the flake inputs and
|
||||
# calls the flake's 'outputs' function. It then returns an attrset
|
||||
# containing 'defaultNix' (to be used in 'default.nix'), 'shellNix'
|
||||
# (to be used in 'shell.nix').
|
||||
|
||||
{ src
|
||||
, system ? builtins.currentSystem or "unknown-system"
|
||||
,
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (builtins) mapAttrs;
|
||||
|
||||
lockFilePath = src + "/flake.lock";
|
||||
|
||||
lockFile = builtins.fromJSON (builtins.readFile lockFilePath);
|
||||
|
||||
fetchTree =
|
||||
builtins.fetchTree or (
|
||||
info:
|
||||
if info.type == "github" then
|
||||
{
|
||||
outPath = fetchTarball (
|
||||
{
|
||||
url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}";
|
||||
}
|
||||
// (if info ? narHash then { sha256 = info.narHash; } else { })
|
||||
);
|
||||
rev = info.rev;
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
lastModified = info.lastModified;
|
||||
lastModifiedDate = formatSecondsSinceEpoch info.lastModified;
|
||||
narHash = info.narHash;
|
||||
}
|
||||
else if info.type == "git" then
|
||||
{
|
||||
outPath = builtins.fetchGit (
|
||||
{
|
||||
url = info.url;
|
||||
}
|
||||
// (if info ? rev then { inherit (info) rev; } else { })
|
||||
// (if info ? ref then { inherit (info) ref; } else { })
|
||||
// (if info ? submodules then { inherit (info) submodules; } else { })
|
||||
);
|
||||
lastModified = info.lastModified;
|
||||
lastModifiedDate = formatSecondsSinceEpoch info.lastModified;
|
||||
narHash = info.narHash;
|
||||
revCount = info.revCount or 0;
|
||||
}
|
||||
// (
|
||||
if info ? rev then
|
||||
{
|
||||
rev = info.rev;
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
}
|
||||
else
|
||||
{ }
|
||||
)
|
||||
else if info.type == "path" then
|
||||
{
|
||||
outPath = builtins.path {
|
||||
path = info.path;
|
||||
sha256 = info.narHash;
|
||||
};
|
||||
narHash = info.narHash;
|
||||
}
|
||||
else if info.type == "tarball" then
|
||||
{
|
||||
outPath = fetchTarball (
|
||||
{ inherit (info) url; } // (if info ? narHash then { sha256 = info.narHash; } else { })
|
||||
);
|
||||
}
|
||||
else if info.type == "gitlab" then
|
||||
{
|
||||
inherit (info) rev narHash lastModified;
|
||||
outPath = fetchTarball (
|
||||
{
|
||||
url = "https://${info.host or "gitlab.com"}/api/v4/projects/${info.owner}%2F${info.repo}/repository/archive.tar.gz?sha=${info.rev}";
|
||||
}
|
||||
// (if info ? narHash then { sha256 = info.narHash; } else { })
|
||||
);
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
}
|
||||
else if info.type == "sourcehut" then
|
||||
{
|
||||
inherit (info) rev narHash lastModified;
|
||||
outPath = fetchTarball (
|
||||
{
|
||||
url = "https://${info.host or "git.sr.ht"}/${info.owner}/${info.repo}/archive/${info.rev}.tar.gz";
|
||||
}
|
||||
// (if info ? narHash then { sha256 = info.narHash; } else { })
|
||||
);
|
||||
shortRev = builtins.substring 0 7 info.rev;
|
||||
}
|
||||
else
|
||||
# FIXME: add Mercurial, tarball inputs.
|
||||
throw "flake input has unsupported input type '${info.type}'"
|
||||
);
|
||||
|
||||
callFlake4 =
|
||||
flakeSrc: locks:
|
||||
let
|
||||
flake = import (flakeSrc + "/flake.nix");
|
||||
|
||||
inputs = mapAttrs
|
||||
(
|
||||
n: v:
|
||||
if v.flake or true then
|
||||
callFlake4 (fetchTree (v.locked // v.info)) v.inputs
|
||||
else
|
||||
fetchTree (v.locked // v.info)
|
||||
)
|
||||
locks;
|
||||
|
||||
outputs = flakeSrc // (flake.outputs (inputs // { self = outputs; }));
|
||||
in
|
||||
assert flake.edition == 201909;
|
||||
outputs;
|
||||
|
||||
callLocklessFlake =
|
||||
flakeSrc:
|
||||
let
|
||||
flake = import (flakeSrc + "/flake.nix");
|
||||
outputs = flakeSrc // (flake.outputs ({ self = outputs; }));
|
||||
in
|
||||
outputs;
|
||||
|
||||
rootSrc =
|
||||
let
|
||||
# Try to clean the source tree by using fetchGit, if this source
|
||||
# tree is a valid git repository.
|
||||
tryFetchGit =
|
||||
src:
|
||||
if isGit && !isShallow then
|
||||
let
|
||||
res = builtins.fetchGit src;
|
||||
in
|
||||
if res.rev == "0000000000000000000000000000000000000000" then
|
||||
removeAttrs res [
|
||||
"rev"
|
||||
"shortRev"
|
||||
]
|
||||
else
|
||||
res
|
||||
else
|
||||
{
|
||||
outPath =
|
||||
# Massage `src` into a store path.
|
||||
if builtins.isPath src then
|
||||
if
|
||||
dirOf (toString src) == builtins.storeDir
|
||||
# `builtins.storePath` is not available in pure-eval mode.
|
||||
&& builtins ? currentSystem
|
||||
then
|
||||
# If it's already a store path, don't copy it again.
|
||||
builtins.storePath src
|
||||
else
|
||||
"${src}"
|
||||
else
|
||||
src;
|
||||
};
|
||||
# NB git worktrees have a file for .git, so we don't check the type of .git
|
||||
isGit = builtins.pathExists (src + "/.git");
|
||||
isShallow = builtins.pathExists (src + "/.git/shallow");
|
||||
|
||||
in
|
||||
{
|
||||
lastModified = 0;
|
||||
lastModifiedDate = formatSecondsSinceEpoch 0;
|
||||
}
|
||||
// (if src ? outPath then src else tryFetchGit src);
|
||||
|
||||
# Format number of seconds in the Unix epoch as %Y%m%d%H%M%S.
|
||||
formatSecondsSinceEpoch =
|
||||
t:
|
||||
let
|
||||
rem = x: y: x - x / y * y;
|
||||
days = t / 86400;
|
||||
secondsInDay = rem t 86400;
|
||||
hours = secondsInDay / 3600;
|
||||
minutes = (rem secondsInDay 3600) / 60;
|
||||
seconds = rem t 60;
|
||||
|
||||
# Courtesy of https://stackoverflow.com/a/32158604.
|
||||
z = days + 719468;
|
||||
era = (if z >= 0 then z else z - 146096) / 146097;
|
||||
doe = z - era * 146097;
|
||||
yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
y = yoe + era * 400;
|
||||
doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
mp = (5 * doy + 2) / 153;
|
||||
d = doy - (153 * mp + 2) / 5 + 1;
|
||||
m = mp + (if mp < 10 then 3 else -9);
|
||||
y' = y + (if m <= 2 then 1 else 0);
|
||||
|
||||
pad = s: if builtins.stringLength s < 2 then "0" + s else s;
|
||||
in
|
||||
"${toString y'}${pad (toString m)}${pad (toString d)}${pad (toString hours)}${pad (toString minutes)}${pad (toString seconds)}";
|
||||
|
||||
allNodes = mapAttrs
|
||||
(
|
||||
key: node:
|
||||
let
|
||||
isRelative = node.locked.type or null == "path" && builtins.substring 0 1 node.locked.path != "/";
|
||||
|
||||
parentNode = allNodes.${getInputByPath lockFile.root node.parent};
|
||||
|
||||
sourceInfo =
|
||||
if key == lockFile.root then
|
||||
rootSrc
|
||||
else if isRelative then
|
||||
parentNode.sourceInfo
|
||||
else
|
||||
fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]);
|
||||
|
||||
subdir = if key == lockFile.root then "" else node.locked.dir or "";
|
||||
|
||||
outPath =
|
||||
if isRelative then
|
||||
parentNode.outPath + (if node.locked.path == "" then "" else "/" + node.locked.path)
|
||||
else
|
||||
sourceInfo.outPath + (if subdir == "" then "" else "/" + subdir);
|
||||
|
||||
flake = import (outPath + "/flake.nix");
|
||||
|
||||
inputs = mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}.result) (
|
||||
node.inputs or { }
|
||||
);
|
||||
|
||||
# Resolve a input spec into a node name. An input spec is
|
||||
# either a node name, or a 'follows' path from the root
|
||||
# node.
|
||||
resolveInput =
|
||||
inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec;
|
||||
|
||||
# Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the
|
||||
# root node, returning the final node.
|
||||
getInputByPath =
|
||||
nodeName: path:
|
||||
if path == [ ] then
|
||||
nodeName
|
||||
else
|
||||
getInputByPath
|
||||
# Since this could be a 'follows' input, call resolveInput.
|
||||
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
||||
(builtins.tail path);
|
||||
|
||||
outputs = flake.outputs (inputs // { self = result; });
|
||||
|
||||
result =
|
||||
outputs
|
||||
# We add the sourceInfo attribute for its metadata, as they are
|
||||
# relevant metadata for the flake. However, the outPath of the
|
||||
# sourceInfo does not necessarily match the outPath of the flake,
|
||||
# as the flake may be in a subdirectory of a source.
|
||||
# This is shadowed in the next //
|
||||
// sourceInfo
|
||||
// {
|
||||
# This shadows the sourceInfo.outPath
|
||||
inherit outPath;
|
||||
|
||||
inherit inputs;
|
||||
inherit outputs;
|
||||
inherit sourceInfo;
|
||||
_type = "flake";
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
result =
|
||||
if node.flake or true then
|
||||
assert builtins.isFunction flake.outputs;
|
||||
result
|
||||
else
|
||||
sourceInfo // { inherit sourceInfo outPath; };
|
||||
|
||||
inherit outPath sourceInfo;
|
||||
}
|
||||
)
|
||||
lockFile.nodes;
|
||||
|
||||
result =
|
||||
if !(builtins.pathExists lockFilePath) then
|
||||
callLocklessFlake rootSrc
|
||||
else if lockFile.version == 4 then
|
||||
callFlake4 rootSrc (lockFile.inputs)
|
||||
else if lockFile.version >= 5 && lockFile.version <= 7 then
|
||||
allNodes.${lockFile.root}.result
|
||||
else
|
||||
throw "lock file '${lockFilePath}' has unsupported version ${toString lockFile.version}";
|
||||
|
||||
in
|
||||
rec {
|
||||
outputs = result;
|
||||
|
||||
defaultNix =
|
||||
builtins.removeAttrs result [ "__functor" ]
|
||||
// (
|
||||
if result ? defaultPackage.${system} then { default = result.defaultPackage.${system}; } else { }
|
||||
)
|
||||
// (
|
||||
if result ? packages.${system}.default then
|
||||
{ default = result.packages.${system}.default; }
|
||||
else
|
||||
{ }
|
||||
);
|
||||
|
||||
shellNix =
|
||||
defaultNix
|
||||
// (if result ? devShell.${system} then { default = result.devShell.${system}; } else { })
|
||||
// (
|
||||
if result ? devShells.${system}.default then
|
||||
{ default = result.devShells.${system}.default; }
|
||||
else
|
||||
{ }
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue