module System.Directory.OsPath
   (
    
    
      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
   ) where
import Prelude ()
import System.Directory.Internal
import System.Directory.Internal.Prelude
import qualified System.File.OsPath as OS
import System.OsPath
  ( (<.>)
  , (</>)
  , addTrailingPathSeparator
  , dropTrailingPathSeparator
  , hasTrailingPathSeparator
  , isAbsolute
  , joinPath
  , makeRelative
  , splitDirectories
  , splitSearchPath
  , takeDirectory
  , encodeWith
  )
import qualified Data.List.NonEmpty as NE
import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
import GHC.IO.Encoding.UTF8 ( mkUTF8 )
import GHC.IO.Encoding.UTF16 ( mkUTF16le )
import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
emptyPermissions :: Permissions
emptyPermissions :: Permissions
emptyPermissions = 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 Bool
b Permissions
p = Permissions
p { readable = b }
setOwnerWritable :: Bool -> Permissions -> Permissions
setOwnerWritable :: Bool -> Permissions -> Permissions
setOwnerWritable Bool
b Permissions
p = Permissions
p { writable = b }
setOwnerExecutable :: Bool -> Permissions -> Permissions
setOwnerExecutable :: Bool -> Permissions -> Permissions
setOwnerExecutable Bool
b Permissions
p = Permissions
p { executable = b }
setOwnerSearchable :: Bool -> Permissions -> Permissions
setOwnerSearchable :: Bool -> Permissions -> Permissions
setOwnerSearchable Bool
b Permissions
p = Permissions
p { searchable = b }
getPermissions :: OsPath -> IO Permissions
getPermissions :: OsPath -> IO Permissions
getPermissions OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"getPermissions") (IOError -> IOError) -> IO Permissions -> IO Permissions
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> IO Permissions
getAccessPermissions (OsPath -> OsPath
emptyToCurDir OsPath
path)
setPermissions :: OsPath -> Permissions -> IO ()
setPermissions :: OsPath -> Permissions -> IO ()
setPermissions OsPath
path Permissions
p =
  (IOError -> String -> IOError
`ioeAddLocation` String
"setPermissions") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> Permissions -> IO ()
setAccessPermissions (OsPath -> OsPath
emptyToCurDir OsPath
path) Permissions
p
copyPermissions :: OsPath -> OsPath -> IO ()
copyPermissions :: OsPath -> OsPath -> IO ()
copyPermissions OsPath
src OsPath
dst =
  (IOError -> String -> IOError
`ioeAddLocation` String
"copyPermissions") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    m <- OsPath -> IO Metadata
getFileMetadata OsPath
src
    copyPermissionsFromMetadata m dst
copyPermissionsFromMetadata :: Metadata -> OsPath -> IO ()
copyPermissionsFromMetadata :: Metadata -> OsPath -> IO ()
copyPermissionsFromMetadata Metadata
m OsPath
dst = do
  
  
  OsPath -> Mode -> IO ()
setFilePermissions OsPath
dst (Metadata -> Mode
modeFromMetadata Metadata
m)
createDirectory :: OsPath -> IO ()
createDirectory :: OsPath -> IO ()
createDirectory = OsPath -> IO ()
createDirectoryInternal
createDirectoryIfMissing :: Bool     
                         -> OsPath 
                         -> IO ()
createDirectoryIfMissing :: Bool -> OsPath -> IO ()
createDirectoryIfMissing Bool
create_parents OsPath
path0
  | Bool
create_parents = [OsPath] -> IO ()
createDirs (OsPath -> [OsPath]
parents OsPath
path0)
  | Bool
otherwise      = [OsPath] -> IO ()
createDirs (Int -> [OsPath] -> [OsPath]
forall a. Int -> [a] -> [a]
take Int
1 (OsPath -> [OsPath]
parents OsPath
path0))
  where
    parents :: OsPath -> [OsPath]
