This commit is contained in:
mjallen18
2026-01-21 21:43:31 -06:00
parent 94c3d6d6ff
commit e2e2d814fe
23 changed files with 478 additions and 572 deletions

View File

@@ -9,7 +9,8 @@ let
getAttr
attrNames
toString
replaceStrings;
replaceStrings
;
mapAttrs = lib.mapAttrs;
recursiveUpdate = lib.recursiveUpdate;
@@ -18,40 +19,44 @@ let
deepMerge = a: b: recursiveUpdate a b;
# Merge component sources: base.sources overlaid by overrides (component-wise deep merge).
mergeSources = baseSources: overrides:
baseSources //
mapAttrs (name: ov:
if hasAttr name baseSources then deepMerge (getAttr name baseSources) ov else ov
mergeSources =
baseSources: overrides:
baseSources
// mapAttrs (
name: ov: if hasAttr name baseSources then deepMerge (getAttr name baseSources) ov else ov
) overrides;
# Apply a single variant overlay (variables + sources).
applyVariantOnce = selected: variant:
applyVariantOnce =
selected: variant:
let
vVars = if variant ? variables then variant.variables else {};
vSrcs = if variant ? sources then variant.sources else {};
vVars = if variant ? variables then variant.variables else { };
vSrcs = if variant ? sources then variant.sources else { };
in
{
variables = selected.variables // vVars;
sources = mergeSources selected.sources vSrcs;
sources = mergeSources selected.sources vSrcs;
};
# Apply platform-specific overrides if present for the given system.
applyPlatforms = selected: variant: system:
applyPlatforms =
selected: variant: system:
if system == null || !(variant ? platforms) || !(hasAttr system variant.platforms) then
selected
else
let
p = variant.platforms.${system};
pVars = if p ? variables then p.variables else {};
pSrcs = if p ? sources then p.sources else {};
pVars = if p ? variables then p.variables else { };
pSrcs = if p ? sources then p.sources else { };
in
{
variables = selected.variables // pVars;
sources = mergeSources selected.sources pSrcs;
sources = mergeSources selected.sources pSrcs;
};
# Resolve variant chain via inherits (ancestor first), then apply platforms.
resolveVariant = spec: baseSelected: variantName: system:
resolveVariant =
spec: baseSelected: variantName: system:
if variantName == null || !(spec ? variants) || !(hasAttr variantName spec.variants) then
baseSelected
else
@@ -64,7 +69,8 @@ let
applyPlatforms withVariant v system;
# Render ${var} substitutions in any string within attrs/lists.
renderValue = value: vars:
renderValue =
value: vars:
if isString value then
let
keys = attrNames vars;
@@ -80,23 +86,26 @@ let
value;
# Decide fetcher for URL type based on optional extra.unpack hint.
useFetchZip = comp:
comp ? extra && comp.extra ? unpack && comp.extra.unpack == "zip";
useFetchZip = comp: comp ? extra && comp.extra ? unpack && comp.extra.unpack == "zip";
# Build a single src from a rendered component spec.
mkSrcFromRendered = comp:
mkSrcFromRendered =
comp:
let
fetcher = if comp ? fetcher then comp.fetcher else "none";
in
if fetcher == "github" then
pkgs.fetchFromGitHub ({
owner = comp.owner;
repo = comp.repo;
# Allow tag as rev (ignore null/empty tag)
rev = if comp ? tag && comp.tag != null && comp.tag != "" then comp.tag else comp.rev;
fetchSubmodules = if comp ? submodules then comp.submodules else false;
hash = comp.hash;
} // lib.optionalAttrs (comp ? name) { name = comp.name; })
pkgs.fetchFromGitHub (
{
owner = comp.owner;
repo = comp.repo;
# Allow tag as rev (ignore null/empty tag)
rev = if comp ? tag && comp.tag != null && comp.tag != "" then comp.tag else comp.rev;
fetchSubmodules = if comp ? submodules then comp.submodules else false;
hash = comp.hash;
}
// lib.optionalAttrs (comp ? name) { name = comp.name; }
)
else if fetcher == "git" then
pkgs.fetchgit {
url = comp.url;
@@ -110,11 +119,17 @@ let
in
if useFetchZip comp then
pkgs.fetchzip (
{ inherit url; hash = comp.hash; }
{
inherit url;
hash = comp.hash;
}
// lib.optionalAttrs (comp ? extra && comp.extra ? stripRoot) { stripRoot = comp.extra.stripRoot; }
)
else
pkgs.fetchurl { inherit url; hash = comp.hash; }
pkgs.fetchurl {
inherit url;
hash = comp.hash;
}
else if fetcher == "pypi" then
pkgs.python3Packages.fetchPypi {
pname = comp.name;
@@ -125,7 +140,8 @@ let
# fetcher == "none": pass-through (e.g., linux version/hash consumed by custom logic)
comp;
in rec {
in
rec {
/*
Select a variant from a loaded version.json specification.
@@ -135,12 +151,17 @@ in rec {
- variantName: string or null (when null, uses spec.defaultVariant if present)
- system: string like "x86_64-linux" or null (to apply platforms overrides)
*/
selectVariant = spec: variantName: system:
selectVariant =
spec: variantName: system:
let
chosen = if variantName != null then variantName else (if spec ? defaultVariant then spec.defaultVariant else null);
chosen =
if variantName != null then
variantName
else
(if spec ? defaultVariant then spec.defaultVariant else null);
baseSelected = {
variables = if spec ? variables then spec.variables else {};
sources = if spec ? sources then spec.sources else {};
variables = if spec ? variables then spec.variables else { };
sources = if spec ? sources then spec.sources else { };
};
in
resolveVariant spec baseSelected chosen system;
@@ -155,9 +176,12 @@ in rec {
Render a component with variables and then build its src (or pass-through for fetcher "none").
Prefer using mkAllSources, which handles rendering for all components.
*/
mkSrc = comp: variables:
let rendered = renderValue comp variables;
in mkSrcFromRendered rendered;
mkSrc =
comp: variables:
let
rendered = renderValue comp variables;
in
mkSrcFromRendered rendered;
/*
Produce an attrset of all sources for a selected spec:
@@ -167,15 +191,16 @@ in rec {
Returns:
{ componentName = src | renderedComp (for "none"); ... }
*/
mkAllSources = selected:
mapAttrs (_name: comp:
if comp ? fetcher && comp.fetcher == "none"
then renderValue comp selected.variables
else mkSrc (renderValue comp selected.variables) selected.variables
mkAllSources =
selected:
mapAttrs (
_name: comp:
if comp ? fetcher && comp.fetcher == "none" then
renderValue comp selected.variables
else
mkSrc (renderValue comp selected.variables) selected.variables
) selected.sources;
/*
Expose deepMerge for convenience (right-biased).
*/
# Expose deepMerge for convenience (right-biased).
inherit deepMerge;
}