module System.FileSystem.IO
( takeFile
, captureDir
, capture
, releaseEnd
, release
, releaseHere
)
where
import Control.Applicative (pure, liftA2)
import System.FilePath (splitPath, dropFileName, takeFileName, combine
,pathSeparator, makeRelative)
import Data.ByteString (writeFile,readFile)
import System.Directory (getModificationTime, getDirectoryContents
, doesFileExist, doesDirectoryExist
, createDirectoryIfMissing)
import Data.Maybe (catMaybes)
import Data.Monoid (mconcat)
import Control.Arrow ( (&&&) , (|||) , (>>>) )
import Data.List (isSuffixOf)
import Data.ByteString (ByteString)
import System.FileSystem.Types
import System.FileSystem.Utils
import System.FileSystem.Operators
import System.FileSystem.Instances
import System.FileSystem.Across
takeFile :: FilePath -> IO File
takeFile = comb File (comb FD Data.ByteString.readFile
getModificationTime) $
pure . takeFileName
takePath :: AbsPath -> FilePath -> IO Path
takePath afp = comb Path (pure . splitPath . dropFileName . makeRelative afp) $
fmap Just . takeFile
getDirContents :: FilePath -> IO [FilePath]
getDirContents = uncurry (liftA2 $ fmap . combine) . (pure &&& getDirectoryContents)
doesDirectoryExist' :: FilePath -> IO Bool
doesDirectoryExist' = let suffs = uncurry (||) . (isSuffixOf (pathSeparator : "." )
&&& isSuffixOf (pathSeparator : ".."))
in uncurry (liftA2 (&&))
. ( doesDirectoryExist &&& pure . not . suffs )
type AbsPath = FilePath
capturePaths :: AbsPath -> FilePath -> IO [Path]
capturePaths afp =
fmap (mconcat . catMaybes)
. bind (mapM $ options [ ( doesFileExist , fmap pure . takePath afp )
, ( doesDirectoryExist' , capturePaths afp )
]
)
. getDirContents
captureDir :: FilePath -> IO FileSystem
captureDir = fmap buildFileSystem . ( capturePaths $$ )
capture :: IO FileSystem
capture = captureDir "."
writeFileIfMissing :: Bool -> FilePath -> ByteString -> IO ()
writeFileIfMissing b fp cnt =
do let dir = dropFileName fp
createDirectoryIfMissing b dir
Data.ByteString.writeFile fp cnt
releaseEnd :: FilePath -> IO a -> FileSystem -> IO a
releaseEnd fp0 =
foldFileSystem fp0 (Left $
\fp -> let f = createDirectoryIfMissing True . combine fp
||| uncurry (writeFileIfMissing True) . (combine fp . getFN &&& getCnt . getFD)
in (>>>) f . flip (>>)
)
release :: FilePath -> FileSystem -> IO ()
release = ($ return ()) . releaseEnd
releaseHere :: FileSystem -> IO ()
releaseHere = release "."