{-# LANGUAGE DataKinds #-}
module Distribution.Client.Reconfigure (Check (..), reconfigure) where
import Distribution.Client.Compat.Prelude
import Data.Monoid (Any (..))
import System.Directory (doesFileExist)
import Distribution.Simple.Configure (localBuildInfoFile)
import Distribution.Simple.Setup (Flag, flagToMaybe, toFlag)
import Distribution.Simple.Utils
( defaultPackageDescCwd
, existsAndIsMoreRecentThan
, info
)
import Distribution.Utils.Path
import Distribution.Client.Config (SavedConfig (..))
import Distribution.Client.Configure (readConfigFlags)
import Distribution.Client.Nix (findNixExpr, inNixShell, nixInstantiate)
import Distribution.Client.Sandbox (findSavedDistPref, updateInstallDirs)
import Distribution.Client.Sandbox.PackageEnvironment
( userPackageEnvironmentFile
)
import Distribution.Client.Setup
( CommonSetupFlags (..)
, ConfigExFlags
, ConfigFlags (..)
, GlobalFlags (..)
)
newtype Check a = Check
{ forall a. Check a -> Any -> a -> IO (Any, a)
runCheck
:: Any
-> a
-> IO (Any, a)
}
instance Semigroup (Check a) where
<> :: Check a -> Check a -> Check a
(<>) Check a
c Check a
d = (Any -> a -> IO (Any, a)) -> Check a
forall a. (Any -> a -> IO (Any, a)) -> Check a
Check ((Any -> a -> IO (Any, a)) -> Check a)
-> (Any -> a -> IO (Any, a)) -> Check a
forall a b. (a -> b) -> a -> b
$ \Any
any0 a
a0 -> do
(Any
any1, a
a1) <- Check a -> Any -> a -> IO (Any, a)
forall a. Check a -> Any -> a -> IO (Any, a)
runCheck Check a
c Any
any0 a
a0
(Any
any2, a
a2) <- Check a -> Any -> a -> IO (Any, a)
forall a. Check a -> Any -> a -> IO (Any, a)
runCheck Check a
d (Any
any0 Any -> Any -> Any
forall a. Semigroup a => a -> a -> a
<> Any
any1) a
a1
(Any, a) -> IO (Any, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Any
any0 Any -> Any -> Any
forall a. Semigroup a => a -> a -> a
<> Any
any1 Any -> Any -> Any
forall a. Semigroup a => a -> a -> a
<> Any
any2, a
a2)
instance Monoid (Check a) where
mempty :: Check a
mempty = (Any -> a -> IO (Any, a)) -> Check a
forall a. (Any -> a -> IO (Any, a)) -> Check a
Check ((Any -> a -> IO (Any, a)) -> Check a)
-> (Any -> a -> IO (Any, a)) -> Check a
forall a b. (a -> b) -> a -> b
$ \Any
_ a
a -> (Any, a) -> IO (Any, a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Any
forall a. Monoid a => a
mempty, a
a)
mappend :: Check a -> Check a -> Check a
mappend = Check a -> Check a -> Check a
forall a. Semigroup a => a -> a -> a
(<>)
reconfigure
:: ((ConfigFlags, ConfigExFlags) -> [String] -> GlobalFlags -> IO ())
-> Verbosity
-> SymbolicPath Pkg (Dir Dist)
-> Flag (Maybe Int)
-> Check (ConfigFlags, ConfigExFlags)
-> [String]
-> GlobalFlags
-> SavedConfig
-> IO SavedConfig
reconfigure :: ((ConfigFlags, ConfigExFlags) -> [String] -> GlobalFlags -> IO ())
-> Verbosity
-> SymbolicPath Pkg ('Dir Dist)
-> Flag (Maybe Int)
-> Check (ConfigFlags, ConfigExFlags)
-> [String]
-> GlobalFlags
-> SavedConfig
-> IO SavedConfig
reconfigure
(ConfigFlags, ConfigExFlags) -> [String] -> GlobalFlags -> IO ()
configureAction
Verbosity
verbosity
SymbolicPath Pkg ('Dir Dist)
dist
Flag (Maybe Int)
_numJobsFlag
Check (ConfigFlags, ConfigExFlags)
check
[String]
extraArgs
GlobalFlags
globalFlags
SavedConfig
config =
do
savedFlags :: (ConfigFlags, ConfigExFlags)
savedFlags@(ConfigFlags
_, ConfigExFlags
_) <- String -> IO (ConfigFlags, ConfigExFlags)
readConfigFlags (String -> IO (ConfigFlags, ConfigExFlags))
-> String -> IO (ConfigFlags, ConfigExFlags)
forall a b. (a -> b) -> a -> b
$ SymbolicPath Pkg ('Dir Dist) -> String
forall (allowAbsolute :: AllowAbsolute) from (to :: FileOrDir).
SymbolicPathX allowAbsolute from to -> String
getSymbolicPath SymbolicPath Pkg ('Dir Dist)
dist
Bool
useNix <- (Maybe String -> Bool) -> IO (Maybe String) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe String -> Bool
forall a. Maybe a -> Bool
isJust (GlobalFlags -> SavedConfig -> IO (Maybe String)
findNixExpr GlobalFlags
globalFlags SavedConfig
config)
Bool
alreadyInNixShell <- IO Bool
inNixShell
if Bool
useNix Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
alreadyInNixShell
then do
Verbosity -> String -> Bool -> GlobalFlags -> SavedConfig -> IO ()
nixInstantiate Verbosity
verbosity (SymbolicPath Pkg ('Dir Dist) -> String
forall (allowAbsolute :: AllowAbsolute) from (to :: FileOrDir).
SymbolicPathX allowAbsolute from to -> String
getSymbolicPath SymbolicPath Pkg ('Dir Dist)
dist) Bool
False GlobalFlags
globalFlags SavedConfig
config
SavedConfig -> IO SavedConfig
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return SavedConfig
config
else do
let checks :: Check (ConfigFlags, ConfigExFlags)
checks :: Check (ConfigFlags, ConfigExFlags)
checks =
Check (ConfigFlags, ConfigExFlags)
forall b. Check (ConfigFlags, b)
checkVerb
Check (ConfigFlags, ConfigExFlags)
-> Check (ConfigFlags, ConfigExFlags)
-> Check (ConfigFlags, ConfigExFlags)
forall a. Semigroup a => a -> a -> a
<> Check (ConfigFlags, ConfigExFlags)
forall b. Check (ConfigFlags, b)
checkDist
Check (ConfigFlags, ConfigExFlags)
-> Check (ConfigFlags, ConfigExFlags)
-> Check (ConfigFlags, ConfigExFlags)
forall a. Semigroup a => a -> a -> a
<> Check (ConfigFlags, ConfigExFlags)
forall b. Check (ConfigFlags, b)
checkOutdated
Check (ConfigFlags, ConfigExFlags)
-> Check (ConfigFlags, ConfigExFlags)
-> Check (ConfigFlags, ConfigExFlags)
forall a. Semigroup a => a -> a -> a
<> Check (ConfigFlags, ConfigExFlags)
check
(Any Bool
frc, flags :: (ConfigFlags, ConfigExFlags)
flags@(ConfigFlags
configFlags, ConfigExFlags
_)) <- Check (ConfigFlags, ConfigExFlags)
-> Any
-> (ConfigFlags, ConfigExFlags)
-> IO (Any, (ConfigFlags, ConfigExFlags))
forall a. Check a -> Any -> a -> IO (Any, a)
runCheck Check (ConfigFlags, ConfigExFlags)
checks Any
forall a. Monoid a => a
mempty (ConfigFlags, ConfigExFlags)
savedFlags
let config' :: SavedConfig
config' :: SavedConfig
config' = Flag Bool -> SavedConfig -> SavedConfig
updateInstallDirs (ConfigFlags -> Flag Bool
configUserInstall ConfigFlags
configFlags) SavedConfig
config
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
frc (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ (ConfigFlags, ConfigExFlags) -> [String] -> GlobalFlags -> IO ()
configureAction (ConfigFlags, ConfigExFlags)
flags [String]
extraArgs GlobalFlags
globalFlags
SavedConfig -> IO SavedConfig
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return SavedConfig
config'
where
mbWorkDir :: Maybe (SymbolicPath CWD ('Dir Pkg))
mbWorkDir = Flag (SymbolicPath CWD ('Dir Pkg))
-> Maybe (SymbolicPath CWD ('Dir Pkg))
forall a. Flag a -> Maybe a
flagToMaybe (Flag (SymbolicPath CWD ('Dir Pkg))
-> Maybe (SymbolicPath CWD ('Dir Pkg)))
-> Flag (SymbolicPath CWD ('Dir Pkg))
-> Maybe (SymbolicPath CWD ('Dir Pkg))
forall a b. (a -> b) -> a -> b
$ ConfigFlags -> Flag (SymbolicPath CWD ('Dir Pkg))
configWorkingDir (ConfigFlags -> Flag (SymbolicPath CWD ('Dir Pkg)))
-> ConfigFlags -> Flag (SymbolicPath CWD ('Dir Pkg))
forall a b. (a -> b) -> a -> b
$ SavedConfig -> ConfigFlags
savedConfigureFlags SavedConfig
config
checkVerb :: Check (ConfigFlags, b)
checkVerb :: forall b. Check (ConfigFlags, b)
checkVerb = (Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b)
forall a. (Any -> a -> IO (Any, a)) -> Check a
Check ((Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b))
-> (Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b)
forall a b. (a -> b) -> a -> b
$ \Any
_ (ConfigFlags
configFlags, b
configExFlags) -> do
let common :: CommonSetupFlags
common = ConfigFlags -> CommonSetupFlags
configCommonFlags ConfigFlags
configFlags
configFlags' :: ConfigFlags
configFlags' :: ConfigFlags
configFlags' =
ConfigFlags
configFlags
{ configCommonFlags =
common{setupVerbosity = toFlag verbosity}
}
(Any, (ConfigFlags, b)) -> IO (Any, (ConfigFlags, b))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Any
forall a. Monoid a => a
mempty, (ConfigFlags
configFlags', b
configExFlags))
checkDist :: Check (ConfigFlags, b)
checkDist :: forall b. Check (ConfigFlags, b)
checkDist = (Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b)
forall a. (Any -> a -> IO (Any, a)) -> Check a
Check ((Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b))
-> (Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b)
forall a b. (a -> b) -> a -> b
$ \Any
_ (ConfigFlags
configFlags, b
configExFlags) -> do
let common :: CommonSetupFlags
common = ConfigFlags -> CommonSetupFlags
configCommonFlags ConfigFlags
configFlags
SymbolicPath Pkg ('Dir Dist)
savedDist <- SavedConfig
-> Flag (SymbolicPath Pkg ('Dir Dist))
-> IO (SymbolicPath Pkg ('Dir Dist))
findSavedDistPref SavedConfig
config (CommonSetupFlags -> Flag (SymbolicPath Pkg ('Dir Dist))
setupDistPref CommonSetupFlags
common)
let distChanged :: Bool
distChanged :: Bool
distChanged = SymbolicPath Pkg ('Dir Dist)
dist SymbolicPath Pkg ('Dir Dist)
-> SymbolicPath Pkg ('Dir Dist) -> Bool
forall a. Eq a => a -> a -> Bool
/= SymbolicPath Pkg ('Dir Dist)
savedDist
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
distChanged (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Verbosity -> String -> IO ()
info Verbosity
verbosity String
"build directory changed"
let configFlags' :: ConfigFlags
configFlags' :: ConfigFlags
configFlags' =
ConfigFlags
configFlags
{ configCommonFlags =
common{setupDistPref = toFlag dist}
}
(Any, (ConfigFlags, b)) -> IO (Any, (ConfigFlags, b))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Any
Any Bool
distChanged, (ConfigFlags
configFlags', b
configExFlags))
checkOutdated :: Check (ConfigFlags, b)
checkOutdated :: forall b. Check (ConfigFlags, b)
checkOutdated = (Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b)
forall a. (Any -> a -> IO (Any, a)) -> Check a
Check ((Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b))
-> (Any -> (ConfigFlags, b) -> IO (Any, (ConfigFlags, b)))
-> Check (ConfigFlags, b)
forall a b. (a -> b) -> a -> b
$ \Any
_ flags :: (ConfigFlags, b)
flags@(ConfigFlags
configFlags, b
_) -> do
let common :: CommonSetupFlags
common = ConfigFlags -> CommonSetupFlags
configCommonFlags ConfigFlags
configFlags
buildConfig, userCabalConfig :: FilePath
buildConfig :: String
buildConfig = Maybe (SymbolicPath CWD ('Dir Pkg))
-> SymbolicPathX 'AllowAbsolute Pkg 'File -> String
forall from (allowAbsolute :: AllowAbsolute) (to :: FileOrDir).
Maybe (SymbolicPath CWD ('Dir from))
-> SymbolicPathX allowAbsolute from to -> String
interpretSymbolicPath Maybe (SymbolicPath CWD ('Dir Pkg))
mbWorkDir (SymbolicPathX 'AllowAbsolute Pkg 'File -> String)
-> SymbolicPathX 'AllowAbsolute Pkg 'File -> String
forall a b. (a -> b) -> a -> b
$ SymbolicPath Pkg ('Dir Dist)
-> SymbolicPathX 'AllowAbsolute Pkg 'File
localBuildInfoFile SymbolicPath Pkg ('Dir Dist)
dist
userCabalConfig :: String
userCabalConfig = String
userPackageEnvironmentFile
Bool
configured <- String -> IO Bool
doesFileExist String
buildConfig
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
configured (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Verbosity -> String -> IO ()
info Verbosity
verbosity String
"package has never been configured"
Bool
userPackageEnvironmentFileModified <-
String -> String -> IO Bool
existsAndIsMoreRecentThan String
userCabalConfig String
buildConfig
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
userPackageEnvironmentFileModified (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Verbosity -> String -> IO ()
info
Verbosity
verbosity
( String
"user package environment file ('"
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
userPackageEnvironmentFile
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"') was modified"
)
SymbolicPathX 'AllowAbsolute Pkg 'File
descrFile <-
IO (SymbolicPathX 'AllowAbsolute Pkg 'File)
-> (SymbolicPathX 'AllowAbsolute Pkg 'File
-> IO (SymbolicPathX 'AllowAbsolute Pkg 'File))
-> Maybe (SymbolicPathX 'AllowAbsolute Pkg 'File)
-> IO (SymbolicPathX 'AllowAbsolute Pkg 'File)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
(RelativePath Pkg 'File -> SymbolicPathX 'AllowAbsolute Pkg 'File
forall from (to :: FileOrDir).
RelativePath from to -> SymbolicPath from to
relativeSymbolicPath (RelativePath Pkg 'File -> SymbolicPathX 'AllowAbsolute Pkg 'File)
-> IO (RelativePath Pkg 'File)
-> IO (SymbolicPathX 'AllowAbsolute Pkg 'File)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Verbosity -> IO (RelativePath Pkg 'File)
defaultPackageDescCwd Verbosity
verbosity)
SymbolicPathX 'AllowAbsolute Pkg 'File
-> IO (SymbolicPathX 'AllowAbsolute Pkg 'File)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
(Flag (SymbolicPathX 'AllowAbsolute Pkg 'File)
-> Maybe (SymbolicPathX 'AllowAbsolute Pkg 'File)
forall a. Flag a -> Maybe a
flagToMaybe (CommonSetupFlags -> Flag (SymbolicPathX 'AllowAbsolute Pkg 'File)
setupCabalFilePath CommonSetupFlags
common))
let descrPath :: String
descrPath = Maybe (SymbolicPath CWD ('Dir Pkg))
-> SymbolicPathX 'AllowAbsolute Pkg 'File -> String
forall from (allowAbsolute :: AllowAbsolute) (to :: FileOrDir).
Maybe (SymbolicPath CWD ('Dir from))
-> SymbolicPathX allowAbsolute from to -> String
interpretSymbolicPath Maybe (SymbolicPath CWD ('Dir Pkg))
mbWorkDir SymbolicPathX 'AllowAbsolute Pkg 'File
descrFile
Bool
outdated <- String -> String -> IO Bool
existsAndIsMoreRecentThan String
descrPath String
buildConfig
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
outdated (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Verbosity -> String -> IO ()
info Verbosity
verbosity (SymbolicPathX 'AllowAbsolute Pkg 'File -> String
forall (allowAbsolute :: AllowAbsolute) from (to :: FileOrDir).
SymbolicPathX allowAbsolute from to -> String
getSymbolicPath SymbolicPathX 'AllowAbsolute Pkg 'File
descrFile String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" was changed")
let failed :: Any
failed :: Any
failed =
Bool -> Any
Any Bool
outdated
Any -> Any -> Any
forall a. Semigroup a => a -> a -> a
<> Bool -> Any
Any Bool
userPackageEnvironmentFileModified
Any -> Any -> Any
forall a. Semigroup a => a -> a -> a
<> Bool -> Any
Any (Bool -> Bool
not Bool
configured)
(Any, (ConfigFlags, b)) -> IO (Any, (ConfigFlags, b))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Any
failed, (ConfigFlags, b)
flags)