hakyll 4.13.3.0 → 4.13.4.0
raw patch · 14 files changed
+107/−48 lines, 14 filesdep ~cryptonitedep ~directorydep ~file-embedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: cryptonite, directory, file-embed, tasty
API changes (from Hackage documentation)
+ Hakyll.Core.Util.String: removeWinPathSeparator :: String -> String
Files
- CHANGELOG.md +6/−0
- hakyll.cabal +4/−4
- lib/Hakyll/Core/Identifier.hs +3/−8
- lib/Hakyll/Core/Identifier/Pattern.hs +10/−8
- lib/Hakyll/Core/Routes.hs +6/−2
- lib/Hakyll/Core/Util/File.hs +29/−1
- lib/Hakyll/Core/Util/String.hs +7/−0
- lib/Hakyll/Web/Html.hs +8/−4
- tests/Hakyll/Core/Identifier/Tests.hs +16/−16
- tests/Hakyll/Core/Routes/Tests.hs +2/−2
- tests/Hakyll/Core/Rules/Tests.hs +2/−2
- tests/Hakyll/Core/UnixFilter/Tests.hs +8/−0
- tests/Hakyll/Web/Html/Tests.hs +1/−0
- tests/Hakyll/Web/Template/Tests.hs +5/−1
CHANGELOG.md view
@@ -4,6 +4,12 @@ # Releases +## Hakyll 4.13.4.0 (2020-06-20)++- Miscellaneous Windows-specific fixes and CI (by Laurent P. René de Cotret)+- Bump upper bound for `cryptonite` to 0.28+- Bump upper bound for `tasty` to 1.4+ ## Hakyll 4.13.3.0 (2020-04-12) - Fix compilation issue related to `MonadFail` on Windows (by Martín Emanuel)
hakyll.cabal view
@@ -1,5 +1,5 @@ Name: hakyll-Version: 4.13.3.0+Version: 4.13.4.0 Synopsis: A static website compiler library Description:@@ -170,10 +170,10 @@ blaze-markup >= 0.5.1 && < 0.9, bytestring >= 0.9 && < 0.11, containers >= 0.3 && < 0.7,- cryptonite >= 0.25 && < 0.27,+ cryptonite >= 0.25 && < 0.28, data-default >= 0.4 && < 0.8, deepseq >= 1.3 && < 1.5,- directory >= 1.0 && < 1.4,+ directory >= 1.2.7.0 && < 1.4, file-embed >= 0.0.10.1 && < 0.0.12, filepath >= 1.0 && < 1.5, lrucache >= 1.1.1 && < 1.3,@@ -266,7 +266,7 @@ Build-Depends: hakyll, QuickCheck >= 2.8 && < 2.14,- tasty >= 0.11 && < 1.3,+ tasty >= 0.11 && < 1.4, tasty-hunit >= 0.9 && < 0.11, tasty-quickcheck >= 0.8 && < 0.11, -- Copy pasted from hakyll dependencies:
lib/Hakyll/Core/Identifier.hs view
@@ -22,7 +22,7 @@ import Control.DeepSeq (NFData (..)) import Data.List (intercalate) import System.FilePath (dropTrailingPathSeparator, splitPath,- pathSeparator)+ pathSeparator, normalise) --------------------------------------------------------------------------------@@ -64,18 +64,13 @@ -------------------------------------------------------------------------------- -- | Parse an identifier from a string fromFilePath :: FilePath -> Identifier-fromFilePath = Identifier Nothing .- intercalate "/" . filter (not . null) . split'- where- split' = map dropTrailingPathSeparator . splitPath+fromFilePath = Identifier Nothing . normalise -------------------------------------------------------------------------------- -- | Convert an identifier to a relative 'FilePath' toFilePath :: Identifier -> FilePath-toFilePath = intercalate [pathSeparator] . split' . identifierPath- where- split' = map dropTrailingPathSeparator . splitPath+toFilePath = normalise . identifierPath --------------------------------------------------------------------------------
lib/Hakyll/Core/Identifier/Pattern.hs view
@@ -64,6 +64,7 @@ tails) import Data.Maybe (isJust) import qualified Data.Set as S+import System.FilePath (normalise, pathSeparator) --------------------------------------------------------------------------------@@ -74,6 +75,7 @@ -------------------------------------------------------------------------------- import Hakyll.Core.Identifier import Hakyll.Core.Identifier.Pattern.Internal+import Hakyll.Core.Util.String (removeWinPathSeparator) --------------------------------------------------------------------------------@@ -84,14 +86,14 @@ -------------------------------------------------------------------------------- -- | Parse a pattern from a string fromGlob :: String -> Pattern-fromGlob = Glob . parse'+fromGlob = Glob . parse' . normalise where- parse' str =- let (chunk, rest) = break (`elem` "\\*") str+ parse' str = + let (chunk, rest) = break (== '*') str in case rest of- ('\\' : x : xs) -> Literal (chunk ++ [x]) : parse' xs ('*' : '*' : xs) -> Literal chunk : CaptureMany : parse' xs ('*' : xs) -> Literal chunk : Capture : parse' xs+ "" -> Literal chunk : [] xs -> Literal chunk : Literal xs : [] @@ -182,7 +184,7 @@ matches (And x y) i = matches x i && matches y i matches (Glob p) i = isJust $ capture (Glob p) i matches (List l) i = i `S.member` l-matches (Regex r) i = toFilePath i =~ r+matches (Regex r) i = (removeWinPathSeparator $ toFilePath i) =~ r matches (Version v) i = identifierVersion i == v @@ -204,7 +206,7 @@ capture :: Pattern -> Identifier -> Maybe [String] capture (Glob p) i = capture' p (toFilePath i) capture (Regex pat) i = Just groups- where (_, _, _, groups) = ((toFilePath i) =~ pat) :: (String, String, String, [String])+ where (_, _, _, groups) = ((removeWinPathSeparator $ toFilePath i) =~ pat) :: (String, String, String, [String]) capture _ _ = Nothing @@ -218,8 +220,8 @@ | l `isPrefixOf` str = capture' ms $ drop (length l) str | otherwise = Nothing capture' (Capture : ms) str =- -- Match until the next /- let (chunk, rest) = break (== '/') str+ -- Match until the next path separator+ let (chunk, rest) = break (== pathSeparator) str in msum $ [ fmap (i :) (capture' ms (t ++ rest)) | (i, t) <- splits chunk ] capture' (CaptureMany : ms) str = -- Match everything
lib/Hakyll/Core/Routes.hs view
@@ -46,7 +46,7 @@ #if MIN_VERSION_base(4,9,0) import Data.Semigroup (Semigroup (..)) #endif-import System.FilePath (replaceExtension)+import System.FilePath (replaceExtension, normalise) --------------------------------------------------------------------------------@@ -174,7 +174,11 @@ -> (String -> String) -- ^ Replacement -> Routes -- ^ Resulting route gsubRoute pattern replacement = customRoute $- replaceAll pattern replacement . toFilePath+ normalise . replaceAll pattern (replacement . removeWinPathSeparator) . removeWinPathSeparator . toFilePath+ where+ -- Filepaths on Windows containing `\\' will trip Regex matching, which+ -- is used in replaceAll. We normalise filepaths to have '/' as a path separator+ -- using removeWinPathSeparator --------------------------------------------------------------------------------
lib/Hakyll/Core/Util/File.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-} -------------------------------------------------------------------------------- -- | A module containing various file utility functions module Hakyll.Core.Util.File@@ -8,10 +10,12 @@ --------------------------------------------------------------------------------+import Control.Concurrent (threadDelay)+import Control.Exception (SomeException, catch) import Control.Monad (filterM, forM, when) import System.Directory (createDirectoryIfMissing, doesDirectoryExist, getDirectoryContents,- removeDirectoryRecursive)+ removeDirectoryRecursive, removePathForcibly) import System.FilePath (takeDirectory, (</>)) @@ -51,6 +55,30 @@ -------------------------------------------------------------------------------- removeDirectory :: FilePath -> IO ()+#ifndef mingw32_HOST_OS removeDirectory fp = do e <- doesDirectoryExist fp when e $ removeDirectoryRecursive fp+#else+-- Deleting files on Windows is unreliable. If a file/directory is open by a program (e.g. antivirus),+-- then removing related directories *quickly* may fail with strange messages.+-- See here for discussions:+-- https://github.com/haskell/directory/issues/96+-- https://github.com/haskell/win32/pull/129+--+-- The hacky solution is to retry deleting directories a few times, +-- with a delay, on Windows only.+removeDirectory = retryWithDelay 10 . removePathForcibly+#endif+++--------------------------------------------------------------------------------+-- | Retry an operation at most /n/ times (/n/ must be positive).+-- If the operation fails the /n/th time it will throw that final exception.+-- A delay of 100ms is introduced between every retry.+retryWithDelay :: Int -> IO a -> IO a+retryWithDelay i x + | i <= 0 = error "Hakyll.Core.Util.File.retry: retry count must be 1 or more"+ | i == 1 = x+ | otherwise = catch x $ \(_::SomeException) -> threadDelay 100 >> retryWithDelay (i-1) x+
lib/Hakyll/Core/Util/String.hs view
@@ -6,6 +6,7 @@ , replaceAll , splitAll , needlePrefix+ , removeWinPathSeparator ) where @@ -76,3 +77,9 @@ go acc xss@(x:xs) | needle `isPrefixOf` xss = Just $ reverse acc | otherwise = go (x : acc) xs+++--------------------------------------------------------------------------------+-- | Translate native Windows path separators '\\' to '/' if present.+removeWinPathSeparator :: String -> String+removeWinPathSeparator = concatMap (\c -> if c == '\\' then ['/'] else [c])
lib/Hakyll/Web/Html.hs view
@@ -26,7 +26,7 @@ isDigit, toLower) import Data.List (isPrefixOf) import qualified Data.Set as S-import System.FilePath.Posix (joinPath, splitPath,+import System.FilePath (joinPath, splitPath, takeDirectory) import Text.Blaze.Html (toHtml) import Text.Blaze.Html.Renderer.String (renderHtml)@@ -35,6 +35,10 @@ --------------------------------------------------------------------------------+import Hakyll.Core.Util.String (removeWinPathSeparator)+++-------------------------------------------------------------------------------- -- | Map over all tags in the document withTags :: (TS.Tag String -> TS.Tag String) -> String -> String withTags = withTagList . map@@ -116,7 +120,7 @@ -- -- This also sanitizes the URL, e.g. converting spaces into '%20' toUrl :: FilePath -> String-toUrl url = case url of+toUrl url = case (removeWinPathSeparator url) of ('/' : xs) -> '/' : sanitize xs xs -> '/' : sanitize xs where@@ -130,8 +134,8 @@ -------------------------------------------------------------------------------- -- | Get the relative url to the site root, for a given (absolute) url toSiteRoot :: String -> String-toSiteRoot = emptyException . joinPath . map parent- . filter relevant . splitPath . takeDirectory+toSiteRoot = removeWinPathSeparator . emptyException . joinPath + . map parent . filter relevant . splitPath . takeDirectory where parent = const ".." emptyException [] = "."
tests/Hakyll/Core/Identifier/Tests.hs view
@@ -13,6 +13,7 @@ -------------------------------------------------------------------------------- import Hakyll.Core.Identifier import Hakyll.Core.Identifier.Pattern+import System.FilePath ((</>)) import TestSuite.Util @@ -27,22 +28,21 @@ -------------------------------------------------------------------------------- captureTests :: [TestTree] captureTests = fromAssertions "capture"- [ Just ["bar"] @=? capture "foo/**" "foo/bar"- , Just ["foo/bar"] @=? capture "**" "foo/bar"- , Nothing @=? capture "*" "foo/bar"- , Just [] @=? capture "foo" "foo"- , Just ["foo"] @=? capture "*/bar" "foo/bar"- , Just ["foo/bar"] @=? capture "**/qux" "foo/bar/qux"- , Just ["foo/bar", "qux"] @=? capture "**/*" "foo/bar/qux"- , Just ["foo", "bar/qux"] @=? capture "*/**" "foo/bar/qux"- , Just ["foo"] @=? capture "*.html" "foo.html"- , Nothing @=? capture "*.html" "foo/bar.html"- , Just ["foo/bar"] @=? capture "**.html" "foo/bar.html"- , Just ["foo/bar", "wut"] @=? capture "**/qux/*" "foo/bar/qux/wut"- , Just ["lol", "fun/large"] @=? capture "*cat/**.jpg" "lolcat/fun/large.jpg"- , Just [] @=? capture "\\*.jpg" "*.jpg"- , Nothing @=? capture "\\*.jpg" "foo.jpg"- , Just ["xyz","42"] @=? capture (fromRegex "cat-([a-z]+)/foo([0-9]+).jpg") "cat-xyz/foo42.jpg"+ [ Just ["bar"] @=? capture "foo/**" "foo/bar"+ , Just ["foo" </> "bar"] @=? capture "**" "foo/bar"+ , Nothing @=? capture "*" "foo/bar"+ , Just [] @=? capture "foo" "foo"+ , Just ["foo"] @=? capture "*/bar" "foo/bar"+ , Just ["foo" </> "bar"] @=? capture "**/qux" "foo/bar/qux"+ , Just ["foo" </> "bar", "qux"] @=? capture "**/*" "foo/bar/qux"+ , Just ["foo", "bar" </> "qux"] @=? capture "*/**" "foo/bar/qux"+ , Just ["foo"] @=? capture "*.html" "foo.html"+ , Nothing @=? capture "*.html" "foo/bar.html"+ , Just ["foo" </> "bar"] @=? capture "**.html" "foo/bar.html"+ , Just ["foo" </> "bar", "wut"] @=? capture "**/qux/*" "foo/bar/qux/wut"+ , Just ["lol", "fun" </> "large"] @=? capture "*cat/**.jpg" "lolcat/fun/large.jpg"+ , Nothing @=? capture "\\*.jpg" "foo.jpg"+ , Just ["xyz","42"] @=? capture (fromRegex "cat-([a-z]+)/foo([0-9]+).jpg") "cat-xyz/foo42.jpg" ]
tests/Hakyll/Core/Routes/Tests.hs view
@@ -10,7 +10,7 @@ import Hakyll.Core.Identifier import Hakyll.Core.Metadata import Hakyll.Core.Routes-import System.FilePath ((</>))+import System.FilePath ((</>), normalise) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (Assertion, (@=?)) import TestSuite.Util@@ -46,5 +46,5 @@ store <- newTestStore provider <- newTestProvider store (route, _) <- runRoutes r provider id'- Just expected @=? route+ Just (normalise expected) @=? route cleanTestEnv
tests/Hakyll/Core/Rules/Tests.hs view
@@ -17,7 +17,7 @@ import Hakyll.Core.Routes import Hakyll.Core.Rules import Hakyll.Core.Rules.Internal-import System.FilePath ((</>))+import System.FilePath ((</>), normalise) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (Assertion, (@=?)) import TestSuite.Util@@ -39,7 +39,7 @@ let identifiers = S.fromList $ map fst $ rulesCompilers ruleSet routes = rulesRoutes ruleSet checkRoute ex i =- runRoutes routes provider i >>= \(r, _) -> Just ex @=? r+ runRoutes routes provider i >>= \(r, _) -> Just (normalise ex) @=? r -- Test that we have some identifiers and that the routes work out S.fromList expected @=? identifiers
tests/Hakyll/Core/UnixFilter/Tests.hs view
@@ -1,5 +1,6 @@ -------------------------------------------------------------------------------- {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-} module Hakyll.Core.UnixFilter.Tests ( tests ) where@@ -22,10 +23,17 @@ -------------------------------------------------------------------------------- tests :: TestTree tests = testGroup "Hakyll.Core.UnixFilter.Tests"+#ifdef mingw32_HOST_OS+ -- The `rev` utility is not present by default on Windows+ [ testCase "unixFilter false" unixFilterFalse+ , testCase "unixFilter error" unixFilterError+ ]+#else [ testCase "unixFilter rev" unixFilterRev , testCase "unixFilter false" unixFilterFalse , testCase "unixFilter error" unixFilterError ]+#endif testMarkdown :: Identifier testMarkdown = "russian.md"
tests/Hakyll/Web/Html/Tests.hs view
@@ -44,6 +44,7 @@ , fromAssertions "toUrl" [ "/foo/bar.html" @=? toUrl "foo/bar.html"+ , "/foo/bar.html" @=? toUrl "foo\\bar.html" -- Windows-specific , "/" @=? toUrl "/" , "/funny-pics.html" @=? toUrl "/funny-pics.html" , "/funny%20pics.html" @=? toUrl "funny pics.html"
tests/Hakyll/Web/Template/Tests.hs view
@@ -12,6 +12,7 @@ (@=?), (@?=)) import Data.Either (isLeft)+import System.IO (nativeNewline, Newline(..)) -------------------------------------------------------------------------------- import Hakyll.Core.Compiler@@ -149,8 +150,11 @@ str <- testCompilerDone store provider "item3" $ applyTemplate embeddedTemplate defaultContext item - itemBody str @?= "<p>Hello, world</p>\n"+ itemBody str @?= ("<p>Hello, world</p>" ++ (newline nativeNewline)) cleanTestEnv where item = Item "item1" "Hello, world"+ + newline LF = "\n"+ newline CRLF = "\r\n"