parents = [OsPath] -> [OsPath]
forall a. [a] -> [a]
reverse ([OsPath] -> [OsPath])
-> (OsPath -> [OsPath]) -> OsPath -> [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OsPath -> OsPath -> OsPath) -> [OsPath] -> [OsPath]
forall a. (a -> a -> a) -> [a] -> [a]
scanl1 OsPath -> OsPath -> OsPath
(</>) ([OsPath] -> [OsPath])
-> (OsPath -> [OsPath]) -> OsPath -> [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> [OsPath]
splitDirectories (OsPath -> [OsPath]) -> (OsPath -> OsPath) -> OsPath -> [OsPath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> OsPath
simplify
    createDirs :: [OsPath] -> IO ()
createDirs []         = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    createDirs (OsPath
dir:[])   = OsPath -> (IOError -> IO ()) -> IO ()
createDir OsPath
dir IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError
    createDirs (OsPath
dir:[OsPath]
dirs) =
      OsPath -> (IOError -> IO ()) -> IO ()
createDir OsPath
dir ((IOError -> IO ()) -> IO ()) -> (IOError -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \IOError
_ -> do
        [OsPath] -> IO ()
createDirs [OsPath]
dirs
        OsPath -> (IOError -> IO ()) -> IO ()
createDir OsPath
dir IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError
    createDir :: OsPath -> (IOError -> IO ()) -> IO ()
createDir OsPath
dir IOError -> IO ()
notExistHandler = do
      r <- IO () -> IO (Either IOError ())
forall a. IO a -> IO (Either IOError a)
tryIOError (OsPath -> IO ()
createDirectory OsPath
dir)
      case r of
        Right ()                   -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Left  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
              canIgnore <- OsPath -> IO Bool
pathIsDirectory OsPath
dir
                             IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ IOError
_ ->
                               Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (IOError -> Bool
isAlreadyExistsError IOError
e)
              unless canIgnore (ioError e)
          | Bool
otherwise              -> IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError IOError
e
removeDirectory :: OsPath -> IO ()
removeDirectory :: OsPath -> IO ()
removeDirectory = Bool -> OsPath -> IO ()
removePathInternal Bool
True
type Preremover = Maybe RawHandle -> OsPath -> Metadata -> IO ()
noPreremover :: Preremover
noPreremover :: Preremover
noPreremover Maybe RawHandle
_ OsPath
_ Metadata
_ = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
forcePreremover :: Preremover
forcePreremover :: Preremover
forcePreremover Maybe RawHandle
dir OsPath
path Metadata
metadata = do
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FileType -> Bool
fileTypeIsDirectory (Metadata -> FileType
fileTypeFromMetadata Metadata
metadata)
        Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
filesAlwaysRemovable) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    WhetherFollow -> Maybe RawHandle -> OsPath -> Mode -> IO ()
setModeAt WhetherFollow
NoFollow Maybe RawHandle
dir OsPath
path Mode
mode
      IO () -> (IOError -> IO ()) -> IO ()
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ IOError
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  where
    mode :: Mode
mode = Mode -> Mode
setForceRemoveMode (Metadata -> Mode
modeFromMetadata Metadata
metadata)
removeRecursivelyAt
  :: (IO () -> IO ())
  -> ([IO ()] -> IO ())
  -> Preremover
  -> Maybe RawHandle
  -> OsPath
  -> IO ()
removeRecursivelyAt :: (IO () -> IO ())
-> ([IO ()] -> IO ())
-> Preremover
-> Maybe RawHandle
-> OsPath
-> IO ()
removeRecursivelyAt IO () -> IO ()
catcher [IO ()] -> IO ()
sequencer Preremover
preremover Maybe RawHandle
dir OsPath
name = IO () -> IO ()
catcher (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
  metadata <- WhetherFollow -> Maybe RawHandle -> OsPath -> IO Metadata
getMetadataAt WhetherFollow
NoFollow Maybe RawHandle
dir OsPath
name
  preremover dir name metadata
  let
    fileType = Metadata -> FileType
fileTypeFromMetadata Metadata
metadata
    subremovals = do
      Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FileType
fileType FileType -> FileType -> Bool
forall a. Eq a => a -> a -> Bool
== FileType
Directory) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        IO RawHandle
-> (RawHandle -> IO ()) -> (RawHandle -> IO ()) -> IO ()
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (WhetherFollow -> Maybe RawHandle -> OsPath -> IO RawHandle
openRaw WhetherFollow
NoFollow Maybe RawHandle
dir OsPath
name) RawHandle -> IO ()
closeRaw ((RawHandle -> IO ()) -> IO ()) -> (RawHandle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ RawHandle
handle -> do
          
          
          names <- [OsPath] -> [OsPath]
dropSpecialDotDirs ([OsPath] -> [OsPath]) -> IO [OsPath] -> IO [OsPath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RawHandle -> IO [OsPath]
readDirToEnd RawHandle
handle
          sequencer (recurse (Just handle) <$> names)
  sequencer [subremovals, removePathAt fileType dir name]
  where recurse :: Maybe RawHandle -> OsPath -> IO ()
recurse = (IO () -> IO ())
-> ([IO ()] -> IO ())
-> Preremover
-> Maybe RawHandle
-> OsPath
-> IO ()
removeRecursivelyAt IO () -> IO ()
catcher [IO ()] -> IO ()
sequencer Preremover
preremover
removeDirectoryRecursive :: OsPath -> IO ()
removeDirectoryRecursive :: OsPath -> IO ()
removeDirectoryRecursive OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"removeDirectoryRecursive") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    m <- OsPath -> IO Metadata
getSymbolicLinkMetadata OsPath
path
    case fileTypeFromMetadata m of
      FileType
Directory ->
        (IO () -> IO ())
-> ([IO ()] -> IO ())
-> Preremover
-> Maybe RawHandle
-> OsPath
-> IO ()
removeRecursivelyAt IO () -> IO ()
forall a. a -> a
id [IO ()] -> IO ()
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Applicative f) =>
t (f a) -> f ()
sequenceA_ Preremover
noPreremover Maybe RawHandle
forall a. Maybe a
Nothing OsPath
path
      FileType
DirectoryLink ->
        IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError (IOError
err IOError -> String -> IOError
`ioeSetErrorString` String
"is a directory symbolic link")
      FileType
_ ->
        IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError (IOError
err IOError -> String -> IOError
`ioeSetErrorString` String
"not a directory")
  where err :: IOError
err = IOErrorType -> String -> Maybe Handle -> Maybe String -> IOError
mkIOError IOErrorType
InappropriateType String
"" Maybe Handle
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
path
removePathForcibly :: OsPath -> IO ()
removePathForcibly :: OsPath -> IO ()
removePathForcibly OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"removePathForcibly") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    (IO () -> IO ())
-> ([IO ()] -> IO ())
-> Preremover
-> Maybe RawHandle
-> OsPath
-> IO ()
removeRecursivelyAt
      IO () -> IO ()
ignoreDoesNotExistError
      [IO ()] -> IO ()
sequenceWithIOErrors_
      Preremover
forcePreremover
      Maybe RawHandle
forall a. Maybe a
Nothing
      OsPath
path
  where
    ignoreDoesNotExistError :: IO () -> IO ()
    ignoreDoesNotExistError :: IO () -> IO ()
ignoreDoesNotExistError IO ()
action =
      () () -> IO (Either IOError ()) -> IO ()
forall a b. a -> IO b -> IO a
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
removeFile :: OsPath -> IO ()
removeFile :: OsPath -> IO ()
removeFile = Bool -> OsPath -> IO ()
removePathInternal Bool
False
renameDirectory :: OsPath -> OsPath -> IO ()
renameDirectory :: OsPath -> OsPath -> IO ()
renameDirectory OsPath
opath OsPath
npath =
   (IOError -> String -> IOError
`ioeAddLocation` String
"renameDirectory") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
     
     isDir <- OsPath -> IO Bool
pathIsDirectory OsPath
opath
     when (not isDir) . ioError $
       mkIOError InappropriateType "renameDirectory" Nothing Nothing
       `ioeSetErrorString` "not a directory"
       `ioeSetOsPath` opath
     renamePath opath npath
renameFile :: OsPath -> OsPath -> IO ()
renameFile :: OsPath -> OsPath -> IO ()
renameFile OsPath
opath OsPath
npath =
  (IOError -> String -> IOError
`ioeAddLocation` String
"renameFile") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    
    OsPath -> IO ()
checkNotDir OsPath
opath
    OsPath -> OsPath -> IO ()
renamePath OsPath
opath OsPath
npath
      
      
      
      
      
      
      IO () -> (IOError -> IO ()) -> IO ()
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ IOError
err -> do
        OsPath -> IO ()
checkNotDir OsPath
npath
        IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError IOError
err
  where checkNotDir :: OsPath -> IO ()
checkNotDir OsPath
path = do
          m <- IO Metadata -> IO (Either IOError Metadata)
forall a. IO a -> IO (Either IOError a)
tryIOError (OsPath -> IO Metadata
getSymbolicLinkMetadata OsPath
path)
          case fileTypeIsDirectory . fileTypeFromMetadata <$> m of
            Right Bool
True ->
              IOError -> IO ()
forall a. HasCallStack => IOError -> IO a
ioError (IOError -> IO ()) -> IOError -> IO ()
forall a b. (a -> b) -> a -> b
$
              IOErrorType -> String -> Maybe Handle -> Maybe String -> IOError
mkIOError IOErrorType
InappropriateType String
"" Maybe Handle
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing
              IOError -> String -> IOError
`ioeSetErrorString` String
"is a directory"
              IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
path
            Either IOError Bool
_          -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
renamePath :: OsPath                  
           -> OsPath                  
           -> IO ()
renamePath :: OsPath -> OsPath -> IO ()
renamePath OsPath
opath OsPath
npath =
  (IOError -> String -> IOError
`ioeAddLocation` String
"renamePath") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> OsPath -> IO ()
renamePathInternal OsPath
opath OsPath
npath
copyFile :: OsPath                    
         -> OsPath                    
         -> IO ()
copyFile :: OsPath -> OsPath -> IO ()
copyFile OsPath
fromFPath OsPath
toFPath =
  (IOError -> String -> IOError
`ioeAddLocation` String
"copyFile") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> OsPath -> (OsPath -> IO ()) -> IO ()
atomicCopyFileContents OsPath
fromFPath OsPath
toFPath
      (IO () -> IO ()
ignoreIOExceptions (IO () -> IO ()) -> (OsPath -> IO ()) -> OsPath -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> OsPath -> IO ()
copyPermissions OsPath
fromFPath)
copyFileToHandle :: OsPath              
                 -> Handle              
                 -> IO ()
copyFileToHandle :: OsPath -> Handle -> IO ()
copyFileToHandle OsPath
fromFPath Handle
hTo =
  (IOError -> String -> IOError
`ioeAddLocation` String
"copyFileToHandle") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> IOMode -> (Handle -> IO ()) -> IO ()
forall r. OsPath -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile OsPath
fromFPath IOMode
ReadMode ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Handle
hFrom ->
      Handle -> Handle -> IO ()
copyHandleData Handle
hFrom Handle
hTo
atomicCopyFileContents :: OsPath            
                       -> OsPath            
                       -> (OsPath -> IO ()) 
                       -> IO ()
atomicCopyFileContents :: OsPath -> OsPath -> (OsPath -> IO ()) -> IO ()
atomicCopyFileContents OsPath
fromFPath OsPath
toFPath OsPath -> IO ()
postAction =
  (IOError -> String -> IOError
`ioeAddLocation` String
"atomicCopyFileContents") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> (OsPath -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a. OsPath -> (OsPath -> IO ()) -> (Handle -> IO a) -> IO a
withReplacementFile OsPath
toFPath OsPath -> IO ()
postAction ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Handle
hTo -> do
      OsPath -> Handle -> IO ()
copyFileToHandle OsPath
fromFPath Handle
hTo
withReplacementFile :: OsPath            
                    -> (OsPath -> IO ()) 
                    -> (Handle -> IO a)    
                    -> IO a
withReplacementFile :: forall a. OsPath -> (OsPath -> IO ()) -> (Handle -> IO a) -> IO a
withReplacementFile OsPath
path OsPath -> IO ()
postAction Handle -> IO a
action =
  (IOError -> String -> IOError
`ioeAddLocation` String
"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
$ \ forall a. IO a -> IO a
restore -> do
      let tmpPath :: OsPath
tmpPath = case TextEncoding
-> TextEncoding -> String -> Either EncodingException OsPath
encodeWith (CodingFailureMode -> TextEncoding
mkUTF8 CodingFailureMode
ErrorOnCodingFailure)
                                    (CodingFailureMode -> TextEncoding
mkUTF16le CodingFailureMode
ErrorOnCodingFailure)
                                    String
".copyFile.tmp"
                         of
            Left EncodingException
err -> String -> OsPath
forall a. HasCallStack => String -> a
error (String
"withReplacementFile: invalid encoding: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ EncodingException -> String
forall a. Show a => a -> String
show EncodingException
err)
            Right OsPath
p -> OsPath
p
      (tmpFPath, hTmp) <- OsPath -> OsPath -> IO (OsPath, Handle)
OS.openBinaryTempFile (OsPath -> OsPath
takeDirectory OsPath
path) OsPath
tmpPath
      (`onException` ignoreIOExceptions (removeFile tmpFPath)) $ do
        r <- (`onException` ignoreIOExceptions (hClose hTmp)) $ do
          restore (action hTmp)
        hClose hTmp
        restore (postAction tmpFPath)
        renameFile tmpFPath path
        pure r
copyFileWithMetadata :: OsPath        
                     -> OsPath        
                     -> IO ()
copyFileWithMetadata :: OsPath -> OsPath -> IO ()
copyFileWithMetadata OsPath
src OsPath
dst =
  (IOError -> String -> IOError
`ioeAddLocation` String
"copyFileWithMetadata") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError`
    (Metadata -> OsPath -> IO ())
-> (Metadata -> OsPath -> IO ()) -> OsPath -> OsPath -> IO ()
copyFileWithMetadataInternal Metadata -> OsPath -> IO ()
copyPermissionsFromMetadata
                                 Metadata -> OsPath -> IO ()
copyTimesFromMetadata
                                 OsPath
src
                                 OsPath
dst
copyTimesFromMetadata :: Metadata -> OsPath -> IO ()
copyTimesFromMetadata :: Metadata -> OsPath -> IO ()
copyTimesFromMetadata Metadata
st OsPath
dst = do
  let atime :: UTCTime
atime = Metadata -> UTCTime
accessTimeFromMetadata Metadata
st
  let mtime :: UTCTime
mtime = Metadata -> UTCTime
modificationTimeFromMetadata Metadata
st
  OsPath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes OsPath
dst (UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
atime, UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
mtime)
canonicalizePath :: OsPath -> IO OsPath
canonicalizePath :: OsPath -> IO OsPath
canonicalizePath = \ OsPath
path ->
  ((IOError -> String -> IOError
`ioeAddLocation` String
"canonicalizePath") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
path)) (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    
    OsPath -> OsPath
dropTrailingPathSeparator (OsPath -> OsPath) -> (OsPath -> OsPath) -> OsPath -> OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> OsPath
simplify (OsPath -> OsPath) -> IO OsPath -> IO OsPath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
      ((OsPath -> IO OsPath) -> OsPath -> IO OsPath
attemptRealpath OsPath -> IO OsPath
realPath (OsPath -> IO OsPath) -> IO OsPath -> IO OsPath
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< OsPath -> IO OsPath
prependCurrentDirectory OsPath
path)
  where
    
    attemptRealpath :: (OsPath -> IO OsPath) -> OsPath -> IO OsPath
attemptRealpath OsPath -> IO OsPath
realpath =
      Int -> Maybe OsPath -> (OsPath -> IO OsPath) -> OsPath -> IO OsPath
forall {a}.
(Ord a, Num a) =>
a -> Maybe OsPath -> (OsPath -> IO OsPath) -> OsPath -> IO OsPath
attemptRealpathWith (Int
64 :: Int) Maybe OsPath
forall a. Maybe a
Nothing OsPath -> IO OsPath
realpath
      (OsPath -> IO OsPath)
-> (OsPath -> IO OsPath) -> OsPath -> IO OsPath
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< OsPath -> IO OsPath
canonicalizePathSimplify
    
    
    
    attemptRealpathWith :: a -> Maybe OsPath -> (OsPath -> IO OsPath) -> OsPath -> IO OsPath
attemptRealpathWith a
n Maybe OsPath
mFallback OsPath -> IO OsPath
realpath OsPath
path =
      case Maybe OsPath
mFallback of
        
        Just OsPath
fallback | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 -> OsPath -> IO OsPath
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure OsPath
fallback
        
        
        Maybe OsPath
_ -> [(OsPath, OsPath)] -> IO OsPath
realpathPrefix ([(OsPath, OsPath)] -> [(OsPath, OsPath)]
forall a. [a] -> [a]
reverse ([OsPath] -> [OsPath] -> [(OsPath, OsPath)]
forall a b. [a] -> [b] -> [(a, b)]
zip [OsPath]
prefixes [OsPath]
suffixes))
      where
        segments :: [OsPath]
segments = OsPath -> [OsPath]
splitDirectories OsPath
path
        prefixes :: [OsPath]
prefixes = (OsPath -> OsPath -> OsPath) -> [OsPath] -> [OsPath]
forall a. (a -> a -> a) -> [a] -> [a]
scanl1 OsPath -> OsPath -> OsPath
(</>) [OsPath]
segments
        suffixes :: [OsPath]
suffixes = NonEmpty OsPath -> [OsPath]
forall a. NonEmpty a -> [a]
NE.tail ((OsPath -> OsPath -> OsPath)
-> OsPath -> [OsPath] -> NonEmpty OsPath
forall (f :: * -> *) a b.
Foldable f =>
(a -> b -> b) -> b -> f a -> NonEmpty b
NE.scanr OsPath -> OsPath -> OsPath
(</>) OsPath
forall a. Monoid a => a
mempty [OsPath]
segments)
        
        realpathPrefix :: [(OsPath, OsPath)] -> IO OsPath
realpathPrefix [(OsPath, OsPath)]
candidates =
          case [(OsPath, OsPath)]
candidates of
            [] -> OsPath -> IO OsPath
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure OsPath
path
            (OsPath
prefix, OsPath
suffix) : [(OsPath, OsPath)]
rest -> do
              exist <- OsPath -> IO Bool
doesPathExist OsPath
prefix
              if not exist
                
                
                
                then realpathPrefix rest
                else do
                  mp <- tryIOError (realpath prefix)
                  case mp of
                    
                    Left IOError
_ -> [(OsPath, OsPath)] -> IO OsPath
realpathPrefix [(OsPath, OsPath)]
rest
                    
                    Right OsPath
p -> OsPath -> OsPath -> OsPath -> IO OsPath
realpathFurther (OsPath
p OsPath -> OsPath -> OsPath
</> OsPath
suffix) OsPath
p OsPath
suffix
        
        
        
        
        realpathFurther :: OsPath -> OsPath -> OsPath -> IO OsPath
realpathFurther OsPath
fallback OsPath
p OsPath
suffix =
          case OsPath -> [OsPath]
splitDirectories OsPath
suffix of
            [] -> OsPath -> IO OsPath
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure OsPath
fallback
            OsPath
next : [OsPath]
restSuffix -> do
              
              mTarget <- IO OsPath -> IO (Either IOError OsPath)
forall a. IO a -> IO (Either IOError a)
tryIOError (OsPath -> IO OsPath
getSymbolicLinkTarget (OsPath
p OsPath -> OsPath -> OsPath
</> OsPath
next))
              case mTarget of
                Left IOError
_ -> OsPath -> IO OsPath
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure OsPath
fallback
                Right OsPath
target -> do
                  
                  let mFallback' :: Maybe OsPath
mFallback' = OsPath -> Maybe OsPath
forall a. a -> Maybe a
Just (OsPath -> Maybe OsPath -> OsPath
forall a. a -> Maybe a -> a
fromMaybe OsPath
fallback Maybe OsPath
mFallback)
                  path' <- OsPath -> IO OsPath
canonicalizePathSimplify
                             (OsPath
p OsPath -> OsPath -> OsPath
</> OsPath
target OsPath -> OsPath -> OsPath
</> [OsPath] -> OsPath
joinPath [OsPath]
restSuffix)
                  attemptRealpathWith (n - 1) mFallback' realpath path'
makeAbsolute :: OsPath -> IO OsPath
makeAbsolute :: OsPath -> IO OsPath
makeAbsolute OsPath
path =
  ((IOError -> String -> IOError
`ioeAddLocation` String
"makeAbsolute") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
path)) (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> OsPath -> OsPath
matchTrailingSeparator OsPath
path (OsPath -> OsPath) -> (OsPath -> OsPath) -> OsPath -> OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsPath -> OsPath
simplify (OsPath -> OsPath) -> IO OsPath -> IO OsPath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> IO OsPath
prependCurrentDirectory OsPath
path
matchTrailingSeparator :: OsPath -> OsPath -> OsPath
matchTrailingSeparator :: OsPath -> OsPath -> OsPath
matchTrailingSeparator OsPath
path
  | OsPath -> Bool
hasTrailingPathSeparator OsPath
path = OsPath -> OsPath
addTrailingPathSeparator
  | Bool
otherwise                     = OsPath -> OsPath
dropTrailingPathSeparator
makeRelativeToCurrentDirectory :: OsPath -> IO OsPath
makeRelativeToCurrentDirectory :: OsPath -> IO OsPath
makeRelativeToCurrentDirectory OsPath
x = do
  (OsPath -> OsPath -> OsPath
`makeRelative` OsPath
x) (OsPath -> OsPath) -> IO OsPath -> IO OsPath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO OsPath
getCurrentDirectory
findExecutable :: OsString -> IO (Maybe OsPath)
findExecutable :: OsPath -> IO (Maybe OsPath)
findExecutable OsPath
binary =
  ListT IO OsPath -> IO (Maybe OsPath)
forall (m :: * -> *) a. Functor m => ListT m a -> m (Maybe a)
listTHead
    (([OsPath] -> OsPath -> ListT IO OsPath)
-> OsPath -> ListT IO OsPath
findExecutablesLazyInternal [OsPath] -> OsPath -> ListT IO OsPath
findExecutablesInDirectoriesLazy OsPath
binary)
findExecutables :: OsString -> IO [OsPath]
findExecutables :: OsPath -> IO [OsPath]
findExecutables OsPath
binary =
  ListT IO OsPath -> IO [OsPath]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
listTToList
    (([OsPath] -> OsPath -> ListT IO OsPath)
-> OsPath -> ListT IO OsPath
findExecutablesLazyInternal [OsPath] -> OsPath -> ListT IO OsPath
findExecutablesInDirectoriesLazy OsPath
binary)
findExecutablesInDirectories :: [OsPath] -> OsString -> IO [OsPath]
findExecutablesInDirectories :: [OsPath] -> OsPath -> IO [OsPath]
findExecutablesInDirectories [OsPath]
path OsPath
binary =
  ListT IO OsPath -> IO [OsPath]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
listTToList ([OsPath] -> OsPath -> ListT IO OsPath
findExecutablesInDirectoriesLazy [OsPath]
path OsPath
binary)
findExecutablesInDirectoriesLazy :: [OsPath] -> OsString -> ListT IO OsPath
findExecutablesInDirectoriesLazy :: [OsPath] -> OsPath -> ListT IO OsPath
findExecutablesInDirectoriesLazy [OsPath]
path OsPath
binary =
  (OsPath -> IO Bool) -> [OsPath] -> OsPath -> ListT IO OsPath
findFilesWithLazy OsPath -> IO Bool
isExecutable [OsPath]
path (OsPath
binary OsPath -> OsPath -> OsPath
<.> OsPath
exeExtension)
isExecutable :: OsPath -> IO Bool
isExecutable :: OsPath -> IO Bool
isExecutable OsPath
file = Permissions -> Bool
executable (Permissions -> Bool) -> IO Permissions -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> IO Permissions
getPermissions OsPath
file
findFile :: [OsPath] -> OsString -> IO (Maybe OsPath)
findFile :: [OsPath] -> OsPath -> IO (Maybe OsPath)
findFile = (OsPath -> IO Bool) -> [OsPath] -> OsPath -> IO (Maybe OsPath)
findFileWith (\ OsPath
_ -> Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
findFiles :: [OsPath] -> OsString -> IO [OsPath]
findFiles :: [OsPath] -> OsPath -> IO [OsPath]
findFiles = (OsPath -> IO Bool) -> [OsPath] -> OsPath -> IO [OsPath]
findFilesWith (\ OsPath
_ -> Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
findFileWith :: (OsPath -> IO Bool) -> [OsPath] -> OsString -> IO (Maybe OsPath)
findFileWith :: (OsPath -> IO Bool) -> [OsPath] -> OsPath -> IO (Maybe OsPath)
findFileWith OsPath -> IO Bool
f [OsPath]
ds OsPath
name = ListT IO OsPath -> IO (Maybe OsPath)
forall (m :: * -> *) a. Functor m => ListT m a -> m (Maybe a)
listTHead ((OsPath -> IO Bool) -> [OsPath] -> OsPath -> ListT IO OsPath
findFilesWithLazy OsPath -> IO Bool
f [OsPath]
ds OsPath
name)
findFilesWith :: (OsPath -> IO Bool) -> [OsPath] -> OsString -> IO [OsPath]
findFilesWith :: (OsPath -> IO Bool) -> [OsPath] -> OsPath -> IO [OsPath]
findFilesWith OsPath -> IO Bool
f [OsPath]
ds OsPath
name = ListT IO OsPath -> IO [OsPath]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
listTToList ((OsPath -> IO Bool) -> [OsPath] -> OsPath -> ListT IO OsPath
findFilesWithLazy OsPath -> IO Bool
f [OsPath]
ds OsPath
name)
findFilesWithLazy
  :: (OsPath -> IO Bool) -> [OsPath] -> OsString -> ListT IO OsPath
findFilesWithLazy :: (OsPath -> IO Bool) -> [OsPath] -> OsPath -> ListT IO OsPath
findFilesWithLazy OsPath -> IO Bool
f [OsPath]
dirs OsPath
path
  
  
  | OsPath -> Bool
isAbsolute OsPath
path = IO (Maybe (OsPath, ListT IO OsPath)) -> ListT IO OsPath
forall (m :: * -> *) a. m (Maybe (a, ListT m a)) -> ListT m a
ListT ([OsPath] -> IO (Maybe (OsPath, ListT IO OsPath))
find [OsPath
forall a. Monoid a => a
mempty])
  | Bool
otherwise       = IO (Maybe (OsPath, ListT IO OsPath)) -> ListT IO OsPath
forall (m :: * -> *) a. m (Maybe (a, ListT m a)) -> ListT m a
ListT ([OsPath] -> IO (Maybe (OsPath, ListT IO OsPath))
find [OsPath]
dirs)
  where
    find :: [OsPath] -> IO (Maybe (OsPath, ListT IO OsPath))
find []       = Maybe (OsPath, ListT IO OsPath)
-> IO (Maybe (OsPath, ListT IO OsPath))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (OsPath, ListT IO OsPath)
forall a. Maybe a
Nothing
    find (OsPath
d : [OsPath]
ds) = do
      let p :: OsPath
p = OsPath
d OsPath -> OsPath -> OsPath
</> OsPath
path
      found <- OsPath -> IO Bool
doesFileExist OsPath
p IO Bool -> IO Bool -> IO Bool
forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
`andM` OsPath -> IO Bool
f OsPath
p
      if found
        then pure (Just (p, ListT (find ds)))
        else find ds
exeExtension :: OsString
exeExtension :: OsPath
exeExtension = OsPath
exeExtensionInternal
getDirectoryContents :: OsPath -> IO [OsPath]
getDirectoryContents :: OsPath -> IO [OsPath]
getDirectoryContents OsPath
path =
  ((IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
path) (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (IOError -> String -> IOError
`ioeAddLocation` String
"getDirectoryContents")) (IOError -> IOError) -> IO [OsPath] -> IO [OsPath]
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> IO [OsPath]
getDirectoryContentsInternal OsPath
path
listDirectory :: OsPath -> IO [OsPath]
listDirectory :: OsPath -> IO [OsPath]
listDirectory OsPath
path = [OsPath] -> [OsPath]
dropSpecialDotDirs ([OsPath] -> [OsPath]) -> IO [OsPath] -> IO [OsPath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> IO [OsPath]
getDirectoryContents OsPath
path
getCurrentDirectory :: IO OsPath
getCurrentDirectory :: IO OsPath
getCurrentDirectory =
  (IOError -> String -> IOError
`ioeAddLocation` String
"getCurrentDirectory") (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    String -> (IOError -> Bool) -> IO OsPath -> IO OsPath
forall a. String -> (IOError -> Bool) -> IO a -> IO a
specializeErrorString
      String
"Current working directory no longer exists"
      IOError -> Bool
isDoesNotExistError
      IO OsPath
getCurrentDirectoryInternal
setCurrentDirectory :: OsPath -> IO ()
setCurrentDirectory :: OsPath -> IO ()
setCurrentDirectory = OsPath -> IO ()
setCurrentDirectoryInternal
withCurrentDirectory :: OsPath    
                     -> IO a      
                     -> IO a
withCurrentDirectory :: forall a. OsPath -> IO a -> IO a
withCurrentDirectory OsPath
dir IO a
action =
  IO OsPath -> (OsPath -> IO ()) -> (OsPath -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO OsPath
getCurrentDirectory OsPath -> IO ()
setCurrentDirectory ((OsPath -> IO a) -> IO a) -> (OsPath -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \ OsPath
_ -> do
    OsPath -> IO ()
setCurrentDirectory OsPath
dir
    IO a
action
getFileSize :: OsPath -> IO Integer
getFileSize :: OsPath -> IO Integer
getFileSize OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"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
<$> OsPath -> IO Metadata
getFileMetadata OsPath
path
doesPathExist :: OsPath -> IO Bool
doesPathExist :: OsPath -> IO Bool
doesPathExist OsPath
path = do
  (Bool
True Bool -> IO Metadata -> IO Bool
forall a b. a -> IO b -> IO a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ OsPath -> IO Metadata
getFileMetadata OsPath
path)
    IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ IOError
_ ->
      Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
doesDirectoryExist :: OsPath -> IO Bool
doesDirectoryExist :: OsPath -> IO Bool
doesDirectoryExist OsPath
path = do
  OsPath -> IO Bool
pathIsDirectory OsPath
path
    IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ IOError
_ ->
      Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
doesFileExist :: OsPath -> IO Bool
doesFileExist :: OsPath -> IO Bool
doesFileExist OsPath
path = do
  (Bool -> Bool
not (Bool -> Bool) -> IO Bool -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> IO Bool
pathIsDirectory OsPath
path)
    IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` \ IOError
_ ->
      Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
pathIsDirectory :: OsPath -> IO Bool
pathIsDirectory :: OsPath -> IO Bool
pathIsDirectory OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"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
<$> OsPath -> IO Metadata
getFileMetadata OsPath
path
createFileLink
  :: OsPath                           
  -> OsPath                           
  -> IO ()
createFileLink :: OsPath -> OsPath -> IO ()
createFileLink OsPath
target OsPath
link =
  (IOError -> String -> IOError
`ioeAddLocation` String
"createFileLink") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    Bool -> OsPath -> OsPath -> IO ()
createSymbolicLink Bool
False OsPath
target OsPath
link
createDirectoryLink
  :: OsPath                           
  -> OsPath                           
  -> IO ()
createDirectoryLink :: OsPath -> OsPath -> IO ()
createDirectoryLink OsPath
target OsPath
link =
  (IOError -> String -> IOError
`ioeAddLocation` String
"createDirectoryLink") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    Bool -> OsPath -> OsPath -> IO ()
createSymbolicLink Bool
True OsPath
target OsPath
link
removeDirectoryLink :: OsPath -> IO ()
removeDirectoryLink :: OsPath -> IO ()
removeDirectoryLink OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"removeDirectoryLink") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    Bool -> OsPath -> IO ()
removePathInternal Bool
linkToDirectoryIsDirectory OsPath
path
pathIsSymbolicLink :: OsPath -> IO Bool
pathIsSymbolicLink :: OsPath -> IO Bool
pathIsSymbolicLink OsPath
path =
  ((IOError -> String -> IOError
`ioeAddLocation` String
"pathIsSymbolicLink") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
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
<$> OsPath -> IO Metadata
getSymbolicLinkMetadata OsPath
path
getSymbolicLinkTarget :: OsPath -> IO OsPath
getSymbolicLinkTarget :: OsPath -> IO OsPath
getSymbolicLinkTarget OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"getSymbolicLinkTarget") (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> IO OsPath
readSymbolicLink OsPath
path
getAccessTime :: OsPath -> IO UTCTime
getAccessTime :: OsPath -> IO UTCTime
getAccessTime OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"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
<$> OsPath -> IO Metadata
getFileMetadata (OsPath -> OsPath
emptyToCurDir OsPath
path)
getModificationTime :: OsPath -> IO UTCTime
getModificationTime :: OsPath -> IO UTCTime
getModificationTime OsPath
path =
  (IOError -> String -> IOError
`ioeAddLocation` String
"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
<$> OsPath -> IO Metadata
getFileMetadata (OsPath -> OsPath
emptyToCurDir OsPath
path)
setAccessTime :: OsPath -> UTCTime -> IO ()
setAccessTime :: OsPath -> UTCTime -> IO ()
setAccessTime OsPath
path UTCTime
atime =
  (IOError -> String -> IOError
`ioeAddLocation` String
"setAccessTime") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes OsPath
path (UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
atime, Maybe UTCTime
forall a. Maybe a
Nothing)
setModificationTime :: OsPath -> UTCTime -> IO ()
setModificationTime :: OsPath -> UTCTime -> IO ()
setModificationTime OsPath
path UTCTime
mtime =
  (IOError -> String -> IOError
`ioeAddLocation` String
"setModificationTime") (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes OsPath
path (Maybe UTCTime
forall a. Maybe a
Nothing, UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
mtime)
setFileTimes :: OsPath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes :: OsPath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()
setFileTimes OsPath
_ (Maybe UTCTime
Nothing, Maybe UTCTime
Nothing) = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
setFileTimes OsPath
path (Maybe UTCTime
atime, Maybe UTCTime
mtime) =
  ((IOError -> String -> IOError
`ioeAddLocation` String
"setFileTimes") (IOError -> IOError) -> (IOError -> IOError) -> IOError -> IOError
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (IOError -> OsPath -> IOError
`ioeSetOsPath` OsPath
path)) (IOError -> IOError) -> IO () -> IO ()
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> (Maybe POSIXTime, Maybe POSIXTime) -> IO ()
setTimes (OsPath -> OsPath
emptyToCurDir OsPath
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 OsPath
getHomeDirectory :: IO OsPath
getHomeDirectory =
  (IOError -> String -> IOError
`ioeAddLocation` String
"getHomeDirectory") (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    getHomeDirectoryInternal
getXdgDirectory :: XdgDirectory         
                -> OsPath             
                                        
                                        
                -> IO OsPath
getXdgDirectory :: XdgDirectory -> OsPath -> IO OsPath
getXdgDirectory XdgDirectory
xdgDir OsPath
suffix =
  (IOError -> String -> IOError
`ioeAddLocation` String
"getXdgDirectory") (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> OsPath
simplify (OsPath -> OsPath) -> (OsPath -> OsPath) -> OsPath -> OsPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OsPath -> OsPath -> OsPath
</> OsPath
suffix) (OsPath -> OsPath) -> IO OsPath -> IO OsPath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> do
      env <- OsPath -> IO (Maybe OsPath)
lookupEnvOs (OsPath -> IO (Maybe OsPath))
-> (String -> OsPath) -> String -> IO (Maybe OsPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> OsPath
os (String -> IO (Maybe OsPath)) -> String -> IO (Maybe OsPath)
forall a b. (a -> b) -> a -> b
$ case XdgDirectory
xdgDir of
        XdgDirectory
XdgData   -> String
"XDG_DATA_HOME"
        XdgDirectory
XdgConfig -> String
"XDG_CONFIG_HOME"
        XdgDirectory
XdgCache  -> String
"XDG_CACHE_HOME"
        XdgDirectory
XdgState  -> String
"XDG_STATE_HOME"
      case env of
        Just OsPath
path | OsPath -> Bool
isAbsolute OsPath
path -> OsPath -> IO OsPath
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure OsPath
path
        Maybe OsPath
_                           -> IO OsPath -> XdgDirectory -> IO OsPath
getXdgDirectoryFallback IO OsPath
getHomeDirectory XdgDirectory
xdgDir
getXdgDirectoryList :: XdgDirectoryList 
                    -> IO [OsPath]
getXdgDirectoryList :: XdgDirectoryList -> IO [OsPath]
getXdgDirectoryList XdgDirectoryList
xdgDirs =
  (IOError -> String -> IOError
`ioeAddLocation` String
"getXdgDirectoryList") (IOError -> IOError) -> IO [OsPath] -> IO [OsPath]
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    env <- OsPath -> IO (Maybe OsPath)
lookupEnvOs (OsPath -> IO (Maybe OsPath))
-> (String -> OsPath) -> String -> IO (Maybe OsPath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> OsPath
os (String -> IO (Maybe OsPath)) -> String -> IO (Maybe OsPath)
forall a b. (a -> b) -> a -> b
$ case XdgDirectoryList
xdgDirs of
      XdgDirectoryList
XdgDataDirs   -> String
"XDG_DATA_DIRS"
      XdgDirectoryList
XdgConfigDirs -> String
"XDG_CONFIG_DIRS"
    case env of
      Maybe OsPath
Nothing    -> XdgDirectoryList -> IO [OsPath]
getXdgDirectoryListFallback XdgDirectoryList
xdgDirs
      Just OsPath
paths -> [OsPath] -> IO [OsPath]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OsPath -> [OsPath]
splitSearchPath OsPath
paths)
getAppUserDataDirectory :: OsPath     
                                        
                        -> IO OsPath
getAppUserDataDirectory :: OsPath -> IO OsPath
getAppUserDataDirectory OsPath
appName = do
  (IOError -> String -> IOError
`ioeAddLocation` String
"getAppUserDataDirectory") (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    OsPath -> IO OsPath
getAppUserDataDirectoryInternal OsPath
appName
getUserDocumentsDirectory :: IO OsPath
getUserDocumentsDirectory :: IO OsPath
getUserDocumentsDirectory = do
  (IOError -> String -> IOError
`ioeAddLocation` String
"getUserDocumentsDirectory") (IOError -> IOError) -> IO OsPath -> IO OsPath
forall a. (IOError -> IOError) -> IO a -> IO a
`modifyIOError` do
    getUserDocumentsDirectoryInternal
getTemporaryDirectory :: IO OsPath
getTemporaryDirectory :: IO OsPath
getTemporaryDirectory = IO OsPath
getTemporaryDirectoryInternal