hakyll 4.16.2.0 → 4.16.2.1
raw patch · 8 files changed
+156/−66 lines, 8 filesdep ~QuickCheckdep ~containersdep ~pandocPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: QuickCheck, containers, pandoc, time
API changes (from Hackage documentation)
- Hakyll.Core.Writable: instance Hakyll.Core.Writable.Writable Data.ByteString.Internal.ByteString
+ Hakyll.Core.Writable: instance Hakyll.Core.Writable.Writable Data.ByteString.Internal.Type.ByteString
Files
- CHANGELOG.md +22/−0
- hakyll.cabal +23/−20
- lib/Hakyll/Check.hs +3/−1
- lib/Hakyll/Commands.hs +22/−16
- lib/Hakyll/Core/Routes.hs +10/−9
- lib/Hakyll/Core/Runtime.hs +28/−14
- lib/Hakyll/Web/Template/Context.hs +20/−5
- tests/Hakyll/Core/Runtime/Tests.hs +28/−1
CHANGELOG.md view
@@ -4,6 +4,28 @@ # Releases +## Hakyll 4.16.2.1 (2024-06-02)++- Fix "thread blocked indefinitely in an MVar operation" errors caused by+ exceptions produced by `Items` (#1014) (contribution by Jasper Van der Jeugt)+- Improve `+watchServer` and `+previewServer` error messages: they now explain+ *how* to enable the flag when the user tries to run `watch`/`preview`+ without them (#1022) (contribution by Jasper Van der Jeugt)+- Assorted fixes and improvements to documentation (contributions by Alexander+ Batischev, Adrien, Tanya Bouman)+- Bump `bytestring` upper bound to 0.13 (contribution by Alexander Batischev)+- Bump `deepseq` upper bound to 1.6 (contribution by Laurent P. René de Cotret)+- Bump `template-haskell` upper bound to 2.22 (contribution by Laurent P. René+ de Cotret)+- Bump `text` upper bound to 2.2 (contribution by Laurent P. René de Cotret)+- Bump `file-embed` upper bound to 0.0.17 (contribution by Alexander Batischev)+- Bump `warp` upper bound to 3.5 (contribution by Alexander Batischev)+- Bump `filepath` upper bound to 1.6 (contribution by Alexander Batischev)+- Bump `containers` upper bound to 0.8 (contribution by Andreas Abel)+- Bump `time` upper bound to 1.15 (contribution by Andreas Abel)+- Bump `QuickCheck` upper bound to 2.16 (contribution by Andreas Abel)+- Bump `pandoc` upper bound to 3.3 (contribution by Alexander Batischev)+ ## Hakyll 4.16.2.0 (2023-09-20) - Add errors for multiple `match`es that are routed to the same file
hakyll.cabal view
@@ -1,5 +1,5 @@ Name: hakyll-Version: 4.16.2.0+Version: 4.16.2.1 Synopsis: A static website compiler library Description:@@ -104,14 +104,17 @@ Flag previewServer Description: Include the preview server Default: True+ Manual: True Flag watchServer Description: Include the watch server Default: True+ Manual: True Flag checkExternal Description: Include external link checking Default: True+ Manual: True Flag buildWebsite Description: Build the hakyll website@@ -188,13 +191,13 @@ binary >= 0.5 && < 0.10, blaze-html >= 0.5 && < 0.10, blaze-markup >= 0.5.1 && < 0.9,- bytestring >= 0.9 && < 0.12,- containers >= 0.3 && < 0.7,+ bytestring >= 0.9 && < 0.13,+ containers >= 0.3 && < 0.8, data-default >= 0.4 && < 0.8,- deepseq >= 1.3 && < 1.5,+ deepseq >= 1.3 && < 1.6, directory >= 1.2.7.0 && < 1.4,- file-embed >= 0.0.10.1 && < 0.0.16,- filepath >= 1.0 && < 1.5,+ file-embed >= 0.0.10.1 && < 0.0.17,+ filepath >= 1.0 && < 1.6, hashable >= 1.0 && < 2, lrucache >= 1.1.1 && < 1.3, mtl >= 1 && < 2.4,@@ -207,9 +210,9 @@ resourcet >= 1.1 && < 1.4, scientific >= 0.3.4 && < 0.4, tagsoup >= 0.13.1 && < 0.15,- template-haskell >= 2.14 && < 2.21,- text >= 0.11 && < 1.3 || >= 2.0 && < 2.1,- time >= 1.8 && < 1.13,+ template-haskell >= 2.14 && < 2.22,+ text >= 0.11 && < 1.3 || >= 2.0 && < 2.2,+ time >= 1.8 && < 1.15, time-locale-compat >= 0.1 && < 0.2, unordered-containers >= 0.2 && < 0.3, vector >= 0.11 && < 0.14,@@ -219,7 +222,7 @@ If flag(previewServer) Build-depends: wai >= 3.2 && < 3.3,- warp >= 3.2 && < 3.4,+ warp >= 3.2 && < 3.5, http-types >= 0.9 && < 0.13, fsnotify >= 0.2 && < 0.5 Cpp-options:@@ -251,7 +254,7 @@ Other-Modules: Hakyll.Web.Pandoc.Binary Build-Depends:- pandoc >= 2.11 && < 2.20 || >= 3.0 && < 3.2+ pandoc >= 2.11 && < 2.20 || >= 3.0 && < 3.3 Cpp-options: -DUSE_PANDOC @@ -283,7 +286,7 @@ Build-Depends: hakyll,- QuickCheck >= 2.8 && < 2.15,+ QuickCheck >= 2.8 && < 2.16, tasty >= 0.11 && < 1.6, tasty-golden >= 2.3 && < 2.4, tasty-hunit >= 0.9 && < 0.11,@@ -291,11 +294,11 @@ -- Copy pasted from hakyll dependencies: aeson >= 1.0 && < 1.6 || >= 2.0 && < 2.3, base >= 4.12 && < 5,- bytestring >= 0.9 && < 0.12,- containers >= 0.3 && < 0.7,- filepath >= 1.0 && < 1.5,+ bytestring >= 0.9 && < 0.13,+ containers >= 0.3 && < 0.8,+ filepath >= 1.0 && < 1.6, tagsoup >= 0.13.1 && < 0.15,- text >= 0.11 && < 1.3 || >= 2.0 && < 2.1,+ text >= 0.11 && < 1.3 || >= 2.0 && < 2.2, unordered-containers >= 0.2 && < 0.3, yaml >= 0.8.11 && < 0.12 @@ -318,7 +321,7 @@ Cpp-options: -DUSE_PANDOC Build-Depends:- pandoc >= 2.11 && < 2.20 || >= 3.0 && < 3.2+ pandoc >= 2.11 && < 2.20 || >= 3.0 && < 3.3 Executable hakyll-init@@ -334,7 +337,7 @@ hakyll, base >= 4.12 && < 5, directory >= 1.0 && < 1.4,- filepath >= 1.0 && < 1.5+ filepath >= 1.0 && < 1.6 Executable hakyll-website Main-is: site.hs@@ -351,5 +354,5 @@ hakyll, base >= 4.12 && < 5, directory >= 1.0 && < 1.4,- filepath >= 1.0 && < 1.5,- pandoc >= 2.11 && < 2.20 || >= 3.0 && < 3.2+ filepath >= 1.0 && < 1.6,+ pandoc >= 2.11 && < 2.20 || >= 3.0 && < 3.3
lib/Hakyll/Check.hs view
@@ -248,7 +248,9 @@ -- Convert exception to a concise form showException e = case cast e of Just (Http.HttpExceptionRequest _ e') -> show e'- _ -> head $ words $ show e+ _ -> case words $ show e of+ w:_ -> w+ [] -> error "Hakyll.Check.checkExternalUrl: impossible" requestExternalUrl :: URL -> Checker (Either SomeException Bool) requestExternalUrl url = liftIO $ try $ do
lib/Hakyll/Commands.hs view
@@ -141,24 +141,30 @@ -- | Print a warning message about the preview serving not being enabled #ifndef PREVIEW_SERVER previewServerDisabled :: IO ()-previewServerDisabled =- mapM_ putStrLn- [ "PREVIEW SERVER"- , ""- , "The preview server is not enabled in the version of Hakyll. To"- , "enable it, set the flag to True and recompile Hakyll."- , "Alternatively, use an external tool to serve your site directory."- ]+previewServerDisabled = mapM_ putStrLn+ [ "PREVIEW SERVER"+ , ""+ , "The preview server is not enabled in this version of Hakyll. To enable"+ , "it, toggle the cabal configuration flag to True, for example by adding"+ , "the following to your `cabal.project` file:"+ , ""+ , " constraints: hakyll +previewServer"+ , ""+ , "Alternatively, use an external tool to serve your site directory."+ ] #endif #ifndef WATCH_SERVER watchServerDisabled :: IO ()-watchServerDisabled =- mapM_ putStrLn- [ "WATCH SERVER"- , ""- , "The watch server is not enabled in the version of Hakyll. To"- , "enable it, set the flag to True and recompile Hakyll."- , "Alternatively, use an external tool to serve your site directory."- ]+watchServerDisabled = mapM_ putStrLn+ [ "WATCH SERVER"+ , ""+ , "The watch server is not enabled in this version of Hakyll. To enable"+ , "it, toggle the cabal configuration flag to True, for example by adding"+ , "the following to your `cabal.project` file:"+ , ""+ , " constraints: hakyll +watchServer"+ , ""+ , "Alternatively, use an external tool to serve your site directory."+ ] #endif
lib/Hakyll/Core/Routes.hs view
@@ -5,8 +5,8 @@ (relative to the destination directory as configured in 'Hakyll.Core.Configuration.destinationDirectory'). -* __If there is no route for an item, the compiled item won't be written-out to a file__ and so won't appear in the destination (site) directory.+* __If there is no route for an item, the compiled item won't be written__+__out to a file__ and so won't appear in the destination (site) directory. * If an item matches multiple routes, the first route will be chosen. @@ -32,8 +32,9 @@ That will route the file @posts\/hakyll.md@ from the project directory to @posts\/hakyll.md@ in the destination directory. -Note: __The extension of the destination filepath says nothing about the-content!__ If you set the extension to @.html@, you have to ensure that the+Note:+__The extension of the destination filepath says nothing about the content!__+If you set the extension to @.html@, you have to ensure that the compilation result is indeed HTML (for example with the 'Hakyll.Web.Pandoc.pandocCompiler' to transform Markdown to HTML). @@ -205,9 +206,9 @@ -------------------------------------------------------------------------------- {- | Create a route that writes the compiled item to the given destination filepath (ignoring any identifier or other data about the item being processed).-Warning: you should __use a specific destination path only for a single file in-a single compilation rule__. Otherwise it's unclear which of the contents should-be written to that route.+Warning: you should __use a specific destination path only for a single file in__+__a single compilation rule__. Otherwise it's unclear which of the contents+should be written to that route. === __Examples__ __Route to a specific filepath__@@ -278,8 +279,8 @@ {- | Wrapper function around other route construction functions to get access to the metadata (of the underlying item being processed) and use that for the destination filepath construction.-Warning: you have to __ensure that the accessed metadata fields actually-exists__.+Warning: you have to+__ensure that the accessed metadata fields actually exist__. === __Examples__ __Route that uses a custom slug markdown metadata field__
lib/Hakyll/Core/Runtime.hs view
@@ -10,7 +10,8 @@ import Control.Concurrent (forkIO, getNumCapabilities, rtsSupportsBoundThreads) import qualified Control.Concurrent.MVar as MVar-import Control.Monad (replicateM_, unless, void)+import Control.Exception (SomeException, try)+import Control.Monad (replicateM_, unless, void, when) import Control.Monad.Reader (ReaderT, ask, runReaderT) import Control.Monad.Trans (liftIO) import Data.Foldable (for_, traverse_)@@ -377,7 +378,8 @@ RunModeNormal -> do Logger.header logger "Compiling" if rtsSupportsBoundThreads then pickAndChaseAsync else pickAndChase- Logger.header logger "Success"+ errs <- liftIO $ schedulerErrors <$> IORef.readIORef schedulerRef+ when (null errs) $ Logger.header logger "Success" facts <- liftIO $ schedulerFacts <$> IORef.readIORef schedulerRef store <- runtimeStore <$> ask liftIO $ Store.set store factsKey facts@@ -496,21 +498,33 @@ "an Item with Identifier " ++ show id' ++ " " ++ "(you probably want to call makeItem to solve this problem)" - -- Write if necessary- (mroute, _) <- liftIO $ runRoutes routes provider id'- case mroute of- Nothing -> return ()- Just route -> do- liftIO . IORef.atomicModifyIORef' scheduler $+ -- Write if necessary. Note that we want another exception handler+ -- around this: some compilers may successfully produce a+ -- 'CompilerResult', but the thing they are supposed to 'write' can+ -- have an un-evaluated 'error' them.+ routeOrErr <- liftIO $ try $ do+ (mroute, _) <- runRoutes routes provider id'+ for_ mroute $ \route -> do+ IORef.atomicModifyIORef' scheduler $ schedulerRoute id' route let path = destinationDirectory config </> route- liftIO $ makeDirectories path- liftIO $ write path item- Logger.debug logger $ "Routed to " ++ path+ makeDirectories path+ write path item+ save store item+ pure mroute - liftIO $ save store item- liftIO . IORef.atomicModifyIORef' scheduler $- schedulerWrite id' facts+ case routeOrErr of+ Left e -> do+ liftIO $ IORef.atomicModifyIORef' scheduler $+ schedulerError (Just id') $+ "An exception was thrown when persisting " +++ "the compiler result: " ++ show (e :: SomeException)+ pure SchedulerError+ Right mroute -> do+ for_ mroute $ \route ->+ Logger.debug logger $ "Routed to " ++ show route+ liftIO . IORef.atomicModifyIORef' scheduler $+ schedulerWrite id' facts CompilerRequire reqs c -> liftIO . IORef.atomicModifyIORef' scheduler $
lib/Hakyll/Web/Template/Context.hs view
@@ -247,7 +247,7 @@ -------------------------------------------------------------------------------- -- | A context that contains (in that order) ----- 1. A @$body$@ field+-- 1. A @$body$@ 'bodyField' -- -- 2. Metadata fields --@@ -256,6 +256,17 @@ -- 4. A @$path$@ 'pathField' -- -- 5. A @$title$@ 'titleField'+--+-- This order means that all of the fields, except @$body$@,+-- can have their values replaced by metadata fields of the same name.+-- For example, a context from a file at @posts/foo.markdown@ has a default title+-- @foo@. However, with a metadata field:+--+-- > ---+-- > title: The Foo Story+-- > ---+--+-- The @$title$@ will be replaced with @The Foo Story@. defaultContext :: Context String defaultContext = bodyField "body" `mappend`@@ -271,7 +282,7 @@ ----------------------------------------------------------------------------------- | Constructs a 'field' that contains the body of the item.+-- | Body of the item, that is, the main content of the underlying file bodyField :: String -> Context String bodyField key = field key $ return . itemBody @@ -288,7 +299,8 @@ ----------------------------------------------------------------------------------- | Absolute url to the resulting item+-- | Absolute url to the resulting item. For an example item that produces a+-- file @posts/foo.html@, this field contains "posts/foo.html" urlField :: String -> Context a urlField key = field key $ \i -> do let id = itemIdentifier i@@ -297,13 +309,16 @@ ----------------------------------------------------------------------------------- | Filepath of the underlying file of the item+-- | Filepath of the underlying file of the item. For an example+-- underlying file @posts/foo.markdown@, this field contains+-- "posts/foo.markdown" pathField :: String -> Context a pathField key = field key $ return . toFilePath . itemIdentifier ----------------------------------------------------------------------------------- | This title 'field' takes the basename of the underlying file by default+-- | Basename of the underlying file of the item. For an example+-- underlying file @posts/foo.markdown@, this field contains "foo" titleField :: String -> Context a titleField = mapContext takeBaseName . pathField
tests/Hakyll/Core/Runtime/Tests.hs view
@@ -32,6 +32,7 @@ , case05 , case06 , issue1000+ , issue1014 ] @@ -77,7 +78,7 @@ lines example @?= ["<p>This is an example.</p>"] bodies <- readFile $ destinationDirectory testConfiguration </> "bodies.txt"- head (lines bodies) @?= "This is an example."+ head' (lines bodies) @?= "This is an example." partial <- readFile $ providerDirectory testConfiguration </> "partial.html.out" partial' <- readFile $ destinationDirectory testConfiguration </> "partial.html.out"@@ -85,7 +86,11 @@ cleanTestEnv + where+ head' (x:_) = x+ head' [] = error "Hakyll.Core.Runtime.Tests.case01: impossible" + -------------------------------------------------------------------------------- case02 :: Assertion case02 = do@@ -260,4 +265,26 @@ | (Logger.Error, msg) <- msgs, "multiple writes" `isInfixOf` msg ] + cleanTestEnv+++--------------------------------------------------------------------------------+issue1014 :: Assertion+issue1014 = do+ (logger, inMemLog) <- Logger.newInMem+ (ec, _) <- run RunModeNormal testConfiguration logger $ do+ match "*.md" $ do+ route $ setExtension "html"+ -- This compiler will succeed due to laziness, but writing the+ -- result will throw an exception.+ compile $ makeItem ("hello" ++ error "lazyworld")++ ec @?= ExitFailure 1+ msgs <- inMemLog+ assertBool "missing 'lazyworld' error" $ not $ null $+ [ msg+ | (Logger.Error, msg) <- msgs, "lazyworld" `isInfixOf` msg+ ]+ assertBool "unwanted 'Success' message" $ not $+ (Logger.Message, "Success") `elem` msgs cleanTestEnv