@@ -26,8 +26,9 @@ module Obelisk.Command.Project
2626 ) where
2727
2828import Control.Concurrent.MVar (MVar, newMVar, withMVarMasked)
29−import Control.Lens ((.~), (?~), (<&>), (^.), _3)
29+import Control.Lens ((.~), (?~), (<&>), (^.), _2, _3)
3030import Control.Monad
31+import Control.Monad.Except
3132import Control.Monad.IO.Class (liftIO)
3233import Control.Monad.Log
3334import Control.Monad.State
@@ -47,8 +48,9 @@ import Reflex.FSNotify
4748import Reflex.Host.Headless
4849import System.Directory
4950import System.Environment (lookupEnv)
51+import System.Exit (ExitCode(..))
5052import System.FilePath
51−import System.FSNotify (defaultConfig)
53+import System.FSNotify (defaultConfig, eventPath)
5254import System.IO.Temp
5355import System.IO.Unsafe (unsafePerformIO)
5456import System.PosixCompat.Files
@@ -374,7 +376,9 @@ findProjectAssets root = do
374376 -- Check whether the impure static files are a derivation (and so must be built)
375377 if isDerivation == "1"
376378 then do
377− _ <- buildStaticFilesDerivationAndSymlink root
379+ _ <- buildStaticFilesDerivationAndSymlink
380+ (readProcessAndLogStderr Debug)
381+ root
378382 pure (AssetSource_Derivation, T.pack $ root </> "static.out")
379383 else fmap (AssetSource_Files,) $ readProcessAndLogStderr Debug $ setCwd (Just root) $
380384 proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure", "--raw"]
@@ -399,31 +403,54 @@ watchStaticFilesDerivation root = do
399403 drv0 <- showDerivation
400404 liftIO $ runHeadlessApp $ do
401405 pb <- getPostBuild
402− checkForChanges <- watchDirectoryTree defaultConfig (root <$ pb) (const True)
406+ checkForChanges <- batchOccurrences 0.25 =<< watchDirectoryTree
407+ defaultConfig
408+ (root <$ pb)
409+ ((/="static.out") . takeFileName . eventPath)
403410 drv <- performEvent $ ffor checkForChanges $ \_ ->
404411 liftIO $ runObelisk ob showDerivation
405412 drvs <- foldDyn (\new (_, old, _) -> (old, new, old /= new)) (drv0, drv0, False) drv
406413 out <- throttleBatchWithLag
407− (\e -> performEvent $ ffor e $ \_ -> liftIO $ runObelisk ob $
408− buildStaticFilesDerivationAndSymlink root >> pure ())
409− (void $ ffilter (^._3) $ updated drvs)
414+ (\e -> performEvent $ ffor e $ \_ ->
415+ liftIO $ runObelisk ob $ buildStaticCatchErrors >> pure ())
416+ (void $ fmapMaybe (^._2) $ ffilter (^._3) $ updated drvs)
410417 performEvent_ $ ffor out $ \_ -> runObelisk ob $
411418 putLog Notice "Static assets rebuilt and symlinked to static.out"
412419 pure never
413420 where
414− showDerivation :: MonadObelisk m => m Text
415− showDerivation = readProcessAndLogStderr Debug $
416− setCwd (Just root) $ ProcessSpec
417− { _processSpec_createProcess = Proc.proc nixExePath
418− [ "show-derivation"
419− , "-f", "."
420− , "passthru.staticFilesImpure"
421− ]
422− , _processSpec_overrideEnv = Nothing
423− }
424−
425−buildStaticFilesDerivationAndSymlink :: MonadObelisk m => FilePath -> m Text
426−buildStaticFilesDerivationAndSymlink root = readProcessAndLogStderr Debug $
421+ handleBuildFailure
422+ :: MonadObelisk m
423+ => (ExitCode, String, String)
424+ -> m (Maybe Text)
425+ handleBuildFailure (ex, out, err) = case ex of
426+ ExitSuccess -> pure $ Just $ T.pack out
427+ _ -> do
428+ putLog Error $
429+ "Static assets build failed: " <> T.pack err
430+ pure Nothing
431+ showDerivation :: MonadObelisk m => m (Maybe Text)
432+ showDerivation =
433+ handleBuildFailure <=< readCreateProcessWithExitCode $
434+ setCwd (Just root) $ ProcessSpec
435+ { _processSpec_createProcess = Proc.proc nixExePath
436+ [ "show-derivation"
437+ , "-f", "."
438+ , "passthru.staticFilesImpure"
439+ ]
440+ , _processSpec_overrideEnv = Nothing
441+ }
442+ buildStaticCatchErrors :: MonadObelisk m => m (Maybe Text)
443+ buildStaticCatchErrors = handleBuildFailure =<<
444+ buildStaticFilesDerivationAndSymlink
445+ readCreateProcessWithExitCode
446+ root
447+
448+buildStaticFilesDerivationAndSymlink
449+ :: MonadObelisk m
450+ => (ProcessSpec -> m a)
451+ -> FilePath
452+ -> m a
453+buildStaticFilesDerivationAndSymlink f root = f $
427454 setCwd (Just root) $ ProcessSpec
428455 { _processSpec_createProcess = Proc.proc
429456 nixBuildExePath