content: {-# LANGUAGE NoImplicitPrelude     #-}
  {-# LANGUAGE DuplicateRecordFields #-}
  {-# LANGUAGE OverloadedRecordDot   #-}
  {-# LANGUAGE OverloadedStrings     #-}
  
  module Stack.NixSpec
    ( sampleConfigNixEnabled
    , sampleConfigNixDisabled
    , setup
    , spec
    ) where
  
  import           Data.Maybe ( fromJust )
  import           Options.Applicative
                     ( defaultPrefs, execParserPure, getParseResult, info )
  import           Prelude ( writeFile )
  import           Stack.Config ( loadConfig )
  import           Stack.Config.Nix ( nixCompiler )
  import           Stack.Constants ( osIsWindows, stackDotYaml )
  import           Stack.Options.GlobalParser ( globalOptsFromMonoid )
  import           Stack.Options.NixParser ( nixOptsParser )
  import           Stack.Prelude
  import           Stack.Runners ( withRunnerGlobal )
  import           Stack.Types.Config ( Config (..) )
  import           Stack.Types.ConfigMonoid ( ConfigMonoid (..) )
  import qualified Stack.Types.GlobalOpts as GlobalOpts ( GlobalOpts (..) )
  import           Stack.Types.GlobalOptsMonoid ( GlobalOptsMonoid (..) )
  import           Stack.Types.Nix ( NixOpts (..) )
  import           System.Directory ( getCurrentDirectory, setCurrentDirectory )
  import           System.Environment ( unsetEnv )
  import           Test.Hspec ( Spec, around_, beforeAll, describe, it, shouldBe )
  
  sampleConfigNixEnabled :: String
  sampleConfigNixEnabled =
    "snapshot: lts-19.22\n" ++
    "packages: ['.']\n" ++
    "system-ghc: true\n" ++
    "nix:\n" ++
    "   enable: True\n" ++
    "   packages: [glpk]"
  
  sampleConfigNixDisabled :: String
  sampleConfigNixDisabled =
    "snapshot: lts-19.22\n" ++
    "packages: ['.']\n" ++
    "nix:\n" ++
    "   enable: False"
  
  setup :: IO ()
  setup = unsetEnv "STACK_YAML"
  
  spec :: Spec
  spec = beforeAll setup $ do
    let loadConfig' :: ConfigMonoid -> (Config -> IO ()) -> IO ()
        loadConfig' cmdLineArgs inner = do
          globalOpts <-
            globalOptsFromMonoid "" Nothing False mempty { configMonoid = cmdLineArgs }
          withRunnerGlobal globalOpts { GlobalOpts.logLevel = LevelOther "silent" } $
            loadConfig (liftIO . inner)
        inTempDir test = do
          currentDirectory <- getCurrentDirectory
          withSystemTempDirectory "Stack_ConfigSpec" $ \tempDir -> do
            let enterDir = setCurrentDirectory tempDir
                exitDir = setCurrentDirectory currentDirectory
            bracket_ enterDir exitDir test
        withStackDotYaml config test = inTempDir $ do
          writeFile (toFilePath stackDotYaml) config
          test
        parseNixOpts cmdLineOpts = fromJust $ getParseResult $ execParserPure
          defaultPrefs
          (info (nixOptsParser False) mempty)
          cmdLineOpts
        parseOpts cmdLineOpts = mempty { nixOpts = parseNixOpts cmdLineOpts }
    let trueOnNonWindows = not osIsWindows
    describe "nix disabled in config file" $
      around_ (withStackDotYaml sampleConfigNixDisabled) $ do
        it "sees that the nix shell is not enabled" $ loadConfig' mempty $ \config ->
           config.nix.enable `shouldBe` False
        describe "--nix given on command line" $
          it "sees that the nix shell is enabled" $
            loadConfig' (parseOpts ["--nix"]) $ \config ->
            config.nix.enable `shouldBe` trueOnNonWindows
        describe "--nix-pure given on command line" $
          it "sees that the nix shell is enabled" $
            loadConfig' (parseOpts ["--nix-pure"]) $ \config ->
            config.nix.enable `shouldBe` trueOnNonWindows
        describe "--no-nix given on command line" $
          it "sees that the nix shell is not enabled" $
            loadConfig' (parseOpts ["--no-nix"]) $ \config ->
            config.nix.enable `shouldBe` False
        describe "--no-nix-pure given on command line" $
          it "sees that the nix shell is not enabled" $
            loadConfig' (parseOpts ["--no-nix-pure"]) $ \config ->
            config.nix.enable `shouldBe` False
    describe "nix enabled in config file" $
      around_ (withStackDotYaml sampleConfigNixEnabled) $ do
        it "sees that the nix shell is enabled" $
          loadConfig' mempty $ \config ->
          config.nix.enable `shouldBe` trueOnNonWindows
        describe "--no-nix given on command line" $
          it "sees that the nix shell is not enabled" $
            loadConfig' (parseOpts ["--no-nix"]) $ \config ->
            config.nix.enable `shouldBe` False
        describe "--nix-pure given on command line" $
          it "sees that the nix shell is enabled" $
            loadConfig' (parseOpts ["--nix-pure"]) $ \config ->
            config.nix.enable `shouldBe` trueOnNonWindows
        describe "--no-nix-pure given on command line" $
          it "sees that the nix shell is enabled" $
            loadConfig' (parseOpts ["--no-nix-pure"]) $ \config ->
            config.nix.enable `shouldBe` trueOnNonWindows
        it "sees that the only package asked for is glpk and asks for the correct GHC derivation" $ loadConfig' mempty $ \config -> do
          config.nix.packages `shouldBe` ["glpk"]
          v <- parseVersionThrowing "9.0.2"
          ghc <- either throwIO pure $ nixCompiler (WCGhc v)
          ghc `shouldBe` "haskell.compiler.ghc902"
  