From bda7bc31d6a8f90087dc7b83c00209ae9d0d3390 Mon Sep 17 00:00:00 2001 From: Tommy Bidne Date: Thu, 7 Nov 2024 12:48:51 +1300 Subject: [PATCH] Add mergeApps for merging multiple app AttrSets --- .github/workflows/ci.yaml | 5 +++ README.md | 21 ++++------ flake.nix | 1 + lib/apps.nix | 84 +++++++++++++++++++++++++++++++++++++-- test/flake.nix | 11 +++++ 5 files changed, 106 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 499f99d..d67a620 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -120,3 +120,8 @@ jobs: run: | cd test nix run .#lint-yaml + + - name: Lint merged + run: | + cd test + nix run .#lint-merged diff --git a/README.md b/README.md index 63ec2f8..1ea8c9a 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ Nix utility functions for haskell flakes. } ``` -Note that we can also merge multiple apps together, using the `mkDrv` argument (default `true`): +Note that we can also merge multiple apps together, using the `mkDrv` argument (default `true`) and `mergeApps`: ```nix let @@ -135,17 +135,12 @@ let formatHsNix = nix-hs-utils.format { ... mkDrv = false; ... }; formatYaml = nix-hs-utils.format-yaml { ... mkDrv = false; ... }; - # Because of 'mkDrv = false', we need to call mkShellApp ourselves. - format = nix-hs-utils.mkShellApp { - inherit pkgs; - name = "format"; - - # Now we can combine the command and inputs in a straightforward manner. - text = '' - ${formatHsNix.text} - - ${formatYaml.text} - ''; - runtimeInputs = formatHsNix.runtimeInputs ++ formatYaml.runtimeInputs; + # mergeApps takes in a list of app AttrSet and merges them together into a + # single app. + format = nix-hs-utils.mergeApps { + apps = [ + (nix-hs-utils.format (compilerPkgs // pkgsMkDrv)) + (nix-hs-utils.format-yaml pkgsMkDrv) + ]; }; ``` diff --git a/flake.nix b/flake.nix index dd62a0e..998b080 100644 --- a/flake.nix +++ b/flake.nix @@ -26,6 +26,7 @@ lint-yaml mkApp mkShellApp + mergeApps ; }; } diff --git a/lib/apps.nix b/lib/apps.nix index f9d73c2..4465bb0 100644 --- a/lib/apps.nix +++ b/lib/apps.nix @@ -18,11 +18,89 @@ let mkApp (pkgs.writeShellApplication { inherit name text runtimeInputs; }); # Returns either a shell app derivation or the set itself. - drvOrSet = mkDrv: s: - if mkDrv then mkShellApp s else s; + drvOrSet = mkDrv: s: if mkDrv then mkShellApp s else s; + + /* + Merges a list of attr sets representing shell apps into a single app. + + Fields: + + - apps (List AttrSet): + NonEmpty list of AttrSet shell apps. Each app requires the 'text' + and 'runtimeInputs' fields. + + - mkDrv (Boolean): + If true (default), returns a derivation i.e. the shell app. Otherwise + returns the merged set. + + - name (String): + The name to use for the merged app. If null or unspecified, we take + the name of the __first__ app with a non-null name. At least one name + is required. + + - pkgs (AttrSet): + The nixpkgs for creating the shell app. Follows the same semantics + as name. + + Example: + a1 = ... + a2 = ... + a3 = ... + + app = mergeApps { apps = [a1 a2 a3]; }; + + Type: mkLibs :: + List AttrSet -> + Boolean -> + Maybe String -> + Maybe AttrSet -> + (AttrSet | Derivation) + */ + mergeApps = + { + apps, + mkDrv ? true, + name ? null, + pkgs ? null, + }: + let + init = { + inherit name pkgs; + text = ""; + runtimeInputs = [ ]; + }; + mergeApp = acc: app: { + # Take the first non-null name we find. Apps are not required to + # have a name, but we need at least one (or top-level) name. + name = + if acc.name != null then + acc.name + else if app ? name then + app.name + else + acc.name; + + # Same semantics as name: Take the first non-null or top-level. + pkgs = + if acc.pkgs != null then + acc.pkgs + else if app ? pkgs then + app.pkgs + else + acc.pkgs; + + text = '' + ${acc.text} + + ${app.text} + ''; + runtimeInputs = acc.runtimeInputs ++ app.runtimeInputs; + }; + in + drvOrSet mkDrv (builtins.foldl' mergeApp init apps); in { - inherit mkApp mkShellApp; + inherit mkApp mkShellApp mergeApps; # ShellApp that formats cabal, nix, and haskell via ormolu (default) or # fourmolu. diff --git a/test/flake.nix b/test/flake.nix index b848456..ac55297 100644 --- a/test/flake.nix +++ b/test/flake.nix @@ -38,6 +38,10 @@ compilerPkgs = { inherit compiler pkgs; }; + pkgsMkDrv = { + inherit pkgs; + mkDrv = false; + }; in { packages."${system}".default = mkShell false; @@ -87,6 +91,13 @@ }; lint-yaml = nix-hs-utils.lint-yaml { inherit pkgs; }; + + lint-merged = nix-hs-utils.mergeApps { + apps = [ + (nix-hs-utils.lint (compilerPkgs // pkgsMkDrv)) + (nix-hs-utils.lint-yaml pkgsMkDrv) + ]; + }; }; }; }