hakyll 4.16.5.0 → 4.16.6.0
raw patch · 4 files changed
+56/−15 lines, 4 filesdep ~QuickCheckdep ~optparse-applicativedep ~pandocPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: QuickCheck, optparse-applicative, pandoc
API changes (from Hackage documentation)
+ Hakyll.Core.Util.File: withPermissions :: IO a -> a -> IO a
Files
- CHANGELOG.md +12/−0
- hakyll.cabal +2/−2
- lib/Hakyll/Core/Configuration.hs +3/−1
- lib/Hakyll/Core/Util/File.hs +39/−12
CHANGELOG.md view
@@ -4,6 +4,18 @@ # Releases +## Hakyll 4.16.6.0 (2025-02-18)++- Do not crawl directories for which we do not have permissions + with `Hakyll.Core.Util.File.getRecursiveContents`. This used to + throw an exception.+- Do not return broken symbolic links from+ `Hakyll.Core.Util.File.getRecursiveContents`. This used to cause+ subsequent code to throw exceptions (e.g., when it attempts to+ `getModificationTime`) (#1065) (Contribution by Wren Romano).+- Ignore files in `dist-newstyle` and `.stack-work` directories, which+ are Haskell build directories.+ ## Hakyll 4.16.5.0 (2025-01-11) - GHC 9.12 compatibility: bump `template-haskell` upper bound to include 2.23
hakyll.cabal view
@@ -1,5 +1,5 @@ Name: hakyll-Version: 4.16.5.0+Version: 4.16.6.0 Synopsis: A static website compiler library Description:@@ -99,7 +99,7 @@ Source-Repository head Type: git- Location: git://github.com/jaspervdj/hakyll.git+ Location: https://github.com/jaspervdj/hakyll.git Flag previewServer Description: Include the preview server
lib/Hakyll/Core/Configuration.hs view
@@ -135,7 +135,9 @@ -- | Check if a file should be ignored shouldIgnoreFile :: Configuration -> FilePath -> IO Bool shouldIgnoreFile conf path = orM- [ inDir (destinationDirectory conf)+ [ inDir ("dist-newstyle") -- build directory for cabal-install+ , inDir (".stack-work") -- build directory for stack+ , inDir (destinationDirectory conf) , inDir (storeDirectory conf) , inDir (tmpDirectory conf) , return (ignoreFile conf path')
lib/Hakyll/Core/Util/File.hs view
@@ -6,14 +6,17 @@ ( makeDirectories , getRecursiveContents , removeDirectory+ , withPermissions ) where --------------------------------------------------------------------------------+import Control.Exception (throw) import Control.Monad (filterM, forM)-import System.Directory (createDirectoryIfMissing,+import System.Directory (createDirectoryIfMissing, doesPathExist, doesDirectoryExist, getDirectoryContents) import System.FilePath (takeDirectory, (</>))+import System.IO.Error (catchIOError, isPermissionError) #ifndef mingw32_HOST_OS import Control.Monad (when) import System.Directory (removeDirectoryRecursive)@@ -33,29 +36,41 @@ -------------------------------------------------------------------------------- -- | Get all contents of a directory.+--+-- If a directory is encountered for which you do not have+-- permission, the directory will be skipped instead of+-- an exception being thrown.+--+-- If a dangling\/broken symbolic link is encountered, then it will+-- be skipped (since returning it may cause callers to throw exceptions). getRecursiveContents :: (FilePath -> IO Bool) -- ^ Ignore this file/directory -> FilePath -- ^ Directory to search- -> IO [FilePath] -- ^ List of files found+ -> IO [FilePath] -- ^ List of files found for which you have permissions getRecursiveContents ignore top = go "" where isProper x | x `elem` [".", ".."] = return False | otherwise = not <$> ignore x - go dir = do- dirExists <- doesDirectoryExist (top </> dir)+ getProperDirectoryContents absDir =+ filterM isProper =<< withPermissions (getDirectoryContents absDir) []++ go relDir = do+ let absDir = top </> relDir+ dirExists <- doesDirectoryExist absDir if not dirExists then return [] else do- names <- filterM isProper =<< getDirectoryContents (top </> dir)- paths <- forM names $ \name -> do- let rel = dir </> name- isDirectory <- doesDirectoryExist (top </> rel)+ names <- getProperDirectoryContents absDir+ fmap concat . forM names $ \name -> do+ let relPath = relDir </> name+ absPath = top </> relPath+ isDirectory <- doesDirectoryExist absPath if isDirectory- then go rel- else return [rel]-- return $ concat paths+ then go relPath+ else do+ pathExists <- doesPathExist absPath+ return $ if pathExists then [relPath] else [] --------------------------------------------------------------------------------@@ -85,3 +100,15 @@ | i == 1 = x | otherwise = catch x $ \(_::SomeException) -> threadDelay 100 >> retryWithDelay (i-1) x #endif++--------------------------------------------------------------------------------+-- | Perform an IO action, catching any permission errors and returning+-- a default value in their place. All other exceptions are rethrown.+withPermissions :: IO a+ -> a -- ^ Default value to return in case of a permission error+ -> IO a+withPermissions act onError+ = act `catchIOError` \e ->+ if isPermissionError e+ then pure onError+ else throw e