{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Autonix.KF5 where
import Control.Lens
import Control.Monad.IO.Class
import Control.Monad.State
import qualified Data.ByteString.Char8 as B
import Data.Conduit
import Data.List (isPrefixOf)
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Data.Monoid
import qualified Data.Set as S
import System.FilePath (takeBaseName, takeExtensions, takeFileName)
import Autonix.Analyze
import Autonix.CMake
import Autonix.Deps
import Autonix.Regex
printFilePaths :: MonadIO m => Analyzer m
printFilePaths _ = awaitForever $ \(path, _) -> liftIO $ putStrLn path
renameKF5Pkgs :: (MonadIO m, MonadState Deps m) => Analyzer m
renameKF5Pkgs pkg = awaitForever $ \(path, contents) ->
when (takeFileName path == "metainfo.yaml") $ do
let regex = makeRegex "cmakename:[[:space:]]*([[:alnum:]]*)"
matches = match regex contents
case matches of
((_ : cmakeName : _) : _) -> rename cmakeName pkg
_ -> return ()
propagateKF5Deps :: (MonadIO m, MonadState Deps m) => Analyzer m
propagateKF5Deps newPkg = awaitForever $ \(path, contents) ->
when (".cmake" `isPrefixOf` takeExtensions path) $ do
let base = takeBaseName $ takeBaseName path
regex = makeRegex
"find_dependency[[:space:]]*\\([[:space:]]*\
\([^[:space:],$\\)]+)"
case splitAt (length base - 6) base of
(oldPkg, "Config") -> do
let new = concatMap (take 1 . drop 1) $ match regex contents
rename (B.pack oldPkg) newPkg
at newPkg %=
Just
. (propagatedBuildInputs %~ S.union (S.fromList new))
. fromMaybe mempty
_ -> return ()
findKF5Components :: (MonadIO m, MonadState Deps m) => Analyzer m
findKF5Components pkg = awaitForever $ \(path, contents) ->
when ("CMakeLists.txt" == takeFileName path) $ do
let new = filter (not . cmakeReserved)
$ filter (not . B.null)
$ concatMap B.words
$ concatMap (take 1 . drop 1)
$ match regex contents
regex = makeRegex
"find_package[[:space:]]*\\([[:space:]]*KF5\
\[[:space:]]*([#\\.${}_[:alnum:][:space:]]+)\\)"
ix pkg . buildInputs %= S.union (S.fromList $ map ("KF5" <>) new)
cmakeReserved :: ByteString -> Bool
cmakeReserved bs = or $ map ($ bs)
[ B.elem '$'
, B.elem '{'
, B.elem '}'
, B.elem '#'
, B.elem '.'
, (==) "COMPONENTS"
, (==) "REQUIRED"
, (==) "CONFIG"
]
kf5Analyzers :: (MonadIO m, MonadState Deps m) => [Analyzer m]
kf5Analyzers = [findKF5Components, renameKF5Pkgs, propagateKF5Deps]
++ cmakeAnalyzers
kf5PostAnalyze :: MonadState Deps m => m ()
kf5PostAnalyze = do
moveNativeInputs
movePropagatedInputs
moveUserEnvPkgs
moveNativeInputs :: MonadState Deps m => m ()
moveNativeInputs = deps %= M.map makeNative
where
makeNative = execState $ forM_ native $ \dep -> do
hasDep <- use (buildInputs.to (S.member dep))
when hasDep $ do
buildInputs %= S.delete dep
nativeBuildInputs %= S.insert dep
hasPropDep <- use (propagatedBuildInputs.to (S.member dep))
when hasPropDep $ do
propagatedBuildInputs %= S.delete dep
propagatedNativeBuildInputs %= S.insert dep
native = [ "BISON"
, "extra-cmake-modules"
, "FLEX"
, "kdoctools"
, "ki18n"
, "LibXslt"
, "Perl"
, "PythonInterp"
]
movePropagatedInputs :: MonadState Deps m => m ()
movePropagatedInputs = deps %= M.map propagate
where
propagate = execState $ forM_ propagated $ \dep -> do
hasDep <- use (buildInputs.to (S.member dep))
when hasDep $ do
buildInputs %= S.delete dep
propagatedBuildInputs %= S.insert dep
hasNativeDep <- use (nativeBuildInputs.to (S.member dep))
when hasNativeDep $ do
nativeBuildInputs %= S.delete dep
propagatedNativeBuildInputs %= S.insert dep
propagated = [ "extra-cmake-modules" ]
moveUserEnvPkgs :: MonadState Deps m => m ()
moveUserEnvPkgs = deps %= M.map propagate
where
propagate = execState $ forM_ userEnv $ \dep -> do
hasDep <- use (buildInputs.to (S.member dep))
hasNativeDep <- use (buildInputs.to (S.member dep))
hasPropDep <- use (buildInputs.to (S.member dep))
hasPropNativeDep <- use (buildInputs.to (S.member dep))
when (hasDep || hasNativeDep || hasPropDep || hasPropNativeDep)
$ propagatedUserEnvPkgs %= S.insert dep
userEnv = [ "SharedMimeInfo" ]