on master help sign in
Add prototype inotify backend
commitc03607e08751c3ce0e7c4cb70f9168f7f0237663 authorJasper Van der Jeugt <jaspervdj@gmail.com> dateThu 10 Feb 2011, 20:05 (16 years ago) parent77f37c1
3 files changed+74−5
src/Hakyll/Core/Run.hs−3 src/Hakyll/Main.hs+14−2 src/Hakyll/Web/Preview/INotify.hs+60
src/Hakyll/Core/Run.hs−3
@@ -25,7 +25,6 @@ import Hakyll.Core.ResourceProvider
2525import Hakyll.Core.ResourceProvider.FileResourceProvider
2626import Hakyll.Core.Rules
2727import Hakyll.Core.DirectedGraph
28−import Hakyll.Core.DirectedGraph.Dot
2928import Hakyll.Core.DirectedGraph.DependencySolver
3029import Hakyll.Core.Writable
3130import Hakyll.Core.Store
@@ -114,8 +113,6 @@ addNewCompilers oldCompilers newCompilers = Runtime $ do
114113 -- complete graph
115114 completeGraph <- mappend currentGraph . hakyllGraph <$> get
116115
117− liftIO $ writeDot "dependencies.dot" show completeGraph
118−
119116 -- Check which items are up-to-date. This only needs to happen for the new
120117 -- compilers
121118 oldModified <- hakyllModified <$> get
src/Hakyll/Main.hs+14−2
@@ -5,6 +5,7 @@ module Hakyll.Main
55 , hakyllWith
66 ) where
77
8+import Control.Concurrent (forkIO)
89import Control.Monad (when)
910import System.Environment (getProgName, getArgs)
1011import System.Directory (doesDirectoryExist, removeDirectoryRecursive)
@@ -12,6 +13,7 @@ import System.Directory (doesDirectoryExist, removeDirectoryRecursive)
1213import Hakyll.Core.Configuration
1314import Hakyll.Core.Run
1415import Hakyll.Core.Rules
16+import Hakyll.Web.Preview.INotify
1517import Hakyll.Web.Preview.Server
1618
1719-- | This usualy is the function with which the user runs the hakyll compiler
@@ -29,8 +31,8 @@ hakyllWith configuration rules = do
2931 ["build"] -> build configuration rules
3032 ["clean"] -> clean configuration
3133 ["help"] -> help
32− ["preview"] -> putStrLn "Not implemented"
33− ["preview", p] -> putStrLn "Not implemented"
34+ ["preview"] -> preview configuration rules 8000
35+ ["preview", p] -> preview configuration rules (read p)
3436 ["rebuild"] -> rebuild configuration rules
3537 ["server"] -> server configuration 8000
3638 ["server", p] -> server configuration (read p)
@@ -74,6 +76,16 @@ help = do
7476 , name ++ " server [port] Run a local test server"
7577 ]
7678
79+-- | Preview the site
80+--
81+preview :: HakyllConfiguration -> Rules -> Int -> IO ()
82+preview configuration rules port = do
83+ -- Fork a thread polling for changes
84+ _ <- forkIO $ previewPoll configuration "." $ build configuration rules
85+
86+ -- Run the server in the main thread
87+ server configuration port
88+
7789-- | Rebuild the site
7890--
7991rebuild :: HakyllConfiguration -> Rules -> IO ()
src/Hakyll/Web/Preview/INotify.hsnew file+60
@@ -0,0 +1,60 @@
1+-- | Filesystem polling with an inotify backend. Works only on linux.
2+--
3+module Hakyll.Web.Preview.INotify
4+ ( previewPoll
5+ ) where
6+
7+import Control.Monad (forM_, when, unless)
8+import System.Directory (doesDirectoryExist)
9+import System.FilePath ((</>))
10+import Data.List (isPrefixOf)
11+
12+import System.INotify
13+
14+import Hakyll.Core.Util.File
15+import Hakyll.Core.Configuration
16+
17+-- | Calls the given callback when the directory tree changes
18+--
19+previewPoll :: HakyllConfiguration -- ^ Configuration
20+ -> FilePath -- ^ Root directory
21+ -> IO () -- ^ Action called when something changes
22+ -> IO () -- ^ Can block forever
23+previewPoll conf directory callback = do
24+ -- Initialize inotify
25+ inotify <- initINotify
26+
27+ -- Start by watching all directories
28+ contents <- getRecursiveContents True directory
29+ forM_ contents $ \file -> do
30+ isDir <- doesDirectoryExist file
31+ when isDir $ watchDirectory conf inotify file callback
32+
33+-- | Start watching a directory recursively: when another directory is created
34+-- inside this directory, start watching that one as well...
35+--
36+watchDirectory :: HakyllConfiguration -- ^ Configuration
37+ -> INotify -- ^ INotify handle
38+ -> FilePath -- ^ Directory to watch
39+ -> IO () -- ^ Callback
40+ -> IO () -- ^ No result
41+watchDirectory conf inotify path callback =
42+ unless (isFileInternal conf path) $ do
43+ _ <- addWatch inotify interesting path $ \event -> do
44+ putStrLn $ "Triggered: " ++ show event
45+ callback' inotify path event
46+ return ()
47+ where
48+ callback' i p (Created True n) = watchDirectory conf i (p </> n) callback
49+ callback' _ _ (Created _ p) = whenProper $ Just p
50+ callback' _ _ (Modified _ p) = whenProper p
51+ callback' _ _ (MovedOut _ p _) = whenProper $ Just p
52+ callback' _ _ (MovedIn _ p _) = whenProper $ Just p
53+ callback' _ _ (Deleted _ p) = whenProper $ Just p
54+ callback' _ _ _ = return ()
55+
56+ interesting = [Modify, Create, Move, Delete]
57+
58+ -- Call the callback only for proper files
59+ whenProper Nothing = return ()
60+ whenProper (Just f) = unless ("." `isPrefixOf` f) callback