packages feed

kit 0.3 → 0.4

raw patch · 7 files changed

+282/−96 lines, 7 filesdep ~cmdargs

Dependency ranges changed: cmdargs

Files

Kit/Main.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} module Kit.Main where   import qualified Data.ByteString as BS @@ -10,25 +11,32 @@   import Kit.Project   import Kit.Repository   import Kit.Spec-  import Kit.Util  +  import Kit.Util   import Kit.XCode.Builder   import qualified Data.Traversable as T   import System.Cmd   import System.Environment   import Text.JSON+  import System.Console.CmdArgs+  import System.Console.CmdArgs as CA +  import Data.Data+  import Data.Typeable++  appVersion = "0.3"+   defaultLocalRepoPath = do       home <- getHomeDirectory       return $ home </> ".kit" </> "repository"   defaultLocalRepository = fmap fileRepo defaultLocalRepoPath-  +   handleFails (Left e) = do     print e     return ()   handleFails (Right _) = return ()-  -  update :: IO ()-  update = unKitIO g >>= handleFails++  doUpdate :: IO ()+  doUpdate = unKitIO g >>= handleFails       where g = do               repo <- liftIO defaultLocalRepository               deps <- getMyDeps repo@@ -39,22 +47,22 @@               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-  -  packageKit :: IO ()-  packageKit = do++  doPackageKit :: IO ()+  doPackageKit = do       mySpec <- unKitIO myKitSpec       T.for mySpec package       return ()-  -  deployLocal :: IO ()-  deployLocal = do++  doDeployLocal :: IO ()+  doDeployLocal = do     mySpec <- unKitIO myKitSpec     T.for mySpec package     T.for mySpec x     handleFails mySpec       where         x :: KitSpec -> IO ()-        x spec = let +        x spec = let               k = specKit spec               kf = kitFileName . specKit $ spec               pkg = (kf ++ ".tar.gz")@@ -64,15 +72,15 @@               mkdir_p thisKitDir               copyFile pkg $ thisKitDir </> pkg               copyFile "KitSpec" $ thisKitDir </> "KitSpec"-  -  verify :: Maybe String -> IO ()-  verify sdk = (unKitIO f >>= handleFails)++  doVerify :: String -> IO ()+  doVerify sdk = (unKitIO f >>= handleFails)     where       f = do         mySpec <- myKitSpec         puts "Checking that the kit can be depended upon..."         puts " #> Deploying locally"-        liftIO deployLocal+        liftIO doDeployLocal         puts " #> Building temporary parent project"         tmp <- liftIO getTemporaryDirectory         liftIO $ inDirectory tmp $ do@@ -80,46 +88,57 @@           cleanOrCreate kitVerifyDir           inDirectory kitVerifyDir $ do             writeFile "KitSpec" $ encode (KitSpec (Kit "verify-kit" "1.0") $ defaultConfiguration{kitConfigDependencies=[specKit mySpec]})-            update+            doUpdate             inDirectory "Kits" $ do-              system $ "xcodebuild -sdk " ++ (fromMaybe "iphonesimulator4.0" sdk)+              system $ "xcodebuild -sdk " ++ sdk           putStrLn "OK."         puts "End checks."       puts = liftIO . putStrLn-      -  createSpec :: String -> String -> IO ()-  createSpec name version = do++  doCreateSpec :: String -> String -> IO ()+  doCreateSpec name version = do     let kit =(Kit name version)     let spec = KitSpec kit defaultConfiguration     writeFile "KitSpec" $ encode spec     putStrLn $ "Created KitSpec for " ++ kitFileName kit     return ()-  -  handleArgs :: [String] -> IO ()-  handleArgs ["update"] = update-  handleArgs ["package"] = packageKit-  handleArgs ["publish-local"] = deployLocal-  handleArgs ["verify"] = verify Nothing-  handleArgs ["verify", sdk] = verify $ Just sdk-  handleArgs ["create-spec", name, version] = createSpec name version-    -  handleArgs _ = putStrLn f where-    f = "Usage: kit command [arguments]" `nl`-        "Commands:" `nl`-        "\tupdate\t\t\t\tCreate an Xcode project to wrap the dependencies defined in ./KitSpec" `nl`-        "\tcreate-spec NAME VERSION\tWrite out a KitSpec file using the given name and version." `nl`-        "\tpackage\t\t\t\tCreate a tar.gz wrapping this kit" `nl`-        "\tverify [SDK]\t\t\tPackage this kit, then attempt to use it as a dependency in an empty project." `nl`-        "\tpublish-local\t\t\tPackage this kit, then deploy it to the local repository (~/.kit/repository)" -    nl a b = a ++ "\n" ++ b-    ++  data KitCmdArgs = Update+                  | Package+                  | PublishLocal+                  | Verify { sdk :: String }+                  | CreateSpec { name :: String, version :: String } deriving (Show, Data, Typeable)++  parseArgs = cmdArgs $ modes [+        Update &= help "Create an Xcode project to wrap the dependencies defined in `KitSpec`"+               &= auto -- The default mode to run. This is most common usage.+      , (CreateSpec { Kit.Main.name = (def &= typ "NAME") &= argPos 0, version = (def &= typ "VERSION") &= argPos 1 }) &=+                            explicit &=+                            CA.name "create-spec" &=+                            help "Write out a KitSpec file using the given name and version."+      , Package &=+                    help "Create a tar.gz wrapping this kit"+      , PublishLocal &= explicit &= CA.name "publish-local" &=+                    help "Package this kit, then deploy it to the local repository (~/.kit/repository)"+      , Verify { sdk = "iphonesimulator4.0" &= typ "SDK" &= help "iphoneos3.1, iphonesimulator4.0, etc."} &=+                    help "Package this kit, then attempt to use it as a dependency in an empty project. This will assert that the kit and all its dependencies can be compiled together."+    ] &= program "kit"+      &= summary ("Kit v" ++ appVersion ++ ". It's a dependency manager for Objective-C projects built with XCode.")++  handleArgs :: KitCmdArgs -> IO ()+  handleArgs Update = doUpdate+  handleArgs Package = doPackageKit+  handleArgs PublishLocal = doDeployLocal+  handleArgs (Verify sdk) = doVerify sdk+  handleArgs (CreateSpec name version) = doCreateSpec name version+   kitMain :: IO ()   kitMain = do       localRepo <- defaultLocalRepository       path <- defaultLocalRepoPath       mkdir_p path-      args <- getArgs-      handleArgs args+      handleArgs =<< parseArgs -- =<< getArgs -      -          +++
Kit/Project.hs view
@@ -1,17 +1,17 @@ module Kit.Project (-  getDeps,   getMyDeps,   installKit,   generateXCodeProject,   myKitSpec)     where-      +   import Control.Monad.Trans   import Control.Monad   import Control.Applicative-  import Data.Foldable+  import qualified Data.Foldable as F   import Data.Maybe   import Data.List+  import Data.Tree   import Data.Monoid   import System.Cmd   import Kit.Kit@@ -23,22 +23,22 @@   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"-    +   -- 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  = +  readKitContents kit  =     let kitDir = kitFileName kit         find tpe = glob ((kitDir </> "src/**/*") ++ tpe)         headers = find ".h"@@ -46,7 +46,7 @@         config = readConfig kit         prefix = readHeader kit     in  KitContents <$> headers <*> sources <*> config <*> prefix-  +   generateXCodeProject :: [Kit] -> IO ()   generateXCodeProject deps = do     mkdir_p kitDir@@ -64,13 +64,13 @@           createHeader cs = do             let headers = catMaybes $ cs |> contentPrefix             let combinedHeader = stringJoin "\n" headers-            writeFile prefixFile $ prefixDefault ++ combinedHeader ++ "\n"            +            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"    readHeader :: Kit -> IO (Maybe String)@@ -79,24 +79,39 @@     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-      +   depsForSpec :: KitRepository -> KitSpec -> KitIO [Kit]   depsForSpec kr spec = do       deps <- mapM (getDeps kr) (specDependencies spec)       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+      where getDeps kr kit = getKitSpec kr kit >>= depsForSpec kr ++  refineDeps :: Tree Kit -> [Kit]+  refineDeps = nub . concat . reverse . drop 1 . levels++  depsForSpec' :: KitRepository -> KitSpec -> KitIO [Kit]+  depsForSpec' kr spec = do+      tree <- unfoldTreeM (unfoldDeps kr) spec+      -- todo: check for dups, check for conflicts+      return $ refineDeps tree++  unfoldDeps :: KitRepository -> KitSpec -> KitIO (Kit, [KitSpec])+  unfoldDeps kr ks = do+      let kit = specKit ks+      let depKits = specDependencies ks+      specs <- mapM (getKitSpec kr) depKits+      return (kit, specs)+   getMyDeps :: KitRepository -> KitIO [Kit]-  getMyDeps kr = myKitSpec >>= depsForSpec kr+  getMyDeps kr = myKitSpec >>= depsForSpec' kr    installKit :: KitRepository -> Kit -> IO ()   installKit kr kit = do@@ -112,7 +127,7 @@    readSpec :: FilePath -> KitIO KitSpec   readSpec kitSpecPath = readSpecContents kitSpecPath >>= KitIO . return . parses-  +   myKitSpec :: KitIO KitSpec   myKitSpec = readSpec "KitSpec" @@ -121,12 +136,12 @@   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 +  parses contents = case (decode contents) of                       Ok a -> Right a                       Error a -> Left [a]-  +
+ Kit/XCode/OldPList.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE TypeSynonymInstances #-}+module Kit.XCode.OldPList where++import Data.List++class AsPListType a where+    asPListType :: a -> PListType++instance AsPListType PListType where+    asPListType = id++data PListType = PListValue String+               | PListArray [PListType]+               | PListObject [(String, PListType)]++val = PListValue+arr = PListArray+obj = PListObject++data PListFile = PListFile { pListFileCharset :: String, pListFileValue :: PListType }++quote s = "\"" ++ s ++ "\""+quotable s = or $ map (\x -> x `isInfixOf` s) ["-", "<", ">", " "]+++instance Show PListType where++    show (PListValue a) = if (quotable a) then quote a else a+    show (PListArray xs) = "(" ++ (map ((++ ",") . show) xs >>= id) ++ ")"+    show (PListObject kvs) = "{" ++ (kvs >>= f) ++ "}"+                                where f (k, v) = k ++ " = " ++ show v ++ ";"++(~=~) = (,)+++projectFile = PListFile "!$*UTF8*$!" $ PListObject [+        "archiveVersion" ~=~ PListValue "1",+        "classes" ~=~ PListObject [],+        "objectVersion" ~=~ PListValue "45",+        "objects" ~=~ PListObject []+    ]+
+ Kit/XCode/PBXProject.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Kit.XCode.PBXProject where++import Kit.XCode.OldPList+import Control.Monad.State+import Control.Monad.Writer++type UUID = String++data PBXProject = PBXProject {+    projectConfigurationList :: XCConfigurationList+  , projectGroups :: [PBXGroup]+  , projectName :: String+}++data XCConfigurationList = XCConfigurationList {+  configurationsList :: [XCBuildConfiguration]+}++data PBXGroup = PBXGroup {+    groupChildren :: [PBXGroup]+  , groupChildrenExtra :: [UUID]+  , groupName :: String+  , groupSourceTree :: String+}++data XCBuildConfiguration = XCBuildConfiguration++instance ProjectPListItem PBXGroup where+  writeEntry group = do+    childUUIDs <- mapM writeEntry (groupChildren group)+    write $ obj [+          "isa" ~=~ val "PBXGroup"+        , "name" ~=~ (val . groupName) group+        , "sourceTree" ~=~ (val . groupSourceTree) group+        , "children" ~=~ (arr $ map val (childUUIDs ++ groupChildrenExtra group))+      ]++type PLObjects = [(UUID, PListType)]+-- Consume UUIDs from state, write out other objects to be added to the plist+newtype PL a = PL { unPL :: WriterT PLObjects (State [UUID]) a }+              deriving (Monad, MonadState [UUID], MonadWriter PLObjects)++class ProjectPListItem a where+  writeEntry :: a -> PL UUID++popS = do+  (x:xs) <- get+  put xs+  return x++write blah = do+  uuid <- popS+  tell [(uuid, blah)]+  return uuid++instance ProjectPListItem PBXProject where+  writeEntry project = do+    config <- write $ val "TODO"+    productGroupUUID <- writeEntry (PBXGroup [] [] "Products" "<group>")+    mainGroupUUID <- writeEntry (PBXGroup [] [productGroupUUID] (projectName project) "<group>")+    write $ obj [+        "isa" ~=~ val "PBXProject"+      , "buildConfigurationList" ~=~ val config+      , "compatibilityVersion" ~=~ val "Xcode 3.1"+      , "hasScannedForEncodings" ~=~ val "1"+      , "mainGroup" ~=~ val mainGroupUUID+      , "productRefGroup" ~=~ val productGroupUUID+      , "projectDirPath" ~=~ val ""+      , "projectRoot" ~=~ val ""+      , "targets" ~=~ arr []+     ]
Kit/XCode/ProjectFile.hs view
@@ -3,20 +3,19 @@   Constant sections of the project file -} module Kit.XCode.ProjectFile (projectPbxProj) where-  -  nl a b = a ++ "\n" ++ b -  -  projectPbxProj bfs fileRefsSection classes headers sources = +  nl a b = a ++ "\n" ++ b++  projectPbxProj bfs fileRefsSection classes headers sources =       top `nl` bfs `nl` fileRefsSection `nl` next1 `nl` classes `nl` next2 `nl` headers `nl` next3 `nl` sources `nl` bottom-  -  top = "// !$*UTF8*$!" `nl` ++  top = "// !$*UTF8*$!" `nl`     "{" `nl`     " archiveVersion = 1;" `nl`     " classes = {" `nl`     " };" `nl`     " objectVersion = 45;" `nl`     " objects = {"-  +   next1 = "/* Begin PBXFrameworksBuildPhase section */" `nl`     		"D2AAC07C0554694100DB518D /* Frameworks */ = {" `nl`     			"isa = PBXFrameworksBuildPhase;" `nl`@@ -67,7 +66,7 @@         			"sourceTree = \"<group>\";" `nl`         		"};" `nl`         "/* End PBXGroup section */"-        +   next3 = "/* Begin PBXNativeTarget section */" `nl`         		"D2AAC07D0554694100DB518D /* KitDeps */ = {" `nl`         			"isa = PBXNativeTarget;" `nl`@@ -103,7 +102,7 @@         			");" `nl`         		"};" `nl`         "/* End PBXProject section */"-  +   bottom = "/* Begin XCBuildConfiguration section */" `nl`         		"1DEB921F08733DC00010E9CD /* Debug */ = {" `nl`         			"isa = XCBuildConfiguration;" `nl`@@ -191,8 +190,8 @@         	"};" `nl`         	"rootObject = 0867D690FE84028FC02AAC07 /* Project object */;" `nl`         "}"-  -  ++   main = do     putStrLn $ projectPbxProj "" "" "" "" ""-    +
Main.hs view
@@ -2,9 +2,11 @@   import Kit.Main   import qualified Data.Map as M   import Kit.XCode.XCConfig-  +  import Kit.XCode.OldPList+  import Kit.XCode.PBXProject+   conf1 = XCC "conf1" (M.fromList [("A", "1")]) []   conf2 = XCC "conf2" (M.fromList [("A", "2")]) []-  +   --main = putStrLn $ show $ multiConfig "combo" [conf1, conf2]   main = kitMain
kit.cabal view
@@ -1,16 +1,53 @@-Name:                kit-Version:             0.3-Synopsis:            A dependency manager for XCode (Objective-C) projects-Description:         A dependency manager for XCode (Objective-C) projects-Category:            Development-License:             BSD3-License-file:        LICENSE-Author:              Nick Partridge-Maintainer:          nkpart@gmail.com-Build-Type:          Simple-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.ProjectFile, Kit.XCode.XCConfig-  Build-Depends:     base >= 3 && < 5, HTTP >= 4000.0.9, network, bytestring, filepath, directory, process, json, mtl, cmdargs, MissingH, containers, QuickCheck-  +name: kit+version: 0.4+cabal-version: >=1.2+build-type: Simple+license: BSD3+license-file: LICENSE+copyright:+maintainer: nkpart@gmail.com+build-depends: HTTP >=4000.0.9, MissingH -any, QuickCheck -any,+               base >=3 && <5, bytestring -any, cmdargs >=0.3, containers -any,+               directory -any, filepath -any, json -any, mtl -any, network -any,+               process -any+stability:+homepage:+package-url:+bug-reports:+synopsis: A dependency manager for XCode (Objective-C) projects+description: A dependency manager for XCode (Objective-C) projects+category: Development+author: Nick Partridge+tested-with:+data-files:+data-dir: ""+extra-source-files:+extra-tmp-files:+ +executable: kit+main-is: Main.hs+buildable: True+build-tools:+cpp-options:+cc-options:+ld-options:+pkgconfig-depends:+frameworks:+c-sources:+extensions:+extra-libraries:+extra-lib-dirs:+includes:+install-includes:+include-dirs:+hs-source-dirs: .+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.OldPList Kit.XCode.PBXProject Kit.XCode.ProjectFile+               Kit.XCode.XCConfig+ghc-prof-options:+ghc-shared-options:+ghc-options:+hugs-options:+nhc98-options:+jhc-options: