1- {-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, MultiWayIf, NamedFieldPuns,
1+ {-# LANGUAGE CPP, ConstraintKinds, DeriveDataTypeable, FlexibleContexts, MultiWayIf, NamedFieldPuns,
22 OverloadedStrings, RankNTypes, RecordWildCards, TemplateHaskell, TupleSections #-}
33
44-- | Run commands in Docker containers
@@ -22,9 +22,10 @@ module Stack.Docker
2222import Control.Applicative
2323import Control.Exception.Lifted
2424import Control.Monad
25- import Control.Monad.Catch (MonadThrow , throwM , MonadCatch )
25+ import Control.Monad.Catch (MonadThrow ,throwM ,MonadCatch )
2626import Control.Monad.IO.Class (MonadIO ,liftIO )
2727import Control.Monad.Logger (MonadLogger ,logError ,logInfo ,logWarn )
28+ import Control.Monad.Reader (MonadReader ,asks )
2829import Control.Monad.Writer (execWriter ,runWriter ,tell )
2930import Control.Monad.Trans.Control (MonadBaseControl )
3031import Data.Aeson.Extended (FromJSON (.. ),(.:) ,(.:?) ,(.!=) ,eitherDecode )
@@ -49,6 +50,7 @@ import Path
4950import Path.IO (getWorkingDir ,listDirectory )
5051import Stack.Constants (projectDockerSandboxDir ,stackProgName ,stackDotYaml ,stackRootEnvVar )
5152import Stack.Types
53+ import Stack.Types.Internal
5254import Stack.Docker.GlobalDB
5355import System.Directory (createDirectoryIfMissing ,removeDirectoryRecursive ,removeFile )
5456import System.Directory (doesDirectoryExist )
@@ -70,10 +72,12 @@ import System.Posix.Signals (installHandler,sigTERM,Handler(Catch))
7072-- | If Docker is enabled, re-runs the currently running OS command in a Docker container.
7173-- Otherwise, runs the inner action.
7274rerunWithOptionalContainer
73- :: (MonadLogger m , MonadIO m , MonadThrow m , MonadBaseControl IO m , MonadCatch m )
74- => Config -> Maybe (Path Abs Dir ) -> IO () -> m ()
75- rerunWithOptionalContainer config mprojectRoot =
76- rerunCmdWithOptionalContainer config mprojectRoot getCmdArgs
75+ :: M env m
76+ => Maybe (Path Abs Dir )
77+ -> IO ()
78+ -> m ()
79+ rerunWithOptionalContainer mprojectRoot =
80+ rerunCmdWithOptionalContainer mprojectRoot getCmdArgs
7781 where
7882 getCmdArgs =
7983 do args <- getArgs
@@ -82,41 +86,41 @@ rerunWithOptionalContainer config mprojectRoot =
8286 let mountPath = concat [" /opt/host/bin/" ,takeBaseName exePath]
8387 return (mountPath
8488 ,args
85- ,config{configDocker= docker{dockerMount= Mount exePath mountPath :
86- dockerMount docker}})
89+ ,\ c -> c{configDocker= (configDocker c)
90+ {dockerMount= Mount exePath mountPath :
91+ dockerMount (configDocker c)}})
8792 else do progName <- getProgName
88- return (takeBaseName progName,args,config)
89- docker = configDocker config
93+ return (takeBaseName progName,args,id )
9094
9195-- | If Docker is enabled, re-runs the OS command returned by the second argument in a
9296-- Docker container. Otherwise, runs the inner action.
9397rerunCmdWithOptionalContainer
94- :: (MonadLogger m ,MonadIO m ,MonadThrow m ,MonadBaseControl IO m , MonadCatch m )
95- => Config
96- -> Maybe (Path Abs Dir )
97- -> IO (FilePath ,[String ],Config )
98+ :: M env m
99+ => Maybe (Path Abs Dir )
100+ -> IO (FilePath ,[String ],Config -> Config )
98101 -> IO ()
99102 -> m ()
100- rerunCmdWithOptionalContainer config mprojectRoot getCmdArgs inner =
101- do inContainer <- getInContainer
103+ rerunCmdWithOptionalContainer mprojectRoot getCmdArgs inner =
104+ do config <- asks getConfig
105+ inContainer <- getInContainer
102106 if inContainer || not (dockerEnable (configDocker config))
103107 then liftIO inner
104- else do (cmd_,args,config' ) <- liftIO getCmdArgs
105- runContainerAndExit config' mprojectRoot cmd_ args [] (return () )
108+ else do (cmd_,args,modConfig ) <- liftIO getCmdArgs
109+ runContainerAndExit modConfig mprojectRoot cmd_ args [] (return () )
106110
107111-- | If Docker is enabled, re-runs the OS command returned by the second argument in a
108112-- Docker container. Otherwise, runs the inner action.
109113rerunCmdWithRequiredContainer
110- :: (MonadLogger m ,MonadIO m ,MonadThrow m ,MonadBaseControl IO m , MonadCatch m )
111- => Config
112- -> Maybe (Path Abs Dir )
113- -> IO (FilePath ,[String ],Config )
114+ :: M env m
115+ => Maybe (Path Abs Dir )
116+ -> IO (FilePath ,[String ],Config -> Config )
114117 -> m ()
115- rerunCmdWithRequiredContainer config mprojectRoot getCmdArgs =
116- do when (not (dockerEnable (configDocker config)))
118+ rerunCmdWithRequiredContainer mprojectRoot getCmdArgs =
119+ do config <- asks getConfig
120+ when (not (dockerEnable (configDocker config)))
117121 (throwM DockerMustBeEnabledException )
118- (cmd_,args,config' ) <- liftIO getCmdArgs
119- runContainerAndExit config' mprojectRoot cmd_ args [] (return () )
122+ (cmd_,args,modConfig ) <- liftIO getCmdArgs
123+ runContainerAndExit modConfig mprojectRoot cmd_ args [] (return () )
120124
121125-- | Error if running in a container.
122126preventInContainer :: (MonadIO m ,MonadThrow m ) => m () -> m ()
@@ -135,21 +139,23 @@ getInContainer =
135139 Just _ -> return True
136140
137141-- | Run a command in a new Docker container, then exit the process.
138- runContainerAndExit :: ( MonadLogger m , MonadIO m , MonadThrow m , MonadBaseControl IO m , MonadCatch m )
139- => Config
142+ runContainerAndExit :: M env m
143+ => ( Config -> Config )
140144 -> Maybe (Path Abs Dir )
141145 -> FilePath
142146 -> [String ]
143147 -> [(String , String )]
144148 -> IO ()
145149 -> m ()
146- runContainerAndExit config
150+ runContainerAndExit modConfig
147151 mprojectRoot
148152 cmnd
149153 args
150154 envVars
151155 successPostAction =
152- do envOverride <- getEnvOverride (configPlatform config)
156+ do config <- fmap modConfig (asks getConfig)
157+ let docker = configDocker config
158+ envOverride <- getEnvOverride (configPlatform config)
153159 checkDockerVersion envOverride
154160 uidOut <- readProcessStdout Nothing envOverride " id" [" -u" ]
155161 gidOut <- readProcessStdout Nothing envOverride " id" [" -g" ]
@@ -275,13 +281,13 @@ runContainerAndExit config
275281 sandboxSubdirArg subdir = [" -v" ,toFPNoTrailingSep subdir++ " :" ++ toFPNoTrailingSep subdir]
276282 toFPNoTrailingSep = dropTrailingPathSeparator . toFilePath
277283 projectRoot = fromMaybeProjectRoot mprojectRoot
278- docker = configDocker config
279284
280285-- | Clean-up old docker images and containers.
281- cleanup :: (MonadLogger m , MonadIO m , MonadThrow m , MonadBaseControl IO m , MonadCatch m )
282- => Config -> CleanupOpts -> m ()
283- cleanup config opts =
284- do envOverride <- getEnvOverride (configPlatform config)
286+ cleanup :: M env m
287+ => CleanupOpts -> m ()
288+ cleanup opts =
289+ do config <- asks getConfig
290+ envOverride <- getEnvOverride (configPlatform config)
285291 checkDockerVersion envOverride
286292 let runDocker = readDockerProcess envOverride
287293 imagesOut <- runDocker [" images" ," --no-trunc" ," -f" ," dangling=false" ]
@@ -529,13 +535,13 @@ inspects envOverride images =
529535 Left e -> throwM e
530536
531537-- | Pull latest version of configured Docker image from registry.
532- pull :: (MonadLogger m , MonadIO m , MonadThrow m , MonadBaseControl IO m , MonadCatch m )
533- => Config -> m ()
534- pull config =
535- do envOverride <- getEnvOverride (configPlatform config)
538+ pull :: M env m => m ()
539+ pull =
540+ do config <- asks getConfig
541+ let docker = configDocker config
542+ envOverride <- getEnvOverride (configPlatform config)
536543 checkDockerVersion envOverride
537544 pullImage envOverride docker (dockerImage docker)
538- where docker = configDocker config
539545
540546-- | Pull Docker image from registry.
541547pullImage :: (MonadLogger m ,MonadIO m ,MonadThrow m )
@@ -948,3 +954,6 @@ instance Show StackDockerException where
948954 " Cannot find 'docker' in PATH. Is Docker installed?"
949955 show (InvalidDatabasePathException ex) =
950956 concat [" Invalid database path: " ,show ex]
957+
958+ type M env m = (MonadIO m ,MonadReader env m ,MonadLogger m ,MonadBaseControl IO m ,MonadCatch m
959+ ,HasConfig env ,HasTerminal env )
0 commit comments