summaryrefslogtreecommitdiff
path: root/Coolbal/CabalPlan.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Coolbal/CabalPlan.hs')
-rw-r--r--Coolbal/CabalPlan.hs66
1 files changed, 66 insertions, 0 deletions
diff --git a/Coolbal/CabalPlan.hs b/Coolbal/CabalPlan.hs
new file mode 100644
index 0000000..6d0bd04
--- /dev/null
+++ b/Coolbal/CabalPlan.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE ViewPatterns #-}
+module Coolbal.CabalPlan (
+ CabalPlan(..),
+ PlanPackage(..),
+ parseCabalPlan,
+) where
+
+import qualified Data.Bytes as Bytes
+import Data.Foldable (toList)
+import Data.List (find)
+import qualified GHC.Exts as IsList (IsList(..))
+import qualified Json
+
+
+data CabalPlan = CabalPlan
+ { planCompiler :: String
+ , planPackages :: [PlanPackage] }
+ deriving (Show)
+
+data PlanPackage
+ = PreExisting
+ { ppName :: String
+ , ppVersion :: String
+ , ppDepends :: [String] }
+ | Configured
+ { ppName :: String
+ , ppVersion :: String
+ , ppLocal :: Bool
+ , ppComponent :: String
+ , ppDepends :: [String] }
+ deriving (Show)
+
+
+parseCabalPlan :: FilePath -> IO (Maybe CabalPlan)
+parseCabalPlan fpath = parseFromValue <$> Bytes.readFile fpath
+ where
+ parseFromValue (Json.decode -> Right toplevel) = do
+ Json.Object obj <- return toplevel
+ Json.String compiler <- locate "compiler-id" obj
+ Json.Array pkgs <- locate "install-plan" obj
+ CabalPlan (IsList.toList compiler) <$> mapM parsePackage (toList pkgs)
+ parseFromValue _ = Nothing
+
+ parsePackage value = do
+ Json.Object obj <- return value
+ Json.String typ <- locate "type" obj
+ Json.String name <- locate "pkg-name" obj
+ Json.String version <- locate "pkg-version" obj
+ Json.Array dependsArr <- locate "depends" obj
+ depends <- mapM (\case Json.String s -> Just s ; _ -> Nothing) (toList dependsArr)
+ if | typ == IsList.fromList "pre-existing" ->
+ return (PreExisting (IsList.toList name) (IsList.toList version) (map IsList.toList depends))
+ | typ == IsList.fromList "configured" -> do
+ Json.String style <- locate "style" obj
+ Json.String component <- locate "component-name" obj
+ return (Configured (IsList.toList name) (IsList.toList version)
+ (style == IsList.fromList "local")
+ (IsList.toList component)
+ (map IsList.toList depends))
+ | otherwise ->
+ Nothing
+
+locate :: Foldable f => String -> f Json.Member -> Maybe Json.Value
+locate key = fmap (\(Json.Member _ v) -> v) . find (\(Json.Member k _) -> k == IsList.fromList key)