@@ -1,9 +1,6 @@
1{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE ScopedTypeVariables #-}
5−{-# LANGUAGE TupleSections #-}
7module Obelisk.Command.Project
4module Obelisk.Command.Project
8 ( InitSource (..)
5 ( InitSource (..)
9 , findProjectObeliskCommand
6 , findProjectObeliskCommand
@@ -19,17 +16,12 @@ module Obelisk.Command.Project
19 , toObeliskDir
16 , toObeliskDir
20 , withProjectRoot
17 , withProjectRoot
21 , bashEscape
18 , bashEscape
22− , getHaskellManifestProjectPath
24− , describeImpureAssetSource
25− , watchStaticFilesDerivation
28import Control.Concurrent.MVar (MVar, newMVar, withMVarMasked)
21import Control.Concurrent.MVar (MVar, newMVar, withMVarMasked)
29−import Control.Lens ((.~), (?~), (<&>), (^.), _3)
22+import Control.Lens ((.~), (?~), (<&>))
30import Control.Monad
23import Control.Monad
31import Control.Monad.IO.Class (liftIO)
24import Control.Monad.IO.Class (liftIO)
32−import Control.Monad.Log
33import Control.Monad.State
25import Control.Monad.State
34import qualified Data.Aeson as Json
26import qualified Data.Aeson as Json
35import qualified Data.ByteString.UTF8 as BSU
27import qualified Data.ByteString.UTF8 as BSU
@@ -42,25 +34,20 @@ import Data.Text (Text)
42import qualified Data.Text as T
34import qualified Data.Text as T
43import Data.Text.Encoding (decodeUtf8, encodeUtf8)
35import Data.Text.Encoding (decodeUtf8, encodeUtf8)
44import Data.Traversable (for)
36import Data.Traversable (for)
46−import Reflex.FSNotify
47−import Reflex.Host.Headless
48import System.Directory
37import System.Directory
49import System.Environment (lookupEnv)
38import System.Environment (lookupEnv)
50import System.FilePath
39import System.FilePath
51−import System.FSNotify (defaultConfig)
52import System.IO.Temp
40import System.IO.Temp
53import System.IO.Unsafe (unsafePerformIO)
41import System.IO.Unsafe (unsafePerformIO)
54import System.PosixCompat.Files
42import System.PosixCompat.Files
55import System.PosixCompat.Types
43import System.PosixCompat.Types
56import System.PosixCompat.User
44import System.PosixCompat.User
57−import qualified System.Process as Proc
58import Text.ShellEscape (bash, bytes)
45import Text.ShellEscape (bash, bytes)
60import GitHub.Data.GitData (Branch)
47import GitHub.Data.GitData (Branch)
61import GitHub.Data.Name (Name)
48import GitHub.Data.Name (Name)
63−import Obelisk.App (MonadObelisk, runObelisk, getObelisk)
50+import Obelisk.App (MonadObelisk)
64import Obelisk.CliApp
51import Obelisk.CliApp
65import Obelisk.Command.Nix
52import Obelisk.Command.Nix
66import Obelisk.Command.Thunk
53import Obelisk.Command.Thunk
@@ -347,21 +334,7 @@ nixShellWithHoogle root isPure shell' command = do
347 \})).project.shells.${shell}"
334 \})).project.shells.${shell}"
348 & nixShellConfig_common . nixCmdConfig_args .~ [ strArg "shell" shell' ]
335 & nixShellConfig_common . nixCmdConfig_args .~ [ strArg "shell" shell' ]
350−-- | Describes the provenance of static assets (i.e., are they the result of a derivation
351−-- that was built, or just a folder full of files.
352−data AssetSource = AssetSource_Derivation
356−-- | Some log messages to make it easier to tell where static files are coming from
357−describeImpureAssetSource :: AssetSource -> Text -> Text
358−describeImpureAssetSource src path = case src of
359− AssetSource_Files -> "Assets impurely loaded from: " <> path
360− AssetSource_Derivation -> "Assets derivation built and impurely loaded from: " <> path
362−-- | Determine where the static files of a project are and whether they're plain files or a derivation.
363−-- If they are a derivation, that derivation will be built.
364−findProjectAssets :: MonadObelisk m => FilePath -> m (AssetSource, Text)
337+findProjectAssets :: MonadObelisk m => FilePath -> m Text
365findProjectAssets root = do
338findProjectAssets root = do
366 isDerivation <- readProcessAndLogStderr Debug $ setCwd (Just root) $
339 isDerivation <- readProcessAndLogStderr Debug $ setCwd (Just root) $
367 proc nixExePath
340 proc nixExePath
@@ -373,62 +346,10 @@ findProjectAssets root = do
374 -- Check whether the impure static files are a derivation (and so must be built)
347 -- Check whether the impure static files are a derivation (and so must be built)
375 if isDerivation == "1"
348 if isDerivation == "1"
377− _ <- buildStaticFilesDerivationAndSymlink root
378− pure (AssetSource_Derivation, T.pack $ root </> "static.out")
379− else fmap (AssetSource_Files,) $ readProcessAndLogStderr Debug $ setCwd (Just root) $
380− proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure", "--raw"]
382−-- | Get the nix store path to the generated static asset manifest module (e.g., "obelisk-generated-static")
383−getHaskellManifestProjectPath :: MonadObelisk m => FilePath -> m Text
384−getHaskellManifestProjectPath root = fmap T.strip $ readProcessAndLogStderr Debug $ setCwd (Just root) $
349+ then fmap T.strip $ readProcessAndLogStderr Debug $ setCwd (Just root) $ -- Strip whitespace here because nix-build has no --raw option
385− proc nixBuildExePath
350+ proc nixBuildExePath
386− [ "--no-out-link"
351+ [ "--no-out-link"
388− , "(let a = import ./. {}; in a.passthru.processedStatic.haskellManifest)"
391−-- | Watch the project directory for file changes and check whether those file changes
392−-- cause changes in the static files nix derivation. If so, rebuild it.
393−watchStaticFilesDerivation
394− :: (MonadIO m, MonadObelisk m)
397−watchStaticFilesDerivation root = do
399− drv0 <- showDerivation
400− liftIO $ runHeadlessApp $ do
402− checkForChanges <- watchDirectoryTree defaultConfig (root <$ pb) (const True)
403− drv <- performEvent $ ffor checkForChanges $ \_ ->
404− liftIO $ runObelisk ob showDerivation
405− drvs <- foldDyn (\new (_, old, _) -> (old, new, old /= new)) (drv0, drv0, False) drv
406− out <- throttleBatchWithLag
407− (\e -> performEvent $ ffor e $ \_ -> liftIO $ runObelisk ob $
408− buildStaticFilesDerivationAndSymlink root >> pure ())
409− (void $ ffilter (^._3) $ updated drvs)
410− performEvent_ $ ffor out $ \_ -> runObelisk ob $
411− putLog Notice "Static assets rebuilt and symlinked to static.out"
414− showDerivation :: MonadObelisk m => m Text
415− showDerivation = readProcessAndLogStderr Debug $
416− setCwd (Just root) $ ProcessSpec
417− { _processSpec_createProcess = Proc.proc nixExePath
420− , "passthru.staticFilesImpure"
422− , _processSpec_overrideEnv = Nothing
425−buildStaticFilesDerivationAndSymlink :: MonadObelisk m => FilePath -> m Text
426−buildStaticFilesDerivationAndSymlink root = readProcessAndLogStderr Debug $
427− setCwd (Just root) $ ProcessSpec
428− { _processSpec_createProcess = Proc.proc
430− [ "-o", "static.out"
431 , "-E", "(import ./. {}).passthru.staticFilesImpure"
352 , "-E", "(import ./. {}).passthru.staticFilesImpure"
433− , _processSpec_overrideEnv = Nothing
354+ else readProcessAndLogStderr Debug $ setCwd (Just root) $
434− }
355+ proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure", "--raw"]