Add createDirRecursive, fixes #6
This commit is contained in:
parent
ac381cbf60
commit
5b08e14b55
@ -82,6 +82,7 @@ test-suite spec
|
|||||||
HPath.IO.CopyFileOverwriteSpec
|
HPath.IO.CopyFileOverwriteSpec
|
||||||
HPath.IO.CopyFileSpec
|
HPath.IO.CopyFileSpec
|
||||||
HPath.IO.CreateDirSpec
|
HPath.IO.CreateDirSpec
|
||||||
|
HPath.IO.CreateDirRecursiveSpec
|
||||||
HPath.IO.CreateRegularFileSpec
|
HPath.IO.CreateRegularFileSpec
|
||||||
HPath.IO.CreateSymlinkSpec
|
HPath.IO.CreateSymlinkSpec
|
||||||
HPath.IO.DeleteDirRecursiveSpec
|
HPath.IO.DeleteDirRecursiveSpec
|
||||||
|
@ -55,6 +55,7 @@ module HPath.IO
|
|||||||
-- * File creation
|
-- * File creation
|
||||||
, createRegularFile
|
, createRegularFile
|
||||||
, createDir
|
, createDir
|
||||||
|
, createDirRecursive
|
||||||
, createSymlink
|
, createSymlink
|
||||||
-- * File renaming/moving
|
-- * File renaming/moving
|
||||||
, renameFile
|
, renameFile
|
||||||
@ -115,9 +116,11 @@ import Foreign.C.Error
|
|||||||
(
|
(
|
||||||
eEXIST
|
eEXIST
|
||||||
, eINVAL
|
, eINVAL
|
||||||
|
, eNOENT
|
||||||
, eNOSYS
|
, eNOSYS
|
||||||
, eNOTEMPTY
|
, eNOTEMPTY
|
||||||
, eXDEV
|
, eXDEV
|
||||||
|
, getErrno
|
||||||
)
|
)
|
||||||
import Foreign.C.Types
|
import Foreign.C.Types
|
||||||
(
|
(
|
||||||
@ -683,6 +686,37 @@ createDir :: FileMode -> Path Abs -> IO ()
|
|||||||
createDir fm dest = createDirectory (fromAbs dest) fm
|
createDir fm dest = createDirectory (fromAbs dest) fm
|
||||||
|
|
||||||
|
|
||||||
|
-- |Create an empty directory at the given directory with the given filename.
|
||||||
|
--
|
||||||
|
-- All parent directories are created with the same filemode. This
|
||||||
|
-- basically behaves like:
|
||||||
|
--
|
||||||
|
-- @
|
||||||
|
-- mkdir -p \/destination\/somedir
|
||||||
|
-- @
|
||||||
|
--
|
||||||
|
-- Safety/reliability concerns:
|
||||||
|
--
|
||||||
|
-- * not atomic
|
||||||
|
--
|
||||||
|
-- Throws:
|
||||||
|
--
|
||||||
|
-- - `PermissionDenied` if any part of the path components do not
|
||||||
|
-- exist and cannot be written to
|
||||||
|
-- - `AlreadyExists` if destination already exists and
|
||||||
|
-- is not a directory
|
||||||
|
createDirRecursive :: FileMode -> Path Abs -> IO ()
|
||||||
|
createDirRecursive fm dest =
|
||||||
|
catchIOError (createDirectory (fromAbs dest) fm) $ \e -> do
|
||||||
|
errno <- getErrno
|
||||||
|
isd <- doesDirectoryExist dest
|
||||||
|
case errno of
|
||||||
|
en | en == eEXIST && isd -> return ()
|
||||||
|
| en == eNOENT -> createDirRecursive fm (dirname dest)
|
||||||
|
>> createDirectory (fromAbs dest) fm
|
||||||
|
| otherwise -> ioError e
|
||||||
|
|
||||||
|
|
||||||
-- |Create a symlink.
|
-- |Create a symlink.
|
||||||
--
|
--
|
||||||
-- Throws:
|
-- Throws:
|
||||||
|
78
test/HPath/IO/CreateDirRecursiveSpec.hs
Normal file
78
test/HPath/IO/CreateDirRecursiveSpec.hs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module HPath.IO.CreateDirRecursiveSpec where
|
||||||
|
|
||||||
|
|
||||||
|
import Test.Hspec
|
||||||
|
import System.IO.Error
|
||||||
|
(
|
||||||
|
ioeGetErrorType
|
||||||
|
)
|
||||||
|
import GHC.IO.Exception
|
||||||
|
(
|
||||||
|
IOErrorType(..)
|
||||||
|
)
|
||||||
|
import Utils
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
upTmpDir :: IO ()
|
||||||
|
upTmpDir = do
|
||||||
|
setTmpDir "CreateDirRecursiveSpec"
|
||||||
|
createTmpDir
|
||||||
|
|
||||||
|
setupFiles :: IO ()
|
||||||
|
setupFiles = do
|
||||||
|
createDir' "alreadyExists"
|
||||||
|
createRegularFile' "alreadyExistsF"
|
||||||
|
createDir' "noPerms"
|
||||||
|
createDir' "noWritePerms"
|
||||||
|
noPerms "noPerms"
|
||||||
|
noWritableDirPerms "noWritePerms"
|
||||||
|
|
||||||
|
cleanupFiles :: IO ()
|
||||||
|
cleanupFiles = do
|
||||||
|
normalDirPerms "noPerms"
|
||||||
|
normalDirPerms "noWritePerms"
|
||||||
|
deleteDir' "alreadyExists"
|
||||||
|
deleteDir' "noPerms"
|
||||||
|
deleteDir' "noWritePerms"
|
||||||
|
deleteFile' "alreadyExistsF"
|
||||||
|
|
||||||
|
|
||||||
|
spec :: Spec
|
||||||
|
spec = beforeAll_ (upTmpDir >> setupFiles) $ afterAll_ cleanupFiles $
|
||||||
|
describe "HPath.IO.createDirRecursive" $ do
|
||||||
|
|
||||||
|
-- successes --
|
||||||
|
it "createDirRecursive, all fine" $ do
|
||||||
|
createDirRecursive' "newDir"
|
||||||
|
deleteDir' "newDir"
|
||||||
|
|
||||||
|
it "createDirRecursive, parent directories do not exist" $ do
|
||||||
|
createDirRecursive' "some/thing/dada"
|
||||||
|
deleteDir' "some/thing/dada"
|
||||||
|
deleteDir' "some/thing"
|
||||||
|
deleteDir' "some"
|
||||||
|
|
||||||
|
it "createDirRecursive, destination directory already exists" $
|
||||||
|
createDirRecursive' "alreadyExists"
|
||||||
|
|
||||||
|
-- posix failures --
|
||||||
|
it "createDirRecursive, destination already exists and is a file" $
|
||||||
|
createDirRecursive' "alreadyExistsF"
|
||||||
|
`shouldThrow`
|
||||||
|
(\e -> ioeGetErrorType e == AlreadyExists)
|
||||||
|
|
||||||
|
it "createDirRecursive, can't write to output directory" $
|
||||||
|
createDirRecursive' "noWritePerms/newDir"
|
||||||
|
`shouldThrow`
|
||||||
|
(\e -> ioeGetErrorType e == PermissionDenied)
|
||||||
|
|
||||||
|
it "createDirRecursive, can't open output directory" $
|
||||||
|
createDirRecursive' "noPerms/newDir"
|
||||||
|
`shouldThrow`
|
||||||
|
(\e -> ioeGetErrorType e == PermissionDenied)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -182,6 +182,9 @@ createDir' :: ByteString -> IO ()
|
|||||||
{-# NOINLINE createDir' #-}
|
{-# NOINLINE createDir' #-}
|
||||||
createDir' dest = withTmpDir dest (createDir newDirPerms)
|
createDir' dest = withTmpDir dest (createDir newDirPerms)
|
||||||
|
|
||||||
|
createDirRecursive' :: ByteString -> IO ()
|
||||||
|
{-# NOINLINE createDirRecursive' #-}
|
||||||
|
createDirRecursive' dest = withTmpDir dest (createDirRecursive newDirPerms)
|
||||||
|
|
||||||
createRegularFile' :: ByteString -> IO ()
|
createRegularFile' :: ByteString -> IO ()
|
||||||
{-# NOINLINE createRegularFile' #-}
|
{-# NOINLINE createRegularFile' #-}
|
||||||
|
Loading…
Reference in New Issue
Block a user