Skip to content

Update collectComponents to use just the package name #2345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,24 @@ in {
let packageToComponents = _name: package:
# look for the components with this group if there are any
let components = package.components.${group} or {};
# set recurseForDerivations unless it's a derivation itself (e.g. the "library" component) or an empty set
in if lib.isDerivation components || components == {}
then components
else recurseIntoAttrs components;
in {
inherit (package.identifier) name;
# set recurseForDerivations unless it's a derivation itself (e.g. the "library" component) or an empty set
components =
if lib.isDerivation components || components == {}
then components
else recurseIntoAttrs components;
};
packageFilter = _name: package: (package.isHaskell or false) && packageSel package;
filteredPkgs = lib.filterAttrs packageFilter haskellPackages;
# at this point we can filter out packages that don't have any of the given kind of component
packagesByComponent = lib.filterAttrs (_: components: components != {}) (lib.mapAttrs packageToComponents filteredPkgs);
in recurseIntoAttrs packagesByComponent;
packagesByComponent = lib.mapAttrsToList packageToComponents filteredPkgs;
packagesGroupedByName = builtins.groupBy (x: x.name) packagesByComponent;
combined =
lib.filterAttrs (_: components: components != {}) (
builtins.mapAttrs (_name: packages:
builtins.foldl' (a: b: a // b) {} (map (x: x.components) packages)) packagesGroupedByName);
in recurseIntoAttrs combined;

# Equivalent to collectComponents with (_: true) as selection function.
# Useful for pre-filtered package-set.
Expand All @@ -184,7 +193,7 @@ in {
# This can be used to collect all the test runs in your project, so that can be run in CI.
collectChecks = packageSel: haskellPackages:
let packageFilter = _name: package: (package.isHaskell or false) && packageSel package;
in recurseIntoAttrs (lib.mapAttrs (_: p: p.checks) (lib.filterAttrs packageFilter haskellPackages));
in recurseIntoAttrs (lib.filterAttrs (_: x: x != {} && x != recurseIntoAttrs {}) (lib.mapAttrs (_: p: p.checks) (lib.filterAttrs packageFilter haskellPackages)));

# Equivalent to collectChecks with (_: true) as selection function.
# Useful for pre-filtered package-set.
Expand Down
65 changes: 35 additions & 30 deletions modules/install-plan/redirect.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Add `hsPkgs.${pkg-name}` based on the available targets in the plan.
{pkgs, lib, config, ...}:
let
redirect = redirectName: packageTargets:
redirect = existing: redirectName: packageTargets:
let
componentsByName = builtins.listToAttrs (map (x: { name = x.component-name; value = x.available; }) packageTargets);
lookupComponent = collectionName: name: available:
Expand All @@ -14,8 +14,8 @@ let
else if builtins.isString (builtins.head available)
then throw "${builtins.head available} looking for ${attrPath}"
else if collectionName == ""
then config.hsPkgs.${(builtins.head available).id}.components.library
else config.hsPkgs.${(builtins.head available).id}.components.${collectionName}.${name};
then existing.${(builtins.head available).id}.components.library
else existing.${(builtins.head available).id}.components.${collectionName}.${name};
componentsWithPrefix = collectionName: prefix:
lib.listToAttrs (lib.concatLists (lib.mapAttrsToList (n: available:
lib.optional (lib.hasPrefix "${prefix}:" n && (builtins.length available != 1 || !builtins.elem (builtins.head available) ["TargetNotBuildable" "TargetNotLocal"])) (
Expand All @@ -24,44 +24,49 @@ let
value = lookupComponent collectionName name available;
in { inherit name value; }
)) componentsByName));
defaultTargetPackage = config.hsPkgs.${(builtins.head (
defaultTargetId = (builtins.head (
# Use the package identified by the library component
componentsByName.lib or
# Or by the first component
componentsByName.${builtins.head (builtins.attrNames componentsByName)}
)).id};
in rec {
isRedirect = true;
)).id;
defaultTargetPackage = existing.${defaultTargetId};
in defaultTargetPackage // rec {
isRedirect = redirectName != defaultTargetId;
identifier = rec { name = (builtins.head packageTargets).pkg-name; version = (builtins.head packageTargets).pkg-version; id = "${name}-${version}"; };
components =
lib.mapAttrs componentsWithPrefix pkgs.haskell-nix.haskellLib.componentPrefix
// lib.optionalAttrs (componentsByName ? lib) {
library = lookupComponent "" "" componentsByName.lib;
};
checks = pkgs.recurseIntoAttrs (builtins.mapAttrs
(_: d: pkgs.haskell-nix.haskellLib.check d)
(lib.filterAttrs (_: d: d.config.doCheck) components.tests));
inherit (defaultTargetPackage) buildType setup;
checks = pkgs.recurseIntoAttrs (
lib.filterAttrs (_: x: x != {}) (
builtins.mapAttrs
(_: d: pkgs.haskell-nix.haskellLib.check d)
(lib.filterAttrs (_: d: d.config.doCheck) components.tests)));
};
in {
hsPkgs =
# Redirects with just the package name
builtins.removeAttrs (builtins.mapAttrs (packageName: packageTargets:
let
byVersion = builtins.groupBy (x: x.pkg-version) packageTargets;
versions = builtins.attrNames byVersion;
in if builtins.length versions != 1
then let
err = throw "Multiple versions for ${packageName} ${builtins.toJSON versions}";
in {
isRedirect = true;
identifier = { name = packageName; version = err; };
components = err;
checks = err;
}
else redirect packageName packageTargets) (builtins.groupBy (x: x.pkg-name) config.plan-json.targets)) config.preExistingPkgs
options.hsPkgs = lib.mkOption {
type = lib.types.unspecified;
apply = existing: existing //
# Redirects with just the package name
builtins.removeAttrs (builtins.mapAttrs (packageName: packageTargets:
let
byVersion = builtins.groupBy (x: x.pkg-version) packageTargets;
versions = builtins.attrNames byVersion;
in if builtins.length versions != 1
then let
err = throw "Multiple versions for ${packageName} ${builtins.toJSON versions}";
in {
isRedirect = true;
identifier = { name = packageName; version = err; };
components = err;
checks = err;
}
else redirect existing packageName packageTargets) (builtins.groupBy (x: x.pkg-name) config.plan-json.targets)) config.preExistingPkgs

# Redirect for `${name}-${version}`
// builtins.mapAttrs (packageNameAndVersion: packageTargets: redirect packageNameAndVersion packageTargets)
(builtins.groupBy (x: "${x.pkg-name}-${x.pkg-version}") config.plan-json.targets);
# Redirect for `${name}-${version}`
// builtins.mapAttrs (packageNameAndVersion: packageTargets: redirect existing packageNameAndVersion packageTargets)
(builtins.groupBy (x: "${x.pkg-name}-${x.pkg-version}") config.plan-json.targets);
};
}
Loading