{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE DeriveGeneric #-} module Control.Funflow.External.Nix ( NixConfig(..) , NixpkgsSource(..) , Environment(..) , nix )where import Control.Funflow import Path import Control.Funflow.ContentHashable import Control.Funflow.ContentStore as CS import Control.Funflow.External as E import Data.Semigroup ((<>)) import qualified Data.Text as T import GHC.Generics (Generic) import Data.List import Text.URI (URI) import qualified Text.URI as URI data NixpkgsSource = NIX_PATH -- ^ Inherit the @NIX_PATH@ from the environment | NixpkgsTarball URI -- ^ The 'URI' pointing to a nixpkgs tarball deriving Generic data NixConfig = NixShellConfig { environment :: Environment, -- ^ Specification of the nix environment nixpkgsSource :: NixpkgsSource, -- ^ Which version of nixpkgs to use command :: T.Text, -- ^ The command to run in the environment args :: [ParamField], -- ^ Arguments to pass to the command env :: [(T.Text, Param)], -- ^ Environmental variables which are set in the environment stdout :: OutputCapture } data Environment = ShellFile (Content File) -- ^ Path to a shell.nix file | PackageList [T.Text] -- ^ A list of packages that -- will be passed by @-p@. deriving Generic instance ContentHashable IO Environment where instance ContentHashable IO NixpkgsSource where contentHashUpdate ctx NIX_PATH = contentHashUpdate_fingerprint ctx NIX_PATH contentHashUpdate ctx (NixpkgsTarball s) = contentHashUpdate ctx (URI.render s) nixpkgsSourceToParam :: NixpkgsSource -> Param nixpkgsSourceToParam NIX_PATH = envParam "NIX_PATH" nixpkgsSourceToParam (NixpkgsTarball uri) = textParam ("nixpkgs=" <> URI.render uri) toExternal :: NixConfig -> ExternalTask toExternal NixShellConfig{..} = ExternalTask { _etCommand = "nix-shell" , _etParams = [ "--run" , Param [ParamCmd (Param (intersperse (ParamText " ") (ParamText command : args)))] ] ++ packageSpec environment , _etEnv = E.EnvExplicit $ ("NIX_PATH", nixpkgsSourceToParam nixpkgsSource ) : env , _etWriteToStdOut = stdout } where packageSpec :: Environment -> [Param] packageSpec (ShellFile ip) = [contentParam ip] packageSpec (PackageList ps) = [textParam ("-p " <> p) | p <- ps] -- | Constructor a flow from a @NixConfig@ nix :: (ContentHashable IO a, ArrowFlow eff ex arr) => (a -> NixConfig) -> arr a CS.Item nix f = external $ toExternal . f