{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Stack2nix
( Args(..)
, stack2nix
, version
) where
import Control.Monad (unless, void, when)
import Data.Maybe (isJust)
import Data.Monoid ((<>))
import Paths_stack2nix (version)
import Stack2nix.External.Stack
import Stack2nix.External.Util (runCmdFrom, failHard)
import Stack2nix.External.VCS.Git (Command (..), ExternalCmd (..),
InternalCmd (..), git)
import Stack2nix.Types (Args (..))
import Stack2nix.Util
import System.Directory (doesFileExist,
getCurrentDirectory, withCurrentDirectory)
import System.Environment (getEnv, setEnv)
import System.FilePath ((</>))
import System.IO.Temp (withSystemTempDirectory)
stack2nix :: Args -> IO ()
stack2nix args@Args{..} = do
when argEnsureExecutables $ do
ensureExecutableExists "cabal" "cabal-install"
ensureExecutableExists "git" "git"
ensureExecutableExists "nix-prefetch-git" "nix-prefetch-scripts"
assertMinVer "git" "2"
assertMinVer "cabal" "2"
setEnv "GIT_QUIET" "y"
updateCabalPackageIndex
let projRoot = argUri
isLocalRepo <- doesFileExist $ projRoot </> argStackYaml
logDebug args $ "stack2nix (isLocalRepo): " ++ show isLocalRepo
logDebug args $ "stack2nix (projRoot): " ++ show projRoot
logDebug args $ "stack2nix (argUri): " ++ show argUri
if isLocalRepo
then handleStackConfig Nothing projRoot
else withSystemTempDirectory "s2n-" $ \tmpDir ->
tryGit tmpDir >> handleStackConfig (Just argUri) tmpDir
where
updateCabalPackageIndex :: IO ()
updateCabalPackageIndex = do
home <- getEnv "HOME"
out <- runCmdFrom home "cabal" ["update"]
void $ failHard out
tryGit :: FilePath -> IO ()
tryGit tmpDir = do
void $ git $ OutsideRepo $ Clone argUri tmpDir
case argRev of
Just r -> void $ git $ InsideRepo tmpDir (Checkout r)
Nothing -> return mempty
handleStackConfig :: Maybe String -> FilePath -> IO ()
handleStackConfig remoteUri localDir = do
cwd <- getCurrentDirectory
logDebug args $ "handleStackConfig (cwd): " ++ cwd
logDebug args $ "handleStackConfig (localDir): " ++ localDir
logDebug args $ "handleStackConfig (remoteUri): " ++ show remoteUri
let stackFile = localDir </> argStackYaml
alreadyExists <- doesFileExist stackFile
unless alreadyExists $ error $ stackFile <> " does not exist. Use 'stack init' to create it."
logDebug args $ "handleStackConfig (alreadyExists): " ++ show alreadyExists
let go = if isJust remoteUri
then withCurrentDirectory localDir
else id
go $ runPlan localDir remoteUri args