autonix-deps-0.3.0.0: src/Autonix/Analyze.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
module Autonix.Analyze
( Analyzer
, analyzeFiles
, analyzePackages
) where
import Codec.Archive
import Control.Lens
import Control.Monad.State
import Control.Monad.Trans.Resource
import Data.ByteString (ByteString)
import Data.Conduit
import Data.Map (Map)
import Data.Semigroup
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Prelude hiding (mapM)
import Autonix.Manifest (Manifest, readManifests)
import qualified Autonix.Manifest as Manifest
import Autonix.Package (Package, package)
import Autonix.Renames
type Analyzer m = Text -> Manifest -> Sink (FilePath, ByteString) (ResourceT m) ()
analyzePackages :: MonadIO m => (Text -> Manifest -> StateT (Map Text Package, Renames) m ())
-> FilePath -> m (Map Text Package, Renames)
analyzePackages perPackage manifestPath = flip execStateT (mempty, mempty) $ do
manifests <- readManifests manifestPath
imapM_ perPackage manifests
sequenceSinks_ :: (Traversable f, Monad m) => f (Sink i m ()) -> Sink i m ()
sequenceSinks_ = void . sequenceSinks
analyzeFiles :: (MonadBaseControl IO m, MonadIO m, MonadState (Map Text Package, Renames) m, MonadThrow m)
=> [Analyzer m] -> Text -> Manifest -> m ()
analyzeFiles analyzers name m
| null (m^.Manifest.store) = error (T.unpack noStore)
| otherwise = do
liftIO $ T.putStrLn $ "package " <> name
let conduits = sourceArchive (m^.Manifest.store) $$ sequenceSinks_ sinks
sinks = analyzers >>= \analyze -> return (analyze name m)
pkg = package (m^.Manifest.name) (m^.Manifest.src)
_1 . at name %= Just . maybe pkg (pkg <>)
runResourceT conduits
where
noStore = "No store path specified for " <> (m^.Manifest.name)