packages feed

hail-0.1.0.0: Hail/Nix.hs

{-# LANGUAGE LambdaCase #-}
module Hail.Nix where

import System.Exit (ExitCode(..))
import System.IO (hPutStrLn, stderr)
import System.IO.Error (tryIOError)

import System.Process (spawnProcess, waitForProcess, callProcess)
import System.FilePath ((</>))

-- | Run the activation script for a profile.
--
-- Errors are logged to stderr.
activate
  :: FilePath -- ^ The path to the profile
  -> ActivateErrorMode
  -> IO ()
activate profilePath error_mode = do
    e_pid <- tryIOError $ spawnProcess activateCommand []
    case e_pid of
      Left err ->
        logger $ "spawning activation command failed: " ++ show err
      Right pid -> do
        code <- waitForProcess pid
        case code of
          ExitSuccess -> return ()
          ExitFailure i -> logger $
            "activation command exited with non-zero code " ++ show i
  where
    logger = case error_mode of
      ActivateIgnoreErrors -> const $ return ()
      ActivateReportErrors -> hPutStrLn stderr
    activateCommand = profilePath </> "bin/activate"

-- | Settings for error handling for 'activate'.
data ActivateErrorMode
  = ActivateIgnoreErrors -- ^ Ignore errors.
  | ActivateReportErrors -- ^ Log errors to stderr.

-- | Update a profile to point to a given store path.
--
-- The store path is realised if necessary.
--
-- Errors are logged to stderr.
switchProfile
  :: FilePath -- ^ The profile.
  -> FilePath -- ^ The store path.
  -> IO Bool  -- ^ Whether the update succeeded.
switchProfile profilePath outPath = tryIOError switch >>= \case
    Left err -> do
      hPutStrLn stderr $  "Switching " ++ profilePath ++ " to "
                       ++ outPath ++ " failed: " ++ (show err)
      return False
    Right () -> return True
  where
    -- TODO Hard-code path to nix-env?
    switch = callProcess "nix-env" [ "--profile", profilePath
                                   , "--set", outPath
                                   ]