LIB/TESTS: fix moveFileOverwrite and add tests

We must not allow to move a file to a directory, deleting that
directory and effectively changing the filetype.
This commit is contained in:
Julian Ospald 2016-05-08 23:20:00 +02:00
parent 8646a6338c
commit 5b6a342a9e
No known key found for this signature in database
GPG Key ID: 511B62C09D50CD28
10 changed files with 112 additions and 3 deletions

View File

@ -133,6 +133,7 @@ Test-Suite spec
FileSystem.FileOperations.GetDirsFilesSpec FileSystem.FileOperations.GetDirsFilesSpec
FileSystem.FileOperations.GetFileTypeSpec FileSystem.FileOperations.GetFileTypeSpec
FileSystem.FileOperations.MoveFileSpec FileSystem.FileOperations.MoveFileSpec
FileSystem.FileOperations.MoveFileOverwriteSpec
FileSystem.FileOperations.RecreateSymlinkSpec FileSystem.FileOperations.RecreateSymlinkSpec
FileSystem.FileOperations.RenameFileSpec FileSystem.FileOperations.RenameFileSpec
Utils Utils

View File

@ -676,7 +676,7 @@ moveFile from to = do
-- Safety/reliability concerns: -- Safety/reliability concerns:
-- --
-- * copy-delete fallback is inherently non-atomic -- * copy-delete fallback is inherently non-atomic
-- * checks for destination file existence explicitly -- * checks for file types and destination file existence explicitly
-- --
-- Throws: -- Throws:
-- --
@ -691,9 +691,20 @@ moveFileOverwrite :: Path Abs -- ^ file to move
-> IO () -> IO ()
moveFileOverwrite from to = do moveFileOverwrite from to = do
throwSameFile from to throwSameFile from to
exists <- (||) <$> doesFileExist to <*> doesDirectoryExist to ft <- getFileType from
writable <- isWritable $ P.dirname to writable <- isWritable $ P.dirname to
when (exists && writable) (easyDelete to) case ft of
RegularFile -> do
exists <- doesFileExist to
when (exists && writable) (deleteFile to)
SymbolicLink -> do
exists <- doesFileExist to
when (exists && writable) (deleteFile to)
Directory -> do
exists <- doesDirectoryExist to
when (exists && writable) (deleteDir to)
_ -> ioError $ userError $ "Don't know how to handle filetype " ++
show ft
moveFile from to moveFile from to

View File

