{-# LANGUAGE CPP #-}
#if !MIN_VERSION_base(4, 8, 0)
{-# LANGUAGE Trustworthy #-}
#endif
module System.Directory
(
createDirectory
, createDirectoryIfMissing
, removeDirectory
, removeDirectoryRecursive
, removePathForcibly
, renameDirectory
, listDirectory
, getDirectoryContents
, getCurrentDirectory
, setCurrentDirectory
, withCurrentDirectory
, getHomeDirectory
, XdgDirectory(..)
, getXdgDirectory
, XdgDirectoryList(..)
, getXdgDirectoryList
, getAppUserDataDirectory
, getUserDocumentsDirectory
, getTemporaryDirectory
, removeFile
, renameFile
, renamePath
, copyFile
, copyFileWithMetadata
, getFileSize
, canonicalizePath
, makeAbsolute
, makeRelativeToCurrentDirectory
, doesPathExist
, doesFileExist
, doesDirectoryExist
, findExecutable
, findExecutables
, findExecutablesInDirectories
, findFile
, findFiles
, findFileWith
, findFilesWith
, exeExtension
, createFileLink
, createDirectoryLink
, removeDirectoryLink
, pathIsSymbolicLink
, getSymbolicLinkTarget
, Permissions
, emptyPermissions
, readable
, writable
, executable
, searchable
, setOwnerReadable
, setOwnerWritable
, setOwnerExecutable
, setOwnerSearchable
, getPermissions
, setPermissions
, copyPermissions
, getAccessTime
, getModificationTime
, setAccessTime
, setModificationTime
, isSymbolicLink
) where
import Prelude ()
import System.Directory.Internal
import System.Directory.Internal.Prelude
import System.FilePath
( (<.>)
, (</>)
, addTrailingPathSeparator
, dropTrailingPathSeparator
, hasTrailingPathSeparator
, isAbsolute
, joinPath
, makeRelative
, splitDirectories
, splitSearchPath
, takeDirectory
)
import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
emptyPermissions :: Permissions
emptyPermissions :: Permissions
emptyPermissions = Permissions :: Bool -> Bool -> Bool -> Bool -> Permissions
Permissions {
readable :: Bool
readable = Bool
False,
writable :: Bool
writable = Bool
False,
executable :: Bool
executable = Bool
False,
searchable :: Bool
searchable = Bool
False
}
setOwnerReadable :: Bool -> Permissions -> Permissions
setOwnerReadable :: Bool -> Permissions -> Permissions
setOwnerReadable b :: Bool
b p :: Permissions
p = Permissions
p { readable :: Bool
readable = Bool
b }
setOwnerWritable :: Bool -> Permissions -> Permissions
setOwnerWritable :: Bool -> Permissions -> Permissions
setOwnerWritable b :: Bool
b p :: Permissions
p = Permissions
p { writable :: Bool
writable = Bool
b }
setOwnerExecutable :: Bool -> Permissions -> Permissions
setOwnerExecutable :: Bool -> Permissions -> Permissions
setOwnerExecutable b :: Bool
b p :: Permissions
p = Permissions
p { executable :: Bool
executable = Bool
b }
setOwnerSearchable :: Bool -> Permissions -> Permissions
setOwnerSearchable :: Bool -> Permissions -> Permissions
setOwnerSearchable b :: Bool
b p :: Permissions
p = Permissions
p { searchable :: Bool
searchable = Bool
b }
getPermissions :: FilePath -> IO Permissions
getPermissions :: FilePath -> IO Permissions
getPermissions path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getPermissions") (IOError -> IOError) -> IO Permissions -> IO Permissions
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> IO Permissions
getAccessPermissions (FilePath -> FilePath
emptyToCurDir FilePath
path)
setPermissions :: FilePath -> Permissions -> IO ()
setPermissions :: FilePath -> Permissions -> IO ()
setPermissions path :: FilePath
path p :: Permissions
p =
(IOError -> FilePath -> IOError
`ioeAddLocation` "setPermissions") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> Permissions -> IO ()
setAccessPermissions (FilePath -> FilePath
emptyToCurDir FilePath
path) Permissions
p
copyPermissions :: FilePath -> FilePath -> IO ()
copyPermissions :: FilePath -> FilePath -> IO ()
copyPermissions src :: FilePath
src dst :: FilePath
dst =
(IOError -> FilePath -> IOError
`ioeAddLocation` "copyPermissions") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Metadata
m <- FilePath -> IO Metadata
getFileMetadata FilePath
src
Metadata -> FilePath -> IO ()
copyPermissionsFromMetadata Metadata
m FilePath
dst
copyPermissionsFromMetadata :: Metadata -> FilePath -> IO ()
copyPermissionsFromMetadata :: Metadata -> FilePath -> IO ()
copyPermissionsFromMetadata m :: Metadata
m dst :: FilePath
dst = do
FilePath -> Mode -> IO ()
setFilePermissions FilePath
dst (Metadata -> Mode
modeFromMetadata Metadata
m)
createDirectory :: FilePath -> IO ()
createDirectory :: FilePath -> IO ()
createDirectory = FilePath -> IO ()
createDirectoryInternal
createDirectoryIfMissing :: Bool
-> FilePath
-> IO ()
createDirectoryIfMissing :: Bool -> FilePath -> IO ()
createDirectoryIfMissing create_parents :: Bool
create_parents path0 :: FilePath
path0
| Bool
create_parents = [FilePath] -> IO ()
createDirs (FilePath -> [FilePath]
parents FilePath
path0)
| Bool
otherwise = [FilePath] -> IO ()
createDirs (Int -> [FilePath] -> [FilePath]
forall a. Int -> [a] -> [a]
take 1 (FilePath -> [FilePath]
parents FilePath
path0))
where
parents :: FilePath -> [FilePath]
parents = [FilePath] -> [FilePath]
forall a. [a] -> [a]
reverse ([FilePath] -> [FilePath])
-> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a. (a -> a -> a) -> [a] -> [a]
scanl1 FilePath -> FilePath -> FilePath
(</>) ([FilePath] -> [FilePath])
-> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
splitDirectories (FilePath -> [FilePath])
-> (FilePath -> FilePath) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
simplify
createDirs :: [FilePath] -> IO ()
createDirs [] = () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
createDirs (dir :: FilePath
dir:[]) = FilePath -> (IOError -> IO ()) -> IO ()
createDir FilePath
dir IOError -> IO ()
forall a. IOError -> IO a
ioError
createDirs (dir :: FilePath
dir:dirs :: [FilePath]
dirs) =
FilePath -> (IOError -> IO ()) -> IO ()
createDir FilePath
dir ((IOError -> IO ()) -> IO ()) -> (IOError -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \_ -> do
[FilePath] -> IO ()
createDirs [FilePath]
dirs
FilePath -> (IOError -> IO ()) -> IO ()
createDir FilePath
dir IOError -> IO ()
forall a. IOError -> IO a
ioError
createDir :: FilePath -> (IOError -> IO ()) -> IO ()
createDir dir :: FilePath
dir notExistHandler :: IOError -> IO ()
notExistHandler = do
Either IOError ()
r <- IO () -> IO (Either IOError ())
forall a. IO a -> IO (Either IOError a)
tryIOError (FilePath -> IO ()
createDirectory FilePath
dir)
case Either IOError ()
r of
Right () -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Left e :: IOError
e
| IOError -> Bool
isDoesNotExistError IOError
e -> IOError -> IO ()
notExistHandler IOError
e
| IOError -> Bool
isAlreadyExistsError IOError
e
Bool -> Bool -> Bool
|| IOError -> Bool
isPermissionError IOError
e -> do
Bool
canIgnore <- FilePath -> IO Bool
pathIsDirectory FilePath
dir
IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ _ ->
Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (IOError -> Bool
isAlreadyExistsError IOError
e)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
canIgnore (IOError -> IO ()
forall a. IOError -> IO a
ioError IOError
e)
| Bool
otherwise -> IOError -> IO ()
forall a. IOError -> IO a
ioError IOError
e
removeDirectory :: FilePath -> IO ()
removeDirectory :: FilePath -> IO ()
removeDirectory = Bool -> FilePath -> IO ()
removePathInternal Bool
True
removeDirectoryRecursive :: FilePath -> IO ()
removeDirectoryRecursive :: FilePath -> IO ()
removeDirectoryRecursive path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "removeDirectoryRecursive") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Metadata
m <- FilePath -> IO Metadata
getSymbolicLinkMetadata FilePath
path
case Metadata -> FileType
fileTypeFromMetadata Metadata
m of
Directory ->
FilePath -> IO ()
removeContentsRecursive FilePath
path
DirectoryLink ->
IOError -> IO ()
forall a. IOError -> IO a
ioError (IOError
err IOError -> FilePath -> IOError
`ioeSetErrorString` "is a directory symbolic link")
_ ->
IOError -> IO ()
forall a. IOError -> IO a
ioError (IOError
err IOError -> FilePath -> IOError
`ioeSetErrorString` "not a directory")
where err :: IOError
err = IOErrorType
-> FilePath -> Maybe Handle -> Maybe FilePath -> IOError
mkIOError IOErrorType
InappropriateType "" Maybe Handle
forall a. Maybe a
Nothing (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
path)
removePathRecursive :: FilePath -> IO ()
removePathRecursive :: FilePath -> IO ()
removePathRecursive path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "removePathRecursive") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Metadata
m <- FilePath -> IO Metadata
getSymbolicLinkMetadata FilePath
path
case Metadata -> FileType
fileTypeFromMetadata Metadata
m of
Directory -> FilePath -> IO ()
removeContentsRecursive FilePath
path
DirectoryLink -> FilePath -> IO ()
removeDirectory FilePath
path
_ -> FilePath -> IO ()
removeFile FilePath
path
removeContentsRecursive :: FilePath -> IO ()
removeContentsRecursive :: FilePath -> IO ()
removeContentsRecursive path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "removeContentsRecursive") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
[FilePath]
cont <- FilePath -> IO [FilePath]
listDirectory FilePath
path
(FilePath -> IO ()) -> [FilePath] -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ FilePath -> IO ()
removePathRecursive [FilePath
path FilePath -> FilePath -> FilePath
</> FilePath
x | FilePath
x <- [FilePath]
cont]
FilePath -> IO ()
removeDirectory FilePath
path
removePathForcibly :: FilePath -> IO ()
removePathForcibly :: FilePath -> IO ()
removePathForcibly path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "removePathForcibly") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> IO ()
makeRemovable FilePath
path IO () -> (IOError -> IO ()) -> IO ()
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ _ -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
IO () -> IO ()
ignoreDoesNotExistError (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Metadata
m <- FilePath -> IO Metadata
getSymbolicLinkMetadata FilePath
path
case Metadata -> FileType
fileTypeFromMetadata Metadata
m of
DirectoryLink -> FilePath -> IO ()
removeDirectory FilePath
path
Directory -> do
[FilePath]
names <- FilePath -> IO [FilePath]
listDirectory FilePath
path
[IO ()] -> IO ()
sequenceWithIOErrors_ ([IO ()] -> IO ()) -> [IO ()] -> IO ()
forall a b. (a -> b) -> a -> b
$
[ FilePath -> IO ()
removePathForcibly (FilePath
path FilePath -> FilePath -> FilePath
</> FilePath
name) | FilePath
name <- [FilePath]
names ] [IO ()] -> [IO ()] -> [IO ()]
forall a. [a] -> [a] -> [a]
++
[ FilePath -> IO ()
removeDirectory FilePath
path ]
_ -> FilePath -> IO ()
removeFile FilePath
path
where
ignoreDoesNotExistError :: IO () -> IO ()
ignoreDoesNotExistError :: IO () -> IO ()
ignoreDoesNotExistError action :: IO ()
action =
() () -> IO (Either IOError ()) -> IO ()
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (IOError -> Bool) -> IO () -> IO (Either IOError ())
forall a. (IOError -> Bool) -> IO a -> IO (Either IOError a)
tryIOErrorType IOError -> Bool
isDoesNotExistError IO ()
action
makeRemovable :: FilePath -> IO ()
makeRemovable :: FilePath -> IO ()
makeRemovable p :: FilePath
p = do
Permissions
perms <- FilePath -> IO Permissions
getPermissions FilePath
p
FilePath -> Permissions -> IO ()
setPermissions FilePath
path Permissions
perms{ readable :: Bool
readable = Bool
True
, searchable :: Bool
searchable = Bool
True
, writable :: Bool
writable = Bool
True }
removeFile :: FilePath -> IO ()
removeFile :: FilePath -> IO ()
removeFile = Bool -> FilePath -> IO ()
removePathInternal Bool
False
renameDirectory :: FilePath -> FilePath -> IO ()
renameDirectory :: FilePath -> FilePath -> IO ()
renameDirectory opath :: FilePath
opath npath :: FilePath
npath =
(IOError -> FilePath -> IOError
`ioeAddLocation` "renameDirectory") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Bool
isDir <- FilePath -> IO Bool
pathIsDirectory FilePath
opath
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
IOError -> IO ()
forall a. IOError -> IO a
ioError (IOError -> IO ()) -> (IOError -> IOError) -> IOError -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (IOError -> FilePath -> IOError
`ioeSetErrorString` "not a directory") (IOError -> IO ()) -> IOError -> IO ()
forall a b. (a -> b) -> a -> b
$
(IOErrorType
-> FilePath -> Maybe Handle -> Maybe FilePath -> IOError
mkIOError IOErrorType
InappropriateType "renameDirectory" Maybe Handle
forall a. Maybe a
Nothing (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
opath))
FilePath -> FilePath -> IO ()
renamePath FilePath
opath FilePath
npath
renameFile :: FilePath -> FilePath -> IO ()
renameFile :: FilePath -> FilePath -> IO ()
renameFile opath :: FilePath
opath npath :: FilePath
npath =
(IOError -> FilePath -> IOError
`ioeAddLocation` "renameFile") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> IO ()
checkNotDir FilePath
opath
FilePath -> FilePath -> IO ()
renamePath FilePath
opath FilePath
npath
IO () -> (IOError -> IO ()) -> IO ()
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ err :: IOError
err -> do
FilePath -> IO ()
checkNotDir FilePath
npath
IOError -> IO ()
forall a. IOError -> IO a
ioError IOError
err
where checkNotDir :: FilePath -> IO ()
checkNotDir path :: FilePath
path = do
Either IOError Metadata
m <- IO Metadata -> IO (Either IOError Metadata)
forall a. IO a -> IO (Either IOError a)
tryIOError (FilePath -> IO Metadata
getSymbolicLinkMetadata FilePath
path)
case FileType -> Bool
fileTypeIsDirectory (FileType -> Bool) -> (Metadata -> FileType) -> Metadata -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata -> FileType
fileTypeFromMetadata (Metadata -> Bool)
-> Either IOError Metadata -> Either IOError Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either IOError Metadata
m of
Right True -> IOError -> IO ()
forall a. IOError -> IO a
ioError (IOError -> IO ()) -> (IOError -> IOError) -> IOError -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (IOError -> FilePath -> IOError
`ioeSetErrorString` "is a directory") (IOError -> IO ()) -> IOError -> IO ()
forall a b. (a -> b) -> a -> b
$
IOErrorType
-> FilePath -> Maybe Handle -> Maybe FilePath -> IOError
mkIOError IOErrorType
InappropriateType "" Maybe Handle
forall a. Maybe a
Nothing (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
path)
_ -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
renamePath :: FilePath
-> FilePath
-> IO ()
renamePath :: FilePath -> FilePath -> IO ()
renamePath opath :: FilePath
opath npath :: FilePath
npath =
(IOError -> FilePath -> IOError
`ioeAddLocation` "renamePath") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> FilePath -> IO ()
renamePathInternal FilePath
opath FilePath
npath
copyFile :: FilePath
-> FilePath
-> IO ()
copyFile :: FilePath -> FilePath -> IO ()
copyFile fromFPath :: FilePath
fromFPath toFPath :: FilePath
toFPath =
(IOError -> FilePath -> IOError
`ioeAddLocation` "copyFile") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> FilePath -> (FilePath -> IO ()) -> IO ()
atomicCopyFileContents FilePath
fromFPath FilePath
toFPath
(IO () -> IO ()
ignoreIOExceptions (IO () -> IO ()) -> (FilePath -> IO ()) -> FilePath -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> IO ()
copyPermissions FilePath
fromFPath)
atomicCopyFileContents :: FilePath
-> FilePath
-> (FilePath -> IO ())
-> IO ()
atomicCopyFileContents :: FilePath -> FilePath -> (FilePath -> IO ()) -> IO ()
atomicCopyFileContents fromFPath :: FilePath
fromFPath toFPath :: FilePath
toFPath postAction :: FilePath -> IO ()
postAction =
(IOError -> FilePath -> IOError
`ioeAddLocation` "atomicCopyFileContents") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> (FilePath -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a.
FilePath -> (FilePath -> IO ()) -> (Handle -> IO a) -> IO a
withReplacementFile FilePath
toFPath FilePath -> IO ()
postAction ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ hTo :: Handle
hTo -> do
FilePath -> Handle -> IO ()
copyFileToHandle FilePath
fromFPath Handle
hTo
withReplacementFile :: FilePath
-> (FilePath -> IO ())
-> (Handle -> IO a)
-> IO a
withReplacementFile :: FilePath -> (FilePath -> IO ()) -> (Handle -> IO a) -> IO a
withReplacementFile path :: FilePath
path postAction :: FilePath -> IO ()
postAction action :: Handle -> IO a
action =
(IOError -> FilePath -> IOError
`ioeAddLocation` "withReplacementFile") (IOError -> IOError) -> IO a -> IO a
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
((forall a. IO a -> IO a) -> IO a) -> IO a
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask (((forall a. IO a -> IO a) -> IO a) -> IO a)
-> ((forall a. IO a -> IO a) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \ restore :: forall a. IO a -> IO a
restore -> do
(tmpFPath :: FilePath
tmpFPath, hTmp :: Handle
hTmp) <- FilePath -> FilePath -> IO (FilePath, Handle)
openBinaryTempFile (FilePath -> FilePath
takeDirectory FilePath
path)
".copyFile.tmp"
(IO a -> IO () -> IO a
forall a b. IO a -> IO b -> IO a
`onException` IO () -> IO ()
ignoreIOExceptions (FilePath -> IO ()
removeFile FilePath
tmpFPath)) (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
a
r <- (IO a -> IO () -> IO a
forall a b. IO a -> IO b -> IO a
`onException` IO () -> IO ()
ignoreIOExceptions (Handle -> IO ()
hClose Handle
hTmp)) (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
IO a -> IO a
forall a. IO a -> IO a
restore (Handle -> IO a
action Handle
hTmp)
Handle -> IO ()
hClose Handle
hTmp
IO () -> IO ()
forall a. IO a -> IO a
restore (FilePath -> IO ()
postAction FilePath
tmpFPath)
FilePath -> FilePath -> IO ()
renameFile FilePath
tmpFPath FilePath
path
a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
r
copyFileWithMetadata :: FilePath
-> FilePath
-> IO ()
copyFileWithMetadata :: FilePath -> FilePath -> IO ()
copyFileWithMetadata src :: FilePath
src dst :: FilePath
dst =
(IOError -> FilePath -> IOError
`ioeAddLocation` "copyFileWithMetadata") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError`
(Metadata -> FilePath -> IO ())
-> (Metadata -> FilePath -> IO ()) -> FilePath -> FilePath -> IO ()
copyFileWithMetadataInternal Metadata -> FilePath -> IO ()
copyPermissionsFromMetadata
Metadata -> FilePath -> IO ()
copyTimesFromMetadata
FilePath
src
FilePath
dst
copyTimesFromMetadata :: Metadata -> FilePath -> IO ()
copyTimesFromMetadata :: Metadata -> FilePath -> IO ()
copyTimesFromMetadata st :: Metadata
st dst :: FilePath
dst = do
let atime :: UTCTime
atime = Metadata -> UTCTime
accessTimeFromMetadata Metadata
st
let mtime :: UTCTime
mtime = Metadata -> UTCTime
modificationTimeFromMetadata Metadata
st
FilePath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes FilePath
dst (UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
atime, UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
mtime)
canonicalizePath :: FilePath -> IO FilePath
canonicalizePath :: FilePath -> IO FilePath
canonicalizePath = \ path :: FilePath
path ->
((IOError -> FilePath -> IOError
`ioeAddLocation` "canonicalizePath") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(IOError -> FilePath -> IOError
`ioeSetFileName` FilePath
path)) (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> FilePath
dropTrailingPathSeparator (FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
simplify (FilePath -> FilePath) -> IO FilePath -> IO FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
(((FilePath -> IO FilePath) -> FilePath -> IO FilePath)
-> FilePath -> IO FilePath
canonicalizePathWith (FilePath -> IO FilePath) -> FilePath -> IO FilePath
attemptRealpath (FilePath -> IO FilePath) -> IO FilePath -> IO FilePath
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< FilePath -> IO FilePath
prependCurrentDirectory FilePath
path)
where
attemptRealpath :: (FilePath -> IO FilePath) -> FilePath -> IO FilePath
attemptRealpath realpath :: FilePath -> IO FilePath
realpath =
Int
-> Maybe FilePath
-> (FilePath -> IO FilePath)
-> FilePath
-> IO FilePath
forall t.
(Ord t, Num t) =>
t
-> Maybe FilePath
-> (FilePath -> IO FilePath)
-> FilePath
-> IO FilePath
attemptRealpathWith (64 :: Int) Maybe FilePath
forall a. Maybe a
Nothing FilePath -> IO FilePath
realpath
(FilePath -> IO FilePath)
-> (FilePath -> IO FilePath) -> FilePath -> IO FilePath
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< FilePath -> IO FilePath
canonicalizePathSimplify
attemptRealpathWith :: t
-> Maybe FilePath
-> (FilePath -> IO FilePath)
-> FilePath
-> IO FilePath
attemptRealpathWith n :: t
n mFallback :: Maybe FilePath
mFallback realpath :: FilePath -> IO FilePath
realpath path :: FilePath
path =
case Maybe FilePath
mFallback of
Just fallback :: FilePath
fallback | t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 -> FilePath -> IO FilePath
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
fallback
_ -> [(FilePath, FilePath)] -> IO FilePath
realpathPrefix ([(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a. [a] -> [a]
reverse ([FilePath] -> [FilePath] -> [(FilePath, FilePath)]
forall a b. [a] -> [b] -> [(a, b)]
zip [FilePath]
prefixes [FilePath]
suffixes))
where
segments :: [FilePath]
segments = FilePath -> [FilePath]
splitDirectories FilePath
path
prefixes :: [FilePath]
prefixes = (FilePath -> FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a. (a -> a -> a) -> [a] -> [a]
scanl1 FilePath -> FilePath -> FilePath
(</>) [FilePath]
segments
suffixes :: [FilePath]
suffixes = [FilePath] -> [FilePath]
forall a. [a] -> [a]
tail ((FilePath -> FilePath -> FilePath)
-> FilePath -> [FilePath] -> [FilePath]
forall a b. (a -> b -> b) -> b -> [a] -> [b]
scanr FilePath -> FilePath -> FilePath
(</>) "" [FilePath]
segments)
realpathPrefix :: [(FilePath, FilePath)] -> IO FilePath
realpathPrefix candidates :: [(FilePath, FilePath)]
candidates =
case [(FilePath, FilePath)]
candidates of
[] -> FilePath -> IO FilePath
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
path
(prefix :: FilePath
prefix, suffix :: FilePath
suffix) : rest :: [(FilePath, FilePath)]
rest -> do
Bool
exist <- FilePath -> IO Bool
doesPathExist FilePath
prefix
if Bool -> Bool
not Bool
exist
then [(FilePath, FilePath)] -> IO FilePath
realpathPrefix [(FilePath, FilePath)]
rest
else do
Either IOError FilePath
mp <- IO FilePath -> IO (Either IOError FilePath)
forall a. IO a -> IO (Either IOError a)
tryIOError (FilePath -> IO FilePath
realpath FilePath
prefix)
case Either IOError FilePath
mp of
Left _ -> [(FilePath, FilePath)] -> IO FilePath
realpathPrefix [(FilePath, FilePath)]
rest
Right p :: FilePath
p -> FilePath -> FilePath -> FilePath -> IO FilePath
realpathFurther (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
suffix) FilePath
p FilePath
suffix
realpathFurther :: FilePath -> FilePath -> FilePath -> IO FilePath
realpathFurther fallback :: FilePath
fallback p :: FilePath
p suffix :: FilePath
suffix =
case FilePath -> [FilePath]
splitDirectories FilePath
suffix of
[] -> FilePath -> IO FilePath
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
fallback
next :: FilePath
next : restSuffix :: [FilePath]
restSuffix -> do
Either IOError FilePath
mTarget <- IO FilePath -> IO (Either IOError FilePath)
forall a. IO a -> IO (Either IOError a)
tryIOError (FilePath -> IO FilePath
getSymbolicLinkTarget (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
next))
case Either IOError FilePath
mTarget of
Left _ -> FilePath -> IO FilePath
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
fallback
Right target :: FilePath
target -> do
let mFallback' :: Maybe FilePath
mFallback' = FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath -> FilePath
forall a. a -> Maybe a -> a
fromMaybe FilePath
fallback Maybe FilePath
mFallback)
FilePath
path' <- FilePath -> IO FilePath
canonicalizePathSimplify
(FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
target FilePath -> FilePath -> FilePath
</> [FilePath] -> FilePath
joinPath [FilePath]
restSuffix)
t
-> Maybe FilePath
-> (FilePath -> IO FilePath)
-> FilePath
-> IO FilePath
attemptRealpathWith (t
n t -> t -> t
forall a. Num a => a -> a -> a
- 1) Maybe FilePath
mFallback' FilePath -> IO FilePath
realpath FilePath
path'
makeAbsolute :: FilePath -> IO FilePath
makeAbsolute :: FilePath -> IO FilePath
makeAbsolute path :: FilePath
path =
((IOError -> FilePath -> IOError
`ioeAddLocation` "makeAbsolute") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(IOError -> FilePath -> IOError
`ioeSetFileName` FilePath
path)) (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> FilePath -> FilePath
matchTrailingSeparator FilePath
path (FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
simplify (FilePath -> FilePath) -> IO FilePath -> IO FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO FilePath
prependCurrentDirectory FilePath
path
matchTrailingSeparator :: FilePath -> FilePath -> FilePath
matchTrailingSeparator :: FilePath -> FilePath -> FilePath
matchTrailingSeparator path :: FilePath
path
| FilePath -> Bool
hasTrailingPathSeparator FilePath
path = FilePath -> FilePath
addTrailingPathSeparator
| Bool
otherwise = FilePath -> FilePath
dropTrailingPathSeparator
makeRelativeToCurrentDirectory :: FilePath -> IO FilePath
makeRelativeToCurrentDirectory :: FilePath -> IO FilePath
makeRelativeToCurrentDirectory x :: FilePath
x = do
(FilePath -> FilePath -> FilePath
`makeRelative` FilePath
x) (FilePath -> FilePath) -> IO FilePath -> IO FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO FilePath
getCurrentDirectory
findExecutable :: String -> IO (Maybe FilePath)
findExecutable :: FilePath -> IO (Maybe FilePath)
findExecutable binary :: FilePath
binary =
ListT IO FilePath -> IO (Maybe FilePath)
forall (m :: * -> *) a. Functor m => ListT m a -> m (Maybe a)
listTHead
(([FilePath] -> FilePath -> ListT IO FilePath)
-> FilePath -> ListT IO FilePath
findExecutablesLazyInternal [FilePath] -> FilePath -> ListT IO FilePath
findExecutablesInDirectoriesLazy FilePath
binary)
findExecutables :: String -> IO [FilePath]
findExecutables :: FilePath -> IO [FilePath]
findExecutables binary :: FilePath
binary =
ListT IO FilePath -> IO [FilePath]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
listTToList
(([FilePath] -> FilePath -> ListT IO FilePath)
-> FilePath -> ListT IO FilePath
findExecutablesLazyInternal [FilePath] -> FilePath -> ListT IO FilePath
findExecutablesInDirectoriesLazy FilePath
binary)
findExecutablesInDirectories :: [FilePath] -> String -> IO [FilePath]
findExecutablesInDirectories :: [FilePath] -> FilePath -> IO [FilePath]
findExecutablesInDirectories path :: [FilePath]
path binary :: FilePath
binary =
ListT IO FilePath -> IO [FilePath]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
listTToList ([FilePath] -> FilePath -> ListT IO FilePath
findExecutablesInDirectoriesLazy [FilePath]
path FilePath
binary)
findExecutablesInDirectoriesLazy :: [FilePath] -> String -> ListT IO FilePath
findExecutablesInDirectoriesLazy :: [FilePath] -> FilePath -> ListT IO FilePath
findExecutablesInDirectoriesLazy path :: [FilePath]
path binary :: FilePath
binary =
(FilePath -> IO Bool)
-> [FilePath] -> FilePath -> ListT IO FilePath
findFilesWithLazy FilePath -> IO Bool
isExecutable [FilePath]
path (FilePath
binary FilePath -> FilePath -> FilePath
<.> FilePath
exeExtension)
isExecutable :: FilePath -> IO Bool
isExecutable :: FilePath -> IO Bool
isExecutable file :: FilePath
file = Permissions -> Bool
executable (Permissions -> Bool) -> IO Permissions -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Permissions
getPermissions FilePath
file
findFile :: [FilePath] -> String -> IO (Maybe FilePath)
findFile :: [FilePath] -> FilePath -> IO (Maybe FilePath)
findFile = (FilePath -> IO Bool)
-> [FilePath] -> FilePath -> IO (Maybe FilePath)
findFileWith (\ _ -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
findFiles :: [FilePath] -> String -> IO [FilePath]
findFiles :: [FilePath] -> FilePath -> IO [FilePath]
findFiles = (FilePath -> IO Bool) -> [FilePath] -> FilePath -> IO [FilePath]
findFilesWith (\ _ -> Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
findFileWith :: (FilePath -> IO Bool) -> [FilePath] -> String -> IO (Maybe FilePath)
findFileWith :: (FilePath -> IO Bool)
-> [FilePath] -> FilePath -> IO (Maybe FilePath)
findFileWith f :: FilePath -> IO Bool
f ds :: [FilePath]
ds name :: FilePath
name = ListT IO FilePath -> IO (Maybe FilePath)
forall (m :: * -> *) a. Functor m => ListT m a -> m (Maybe a)
listTHead ((FilePath -> IO Bool)
-> [FilePath] -> FilePath -> ListT IO FilePath
findFilesWithLazy FilePath -> IO Bool
f [FilePath]
ds FilePath
name)
findFilesWith :: (FilePath -> IO Bool) -> [FilePath] -> String -> IO [FilePath]
findFilesWith :: (FilePath -> IO Bool) -> [FilePath] -> FilePath -> IO [FilePath]
findFilesWith f :: FilePath -> IO Bool
f ds :: [FilePath]
ds name :: FilePath
name = ListT IO FilePath -> IO [FilePath]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
listTToList ((FilePath -> IO Bool)
-> [FilePath] -> FilePath -> ListT IO FilePath
findFilesWithLazy FilePath -> IO Bool
f [FilePath]
ds FilePath
name)
findFilesWithLazy
:: (FilePath -> IO Bool) -> [FilePath] -> String -> ListT IO FilePath
findFilesWithLazy :: (FilePath -> IO Bool)
-> [FilePath] -> FilePath -> ListT IO FilePath
findFilesWithLazy f :: FilePath -> IO Bool
f dirs :: [FilePath]
dirs path :: FilePath
path
| FilePath -> Bool
isAbsolute FilePath
path = IO (Maybe (FilePath, ListT IO FilePath)) -> ListT IO FilePath
forall (m :: * -> *) a. m (Maybe (a, ListT m a)) -> ListT m a
ListT ([FilePath] -> IO (Maybe (FilePath, ListT IO FilePath))
find [""])
| Bool
otherwise = IO (Maybe (FilePath, ListT IO FilePath)) -> ListT IO FilePath
forall (m :: * -> *) a. m (Maybe (a, ListT m a)) -> ListT m a
ListT ([FilePath] -> IO (Maybe (FilePath, ListT IO FilePath))
find [FilePath]
dirs)
where
find :: [FilePath] -> IO (Maybe (FilePath, ListT IO FilePath))
find [] = Maybe (FilePath, ListT IO FilePath)
-> IO (Maybe (FilePath, ListT IO FilePath))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (FilePath, ListT IO FilePath)
forall a. Maybe a
Nothing
find (d :: FilePath
d : ds :: [FilePath]
ds) = do
let p :: FilePath
p = FilePath
d FilePath -> FilePath -> FilePath
</> FilePath
path
Bool
found <- FilePath -> IO Bool
doesFileExist FilePath
p IO Bool -> IO Bool -> IO Bool
forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
`andM` FilePath -> IO Bool
f FilePath
p
if Bool
found
then Maybe (FilePath, ListT IO FilePath)
-> IO (Maybe (FilePath, ListT IO FilePath))
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath, ListT IO FilePath)
-> Maybe (FilePath, ListT IO FilePath)
forall a. a -> Maybe a
Just (FilePath
p, IO (Maybe (FilePath, ListT IO FilePath)) -> ListT IO FilePath
forall (m :: * -> *) a. m (Maybe (a, ListT m a)) -> ListT m a
ListT ([FilePath] -> IO (Maybe (FilePath, ListT IO FilePath))
find [FilePath]
ds)))
else [FilePath] -> IO (Maybe (FilePath, ListT IO FilePath))
find [FilePath]
ds
exeExtension :: String
exeExtension :: FilePath
exeExtension = FilePath
exeExtensionInternal
getDirectoryContents :: FilePath -> IO [FilePath]
getDirectoryContents :: FilePath -> IO [FilePath]
getDirectoryContents path :: FilePath
path =
((IOError -> FilePath -> IOError
`ioeSetFileName` FilePath
path) (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(IOError -> FilePath -> IOError
`ioeAddLocation` "getDirectoryContents")) (IOError -> IOError) -> IO [FilePath] -> IO [FilePath]
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> IO [FilePath]
getDirectoryContentsInternal FilePath
path
listDirectory :: FilePath -> IO [FilePath]
listDirectory :: FilePath -> IO [FilePath]
listDirectory path :: FilePath
path = (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
f ([FilePath] -> [FilePath]) -> IO [FilePath] -> IO [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO [FilePath]
getDirectoryContents FilePath
path
where f :: FilePath -> Bool
f filename :: FilePath
filename = FilePath
filename FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
/= "." Bool -> Bool -> Bool
&& FilePath
filename FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
/= ".."
getCurrentDirectory :: IO FilePath
getCurrentDirectory :: IO FilePath
getCurrentDirectory =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getCurrentDirectory") (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> (IOError -> Bool) -> IO FilePath -> IO FilePath
forall a. FilePath -> (IOError -> Bool) -> IO a -> IO a
specializeErrorString
"Current working directory no longer exists"
IOError -> Bool
isDoesNotExistError
IO FilePath
getCurrentDirectoryInternal
setCurrentDirectory :: FilePath -> IO ()
setCurrentDirectory :: FilePath -> IO ()
setCurrentDirectory = FilePath -> IO ()
setCurrentDirectoryInternal
withCurrentDirectory :: FilePath
-> IO a
-> IO a
withCurrentDirectory :: FilePath -> IO a -> IO a
withCurrentDirectory dir :: FilePath
dir action :: IO a
action =
IO FilePath -> (FilePath -> IO ()) -> (FilePath -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO FilePath
getCurrentDirectory FilePath -> IO ()
setCurrentDirectory ((FilePath -> IO a) -> IO a) -> (FilePath -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \ _ -> do
FilePath -> IO ()
setCurrentDirectory FilePath
dir
IO a
action
getFileSize :: FilePath -> IO Integer
getFileSize :: FilePath -> IO Integer
getFileSize path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getFileSize") (IOError -> IOError) -> IO Integer -> IO Integer
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Metadata -> Integer
fileSizeFromMetadata (Metadata -> Integer) -> IO Metadata -> IO Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Metadata
getFileMetadata FilePath
path
doesPathExist :: FilePath -> IO Bool
doesPathExist :: FilePath -> IO Bool
doesPathExist path :: FilePath
path = do
(Bool
True Bool -> IO Metadata -> IO Bool
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ FilePath -> IO Metadata
getFileMetadata FilePath
path)
IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ _ ->
Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
doesDirectoryExist :: FilePath -> IO Bool
doesDirectoryExist :: FilePath -> IO Bool
doesDirectoryExist path :: FilePath
path = do
FilePath -> IO Bool
pathIsDirectory FilePath
path
IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ _ ->
Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
doesFileExist :: FilePath -> IO Bool
doesFileExist :: FilePath -> IO Bool
doesFileExist path :: FilePath
path = do
(Bool -> Bool
not (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Bool
pathIsDirectory FilePath
path)
IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ _ ->
Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
pathIsDirectory :: FilePath -> IO Bool
pathIsDirectory :: FilePath -> IO Bool
pathIsDirectory path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "pathIsDirectory") (IOError -> IOError) -> IO Bool -> IO Bool
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FileType -> Bool
fileTypeIsDirectory (FileType -> Bool) -> (Metadata -> FileType) -> Metadata -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata -> FileType
fileTypeFromMetadata (Metadata -> Bool) -> IO Metadata -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Metadata
getFileMetadata FilePath
path
createFileLink
:: FilePath
-> FilePath
-> IO ()
createFileLink :: FilePath -> FilePath -> IO ()
createFileLink target :: FilePath
target link :: FilePath
link =
(IOError -> FilePath -> IOError
`ioeAddLocation` "createFileLink") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Bool -> FilePath -> FilePath -> IO ()
createSymbolicLink Bool
False FilePath
target FilePath
link
createDirectoryLink
:: FilePath
-> FilePath
-> IO ()
createDirectoryLink :: FilePath -> FilePath -> IO ()
createDirectoryLink target :: FilePath
target link :: FilePath
link =
(IOError -> FilePath -> IOError
`ioeAddLocation` "createDirectoryLink") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Bool -> FilePath -> FilePath -> IO ()
createSymbolicLink Bool
True FilePath
target FilePath
link
removeDirectoryLink :: FilePath -> IO ()
removeDirectoryLink :: FilePath -> IO ()
removeDirectoryLink path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "removeDirectoryLink") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Bool -> FilePath -> IO ()
removePathInternal Bool
linkToDirectoryIsDirectory FilePath
path
pathIsSymbolicLink :: FilePath -> IO Bool
pathIsSymbolicLink :: FilePath -> IO Bool
pathIsSymbolicLink path :: FilePath
path =
((IOError -> FilePath -> IOError
`ioeAddLocation` "pathIsSymbolicLink") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(IOError -> FilePath -> IOError
`ioeSetFileName` FilePath
path)) (IOError -> IOError) -> IO Bool -> IO Bool
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FileType -> Bool
fileTypeIsLink (FileType -> Bool) -> (Metadata -> FileType) -> Metadata -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata -> FileType
fileTypeFromMetadata (Metadata -> Bool) -> IO Metadata -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Metadata
getSymbolicLinkMetadata FilePath
path
{-# DEPRECATED isSymbolicLink "Use 'pathIsSymbolicLink' instead" #-}
isSymbolicLink :: FilePath -> IO Bool
isSymbolicLink :: FilePath -> IO Bool
isSymbolicLink = FilePath -> IO Bool
pathIsSymbolicLink
getSymbolicLinkTarget :: FilePath -> IO FilePath
getSymbolicLinkTarget :: FilePath -> IO FilePath
getSymbolicLinkTarget path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getSymbolicLinkTarget") (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> IO FilePath
readSymbolicLink FilePath
path
getAccessTime :: FilePath -> IO UTCTime
getAccessTime :: FilePath -> IO UTCTime
getAccessTime path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getAccessTime") (IOError -> IOError) -> IO UTCTime -> IO UTCTime
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Metadata -> UTCTime
accessTimeFromMetadata (Metadata -> UTCTime) -> IO Metadata -> IO UTCTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Metadata
getFileMetadata (FilePath -> FilePath
emptyToCurDir FilePath
path)
getModificationTime :: FilePath -> IO UTCTime
getModificationTime :: FilePath -> IO UTCTime
getModificationTime path :: FilePath
path =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getModificationTime") (IOError -> IOError) -> IO UTCTime -> IO UTCTime
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Metadata -> UTCTime
modificationTimeFromMetadata (Metadata -> UTCTime) -> IO Metadata -> IO UTCTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Metadata
getFileMetadata (FilePath -> FilePath
emptyToCurDir FilePath
path)
setAccessTime :: FilePath -> UTCTime -> IO ()
setAccessTime :: FilePath -> UTCTime -> IO ()
setAccessTime path :: FilePath
path atime :: UTCTime
atime =
(IOError -> FilePath -> IOError
`ioeAddLocation` "setAccessTime") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes FilePath
path (UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
atime, Maybe UTCTime
forall a. Maybe a
Nothing)
setModificationTime :: FilePath -> UTCTime -> IO ()
setModificationTime :: FilePath -> UTCTime -> IO ()
setModificationTime path :: FilePath
path mtime :: UTCTime
mtime =
(IOError -> FilePath -> IOError
`ioeAddLocation` "setModificationTime") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes FilePath
path (Maybe UTCTime
forall a. Maybe a
Nothing, UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
mtime)
setFileTimes :: FilePath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes :: FilePath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes _ (Nothing, Nothing) = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
setFileTimes path :: FilePath
path (atime :: Maybe UTCTime
atime, mtime :: Maybe UTCTime
mtime) =
((IOError -> FilePath -> IOError
`ioeAddLocation` "setFileTimes") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(IOError -> FilePath -> IOError
`ioeSetFileName` FilePath
path)) (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> (Maybe POSIXTime, Maybe POSIXTime) -> IO ()
setTimes (FilePath -> FilePath
emptyToCurDir FilePath
path)
(UTCTime -> POSIXTime
utcTimeToPOSIXSeconds (UTCTime -> POSIXTime) -> Maybe UTCTime -> Maybe POSIXTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe UTCTime
atime, UTCTime -> POSIXTime
utcTimeToPOSIXSeconds (UTCTime -> POSIXTime) -> Maybe UTCTime -> Maybe POSIXTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe UTCTime
mtime)
getHomeDirectory :: IO FilePath
getHomeDirectory :: IO FilePath
getHomeDirectory =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getHomeDirectory") (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
IO FilePath
getHomeDirectoryInternal
getXdgDirectory :: XdgDirectory
-> FilePath
-> IO FilePath
getXdgDirectory :: XdgDirectory -> FilePath -> IO FilePath
getXdgDirectory xdgDir :: XdgDirectory
xdgDir suffix :: FilePath
suffix =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getXdgDirectory") (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> FilePath
simplify (FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> FilePath -> FilePath
</> FilePath
suffix) (FilePath -> FilePath) -> IO FilePath -> IO FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> do
Maybe FilePath
env <- FilePath -> IO (Maybe FilePath)
lookupEnv (FilePath -> IO (Maybe FilePath))
-> FilePath -> IO (Maybe FilePath)
forall a b. (a -> b) -> a -> b
$ case XdgDirectory
xdgDir of
XdgData -> "XDG_DATA_HOME"
XdgConfig -> "XDG_CONFIG_HOME"
XdgCache -> "XDG_CACHE_HOME"
case Maybe FilePath
env of
Nothing -> IO FilePath -> XdgDirectory -> IO FilePath
getXdgDirectoryFallback IO FilePath
getHomeDirectory XdgDirectory
xdgDir
Just path :: FilePath
path -> FilePath -> IO FilePath
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
path
getXdgDirectoryList :: XdgDirectoryList
-> IO [FilePath]
getXdgDirectoryList :: XdgDirectoryList -> IO [FilePath]
getXdgDirectoryList xdgDirs :: XdgDirectoryList
xdgDirs =
(IOError -> FilePath -> IOError
`ioeAddLocation` "getXdgDirectoryList") (IOError -> IOError) -> IO [FilePath] -> IO [FilePath]
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
Maybe FilePath
env <- FilePath -> IO (Maybe FilePath)
lookupEnv (FilePath -> IO (Maybe FilePath))
-> FilePath -> IO (Maybe FilePath)
forall a b. (a -> b) -> a -> b
$ case XdgDirectoryList
xdgDirs of
XdgDataDirs -> "XDG_DATA_DIRS"
XdgConfigDirs -> "XDG_CONFIG_DIRS"
case Maybe FilePath
env of
Nothing -> XdgDirectoryList -> IO [FilePath]
getXdgDirectoryListFallback XdgDirectoryList
xdgDirs
Just paths :: FilePath
paths -> [FilePath] -> IO [FilePath]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath -> [FilePath]
splitSearchPath FilePath
paths)
getAppUserDataDirectory :: FilePath
-> IO FilePath
getAppUserDataDirectory :: FilePath -> IO FilePath
getAppUserDataDirectory appName :: FilePath
appName = do
(IOError -> FilePath -> IOError
`ioeAddLocation` "getAppUserDataDirectory") (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
FilePath -> IO FilePath
getAppUserDataDirectoryInternal FilePath
appName
getUserDocumentsDirectory :: IO FilePath
getUserDocumentsDirectory :: IO FilePath
getUserDocumentsDirectory = do
(IOError -> FilePath -> IOError
`ioeAddLocation` "getUserDocumentsDirectory") (IOError -> IOError) -> IO FilePath -> IO FilePath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
IO FilePath
getUserDocumentsDirectoryInternal
getTemporaryDirectory :: IO FilePath
getTemporaryDirectory :: IO FilePath
getTemporaryDirectory = IO FilePath
getTemporaryDirectoryInternal