kit 0.2 → 0.3
raw patch · 8 files changed
+85/−71 lines, 8 files
Files
- Kit/JSON.hs +4/−0
- Kit/Kit.hs +3/−1
- Kit/Main.hs +2/−3
- Kit/Project.hs +52/−28
- Kit/Repository.hs +2/−2
- Kit/Util.hs +20/−22
- Kit/XCode/Prefix.hs +0/−13
- kit.cabal +2/−2
Kit/JSON.hs view
@@ -29,3 +29,7 @@ in KitSpec <$> myKit <*> myConfig where f x = mLookup x jsonObjAssoc >>= readJSON jsonObjAssoc = fromJSObject obj+ + mLookup :: Monad m => String -> [(String, b)] -> m b+ mLookup a as = maybe (fail $ "No such element: " ++ a) return (lookup a as)+
Kit/Kit.hs view
@@ -1,9 +1,11 @@ module Kit.Kit where import Kit.Util + type Version = String+ data Kit = Kit { kitName :: String,- kitVersion :: String+ kitVersion :: Version } deriving (Eq, Show, Ord, Read) kitFileName :: Kit -> String
Kit/Main.hs view
@@ -35,9 +35,8 @@ puts $ "Dependencies: " ++ (stringJoin ", " $ map kitFileName deps) liftIO $ mapM (installKit repo) deps puts " -> Generating XCode project..."- liftIO $ generateXCodeProject $ deps |> kitFileName- liftIO $ generateXCodeConfig $ deps |> kitFileName- puts "Kit complete."+ liftIO $ generateXCodeProject deps+ puts "Kit complete. You may need to restart XCode for it to pick up any changes." where p x = liftIO $ print x puts x = liftIO $ putStrLn x
Kit/Project.hs view
@@ -2,7 +2,6 @@ getDeps, getMyDeps, installKit,- generateXCodeConfig, generateXCodeProject, myKitSpec) where@@ -21,52 +20,77 @@ 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 + -- Paths kitDir = "." </> "Kits" projectDir = "KitDeps.xcodeproj" prefixFile = "KitDeps_Prefix.pch" projectFile = projectDir </> "project.pbxproj"+ xcodeConfigFile = "Kit.xcconfig"+ prefixDefault = "#ifdef __OBJC__\n" ++ " #import <Foundation/Foundation.h>\n #import <UIKit/UIKit.h>\n" ++ "#endif\n"- - generateXCodeProject :: [FilePath] -> IO ()- generateXCodeProject kitFileNames = do+ + -- Represents an extracted project+ -- Headers, Sources, Config, Prefix content+ data KitContents = KitContents { contentHeaders :: [String], contentSources :: [String], contentConfig :: Maybe XCConfig, contentPrefix :: Maybe String }+ + readKitContents :: Kit -> IO KitContents+ readKitContents kit = + let kitDir = kitFileName kit+ find tpe = glob ((kitDir </> "src/**/*") ++ tpe)+ headers = find ".h"+ sources = fmap join $ T.sequence [find ".m", find ".mm", find ".c"]+ config = readConfig kit+ prefix = readHeader kit+ in KitContents <$> headers <*> sources <*> config <*> prefix+ + generateXCodeProject :: [Kit] -> IO ()+ generateXCodeProject deps = 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"+ kitsContents <- T.for deps readKitContents+ createProjectFile kitsContents+ createHeader kitsContents+ createConfig kitsContents+ where kitFileNames = deps |> kitFileName+ createProjectFile cs = do+ let headers = cs >>= contentHeaders+ let sources = cs >>= contentSources+ mkdir_p projectDir+ writeFile projectFile $ buildXCodeProject headers sources+ createHeader cs = do+ let headers = catMaybes $ cs |> contentPrefix+ let combinedHeader = stringJoin "\n" headers+ writeFile prefixFile $ prefixDefault ++ combinedHeader ++ "\n" + createConfig cs = do+ let configs = catMaybes $ cs |> contentConfig+ let combinedConfig = multiConfig "KitConfig" configs+ let kitHeaders = "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"+ writeFile xcodeConfigFile $ kitHeaders ++ "\n" ++ configToString combinedConfig+ + kitPrefixFile = "Prefix.pch" - readConfig' :: Kit -> IO (Maybe XCConfig)- readConfig' kit = do+ readHeader :: Kit -> IO (Maybe String)+ readHeader kit = do+ let fp = kitFileName kit </> kitPrefixFile exists <- doesFileExist fp contents <- T.sequence (fmap readFile $ justTrue exists fp)+ return contents+ + readConfig :: Kit -> IO (Maybe XCConfig)+ readConfig kit = do+ let fp = kitConfigFile kit+ 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 + return . nub . sort $ specDependencies spec ++ join deps -- TODO Check for conflicting versions getDeps :: KitRepository -> Kit -> KitIO [Kit] getDeps kr kit = getKitSpec kr kit >>= depsForSpec kr
Kit/Repository.hs view
@@ -48,7 +48,7 @@ webRepo :: String -> KitRepository webRepo baseUrl = KitRepository save read where- save = download + save = download read = getBody fileRepo :: String -> KitRepository@@ -70,7 +70,7 @@ getBody path = let request = defaultGETRequest_ . fromJust . parseURI checkResponse r = justTrue (rspCode r == (2,0,0)) r- leftMaybe = either (const Nothing) Just + leftMaybe = either (const Nothing) Just in do rr <- Network.HTTP.simpleHTTP $ request path return $ fmap rspBody $ leftMaybe rr
Kit/Util.hs view
@@ -18,7 +18,7 @@ import Data.Monoid import Control.Monad.Trans - (|>) ma f = fmap f ma+ ma |> f = fmap f ma maybeRead :: Read a => String -> Maybe a maybeRead = fmap fst . listToMaybe . reads@@ -34,38 +34,43 @@ maybeToLeft :: b -> Maybe a -> Either a b maybeToLeft _ (Just a) = Left a maybeToLeft b Nothing = Right b- + instance Foldable (Either c) where foldr f z (Left c) = z foldr f z (Right a) = f a z- + instance T.Traversable (Either c) where sequenceA = either (pure . Left) (Right <$>)- + type KitError = String- + data KitIO a = KitIO { unKitIO :: (IO (Either [KitError] a)) }- + kitError :: KitError -> KitIO a kitError e = KitIO . return $ Left [e]- + maybeToKitIO msg = maybe (kitError msg) return- + instance Monad KitIO where (KitIO ioE) >>= f = KitIO $ ioE >>= g where g l@(Left v) = return (Left v) g (Right v) = unKitIO $ f v- + return = KitIO . return . Right - + instance Functor KitIO where fmap f kio = kio >>= (return . f)- + instance MonadIO KitIO where liftIO v = KitIO (fmap Right v)-- mLookup a as = maybe (fail $ "No such element: " ++ a) return (lookup a as) + instance Applicative KitIO where+ pure = return+ mf <*> ma = do+ f <- mf+ a <- ma+ return $ f a+ mkdir_p :: FilePath -> IO () mkdir_p = createDirectoryIfMissing True @@ -74,7 +79,7 @@ exists <- doesDirectoryExist directory when exists $ removeDirectoryRecursive directory mkdir_p directory- + inDirectory :: FilePath -> IO a -> IO a inDirectory dir actions = do cwd <- getCurrentDirectory@@ -85,14 +90,7 @@ glob :: String -> IO [String] glob pattern = fmap lines (readProcess "ruby" ["-e", "puts Dir.glob(\"" ++ pattern ++ "\")"] [])- + stringJoin :: Monoid a => a -> [a] -> a stringJoin x = mconcat . intersperse x - -- For each directory that exists, execute the function with the given filepath- readMany :: MonadIO m => [FilePath] -> FilePath -> (String -> m (Maybe a)) -> m [a]- readMany dirs fileInDir f = do- directories <- liftIO $ filterM doesDirectoryExist dirs- let kitSpecFiles = map (</> fileInDir) directories- kitContents <- mapM f kitSpecFiles- return $ catMaybes kitContents
− Kit/XCode/Prefix.hs
@@ -1,13 +0,0 @@-module Kit.XCode.Prefix where- - import Kit.Util- import qualified Data.Traversable as T- - kitPrefixFile = "Prefix.pch"- - generatePrefixHeader :: [FilePath] -> IO String- generatePrefixHeader kitFileNames = do- ca <- readMany kitFileNames kitPrefixFile $ \s -> do- exists <- doesFileExist s- T.for (justTrue exists s) readFile- return $ stringJoin "\n" ca
kit.cabal view
@@ -1,5 +1,5 @@ Name: kit-Version: 0.2+Version: 0.3 Synopsis: A dependency manager for XCode (Objective-C) projects Description: A dependency manager for XCode (Objective-C) projects Category: Development@@ -11,6 +11,6 @@ Cabal-Version: >=1.2 Executable kit Main-is: Main.hs- Other-Modules: Kit.JSON, Kit.Kit, Kit.Main, Kit.Package, Kit.Project, Kit.Repository, Kit.Spec, Kit.Util, Kit.XCode.Builder, Kit.XCode.Common, Kit.XCode.Prefix, Kit.XCode.ProjectFile, Kit.XCode.XCConfig+ Other-Modules: Kit.JSON, Kit.Kit, Kit.Main, Kit.Package, Kit.Project, Kit.Repository, Kit.Spec, Kit.Util, Kit.XCode.Builder, Kit.XCode.Common, Kit.XCode.ProjectFile, Kit.XCode.XCConfig Build-Depends: base >= 3 && < 5, HTTP >= 4000.0.9, network, bytestring, filepath, directory, process, json, mtl, cmdargs, MissingH, containers, QuickCheck