module Chromatin.Rebuild.Existing( handleExisting, ) where import GHC.IO.Exception (IOException) import qualified Data.ByteString.Lazy.Internal as B (unpackChars) import Data.List.Split (linesBy) import System.Process.Typed (readProcessStderr, proc, setWorkingDir) import UnliftIO (tryIO) import Chromatin.Data.Chromatin (Chromatin) import Chromatin.Data.RebuildTask (RebuildTask(..)) import Chromatin.Data.RunExistingResult (RunExistingResult) import qualified Chromatin.Data.RunExistingResult as RunExistingResult (RunExistingResult(..)) import Chromatin.Data.Rplugin (Rplugin(Rplugin)) import Chromatin.Data.RpluginName (RpluginName) import Chromatin.Data.RpluginSource (RpluginSource(Stack, Pypi)) import Chromatin.Data.RpluginState (RpluginState) import qualified Chromatin.Data.RpluginState as RpluginState (RpluginState(..)) import Chromatin.Run (runRplugin, RunRpluginResult, pypiPluginPackage) import qualified Chromatin.Run as RunRpluginResult (RunRpluginResult(..)) runPreexistingResult :: RebuildTask -> RunRpluginResult -> RunExistingResult runPreexistingResult _ (RunRpluginResult.Success active) = RunExistingResult.Success active runPreexistingResult task (RunRpluginResult.Failure err) = RunExistingResult.Failure task err unsafeStackDryRun :: FilePath -> Chromatin [String] unsafeStackDryRun path = do (_, output) <- readProcessStderr $ setWorkingDir path $ proc "stack" ["build", "--dry-run"] return $ linesBy (=='\n') $ B.unpackChars output stackDryRun :: FilePath -> Chromatin (Either IOException [String]) stackDryRun path = tryIO $ unsafeStackDryRun path rpluginReady :: RpluginName -> RpluginSource -> Chromatin RpluginState rpluginReady _ (Stack path) = do output <- stackDryRun path return $ case output of Right lines' -> if "Would build:" `elem` lines' then RpluginState.Incomplete else RpluginState.Ready Left err -> RpluginState.Broken $ "could not execute `stack build` in " ++ path ++ ": " ++ show err rpluginReady name (Pypi _) = do package <- pypiPluginPackage name return $ maybe RpluginState.Incomplete (const RpluginState.Ready) package rpluginReady _ _ = return $ RpluginState.Broken "NI" runPreexisting :: RebuildTask -> Chromatin RunExistingResult runPreexisting task@(RebuildTask name source) = runPreexistingResult task <$> runRplugin (Rplugin name source) handleExisting :: RebuildTask -> Chromatin RunExistingResult handleExisting task@(RebuildTask name source) = do state <- rpluginReady name source case state of RpluginState.Ready -> runPreexisting task RpluginState.Incomplete -> return $ RunExistingResult.NotReady task RpluginState.Broken reason -> return $ RunExistingResult.Failure task [reason]