    {-# LANGUAGE LambdaCase #-}
    module Cabal (externalCommand) where

    import           Imports

    import           Data.List
    import           Data.Version (makeVersion)
    import           System.IO
    import           System.IO.Temp
    import           System.Environment
    import           System.Directory
    import           System.FilePath
    import           System.Process

    import qualified Info
    import           Cabal.Paths
    import           Cabal.Options

    externalCommand :: [String] -> IO ()
    externalCommand :: [String] -> IO ()
    externalCommand [String]
    args = do
      String -> IO (Maybe String)
    lookupEnv String
    "CABAL" IO (Maybe String) -> (Maybe String -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ case
        Maybe String
    Nothing -> String -> [String] -> IO ()
    run String
    "cabal" [String]
    args
        Just String
    cabal -> String -> [String] -> IO ()
    run String
    cabal (Int -> [String] -> [String]
    forall a. Int -> [a] -> [a]
    drop Int
    1 [String]
    args)

    run :: String -> [String] -> IO ()
    run :: String -> [String] -> IO ()
    run String
    cabal [String]
    args = do
      [String] -> IO ()
    rejectUnsupportedOptions [String]
    args

      Paths{..} <- String -> [String] -> IO Paths
    paths String
    cabal ([String] -> [String]
    discardReplOptions [String]
    args)

      let
        doctest = String
    cache String -> String -> String
    </> String
    "doctest" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    "-" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    Info.version
        script = String
    cache String -> String -> String
    </> String
    "init-ghci-" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    Info.version

      doesFileExist doctest >>= \ case
        Bool
    True -> IO ()
    forall (m :: * -> *). Monad m => m ()
    pass
        Bool
    False -> String -> [String] -> IO ()
    callProcess String
    cabal [
            String
    "install" , String
    "doctest-" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    Info.version
          , String
    "--flag", String
    "-cabal-doctest"
          , String
    "--ignore-project"
          , String
    "--installdir", String
    cache
          , String
    "--program-suffix", String
    "-" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    Info.version
          , String
    "--install-method=copy"
          , String
    "--with-compiler", String
    ghc
          ]

      doesFileExist script >>= \ case
        Bool
    True -> IO ()
    forall (m :: * -> *). Monad m => m ()
    pass
        Bool
    False -> String -> String -> IO ()
    writeFileAtomically String
    script String
    ":seti -w -Wdefault"

      callProcess doctest ["--version"]

      let
        repl [String]
    extraArgs = String -> [String] -> IO ()
    call String
    cabal (String
    "repl"
          String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : String
    "--build-depends=QuickCheck"
          String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : String
    "--build-depends=template-haskell"
          String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : (String
    "--repl-options=-ghci-script=" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    script)
          String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : [String]
    args [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ [String]
    extraArgs)

      case ghcVersion < makeVersion [9,4] of
        Bool
    True -> do
          String -> [String] -> IO ()
    callProcess String
    cabal (String
    "build" String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : String
    "--only-dependencies" String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : [String] -> [String]
    discardReplOptions [String]
    args)
          [String] -> IO ()
    repl [String
    "--with-compiler", String
    doctest, String
    "--with-hc-pkg", String
    ghcPkg]

        Bool
    False -> do
          String -> (String -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    (MonadIO m, MonadMask m) =>
    String -> (String -> m a) -> m a
    withSystemTempDirectory String
    "cabal-doctest" ((String -> IO ()) -> IO ()) -> (String -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \ String
    dir -> do
            [String] -> IO ()
    repl [String
    "--keep-temp-files", String
    "--repl-multi-file", String
    dir]
            files <- (String -> Bool) -> [String] -> [String]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (String -> String -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    isSuffixOf String
    "-inplace") ([String] -> [String]) -> IO [String] -> IO [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO [String]
    listDirectory String
    dir
            options <- concat <$> mapM (fmap lines . readFile . combine dir) files
            call doctest ("--no-magic" : options)

    writeFileAtomically :: FilePath -> String -> IO ()
    writeFileAtomically :: String -> String -> IO ()
    writeFileAtomically String
    name String
    contents = do
      (tmp, h) <- String -> String -> IO (String, Handle)
    openTempFile (String -> String
    takeDirectory String
    name) (String -> String
    takeFileName String
    name)
      hPutStr h contents
      hClose h
      renameFile tmp name