{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
module Distribution.Simple.Program.Db (
ProgramDb,
emptyProgramDb,
defaultProgramDb,
restoreProgramDb,
addKnownProgram,
addKnownPrograms,
lookupKnownProgram,
knownPrograms,
getProgramSearchPath,
setProgramSearchPath,
modifyProgramSearchPath,
userSpecifyPath,
userSpecifyPaths,
userMaybeSpecifyPath,
userSpecifyArgs,
userSpecifyArgss,
userSpecifiedArgs,
lookupProgram,
updateProgram,
configuredPrograms,
configureProgram,
configureAllKnownPrograms,
unconfigureProgram,
lookupProgramVersion,
reconfigurePrograms,
requireProgram,
requireProgramVersion,
needProgram,
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Pretty
import Distribution.Simple.Program.Builtin
import Distribution.Simple.Program.Find
import Distribution.Simple.Program.Types
import Distribution.Simple.Utils
import Distribution.Utils.Structured (Structure (..), Structured (..))
import Distribution.Verbosity
import Distribution.Version
import Data.Tuple (swap)
import qualified Data.Map as Map
data ProgramDb = ProgramDb {
ProgramDb -> UnconfiguredProgs
unconfiguredProgs :: UnconfiguredProgs,
ProgramDb -> ProgramSearchPath
progSearchPath :: ProgramSearchPath,
ProgramDb -> ConfiguredProgs
configuredProgs :: ConfiguredProgs
}
deriving (Typeable)
type UnconfiguredProgram = (Program, Maybe FilePath, [ProgArg])
type UnconfiguredProgs = Map.Map String UnconfiguredProgram
type ConfiguredProgs = Map.Map String ConfiguredProgram
emptyProgramDb :: ProgramDb
emptyProgramDb :: ProgramDb
emptyProgramDb = UnconfiguredProgs
-> ProgramSearchPath -> ConfiguredProgs -> ProgramDb
ProgramDb forall k a. Map k a
Map.empty ProgramSearchPath
defaultProgramSearchPath forall k a. Map k a
Map.empty
defaultProgramDb :: ProgramDb
defaultProgramDb :: ProgramDb
defaultProgramDb = [Program] -> ProgramDb -> ProgramDb
restoreProgramDb [Program]
builtinPrograms ProgramDb
emptyProgramDb
updateUnconfiguredProgs :: (UnconfiguredProgs -> UnconfiguredProgs)
-> ProgramDb -> ProgramDb
updateUnconfiguredProgs :: (UnconfiguredProgs -> UnconfiguredProgs) -> ProgramDb -> ProgramDb
updateUnconfiguredProgs UnconfiguredProgs -> UnconfiguredProgs
update ProgramDb
progdb =
ProgramDb
progdb { unconfiguredProgs :: UnconfiguredProgs
unconfiguredProgs = UnconfiguredProgs -> UnconfiguredProgs
update (ProgramDb -> UnconfiguredProgs
unconfiguredProgs ProgramDb
progdb) }
updateConfiguredProgs :: (ConfiguredProgs -> ConfiguredProgs)
-> ProgramDb -> ProgramDb
updateConfiguredProgs :: (ConfiguredProgs -> ConfiguredProgs) -> ProgramDb -> ProgramDb
updateConfiguredProgs ConfiguredProgs -> ConfiguredProgs
update ProgramDb
progdb =
ProgramDb
progdb { configuredProgs :: ConfiguredProgs
configuredProgs = ConfiguredProgs -> ConfiguredProgs
update (ProgramDb -> ConfiguredProgs
configuredProgs ProgramDb
progdb) }
instance Show ProgramDb where
show :: ProgramDb -> String
show = forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [(k, a)]
Map.toAscList forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramDb -> ConfiguredProgs
configuredProgs
instance Read ProgramDb where
readsPrec :: Int -> ReadS ProgramDb
readsPrec Int
p String
s =
[ (ProgramDb
emptyProgramDb { configuredProgs :: ConfiguredProgs
configuredProgs = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(String, ConfiguredProgram)]
s' }, String
r)
| ([(String, ConfiguredProgram)]
s', String
r) <- forall a. Read a => Int -> ReadS a
readsPrec Int
p String
s ]
instance Binary ProgramDb where
put :: ProgramDb -> Put
put ProgramDb
db = do
forall t. Binary t => t -> Put
put (ProgramDb -> ProgramSearchPath
progSearchPath ProgramDb
db)
forall t. Binary t => t -> Put
put (ProgramDb -> ConfiguredProgs
configuredProgs ProgramDb
db)
get :: Get ProgramDb
get = do
ProgramSearchPath
searchpath <- forall t. Binary t => Get t
get
ConfiguredProgs
progs <- forall t. Binary t => Get t
get
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! ProgramDb
emptyProgramDb {
progSearchPath :: ProgramSearchPath
progSearchPath = ProgramSearchPath
searchpath,
configuredProgs :: ConfiguredProgs
configuredProgs = ConfiguredProgs
progs
}
instance Structured ProgramDb where
structure :: Proxy ProgramDb -> Structure
structure Proxy ProgramDb
p = TypeRep -> TypeVersion -> String -> [Structure] -> Structure
Nominal (forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep Proxy ProgramDb
p) TypeVersion
0 String
"ProgramDb"
[ forall a. Structured a => Proxy a -> Structure
structure (forall {k} (t :: k). Proxy t
Proxy :: Proxy ProgramSearchPath)
, forall a. Structured a => Proxy a -> Structure
structure (forall {k} (t :: k). Proxy t
Proxy :: Proxy ConfiguredProgs)
]
restoreProgramDb :: [Program] -> ProgramDb -> ProgramDb
restoreProgramDb :: [Program] -> ProgramDb -> ProgramDb
restoreProgramDb = [Program] -> ProgramDb -> ProgramDb
addKnownPrograms
addKnownProgram :: Program -> ProgramDb -> ProgramDb
addKnownProgram :: Program -> ProgramDb -> ProgramDb
addKnownProgram Program
prog = (UnconfiguredProgs -> UnconfiguredProgs) -> ProgramDb -> ProgramDb
updateUnconfiguredProgs forall a b. (a -> b) -> a -> b
$
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith forall {p} {a} {b} {c}. p -> (a, b, c) -> (Program, b, c)
combine (Program -> String
programName Program
prog) (Program
prog, forall a. Maybe a
Nothing, [])
where combine :: p -> (a, b, c) -> (Program, b, c)
combine p
_ (a
_, b
path, c
args) = (Program
prog, b
path, c
args)
addKnownPrograms :: [Program] -> ProgramDb -> ProgramDb
addKnownPrograms :: [Program] -> ProgramDb -> ProgramDb
addKnownPrograms [Program]
progs ProgramDb
progdb = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (forall a b c. (a -> b -> c) -> b -> a -> c
flip Program -> ProgramDb -> ProgramDb
addKnownProgram) ProgramDb
progdb [Program]
progs
lookupKnownProgram :: String -> ProgramDb -> Maybe Program
lookupKnownProgram :: String -> ProgramDb -> Maybe Program
lookupKnownProgram String
name =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Program
p,Maybe String
_,[String]
_)->Program
p) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramDb -> UnconfiguredProgs
unconfiguredProgs
knownPrograms :: ProgramDb -> [(Program, Maybe ConfiguredProgram)]
knownPrograms :: ProgramDb -> [(Program, Maybe ConfiguredProgram)]
knownPrograms ProgramDb
progdb =
[ (Program
p,Maybe ConfiguredProgram
p') | (Program
p,Maybe String
_,[String]
_) <- forall k a. Map k a -> [a]
Map.elems (ProgramDb -> UnconfiguredProgs
unconfiguredProgs ProgramDb
progdb)
, let p' :: Maybe ConfiguredProgram
p' = forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Program -> String
programName Program
p) (ProgramDb -> ConfiguredProgs
configuredProgs ProgramDb
progdb) ]
getProgramSearchPath :: ProgramDb -> ProgramSearchPath
getProgramSearchPath :: ProgramDb -> ProgramSearchPath
getProgramSearchPath = ProgramDb -> ProgramSearchPath
progSearchPath
setProgramSearchPath :: ProgramSearchPath -> ProgramDb -> ProgramDb
setProgramSearchPath :: ProgramSearchPath -> ProgramDb -> ProgramDb
setProgramSearchPath ProgramSearchPath
searchpath ProgramDb
db = ProgramDb
db { progSearchPath :: ProgramSearchPath
progSearchPath = ProgramSearchPath
searchpath }
modifyProgramSearchPath :: (ProgramSearchPath -> ProgramSearchPath)
-> ProgramDb
-> ProgramDb
modifyProgramSearchPath :: (ProgramSearchPath -> ProgramSearchPath) -> ProgramDb -> ProgramDb
modifyProgramSearchPath ProgramSearchPath -> ProgramSearchPath
f ProgramDb
db =
ProgramSearchPath -> ProgramDb -> ProgramDb
setProgramSearchPath (ProgramSearchPath -> ProgramSearchPath
f forall a b. (a -> b) -> a -> b
$ ProgramDb -> ProgramSearchPath
getProgramSearchPath ProgramDb
db) ProgramDb
db
userSpecifyPath :: String
-> FilePath
-> ProgramDb -> ProgramDb
userSpecifyPath :: String -> String -> ProgramDb -> ProgramDb
userSpecifyPath String
name String
path = (UnconfiguredProgs -> UnconfiguredProgs) -> ProgramDb -> ProgramDb
updateUnconfiguredProgs forall a b. (a -> b) -> a -> b
$
forall a b c. (a -> b -> c) -> b -> a -> c
flip forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Map.update String
name forall a b. (a -> b) -> a -> b
$ \(Program
prog, Maybe String
_, [String]
args) -> forall a. a -> Maybe a
Just (Program
prog, forall a. a -> Maybe a
Just String
path, [String]
args)
userMaybeSpecifyPath :: String -> Maybe FilePath
-> ProgramDb -> ProgramDb
userMaybeSpecifyPath :: String -> Maybe String -> ProgramDb -> ProgramDb
userMaybeSpecifyPath String
_ Maybe String
Nothing ProgramDb
progdb = ProgramDb
progdb
userMaybeSpecifyPath String
name (Just String
path) ProgramDb
progdb = String -> String -> ProgramDb -> ProgramDb
userSpecifyPath String
name String
path ProgramDb
progdb
userSpecifyArgs :: String
-> [ProgArg]
-> ProgramDb
-> ProgramDb
userSpecifyArgs :: String -> [String] -> ProgramDb -> ProgramDb
userSpecifyArgs String
name [String]
args' =
(UnconfiguredProgs -> UnconfiguredProgs) -> ProgramDb -> ProgramDb
updateUnconfiguredProgs
(forall a b c. (a -> b -> c) -> b -> a -> c
flip forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Map.update String
name forall a b. (a -> b) -> a -> b
$
\(Program
prog, Maybe String
path, [String]
args) -> forall a. a -> Maybe a
Just (Program
prog, Maybe String
path, [String]
args forall a. [a] -> [a] -> [a]
++ [String]
args'))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ConfiguredProgs -> ConfiguredProgs) -> ProgramDb -> ProgramDb
updateConfiguredProgs
(forall a b c. (a -> b -> c) -> b -> a -> c
flip forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Map.update String
name forall a b. (a -> b) -> a -> b
$
\ConfiguredProgram
prog -> forall a. a -> Maybe a
Just ConfiguredProgram
prog { programOverrideArgs :: [String]
programOverrideArgs = ConfiguredProgram -> [String]
programOverrideArgs ConfiguredProgram
prog
forall a. [a] -> [a] -> [a]
++ [String]
args' })
userSpecifyPaths :: [(String, FilePath)]
-> ProgramDb
-> ProgramDb
userSpecifyPaths :: [(String, String)] -> ProgramDb -> ProgramDb
userSpecifyPaths [(String, String)]
paths ProgramDb
progdb =
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\ProgramDb
progdb' (String
prog, String
path) -> String -> String -> ProgramDb -> ProgramDb
userSpecifyPath String
prog String
path ProgramDb
progdb') ProgramDb
progdb [(String, String)]
paths
userSpecifyArgss :: [(String, [ProgArg])]
-> ProgramDb
-> ProgramDb
userSpecifyArgss :: [(String, [String])] -> ProgramDb -> ProgramDb
userSpecifyArgss [(String, [String])]
argss ProgramDb
progdb =
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\ProgramDb
progdb' (String
prog, [String]
args) -> String -> [String] -> ProgramDb -> ProgramDb
userSpecifyArgs String
prog [String]
args ProgramDb
progdb') ProgramDb
progdb [(String, [String])]
argss
userSpecifiedPath :: Program -> ProgramDb -> Maybe FilePath
userSpecifiedPath :: Program -> ProgramDb -> Maybe String
userSpecifiedPath Program
prog =
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Program
_,Maybe String
p,[String]
_)->Maybe String
p) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Program -> String
programName Program
prog) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramDb -> UnconfiguredProgs
unconfiguredProgs
userSpecifiedArgs :: Program -> ProgramDb -> [ProgArg]
userSpecifiedArgs :: Program -> ProgramDb -> [String]
userSpecifiedArgs Program
prog =
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(Program
_,Maybe String
_,[String]
as)->[String]
as) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Program -> String
programName Program
prog) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramDb -> UnconfiguredProgs
unconfiguredProgs
lookupProgram :: Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram :: Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram Program
prog = forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Program -> String
programName Program
prog) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramDb -> ConfiguredProgs
configuredProgs
updateProgram :: ConfiguredProgram -> ProgramDb
-> ProgramDb
updateProgram :: ConfiguredProgram -> ProgramDb -> ProgramDb
updateProgram ConfiguredProgram
prog = (ConfiguredProgs -> ConfiguredProgs) -> ProgramDb -> ProgramDb
updateConfiguredProgs forall a b. (a -> b) -> a -> b
$
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (ConfiguredProgram -> String
programId ConfiguredProgram
prog) ConfiguredProgram
prog
configuredPrograms :: ProgramDb -> [ConfiguredProgram]
configuredPrograms :: ProgramDb -> [ConfiguredProgram]
configuredPrograms = forall k a. Map k a -> [a]
Map.elems forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramDb -> ConfiguredProgs
configuredProgs
configureProgram :: Verbosity
-> Program
-> ProgramDb
-> IO ProgramDb
configureProgram :: Verbosity -> Program -> ProgramDb -> IO ProgramDb
configureProgram Verbosity
verbosity Program
prog ProgramDb
progdb = do
let name :: String
name = Program -> String
programName Program
prog
Maybe (ProgramLocation, [String])
maybeLocation <- case Program -> ProgramDb -> Maybe String
userSpecifiedPath Program
prog ProgramDb
progdb of
Maybe String
Nothing ->
Program
-> Verbosity -> ProgramSearchPath -> IO (Maybe (String, [String]))
programFindLocation Program
prog Verbosity
verbosity (ProgramDb -> ProgramSearchPath
progSearchPath ProgramDb
progdb)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a, b) -> (b, a)
swap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> ProgramLocation
FoundOnSystem forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> (b, a)
swap)
Just String
path -> do
Bool
absolute <- String -> IO Bool
doesExecutableExist String
path
if Bool
absolute
then forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just (String -> ProgramLocation
UserSpecified String
path, []))
else Verbosity
-> ProgramSearchPath -> String -> IO (Maybe (String, [String]))
findProgramOnSearchPath Verbosity
verbosity (ProgramDb -> ProgramSearchPath
progSearchPath ProgramDb
progdb) String
path
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a. Verbosity -> String -> IO a
die' Verbosity
verbosity String
notFound)
(forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> (b, a)
swap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> ProgramLocation
UserSpecified forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> (b, a)
swap)
where notFound :: String
notFound = String
"Cannot find the program '" forall a. [a] -> [a] -> [a]
++ String
name
forall a. [a] -> [a] -> [a]
++ String
"'. User-specified path '"
forall a. [a] -> [a] -> [a]
++ String
path forall a. [a] -> [a] -> [a]
++ String
"' does not refer to an executable and "
forall a. [a] -> [a] -> [a]
++ String
"the program is not on the system path."
case Maybe (ProgramLocation, [String])
maybeLocation of
Maybe (ProgramLocation, [String])
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return ProgramDb
progdb
Just (ProgramLocation
location, [String]
triedLocations) -> do
Maybe Version
version <- Program -> Verbosity -> String -> IO (Maybe Version)
programFindVersion Program
prog Verbosity
verbosity (ProgramLocation -> String
locationPath ProgramLocation
location)
String
newPath <- ProgramSearchPath -> IO String
programSearchPathAsPATHVar (ProgramDb -> ProgramSearchPath
progSearchPath ProgramDb
progdb)
let configuredProg :: ConfiguredProgram
configuredProg = ConfiguredProgram {
programId :: String
programId = String
name,
programVersion :: Maybe Version
programVersion = Maybe Version
version,
programDefaultArgs :: [String]
programDefaultArgs = [],
programOverrideArgs :: [String]
programOverrideArgs = Program -> ProgramDb -> [String]
userSpecifiedArgs Program
prog ProgramDb
progdb,
programOverrideEnv :: [(String, Maybe String)]
programOverrideEnv = [(String
"PATH", forall a. a -> Maybe a
Just String
newPath)],
programProperties :: Map String String
programProperties = forall k a. Map k a
Map.empty,
programLocation :: ProgramLocation
programLocation = ProgramLocation
location,
programMonitorFiles :: [String]
programMonitorFiles = [String]
triedLocations
}
ConfiguredProgram
configuredProg' <- Program -> Verbosity -> ConfiguredProgram -> IO ConfiguredProgram
programPostConf Program
prog Verbosity
verbosity ConfiguredProgram
configuredProg
forall (m :: * -> *) a. Monad m => a -> m a
return ((ConfiguredProgs -> ConfiguredProgs) -> ProgramDb -> ProgramDb
updateConfiguredProgs (forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert String
name ConfiguredProgram
configuredProg') ProgramDb
progdb)
configurePrograms :: Verbosity
-> [Program]
-> ProgramDb
-> IO ProgramDb
configurePrograms :: Verbosity -> [Program] -> ProgramDb -> IO ProgramDb
configurePrograms Verbosity
verbosity [Program]
progs ProgramDb
progdb =
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (forall a b c. (a -> b -> c) -> b -> a -> c
flip (Verbosity -> Program -> ProgramDb -> IO ProgramDb
configureProgram Verbosity
verbosity)) ProgramDb
progdb [Program]
progs
unconfigureProgram :: String -> ProgramDb -> ProgramDb
unconfigureProgram :: String -> ProgramDb -> ProgramDb
unconfigureProgram String
progname =
(ConfiguredProgs -> ConfiguredProgs) -> ProgramDb -> ProgramDb
updateConfiguredProgs forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Map k a
Map.delete String
progname
configureAllKnownPrograms :: Verbosity
-> ProgramDb
-> IO ProgramDb
configureAllKnownPrograms :: Verbosity -> ProgramDb -> IO ProgramDb
configureAllKnownPrograms Verbosity
verbosity ProgramDb
progdb =
Verbosity -> [Program] -> ProgramDb -> IO ProgramDb
configurePrograms Verbosity
verbosity
[ Program
prog | (Program
prog,Maybe String
_,[String]
_) <- forall k a. Map k a -> [a]
Map.elems UnconfiguredProgs
notYetConfigured ] ProgramDb
progdb
where
notYetConfigured :: UnconfiguredProgs
notYetConfigured = ProgramDb -> UnconfiguredProgs
unconfiguredProgs ProgramDb
progdb
forall k a b. Ord k => Map k a -> Map k b -> Map k a
`Map.difference` ProgramDb -> ConfiguredProgs
configuredProgs ProgramDb
progdb
reconfigurePrograms :: Verbosity
-> [(String, FilePath)]
-> [(String, [ProgArg])]
-> ProgramDb
-> IO ProgramDb
reconfigurePrograms :: Verbosity
-> [(String, String)]
-> [(String, [String])]
-> ProgramDb
-> IO ProgramDb
reconfigurePrograms Verbosity
verbosity [(String, String)]
paths [(String, [String])]
argss ProgramDb
progdb = do
Verbosity -> [Program] -> ProgramDb -> IO ProgramDb
configurePrograms Verbosity
verbosity [Program]
progs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, String)] -> ProgramDb -> ProgramDb
userSpecifyPaths [(String, String)]
paths
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, [String])] -> ProgramDb -> ProgramDb
userSpecifyArgss [(String, [String])]
argss
forall a b. (a -> b) -> a -> b
$ ProgramDb
progdb
where
progs :: [Program]
progs = forall a. [Maybe a] -> [a]
catMaybes [ String -> ProgramDb -> Maybe Program
lookupKnownProgram String
name ProgramDb
progdb | (String
name,String
_) <- [(String, String)]
paths ]
requireProgram :: Verbosity -> Program -> ProgramDb
-> IO (ConfiguredProgram, ProgramDb)
requireProgram :: Verbosity
-> Program -> ProgramDb -> IO (ConfiguredProgram, ProgramDb)
requireProgram Verbosity
verbosity Program
prog ProgramDb
progdb = do
Maybe (ConfiguredProgram, ProgramDb)
mres <- Verbosity
-> Program
-> ProgramDb
-> IO (Maybe (ConfiguredProgram, ProgramDb))
needProgram Verbosity
verbosity Program
prog ProgramDb
progdb
case Maybe (ConfiguredProgram, ProgramDb)
mres of
Maybe (ConfiguredProgram, ProgramDb)
Nothing -> forall a. Verbosity -> String -> IO a
die' Verbosity
verbosity String
notFound
Just (ConfiguredProgram, ProgramDb)
res -> forall (m :: * -> *) a. Monad m => a -> m a
return (ConfiguredProgram, ProgramDb)
res
where
notFound :: String
notFound = String
"The program '" forall a. [a] -> [a] -> [a]
++ Program -> String
programName Program
prog forall a. [a] -> [a] -> [a]
++ String
"' is required but it could not be found."
needProgram :: Verbosity -> Program -> ProgramDb
-> IO (Maybe (ConfiguredProgram, ProgramDb))
needProgram :: Verbosity
-> Program
-> ProgramDb
-> IO (Maybe (ConfiguredProgram, ProgramDb))
needProgram Verbosity
verbosity Program
prog ProgramDb
progdb = do
ProgramDb
progdb' <- case Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram Program
prog ProgramDb
progdb of
Maybe ConfiguredProgram
Nothing -> Verbosity -> Program -> ProgramDb -> IO ProgramDb
configureProgram Verbosity
verbosity Program
prog ProgramDb
progdb
Just ConfiguredProgram
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ProgramDb
progdb
case Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram Program
prog ProgramDb
progdb' of
Maybe ConfiguredProgram
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
Just ConfiguredProgram
configuredProg -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just (ConfiguredProgram
configuredProg, ProgramDb
progdb'))
lookupProgramVersion
:: Verbosity -> Program -> VersionRange -> ProgramDb
-> IO (Either String (ConfiguredProgram, Version, ProgramDb))
lookupProgramVersion :: Verbosity
-> Program
-> VersionRange
-> ProgramDb
-> IO (Either String (ConfiguredProgram, Version, ProgramDb))
lookupProgramVersion Verbosity
verbosity Program
prog VersionRange
range ProgramDb
programDb = do
ProgramDb
programDb' <- case Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram Program
prog ProgramDb
programDb of
Maybe ConfiguredProgram
Nothing -> Verbosity -> Program -> ProgramDb -> IO ProgramDb
configureProgram Verbosity
verbosity Program
prog ProgramDb
programDb
Just ConfiguredProgram
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ProgramDb
programDb
case Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram Program
prog ProgramDb
programDb' of
Maybe ConfiguredProgram
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. a -> Either a b
Left String
notFound
Just configuredProg :: ConfiguredProgram
configuredProg@ConfiguredProgram { programLocation :: ConfiguredProgram -> ProgramLocation
programLocation = ProgramLocation
location } ->
case ConfiguredProgram -> Maybe Version
programVersion ConfiguredProgram
configuredProg of
Just Version
version
| Version -> VersionRange -> Bool
withinRange Version
version VersionRange
range ->
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. b -> Either a b
Right (ConfiguredProgram
configuredProg, Version
version ,ProgramDb
programDb')
| Bool
otherwise ->
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. a -> Either a b
Left (forall {a}. Pretty a => a -> ProgramLocation -> String
badVersion Version
version ProgramLocation
location)
Maybe Version
Nothing ->
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. a -> Either a b
Left (ProgramLocation -> String
unknownVersion ProgramLocation
location)
where notFound :: String
notFound = String
"The program '"
forall a. [a] -> [a] -> [a]
++ Program -> String
programName Program
prog forall a. [a] -> [a] -> [a]
++ String
"'" forall a. [a] -> [a] -> [a]
++ String
versionRequirement
forall a. [a] -> [a] -> [a]
++ String
" is required but it could not be found."
badVersion :: a -> ProgramLocation -> String
badVersion a
v ProgramLocation
l = String
"The program '"
forall a. [a] -> [a] -> [a]
++ Program -> String
programName Program
prog forall a. [a] -> [a] -> [a]
++ String
"'" forall a. [a] -> [a] -> [a]
++ String
versionRequirement
forall a. [a] -> [a] -> [a]
++ String
" is required but the version found at "
forall a. [a] -> [a] -> [a]
++ ProgramLocation -> String
locationPath ProgramLocation
l forall a. [a] -> [a] -> [a]
++ String
" is version " forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
prettyShow a
v
unknownVersion :: ProgramLocation -> String
unknownVersion ProgramLocation
l = String
"The program '"
forall a. [a] -> [a] -> [a]
++ Program -> String
programName Program
prog forall a. [a] -> [a] -> [a]
++ String
"'" forall a. [a] -> [a] -> [a]
++ String
versionRequirement
forall a. [a] -> [a] -> [a]
++ String
" is required but the version of "
forall a. [a] -> [a] -> [a]
++ ProgramLocation -> String
locationPath ProgramLocation
l forall a. [a] -> [a] -> [a]
++ String
" could not be determined."
versionRequirement :: String
versionRequirement
| VersionRange -> Bool
isAnyVersion VersionRange
range = String
""
| Bool
otherwise = String
" version " forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
prettyShow VersionRange
range
requireProgramVersion :: Verbosity -> Program -> VersionRange
-> ProgramDb
-> IO (ConfiguredProgram, Version, ProgramDb)
requireProgramVersion :: Verbosity
-> Program
-> VersionRange
-> ProgramDb
-> IO (ConfiguredProgram, Version, ProgramDb)
requireProgramVersion Verbosity
verbosity Program
prog VersionRange
range ProgramDb
programDb =
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a. Verbosity -> String -> IO a
die' Verbosity
verbosity) forall (m :: * -> *) a. Monad m => a -> m a
return forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap`
Verbosity
-> Program
-> VersionRange
-> ProgramDb
-> IO (Either String (ConfiguredProgram, Version, ProgramDb))
lookupProgramVersion Verbosity
verbosity Program
prog VersionRange
range ProgramDb
programDb