@ -0,0 +1,81 @@
{-# LANGUAGE OverloadedStrings #-}
module FileSystem.FileOperations.MoveFileOverwriteSpec where
import Test.Hspec
import HSFM.FileSystem.Errors
import System.IO.Error
(
ioeGetErrorType
)
import GHC.IO.Exception
(
IOErrorType(..)
)
import Utils
moveFileOverwriteSpec :: Spec
moveFileOverwriteSpec =
describe "HSFM.FileSystem.FileOperations.moveFileOverwrite" $ do
-- successes --
it "moveFileOverwrite, all fine" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/movedFile"
it "moveFileOverwrite, all fine" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/dir/movedFile"
it "moveFileOverwrite, all fine on symlink" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFileL"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/movedFile"
it "moveFileOverwrite, all fine on directory" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/dir"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/movedFile"
it "moveFileOverwrite, destination file already exists" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/alreadyExists"
-- posix failures --
it "moveFileOverwrite, source file does not exist" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/fileDoesNotExist"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/movedFile"
`shouldThrow`
(\e -> ioeGetErrorType e == NoSuchThing)
it "moveFileOverwrite, can't write to destination directory" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/noWritePerm/movedFile"
`shouldThrow`
(\e -> ioeGetErrorType e == PermissionDenied)
it "moveFileOverwrite, can't open destination directory" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/noPerms/movedFile"
`shouldThrow`
(\e -> ioeGetErrorType e == PermissionDenied)
it "moveFileOverwrite, can't open source directory" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/noPerms/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/movedFile"
`shouldThrow`
(\e -> ioeGetErrorType e == PermissionDenied)
-- custom failures --
it "moveFileOverwrite, move from file to dir" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/alreadyExistsD"
`shouldThrow`
isDirDoesExist
it "moveFileOverwrite, source and dest are same file" $
moveFileOverwrite' "test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
"test/FileSystem/FileOperations/moveFileOverwriteSpec/myFile"
`shouldThrow`
isSameFile

View File

@ -0,0 +1,4 @@
asd
sda
sda

View File

@ -0,0 +1 @@
myFile

View File

@ -14,6 +14,7 @@ import FileSystem.FileOperations.DeleteFileSpec
import FileSystem.FileOperations.GetDirsFilesSpec import FileSystem.FileOperations.GetDirsFilesSpec
import FileSystem.FileOperations.GetFileTypeSpec import FileSystem.FileOperations.GetFileTypeSpec
import FileSystem.FileOperations.MoveFileSpec import FileSystem.FileOperations.MoveFileSpec
import FileSystem.FileOperations.MoveFileOverwriteSpec
import FileSystem.FileOperations.RecreateSymlinkSpec import FileSystem.FileOperations.RecreateSymlinkSpec
import FileSystem.FileOperations.RenameFileSpec import FileSystem.FileOperations.RenameFileSpec
import Utils import Utils
@ -32,6 +33,7 @@ main = hspec $ before_ fixPermissions $ after_ revertPermissions $ do
,createRegularFileSpec ,createRegularFileSpec
,renameFileSpec ,renameFileSpec
,moveFileSpec ,moveFileSpec
,moveFileOverwriteSpec
,recreateSymlinkSpec ,recreateSymlinkSpec
,deleteFileSpec ,deleteFileSpec
,deleteDirSpec ,deleteDirSpec
@ -55,6 +57,7 @@ main = hspec $ before_ fixPermissions $ after_ revertPermissions $ do
,"test/FileSystem/FileOperations/createRegularFileSpec/noWritePerms" ,"test/FileSystem/FileOperations/createRegularFileSpec/noWritePerms"
,"test/FileSystem/FileOperations/renameFileSpec/noWritePerm" ,"test/FileSystem/FileOperations/renameFileSpec/noWritePerm"
,"test/FileSystem/FileOperations/moveFileSpec/noWritePerm" ,"test/FileSystem/FileOperations/moveFileSpec/noWritePerm"
,"test/FileSystem/FileOperations/moveFileOverwriteSpec/noWritePerm"
,"test/FileSystem/FileOperations/recreateSymlinkSpec/noWritePerm" ,"test/FileSystem/FileOperations/recreateSymlinkSpec/noWritePerm"
] ]
noPermsDirs = ["test/FileSystem/FileOperations/copyFileSpec/noPerms" noPermsDirs = ["test/FileSystem/FileOperations/copyFileSpec/noPerms"
@ -65,6 +68,7 @@ main = hspec $ before_ fixPermissions $ after_ revertPermissions $ do
,"test/FileSystem/FileOperations/createRegularFileSpec/noPerms" ,"test/FileSystem/FileOperations/createRegularFileSpec/noPerms"
,"test/FileSystem/FileOperations/renameFileSpec/noPerms" ,"test/FileSystem/FileOperations/renameFileSpec/noPerms"
,"test/FileSystem/FileOperations/moveFileSpec/noPerms" ,"test/FileSystem/FileOperations/moveFileSpec/noPerms"
,"test/FileSystem/FileOperations/moveFileOverwriteSpec/noPerms"
,"test/FileSystem/FileOperations/recreateSymlinkSpec/noPerms" ,"test/FileSystem/FileOperations/recreateSymlinkSpec/noPerms"
,"test/FileSystem/FileOperations/getFileTypeSpec/noPerms" ,"test/FileSystem/FileOperations/getFileTypeSpec/noPerms"
,"test/FileSystem/FileOperations/getDirsFilesSpec/noPerms" ,"test/FileSystem/FileOperations/getDirsFilesSpec/noPerms"

View File

@ -109,6 +109,13 @@ moveFile' inputFileP outputFileP =
moveFile o i moveFile o i
moveFileOverwrite' :: ByteString -> ByteString -> IO ()
moveFileOverwrite' inputFileP outputFileP =
withPwd' inputFileP outputFileP $ \i o -> do
moveFileOverwrite i o
moveFile o i
recreateSymlink' :: ByteString -> ByteString -> IO () recreateSymlink' :: ByteString -> ByteString -> IO ()
recreateSymlink' inputFileP outputFileP = recreateSymlink' inputFileP outputFileP =
withPwd' inputFileP outputFileP recreateSymlink withPwd' inputFileP outputFileP recreateSymlink