LIB: refactor copyFile
This commit is contained in:
parent
fa7cab69c6
commit
0a71c3c044
@ -32,6 +32,7 @@ module HSFM.FileSystem.FileOperations where
|
|||||||
import Control.Exception
|
import Control.Exception
|
||||||
(
|
(
|
||||||
throw
|
throw
|
||||||
|
, onException
|
||||||
)
|
)
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
(
|
(
|
||||||
@ -48,7 +49,6 @@ import Foreign.C.Error
|
|||||||
import HPath
|
import HPath
|
||||||
(
|
(
|
||||||
Path
|
Path
|
||||||
, Abs
|
|
||||||
, Fn
|
, Fn
|
||||||
)
|
)
|
||||||
import qualified HPath as P
|
import qualified HPath as P
|
||||||
@ -186,9 +186,9 @@ copyDir cm from@(_ :/ Dir fromn FileInfo{ fileMode = fmode })
|
|||||||
|
|
||||||
for_ contents $ \f ->
|
for_ contents $ \f ->
|
||||||
case f of
|
case f of
|
||||||
(_ :/ SymLink {}) -> recreateSymlink cm f destdir
|
(_ :/ SymLink {}) -> recreateSymlink cm f destdir (name . file $ f)
|
||||||
(_ :/ Dir {}) -> copyDir cm f destdir
|
(_ :/ Dir {}) -> copyDir cm f destdir
|
||||||
(_ :/ RegFile {}) -> copyFileToDir Replace f destdir
|
(_ :/ RegFile {}) -> copyFile Replace f destdir (name . file $ f)
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
where
|
where
|
||||||
createDestdir destdir fmode' =
|
createDestdir destdir fmode' =
|
||||||
@ -213,15 +213,16 @@ recreateSymlink :: CopyMode
|
|||||||
-> AnchoredFile FileInfo -- ^ the old symlink file
|
-> AnchoredFile FileInfo -- ^ the old symlink file
|
||||||
-> AnchoredFile FileInfo -- ^ destination dir of the
|
-> AnchoredFile FileInfo -- ^ destination dir of the
|
||||||
-- new symlink file
|
-- new symlink file
|
||||||
|
-> Path Fn -- ^ destination file name
|
||||||
-> IO ()
|
-> IO ()
|
||||||
recreateSymlink _ AFileInvFN _ = throw InvalidFileName
|
recreateSymlink _ AFileInvFN _ _ = throw InvalidFileName
|
||||||
recreateSymlink _ _ AFileInvFN = throw InvalidFileName
|
recreateSymlink _ _ AFileInvFN _ = throw InvalidFileName
|
||||||
recreateSymlink cm symf@(_ :/ SymLink {})
|
recreateSymlink _ _ _ InvFN = throw InvalidFileName
|
||||||
symdest@(_ :/ Dir {})
|
recreateSymlink cm symf@(_ :/ SymLink {}) symdest@(_ :/ Dir {}) fn
|
||||||
= do
|
= do
|
||||||
throwCantOpenDirectory $ fullPath symdest
|
throwCantOpenDirectory $ fullPath symdest
|
||||||
sympoint <- readSymbolicLink (fullPathS $ symf)
|
sympoint <- readSymbolicLink (fullPathS $ symf)
|
||||||
let symname = fullPath symdest P.</> (name . file $ symf)
|
let symname = fullPath symdest P.</> fn
|
||||||
case cm of
|
case cm of
|
||||||
Merge -> delOld symname
|
Merge -> delOld symname
|
||||||
Replace -> delOld symname
|
Replace -> delOld symname
|
||||||
@ -232,24 +233,41 @@ recreateSymlink cm symf@(_ :/ SymLink {})
|
|||||||
f <- HSFM.FileSystem.FileType.readFileWithFileInfo symname
|
f <- HSFM.FileSystem.FileType.readFileWithFileInfo symname
|
||||||
unless (failed . file $ f)
|
unless (failed . file $ f)
|
||||||
(easyDelete f)
|
(easyDelete f)
|
||||||
recreateSymlink _ _ _ = throw $ InvalidOperation "wrong input type"
|
recreateSymlink _ _ _ _ = throw $ InvalidOperation "wrong input type"
|
||||||
|
|
||||||
|
|
||||||
-- |TODO: handle EAGAIN exception for non-blocking IO
|
-- |TODO: handle EAGAIN exception for non-blocking IO
|
||||||
-- |Low-level function to copy a given file to the given path. The fileMode
|
-- TODO: implement for non-regular file? This would deprecate the logic
|
||||||
-- is preserved. The file is always overwritten if accessible.
|
-- in copyDir
|
||||||
copyFile' :: Path Abs -> Path Abs -> IO ()
|
-- |Copies the given file to the given dir with the given filename.
|
||||||
copyFile' from to = do
|
-- Excludes symlinks.
|
||||||
let from' = P.fromAbs from
|
copyFile :: CopyMode
|
||||||
to' = P.fromAbs to
|
-> AnchoredFile FileInfo -- ^ source file
|
||||||
throwCantOpenDirectory $ P.dirname from
|
-> AnchoredFile FileInfo -- ^ destination dir
|
||||||
throwCantOpenDirectory $ P.dirname to
|
-> Path Fn -- ^ destination file name
|
||||||
fromFstatus <- getSymbolicLinkStatus from'
|
-> IO ()
|
||||||
fromContent <- BS.readFile from'
|
copyFile _ AFileInvFN _ _ = throw InvalidFileName
|
||||||
fd <- SPI.createFile to'
|
copyFile _ _ AFileInvFN _ = throw InvalidFileName
|
||||||
(System.Posix.Files.fileMode fromFstatus)
|
copyFile _ _ _ InvFN = throw InvalidFileName
|
||||||
_ <- fdWrite fd fromContent
|
copyFile cm from@(_ :/ RegFile {}) to@(_ :/ Dir {}) fn
|
||||||
SPI.closeFd fd
|
= do
|
||||||
|
let from' = fullPath from
|
||||||
|
to' = fullPath to P.</> fn
|
||||||
|
throwCantOpenDirectory $ fullPath to
|
||||||
|
case cm of
|
||||||
|
Strict -> throwFileDoesExist to'
|
||||||
|
_ -> return ()
|
||||||
|
|
||||||
|
throwCantOpenDirectory . P.dirname . fullPath $ from
|
||||||
|
throwCantOpenDirectory . fullPath $ to
|
||||||
|
fromFstatus <- getSymbolicLinkStatus (P.fromAbs from')
|
||||||
|
fromContent <- BS.readFile (P.fromAbs from')
|
||||||
|
fd <- SPI.createFile (P.fromAbs to')
|
||||||
|
(System.Posix.Files.fileMode fromFstatus)
|
||||||
|
_ <- onException (fdWrite fd fromContent) (SPI.closeFd fd)
|
||||||
|
SPI.closeFd fd
|
||||||
|
|
||||||
|
copyFile _ _ _ _ = throw $ InvalidOperation "wrong input type"
|
||||||
|
|
||||||
|
|
||||||
-- |Copies the given file to the given file destination, overwriting it.
|
-- |Copies the given file to the given file destination, overwriting it.
|
||||||
@ -267,31 +285,10 @@ overwriteFile from@(_ :/ RegFile {})
|
|||||||
throwCantOpenDirectory $ P.dirname from'
|
throwCantOpenDirectory $ P.dirname from'
|
||||||
throwCantOpenDirectory $ P.dirname to'
|
throwCantOpenDirectory $ P.dirname to'
|
||||||
throwSameFile from' to'
|
throwSameFile from' to'
|
||||||
copyFile' from' to'
|
copyFile Replace from to (name . file $ to)
|
||||||
overwriteFile _ _ = throw $ InvalidOperation "wrong input type"
|
overwriteFile _ _ = throw $ InvalidOperation "wrong input type"
|
||||||
|
|
||||||
|
|
||||||
-- |Copies the given file to the given dir with the same filename.
|
|
||||||
-- Excludes symlinks.
|
|
||||||
copyFileToDir :: CopyMode
|
|
||||||
-> AnchoredFile FileInfo
|
|
||||||
-> AnchoredFile FileInfo
|
|
||||||
-> IO ()
|
|
||||||
copyFileToDir _ AFileInvFN _ = throw InvalidFileName
|
|
||||||
copyFileToDir _ _ AFileInvFN = throw InvalidFileName
|
|
||||||
copyFileToDir cm from@(_ :/ RegFile fn _)
|
|
||||||
to@(_ :/ Dir {})
|
|
||||||
= do
|
|
||||||
let from' = fullPath from
|
|
||||||
to' = fullPath to P.</> fn
|
|
||||||
throwCantOpenDirectory $ fullPath to
|
|
||||||
case cm of
|
|
||||||
Strict -> throwFileDoesExist to'
|
|
||||||
_ -> return ()
|
|
||||||
copyFile' from' to'
|
|
||||||
copyFileToDir _ _ _ = throw $ InvalidOperation "wrong input type"
|
|
||||||
|
|
||||||
|
|
||||||
-- |Copies a file, directory or symlink. In case of a symlink, it is just
|
-- |Copies a file, directory or symlink. In case of a symlink, it is just
|
||||||
-- recreated, even if it points to a directory.
|
-- recreated, even if it points to a directory.
|
||||||
easyCopy :: CopyMode
|
easyCopy :: CopyMode
|
||||||
@ -300,10 +297,10 @@ easyCopy :: CopyMode
|
|||||||
-> IO ()
|
-> IO ()
|
||||||
easyCopy cm from@(_ :/ SymLink{})
|
easyCopy cm from@(_ :/ SymLink{})
|
||||||
to@(_ :/ Dir{})
|
to@(_ :/ Dir{})
|
||||||
= recreateSymlink cm from to
|
= recreateSymlink cm from to (name . file $ from)
|
||||||
easyCopy cm from@(_ :/ RegFile{})
|
easyCopy cm from@(_ :/ RegFile{})
|
||||||
to@(_ :/ Dir{})
|
to@(_ :/ Dir{})
|
||||||
= copyFileToDir cm from to
|
= copyFile cm from to (name . file $ from)
|
||||||
easyCopy cm from@(_ :/ Dir{})
|
easyCopy cm from@(_ :/ Dir{})
|
||||||
to@(_ :/ Dir{})
|
to@(_ :/ Dir{})
|
||||||
= copyDir cm from to
|
= copyDir cm from to
|
||||||
|
Loading…
Reference in New Issue
Block a user