packages feed

tricorder-0.2.1.0: src/Tricorder/Daemon/Hpack.hs

module Tricorder.Daemon.Hpack (main) where

import Atelier.Effects.Chan (Chan)
import Atelier.Effects.Clock (Clock)
import Atelier.Effects.Conc (Conc)
import Atelier.Effects.Debounce (Debounce)
import Atelier.Effects.FileWatcher (FileWatcher)
import Atelier.Effects.Log (Log)
import Atelier.Effects.Publishing (runPubSub)
import Atelier.Effects.Publishing.Pub (Pub)
import Effectful.Reader.Static (Reader)

import Atelier.Effects.Conc qualified as Conc
import Atelier.Effects.FileWatcher qualified as FileWatcher
import Atelier.Effects.Log qualified as Log
import Atelier.Effects.Publishing.Pub qualified as Pub
import Atelier.Effects.Publishing.Sub qualified as Sub
import Data.List qualified as List
import Effectful.Reader.Static qualified as Reader

import Tricorder.Daemon.Hpack.Effect (Hpack)
import Tricorder.Runtime (ProjectRoot (..))

import Tricorder.Daemon.Hpack.Effect qualified as Hpack


main
    :: ( Chan :> es
       , Clock :> es
       , Conc :> es
       , Debounce FilePath :> es
       , FileWatcher :> es
       , Hpack :> es
       , Log :> es
       , Reader ProjectRoot :> es
       )
    => Eff es ()
main = runPubSub @RePack $ Conc.scoped do
    hpackInPath <- Hpack.hpackIsInPath
    when hpackInPath do
        projectRoot <- Reader.ask
        Conc.fork_ $ Sub.listen_ \(RePack path) -> runHpack path
        vacuous $ watchPackageYaml projectRoot


runHpack :: (Hpack :> es, Log :> es) => FilePath -> Eff es ()
runHpack path = do
    res <- Hpack.hpack path
    case res of
        Left err -> Log.err $ "Hpack error: " <> err
        Right result ->
            Log.info
                $ "Hpack: " <> case result of
                    Hpack.Generated ->
                        "generated " <> toText path
                    Hpack.Unchanged ->
                        "already up-to-date: " <> toText path
                    Hpack.WasEditedManually ->
                        "cabal file was edited manually: " <> toText path
                    Hpack.WasGeneratedWithNewerHpack ->
                        "cabal file was generated with a newer version of Hpack: " <> toText path
                    Hpack.UnknownSuccess output -> "unknown successful output: " <> output


watchPackageYaml
    :: ( Debounce FilePath :> es
       , FileWatcher :> es
       , Pub RePack :> es
       )
    => ProjectRoot -> Eff es Void
watchPackageYaml root = do
    FileWatcher.watchFilePathsDebounced
        [FileWatcher.dirWhere root.getProjectRoot (packageYaml `List.isSuffixOf`)]
        \path _ -> Pub.publish $ RePack path


data RePack = RePack FilePath


packageYaml :: FilePath
packageYaml = "package.yaml"