summaryrefslogtreecommitdiff
path: root/src/Autonix/KF5.hs
blob: c621a375b91dd77fef39e5c8e439c4344543084f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
{-# 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" ]