<commit_before>{-# LANGUAGE CPP, ConstraintKinds, DeriveDataTypeable, FlexibleContexts, MultiWayIf, NamedFieldPuns,
             OverloadedStrings, PackageImports, RankNTypes, RecordWildCards, ScopedTypeVariables,
             TemplateHaskell, TupleSections #-}

-- | Run commands in Docker containers
module Stack.Docker
  (cleanup
  ,CleanupOpts(..)
  ,CleanupAction(..)
  ,dockerCleanupCmdName
  ,dockerCmdName
  ,dockerHelpOptName
  ,dockerPullCmdName
  ,entrypoint
  ,preventInContainer
  ,pull
  ,reexecWithOptionalContainer
  ,reset
  ,reExecArgName
  ,StackDockerException(..)
  ) where

import           Control.Applicative
import           Control.Concurrent.MVar.Lifted (MVar,modifyMVar_,newMVar)
import           Control.Exception.Lifted
import           Control.Monad
import           Control.Monad.Catch (MonadThrow,throwM,MonadCatch)
import           Control.Monad.IO.Class (MonadIO,liftIO)
import           Control.Monad.Logger (MonadLogger,logError,logInfo,logWarn)
import           Control.Monad.Reader (MonadReader,asks,runReaderT)
import           Control.Monad.Writer (execWriter,runWriter,tell)
import qualified "cryptohash" Crypto.Hash as Hash
import           Data.Aeson.Extended (FromJSON(..),(.:),(.:?),(.!=),eitherDecode)
import           Data.ByteString.Builder (stringUtf8,charUtf8,toLazyByteString)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as LBS
import           Data.Char (isSpace,toUpper,isAscii,isDigit)
import           Data.Conduit.List (sinkNull)
import           Data.List (dropWhileEnd,intercalate,isPrefixOf,isInfixOf,foldl')
import           Data.List.Extra (trim)
import           Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import           Data.Maybe
import           Data.Ord (Down(..))
import           Data.Streaming.Process (ProcessExitedUnsuccessfully(..))
import           Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import           Data.Time (UTCTime,LocalTime(..),diffDays,utcToLocalTime,getZonedTime,ZonedTime(..))
import           Data.Version (showVersion)
import           GHC.Exts (sortWith)
import           Path
import           Path.Extra (toFilePathNoTrailingSep)
import           Path.IO hiding (canonicalizePath)
import qualified Paths_stack as Meta
import           Prelude -- Fix redundant import warnings
import           Stack.Config (getInContainer)
import           Stack.Constants
import           Stack.Docker.GlobalDB
import           Stack.Types.PackageIndex
import           Stack.Types.Version
import           Stack.Types.Config
import           Stack.Types.Docker
import           Stack.Types.Internal
import           Stack.Types.StackT
import           Stack.Setup (ensureDockerStackExe)
import           System.Directory (canonicalizePath,getHomeDirectory)
import           System.Environment (getEnv,getEnvironment,getProgName,getArgs,getExecutablePath)
import           System.Exit (exitSuccess, exitWith, ExitCode(..))
import qualified System.FilePath as FP
import           System.IO (stderr,stdin,stdout,hIsTerminalDevice, hClose)
import           System.IO.Error (isDoesNotExistError)
import           System.IO.Unsafe (unsafePerformIO)
import qualified System.PosixCompat.User as User
import qualified System.PosixCompat.Files as Files
import           System.Process (CreateProcess(..), StdStream(..), waitForProcess)
import           System.Process.PagerEditor (editByteString)
import           System.Process.Read
import           System.Process.Run
import           Text.Printf (printf)

#ifdef WINDOWS
import           Control.Monad.Trans.Control (MonadBaseControl)
#else
import           Control.Concurrent (threadDelay)
import           Control.Monad.Trans.Control (MonadBaseControl)
import qualified Control.Monad.Trans.Control as Control
import           System.Posix.Signals
import qualified System.Posix.User as PosixUser
#endif

-- | If Docker is enabled, re-runs the currently running OS command in a Docker container.
-- Otherwise, runs the inner action.
--
-- This takes an optional release action which should be taken IFF control is
-- transfering away from the current process to the intra-container one.  The main use
-- for this is releasing a lock.  After launching reexecution, the host process becomes
-- nothing but an manager for the call into docker and thus may not hold the lock.
reexecWithOptionalContainer
    :: (StackM env m, HasConfig env)
    => Maybe (Path Abs Dir)
    -> Maybe (m ())
    -> IO ()
    -> Maybe (m ())
    -> Maybe (m ())
    -> m ()
reexecWithOptionalContainer mprojectRoot =
    execWithOptionalContainer mprojectRoot getCmdArgs
  where
    getCmdArgs docker envOverride imageInfo isRemoteDocker = do
        config <- asks getConfig
        deUser <-
            if fromMaybe (not isRemoteDocker) (dockerSetUser docker)
                then liftIO $ do<commit_msg>Compiles _and_ no hlint warnings<commit_after>{-# LANGUAGE CPP, ConstraintKinds, DeriveDataTypeable, FlexibleContexts, MultiWayIf, NamedFieldPuns,
             OverloadedStrings, PackageImports, RankNTypes, RecordWildCards, ScopedTypeVariables,
             TemplateHaskell, TupleSections #-}

-- | Run commands in Docker containers
module Stack.Docker
  (cleanup
  ,CleanupOpts(..)
  ,CleanupAction(..)
  ,dockerCleanupCmdName
  ,dockerCmdName
  ,dockerHelpOptName
  ,dockerPullCmdName
  ,entrypoint
  ,preventInContainer
  ,pull
  ,reexecWithOptionalContainer
  ,reset
  ,reExecArgName
  ,StackDockerException(..)
  ) where

import           Control.Applicative
import           Control.Concurrent.MVar.Lifted (MVar,modifyMVar_,newMVar)
import           Control.Exception.Lifted
import           Control.Monad
import           Control.Monad.Catch (MonadThrow,throwM,MonadCatch)
import           Control.Monad.IO.Class (MonadIO,liftIO)
import           Control.Monad.Logger (MonadLogger,logError,logInfo,logWarn)
import           Control.Monad.Reader (MonadReader,asks,runReaderT)
import           Control.Monad.Trans.Control (MonadBaseControl)
import           Control.Monad.Writer (execWriter,runWriter,tell)
import qualified "cryptohash" Crypto.Hash as Hash
import           Data.Aeson.Extended (FromJSON(..),(.:),(.:?),(.!=),eitherDecode)
import           Data.ByteString.Builder (stringUtf8,charUtf8,toLazyByteString)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as LBS
import           Data.Char (isSpace,toUpper,isAscii,isDigit)
import           Data.Conduit.List (sinkNull)
import           Data.List (dropWhileEnd,intercalate,isPrefixOf,isInfixOf,foldl')
import           Data.List.Extra (trim)
import           Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import           Data.Maybe
import           Data.Ord (Down(..))
import           Data.Streaming.Process (ProcessExitedUnsuccessfully(..))
import           Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import           Data.Time (UTCTime,LocalTime(..),diffDays,utcToLocalTime,getZonedTime,ZonedTime(..))
import           Data.Version (showVersion)
import           GHC.Exts (sortWith)
import           Path
import           Path.Extra (toFilePathNoTrailingSep)
import           Path.IO hiding (canonicalizePath)
import qualified Paths_stack as Meta
import           Prelude -- Fix redundant import warnings
import           Stack.Config (getInContainer)
import           Stack.Constants
import           Stack.Docker.GlobalDB
import           Stack.Types.PackageIndex
import           Stack.Types.Version
import           Stack.Types.Config
import           Stack.Types.Docker
import           Stack.Types.Internal
import           Stack.Types.StackT
import           Stack.Setup (ensureDockerStackExe)
import           System.Directory (canonicalizePath,getHomeDirectory)
import           System.Environment (getEnv,getEnvironment,getProgName,getArgs,getExecutablePath)
import           System.Exit (exitSuccess, exitWith, ExitCode(..))
import qualified System.FilePath as FP
import           System.IO (stderr,stdin,stdout,hIsTerminalDevice, hClose)
import           System.IO.Error (isDoesNotExistError)
import           System.IO.Unsafe (unsafePerformIO)
import qualified System.PosixCompat.User as User
import qualified System.PosixCompat.Files as Files
import           System.Process (CreateProcess(..), StdStream(..), waitForProcess)
import           System.Process.PagerEditor (editByteString)
import           System.Process.Read
import           System.Process.Run
import           Text.Printf (printf)

#ifndef WINDOWS
import           Control.Concurrent (threadDelay)
import qualified Control.Monad.Trans.Control as Control
import           System.Posix.Signals
import qualified System.Posix.User as PosixUser
#endif

-- | If Docker is enabled, re-runs the currently running OS command in a Docker container.
-- Otherwise, runs the inner action.
--
-- This takes an optional release action which should be taken IFF control is
-- transfering away from the current process to the intra-container one.  The main use
-- for this is releasing a lock.  After launching reexecution, the host process becomes
-- nothing but an manager for the call into docker and thus may not hold the lock.
reexecWithOptionalContainer
    :: (StackM env m, HasConfig env)
    => Maybe (Path Abs Dir)
    -> Maybe (m ())
    -> IO ()
    -> Maybe (m ())
    -> Maybe (m ())
    -> m ()
reexecWithOptionalContainer mprojectRoot =
    execWithOptionalContainer mprojectRoot getCmdArgs
  where
    getCmdArgs docker envOverride imageInfo isRemoteDocker = do
        config <- asks getConfig
        deUser <-
            if fromMaybe (not isRemoteDocker) (dockerSetUser docker)
                then liftIO $ do
{'fraction_non_alphanumeric': 0.07968941561095219, 'fraction_numerical': 0.0008173273395995096, 'mean_word_length': 3.018472906403941, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '725426', 'n_tokens_mistral': 2779, 'n_tokens_neox': 2708, 'n_words': 735}