kit-0.2: Kit/Project.hs
module Kit.Project (
getDeps,
getMyDeps,
installKit,
generateXCodeConfig,
generateXCodeProject,
myKitSpec)
where
import Control.Monad.Trans
import Control.Monad
import Control.Applicative
import Data.Foldable
import Data.Maybe
import Data.List
import Data.Monoid
import System.Cmd
import Kit.Kit
import Kit.Repository
import Kit.Util
import Kit.Spec
import Kit.XCode.Builder
import Kit.XCode.XCConfig
import Kit.XCode.Prefix
import Text.JSON
import Kit.JSON
import qualified Data.Traversable as T
kitDir = "." </> "Kits"
projectDir = "KitDeps.xcodeproj"
prefixFile = "KitDeps_Prefix.pch"
projectFile = projectDir </> "project.pbxproj"
prefixDefault = "#ifdef __OBJC__\n" ++ " #import <Foundation/Foundation.h>\n #import <UIKit/UIKit.h>\n" ++ "#endif\n"
generateXCodeProject :: [FilePath] -> IO ()
generateXCodeProject kitFileNames = do
mkdir_p kitDir
inDirectory kitDir $ do
let find tpe inDir = glob (inDir ++ "/src/**/*" ++ tpe)
let find' tpe = fmap join . T.for kitFileNames $ find tpe
headers <- find' ".h"
sources <- (\a b c -> a ++ b ++ c) <$> glob "**/src/**/*.m" <*> glob "**/src/**/*.mm" <*> glob "**/src/**/*.c"
mkdir_p projectDir
writeFile projectFile $ buildXCodeProject headers sources
combinedHeader <- generatePrefixHeader kitFileNames
writeFile prefixFile $ prefixDefault ++ combinedHeader ++ "\n"
readConfig' :: Kit -> IO (Maybe XCConfig)
readConfig' kit = do
exists <- doesFileExist fp
contents <- T.sequence (fmap readFile $ justTrue exists fp)
return $ fmap (fileContentsToXCC $ kitName kit) contents
where
fp = kitConfigFile kit
generateXCodeConfig :: [FilePath] -> IO ()
generateXCodeConfig kitFileNames = do
inDirectory kitDir $ unKitIO $ do
ca <- readMany kitFileNames "KitSpec" (\x -> readSpec x |> specKit >>= (liftIO . readConfig'))
let combinedConfig = multiConfig "KitConfig" ca
let contents = configToString combinedConfig
let xcconfig = "HEADER_SEARCH_PATHS = $(HEADER_SEARCH_PATHS) " ++ (stringJoin " " $ kitFileNames >>= (\x -> [kitDir </> x </> "src", x </> "src"])) ++ "\n" ++ "GCC_PRECOMPILE_PREFIX_HEADER = YES\nGCC_PREFIX_HEADER = $(SRCROOT)/KitDeps_Prefix.pch\n"
liftIO $ writeFile "Kit.xcconfig" $ xcconfig ++ "\n" ++ contents
return ()
depsForSpec :: KitRepository -> KitSpec -> KitIO [Kit]
depsForSpec kr spec = do
deps <- mapM (getDeps kr) (specDependencies spec)
return $ specDependencies spec ++ join deps
getDeps :: KitRepository -> Kit -> KitIO [Kit]
getDeps kr kit = getKitSpec kr kit >>= depsForSpec kr
getMyDeps :: KitRepository -> KitIO [Kit]
getMyDeps kr = myKitSpec >>= depsForSpec kr
installKit :: KitRepository -> Kit -> IO ()
installKit kr kit = do
tmpDir <- getTemporaryDirectory
let fp = tmpDir </> (kitFileName kit ++ ".tar.gz")
putStrLn $ " -> Installing " ++ kitFileName kit
fmap fromJust $ getKit kr kit fp
let dest = kitDir
mkdir_p dest
inDirectory dest $ sh ("tar zxf " ++ fp)
return ()
where sh = system
readSpec :: FilePath -> KitIO KitSpec
readSpec kitSpecPath = readSpecContents kitSpecPath >>= KitIO . return . parses
myKitSpec :: KitIO KitSpec
myKitSpec = readSpec "KitSpec"
-- private!
checkExists :: FilePath -> KitIO FilePath
checkExists kitSpecPath = do
doesExist <- liftIO $ doesFileExist kitSpecPath
maybeToKitIO ("Couldn't find the spec at " ++ kitSpecPath) (justTrue doesExist kitSpecPath)
readSpecContents :: FilePath -> KitIO String
readSpecContents kitSpecPath = checkExists kitSpecPath >>= liftIO . readFile
parses :: String -> Either [KitError] KitSpec
parses contents = case (decode contents) of
Ok a -> Right a
Error a -> Left [a]