directory 1.2.7.0 → 1.2.7.1
raw patch · 4 files changed
+64/−18 lines, 4 filesdep ~Win32dep ~basedep ~timePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: Win32, base, time
API changes (from Hackage documentation)
Files
- System/Directory.hs +52/−12
- changelog.md +7/−1
- directory.cabal +4/−4
- tests/TestUtils.hs +1/−1
System/Directory.hs view
@@ -570,33 +570,68 @@ mapM_ removePathRecursive [path </> x | x <- cont] removeDirectory path --- | @'removePathForcibly@ removes a file or directory at /path/ together with--- its contents and subdirectories. Symbolic links are removed without--- affecting their the targets. If the path does not exist, nothing happens.+-- | Removes a file or directory at /path/ together with its contents and+-- subdirectories. Symbolic links are removed without affecting their+-- targets. If the path does not exist, nothing happens. -- -- Unlike other removal functions, this function will also attempt to delete -- files marked as read-only or otherwise made unremovable due to permissions. -- As a result, if the removal is incomplete, the permissions or attributes on -- the remaining files may be altered.+--+-- If an entry within the directory vanishes while @removePathForcibly@ is+-- running, it is silently ignored.+--+-- If an exception occurs while removing an entry, @removePathForcibly@ will+-- still try to remove as many entries as it can before failing with an+-- exception. The first exception that it encountered is re-thrown.+--+-- @since 1.2.7.0 removePathForcibly :: FilePath -> IO () removePathForcibly path = (`ioeSetLocation` "removePathForcibly") `modifyIOError` do makeRemovable path `catchIOError` \ _ -> return ()- dirType <- tryIOErrorType isDoesNotExistError (getDirectoryType path)- case dirType of- Left _ -> return ()- Right NotDirectory -> removeFile path- Right DirectoryLink -> removeDirectory path- Right Directory -> do- mapM_ (removePathForcibly . (path </>)) =<< listDirectory path- removeDirectory path+ ignoreDoesNotExistError $ do+ dirType <- getDirectoryType path+ case dirType of+ NotDirectory -> removeFile path+ DirectoryLink -> removeDirectory path+ Directory -> do+ names <- listDirectory path+ sequenceWithIOErrors_ $+ [ removePathForcibly (path </> name) | name <- names ] +++ [ removeDirectory path ] where++ ignoreDoesNotExistError :: IO () -> IO ()+ ignoreDoesNotExistError action = do+ _ <- tryIOErrorType isDoesNotExistError action+ return ()++ makeRemovable :: FilePath -> IO () makeRemovable p = do perms <- getPermissions p setPermissions path perms{ readable = True , searchable = True , writable = True } +sequenceWithIOErrors_ :: [IO ()] -> IO ()+sequenceWithIOErrors_ actions = go (Right ()) actions+ where++ go :: Either IOError () -> [IO ()] -> IO ()+ go (Left e) [] = ioError e+ go (Right ()) [] = return ()+ go s (m : ms) = s `seq` do+ r <- tryIOError m+ go (thenEither s r) ms++ -- equivalent to (*>) for Either, defined here to retain compatibility+ -- with base prior to 4.3+ thenEither :: Either b a -> Either b a -> Either b a+ thenEither x@(Left _) _ = x+ thenEither _ y = y+ {- |'removeFile' /file/ removes the directory entry for an existing file /file/, where /file/ is not itself a directory. The implementation may specify additional constraints which must be@@ -633,7 +668,7 @@ removeFile :: FilePath -> IO () removeFile path =-#if mingw32_HOST_OS+#ifdef mingw32_HOST_OS Win32.deleteFile path #else Posix.removeLink path@@ -814,6 +849,7 @@ -- parent segments in the destination path is not a directory. -- @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@ --+-- @since 1.2.7.0 renamePath :: FilePath -- ^ Old path -> FilePath -- ^ New path -> IO ()@@ -1395,6 +1431,8 @@ action -- | Obtain the size of a file in bytes.+--+-- @since 1.2.7.0 getFileSize :: FilePath -> IO Integer getFileSize path = (`ioeSetLocation` "getFileSize") `modifyIOError` do@@ -1407,6 +1445,8 @@ -- | Test whether the given path points to an existing filesystem object. If -- the user lacks necessary permissions to search the parent directories, this -- function may return false even if the file does actually exist.+--+-- @since 1.2.7.0 doesPathExist :: FilePath -> IO Bool doesPathExist path = #ifdef mingw32_HOST_OS
changelog.md view
@@ -1,6 +1,12 @@ Changelog for the [`directory`][1] package ========================================== +## 1.2.7.1 (November 2016)++ * Don't abort `removePathForcibly` if files or directories go missing.+ In addition, keep going even if an exception occurs.+ ([#60](https://github.com/haskell/directory/issues/60))+ ## 1.2.7.0 (August 2016) * Remove deprecated C bits. This means `HsDirectory.h` and its functions@@ -41,7 +47,7 @@ * Add `findFileWith` - * Add `copyFileWithAttrs`, which copies additional metadata+ * Add `copyFileWithMetadata`, which copies additional metadata ([#40](https://github.com/haskell/directory/issues/40)) * Improve error message of `removeDirectoryRecursive` when used on a
directory.cabal view
@@ -1,5 +1,5 @@ name: directory-version: 1.2.7.0+version: 1.2.7.1 -- NOTE: Don't forget to update ./changelog.md license: BSD3 license-file: LICENSE@@ -52,11 +52,11 @@ include-dirs: . build-depends:- base >= 4.5 && < 4.10,- time >= 1.4 && < 1.7,+ base >= 4.5 && < 4.11,+ time >= 1.4 && < 1.8, filepath >= 1.3 && < 1.5 if os(windows)- build-depends: Win32 >= 2.2.2 && < 2.4+ build-depends: Win32 >= 2.2.2 && < 2.5 else build-depends: unix >= 2.5.1 && < 2.8
tests/TestUtils.hs view
@@ -52,7 +52,7 @@ permissions <- getPermissions path setPermissions path (modify permissions) -#if mingw32_HOST_OS+#ifdef mingw32_HOST_OS createSymbolicLink :: String -> String -> IO () createSymbolicLink target link = (`ioeSetLocation` "createSymbolicLink") `modifyIOError` do