module Data.GI.CodeGen.PkgConfig
    ( pkgConfigGetVersion
    , tryPkgConfig
    ) where

import Control.Monad (when)
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid (First(..), (<>))
#else
import Data.Monoid (First(..))
#endif
import qualified Data.Map.Strict as M
import qualified Data.Text as T
import Data.Text (Text)
import System.Exit (ExitCode(..))
import System.Process (readProcessWithExitCode)

-- | Try asking pkg-config for the version of a given module, and
-- return the package name together with its version.
tryPkgConfig :: Text -> IO (Maybe (Text, Text))
tryPkgConfig :: Text -> IO (Maybe (Text, Text))
tryPkgConfig Text
pkgName = do
  (ExitCode
exitcode, String
stdout, String
_) <-
      String -> [String] -> String -> IO (ExitCode, String, String)
readProcessWithExitCode String
"pkg-config" [String
"--modversion", Text -> String
T.unpack Text
pkgName] String
""
  case ExitCode
exitcode of
    ExitCode
ExitSuccess -> case String -> [String]
lines String
stdout of
                     [String
v] -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just (Text
pkgName, String -> Text
T.pack String
v))
                     [String]
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
    ExitFailure Int
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing

-- | Get the pkg-config name and associated installed version of a given
-- gobject-introspection namespace. Since the mapping is not
-- one-to-one some guessing is involved, although in most cases the
-- required information is listed in the GIR file.
pkgConfigGetVersion :: Text     -- name
                    -> Text     -- version
                    -> [Text]   -- known package names
                    -> Bool     -- verbose
                    -> M.Map Text Text -- suggested overrides
                    -> IO (Maybe (Text, Text))
pkgConfigGetVersion :: Text
-> Text
-> [Text]
-> Bool
-> Map Text Text
-> IO (Maybe (Text, Text))
pkgConfigGetVersion Text
name Text
version [Text]
packages Bool
verbose Map Text Text
overridenNames = do
  let lowerName :: Text
lowerName = Text -> Text
T.toLower Text
name
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
verbose forall a b. (a -> b) -> a -> b
$
           String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack (Text
"Querying pkg-config for " forall a. Semigroup a => a -> a -> a
<> Text
name forall a. Semigroup a => a -> a -> a
<>
                              Text
" version " forall a. Semigroup a => a -> a -> a
<> Text
version)
  let alternatives :: [Text]
alternatives = case forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Text
lowerName Map Text Text
overridenNames of
                       Maybe Text
Nothing -> [Text]
packages forall a. [a] -> [a] -> [a]
++ [Text
lowerName forall a. Semigroup a => a -> a -> a
<> Text
"-" forall a. Semigroup a => a -> a -> a
<> Text
version,
                                               Text
lowerName]
                       Just Text
n -> [Text
n forall a. Semigroup a => a -> a -> a
<> Text
"-" forall a. Semigroup a => a -> a -> a
<> Text
version, Text
n]
      firstJust :: [Maybe a] -> Maybe a
firstJust = forall a. First a -> Maybe a
getFirst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. Maybe a -> First a
First
  forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Text -> IO (Maybe (Text, Text))
tryPkgConfig [Text]
alternatives 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 {a}. [Maybe a] -> Maybe a
firstJust