@@ -0,0 +1,66 @@
1+-- | A module containing various file utility functions
2+--
3+module Hakyll.Core.Util.File
4+ ( makeDirectories
5+ , getRecursiveContents
6+ , isFileObsolete
7+ ) where
8+
9+import System.FilePath (normalise, takeDirectory, (</>))
10+import System.Time (ClockTime)
11+import Control.Monad (forM)
12+import System.Directory ( createDirectoryIfMissing, doesDirectoryExist
13+ , doesFileExist, getModificationTime
14+ , getDirectoryContents
15+ )
16+
17+-- | Given a path to a file, try to make the path writable by making
18+-- all directories on the path.
19+--
20+makeDirectories :: FilePath -> IO ()
21+makeDirectories = createDirectoryIfMissing True . takeDirectory
22+
23+-- | Get all contents of a directory. Note that files starting with a dot (.)
24+-- will be ignored.
25+--
26+getRecursiveContents :: FilePath -> IO [FilePath]
27+getRecursiveContents topdir = do
28+ topdirExists <- doesDirectoryExist topdir
29+ if topdirExists
30+ then do names <- getDirectoryContents topdir
31+ let properNames = filter isProper names
32+ paths <- forM properNames $ \name -> do
33+ let path = topdir </> name
34+ isDirectory <- doesDirectoryExist path
35+ if isDirectory
36+ then getRecursiveContents path
37+ else return [normalise path]
38+ return (concat paths)
39+ else return []
40+ where
41+ isProper = not . (== ".") . take 1
42+
43+-- | Check if a timestamp is obsolete compared to the timestamps of a number of
44+-- files. When they are no files, it is never obsolete.
45+--
46+isObsolete :: ClockTime -- ^ The time to check.
47+ -> [FilePath] -- ^ Dependencies of the cached file.
48+ -> IO Bool
49+isObsolete _ [] = return False
50+isObsolete timeStamp depends = do
51+ dependsModified <- mapM getModificationTime depends
52+ return (timeStamp < maximum dependsModified)
53+
54+-- | Check if a file is obsolete, given it's dependencies. When the file does
55+-- not exist, it is always obsolete. Other wise, it is obsolete if any of it's
56+-- dependencies has a more recent modification time than the file.
57+--
58+isFileObsolete :: FilePath -- ^ The cached file
59+ -> [FilePath] -- ^ Dependencies of the cached file
60+ -> IO Bool
61+isFileObsolete file depends = do
62+ exists <- doesFileExist file
63+ if not exists
64+ then return True
65+ else do timeStamp <- getModificationTime file
66+ isObsolete timeStamp depends