autonix-deps-0.3.0.0: src/Autonix/Manifest.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Autonix.Manifest
( Manifest, name, store, src
, readManifests
) where
import Control.Lens
import Control.Monad.IO.Class
import Data.Aeson
import Data.Aeson.Types
import qualified Data.ByteString.Lazy as BL
import qualified Data.Char as Char
import Data.Map (Map)
import qualified Data.Map as M
import Data.Text (Text)
import qualified Data.Text as T
import GHC.Generics
import Autonix.Src (Src)
data Manifest =
Manifest { _name :: Text
, _store :: FilePath
, _src :: Src
}
deriving Generic
makeLenses ''Manifest
manifestOptions :: Options
manifestOptions = defaultOptions { fieldLabelModifier = tail }
instance FromJSON Manifest where
parseJSON = genericParseJSON manifestOptions
instance ToJSON Manifest where
toJSON = genericToJSON manifestOptions
readManifests :: MonadIO m => FilePath -> m (Map Text Manifest)
readManifests path = do
emanifests <- eitherDecode' <$> liftIO (BL.readFile path)
case emanifests :: Either String [Manifest] of
Left err -> error ("readManifests: could not read manifest.json\n" ++ err)
Right manifests -> return (foldr assemble M.empty manifests)
where
assemble :: Manifest -> Map Text Manifest -> Map Text Manifest
assemble manifest =
M.insertWith keepLatestVersion (onlyName $ view name manifest) manifest
onlyName :: Text -> Text
onlyName nameAndVersion =
T.intercalate "-"
$ takeWhile headNotDigit
$ T.splitOn "-" nameAndVersion
headNotDigit :: Text -> Bool
headNotDigit txt | T.null txt = True
| otherwise = not $ Char.isDigit (T.head txt)
keepLatestVersion :: Manifest -> Manifest -> Manifest
keepLatestVersion l r =
case compare (l^.name) (r^.name) of
LT -> r
EQ -> l
GT -> l