hpath-io 0.11.0 → 0.12.0
raw patch · 4 files changed
+52/−49 lines, 4 filesdep ~hpathPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hpath
API changes (from Hackage documentation)
- HPath.IO: getDirsFiles' :: Path b -> IO [Path Fn]
+ HPath.IO: getDirsFiles' :: Path b -> IO [Path Rel]
- HPath.IO: withHandle :: ByteString -> OpenMode -> ((Handle, Path a) -> IO a) -> IO a
+ HPath.IO: withHandle :: ByteString -> OpenMode -> ((Handle, Either (Path Abs) (Path Rel)) -> IO a) -> IO a
- HPath.IO: withRawFilePath :: MonadThrow m => ByteString -> (Path a -> m b) -> m b
+ HPath.IO: withRawFilePath :: MonadThrow m => ByteString -> (Either (Path Abs) (Path Rel) -> m b) -> m b
Files
- CHANGELOG.md +7/−0
- hpath-io.cabal +2/−2
- src/HPath/IO.hs +38/−38
- src/HPath/IO/Errors.hs +5/−9
CHANGELOG.md view
@@ -1,5 +1,12 @@ # Revision history for hpath-io +## 0.12.0 -- 2020-01-20++* breaking API changes+ * RelC and Fn were removed from `hpath`+ * further changes to `parseAny`++ ## 0.11.0 -- 2020-01-18 * `writeFile` not allows to set file mode and create file if it does not exist (this broke API)
hpath-io.cabal view
@@ -1,5 +1,5 @@ name: hpath-io-version: 0.11.0+version: 0.12.0 synopsis: High-level IO operations on files/directories description: High-level IO operations on files/directories, utilizing type-safe Paths -- bug-reports:@@ -39,7 +39,7 @@ , IfElse , bytestring >= 0.10.0.0 , exceptions- , hpath >= 0.10 && < 0.11+ , hpath >= 0.11 && < 0.12 , hpath-filepath >= 0.10.2 && < 0.11 , safe-exceptions >= 0.1 , streamly >= 0.7
src/HPath/IO.hs view
@@ -197,7 +197,6 @@ IOErrorType(..) ) import HPath-import HPath.Internal import HPath.IO.Errors import Prelude hiding (appendFile, readFile, writeFile) import Streamly@@ -393,7 +392,7 @@ where go :: IORef [(RecursiveFailureHint, IOException)] -> Path b1 -> Path b2 -> IO ()- go ce fromp'@(MkPath fromBS) destdirp'@(MkPath destdirpBS) = do+ go ce fromp'@(Path fromBS) destdirp'@(Path destdirpBS) = do -- NOTE: order is important here, so we don't get empty directories -- on failure@@ -477,7 +476,7 @@ -> Path b2 -- ^ destination file -> CopyMode -> IO ()-recreateSymlink symsource@(MkPath symsourceBS) newsym@(MkPath newsymBS) cm+recreateSymlink symsource@(Path symsourceBS) newsym@(Path newsymBS) cm = do throwSameFile symsource newsym sympoint <- readSymbolicLink symsourceBS@@ -536,7 +535,7 @@ -> Path b2 -- ^ destination file -> CopyMode -> IO ()-copyFile fp@(MkPath from) tp@(MkPath to) cm = do+copyFile fp@(Path from) tp@(Path to) cm = do throwSameFile fp tp bracket (do fd <- openFd from SPI.ReadOnly [SPDF.oNofollow] Nothing@@ -608,7 +607,7 @@ -- - `NoSuchThing` if the file does not exist -- - `PermissionDenied` if the directory cannot be read deleteFile :: Path b -> IO ()-deleteFile (MkPath p) = removeLink p+deleteFile (Path p) = removeLink p -- |Deletes the given directory, which must be empty, never symlinks.@@ -623,7 +622,7 @@ -- -- Notes: calls `rmdir` deleteDir :: Path b -> IO ()-deleteDir (MkPath p) = removeDirectory p+deleteDir (Path p) = removeDirectory p -- |Deletes the given directory recursively. Does not follow symbolic@@ -691,7 +690,7 @@ -- is not checked. This forks a process. openFile :: Path b -> IO ProcessID-openFile (MkPath fp) =+openFile (Path fp) = SPP.forkProcess $ SPP.executeFile "xdg-open" True [fp] Nothing @@ -699,7 +698,7 @@ executeFile :: Path b -- ^ program -> [ByteString] -- ^ arguments -> IO ProcessID-executeFile (MkPath fp) args =+executeFile (Path fp) args = SPP.forkProcess $ SPP.executeFile fp True args Nothing @@ -720,7 +719,7 @@ -- - `NoSuchThing` if any of the parent components of the path -- do not exist createRegularFile :: FileMode -> Path b -> IO ()-createRegularFile fm (MkPath destBS) =+createRegularFile fm (Path destBS) = bracket (SPI.openFd destBS SPI.WriteOnly (Just fm) (SPI.defaultFileFlags { exclusive = True })) SPI.closeFd@@ -736,7 +735,7 @@ -- - `NoSuchThing` if any of the parent components of the path -- do not exist createDir :: FileMode -> Path b -> IO ()-createDir fm (MkPath destBS) = createDirectory destBS fm+createDir fm (Path destBS) = createDirectory destBS fm -- |Create an empty directory at the given directory with the given filename. --@@ -746,7 +745,7 @@ -- - `NoSuchThing` if any of the parent components of the path -- do not exist createDirIfMissing :: FileMode -> Path b -> IO ()-createDirIfMissing fm (MkPath destBS) =+createDirIfMissing fm (Path destBS) = hideError AlreadyExists $ createDirectory destBS fm @@ -775,7 +774,7 @@ toAbs p >>= go where go :: Path Abs -> IO ()- go dest@(MkPath destBS) = do+ go dest@(Path destBS) = do catchIOError (createDirectory destBS fm) $ \e -> do errno <- getErrno case errno of@@ -798,7 +797,7 @@ createSymlink :: Path b -- ^ destination file -> ByteString -- ^ path the symlink points to -> IO ()-createSymlink (MkPath destBS) sympoint+createSymlink (Path destBS) sympoint = createSymbolicLink sympoint destBS @@ -830,7 +829,7 @@ -- -- Note: calls `rename` (but does not allow to rename over existing files) renameFile :: Path b1 -> Path b2 -> IO ()-renameFile fromf@(MkPath fromfBS) tof@(MkPath tofBS) = do+renameFile fromf@(Path fromfBS) tof@(Path tofBS) = do throwSameFile fromf tof throwFileDoesExist tof throwDirDoesExist tof@@ -940,7 +939,7 @@ -- - `NoSuchThing` if the file does not exist readFileStream :: Path b -> IO (SerialT IO ByteString)-readFileStream (MkPath fp) = do+readFileStream (Path fp) = do fd <- openFd fp SPI.ReadOnly [] Nothing handle <- SPI.fdToHandle fd let stream = (S.unfold (SU.finally SIO.hClose FH.readChunks) handle) >>= arrayToByteString@@ -967,7 +966,7 @@ -> Maybe FileMode -- ^ if Nothing, file must exist -> ByteString -> IO ()-writeFile (MkPath fp) fmode bs =+writeFile (Path fp) fmode bs = bracket (openFd fp SPI.WriteOnly [SPDF.oTrunc] fmode) (SPI.closeFd) $ \fd -> void $ SPB.fdWrite fd bs @@ -986,7 +985,7 @@ -> Maybe FileMode -- ^ if Nothing, file must exist -> L.ByteString -> IO ()-writeFileL (MkPath fp) fmode lbs = do+writeFileL (Path fp) fmode lbs = do handle <- bracketOnError (openFd fp SPI.WriteOnly [SPDF.oTrunc] fmode) (SPI.closeFd) $ SPI.fdToHandle finally (streamlyCopy handle) (SIO.hClose handle) where@@ -1003,7 +1002,7 @@ -- containting it -- - `NoSuchThing` if the file does not exist appendFile :: Path b -> ByteString -> IO ()-appendFile (MkPath fp) bs =+appendFile (Path fp) bs = bracket (openFd fp SPI.WriteOnly [SPDF.oAppend] Nothing) (SPI.closeFd) $ \fd -> void $ SPB.fdWrite fd bs @@ -1048,7 +1047,7 @@ -- -- Only eNOENT is catched (and returns False). doesExist :: Path b -> IO Bool-doesExist (MkPath bs) =+doesExist (Path bs) = catchErrno [eNOENT] (do _ <- PF.getSymbolicLinkStatus bs return $ True)@@ -1060,7 +1059,7 @@ -- -- Only eNOENT is catched (and returns False). doesFileExist :: Path b -> IO Bool-doesFileExist (MkPath bs) =+doesFileExist (Path bs) = catchErrno [eNOENT] (do fs <- PF.getSymbolicLinkStatus bs return $ not . PF.isDirectory $ fs)@@ -1072,7 +1071,7 @@ -- -- Only eNOENT is catched (and returns False). doesDirectoryExist :: Path b -> IO Bool-doesDirectoryExist (MkPath bs) =+doesDirectoryExist (Path bs) = catchErrno [eNOENT] (do fs <- PF.getSymbolicLinkStatus bs return $ PF.isDirectory fs)@@ -1087,7 +1086,7 @@ -- -- - `NoSuchThing` if the file does not exist isReadable :: Path b -> IO Bool-isReadable (MkPath bs) = fileAccess bs True False False+isReadable (Path bs) = fileAccess bs True False False -- |Checks whether a file or folder is writable. --@@ -1097,7 +1096,7 @@ -- -- - `NoSuchThing` if the file does not exist isWritable :: Path b -> IO Bool-isWritable (MkPath bs) = fileAccess bs False True False+isWritable (Path bs) = fileAccess bs False True False -- |Checks whether a file or folder is executable.@@ -1108,14 +1107,14 @@ -- -- - `NoSuchThing` if the file does not exist isExecutable :: Path b -> IO Bool-isExecutable (MkPath bs) = fileAccess bs False False True+isExecutable (Path bs) = fileAccess bs False False True -- |Checks whether the directory at the given path exists and can be -- opened. This invokes `openDirStream` which follows symlinks. canOpenDirectory :: Path b -> IO Bool-canOpenDirectory (MkPath bs) =+canOpenDirectory (Path bs) = handleIOError (\_ -> return False) $ do bracket (openDirStream bs) closeDirStream@@ -1131,18 +1130,18 @@ getModificationTime :: Path b -> IO UTCTime-getModificationTime (MkPath bs) = do+getModificationTime (Path bs) = do fs <- PF.getFileStatus bs pure $ posixSecondsToUTCTime $ PF.modificationTimeHiRes fs setModificationTime :: Path b -> EpochTime -> IO ()-setModificationTime (MkPath bs) t = do+setModificationTime (Path bs) t = do -- TODO: setFileTimes doesn't allow to pass NULL to utime ctime <- epochTime PF.setFileTimes bs ctime t setModificationTimeHiRes :: Path b -> POSIXTime -> IO ()-setModificationTimeHiRes (MkPath bs) t = do+setModificationTimeHiRes (Path bs) t = do -- TODO: setFileTimesHiRes doesn't allow to pass NULL to utimes ctime <- getPOSIXTime PF.setFileTimesHiRes bs ctime t@@ -1169,7 +1168,7 @@ -- - `PathParseException` if a filename could not be parsed (should never happen) getDirsFiles :: Path b -- ^ dir to read -> IO [Path b]-getDirsFiles p@(MkPath fp) = do+getDirsFiles p@(Path fp) = do contents <- getDirsFiles' p pure $ fmap (p </>) contents @@ -1177,14 +1176,14 @@ -- | Like 'getDirsFiles', but returns the filename only, instead -- of prepending the base path. getDirsFiles' :: Path b -- ^ dir to read- -> IO [Path Fn]-getDirsFiles' p@(MkPath fp) = do+ -> IO [Path Rel]+getDirsFiles' p@(Path fp) = do fd <- openFd fp SPI.ReadOnly [SPDF.oNofollow] Nothing rawContents <- getDirectoryContents' fd fmap catMaybes $ for rawContents $ \(_, f) -> if FP.isSpecialDirectoryEntry f then pure Nothing- else fmap Just $ parseFn f+ else fmap Just $ parseRel f @@ -1202,7 +1201,7 @@ -- - `NoSuchThing` if the file does not exist -- - `PermissionDenied` if any part of the path is not accessible getFileType :: Path b -> IO FileType-getFileType (MkPath fp) = do+getFileType (Path fp) = do fs <- PF.getSymbolicLinkStatus fp decide fs where@@ -1230,10 +1229,11 @@ -- -- - `NoSuchThing` if the file at the given path does not exist -- - `NoSuchThing` if the symlink is broken+-- - `PathParseException` if realpath does not return an absolute path canonicalizePath :: Path b -> IO (Path Abs)-canonicalizePath (MkPath l) = do+canonicalizePath (Path l) = do nl <- SPDT.realpath l- return $ MkPath nl+ parseAbs nl -- |Converts any path to an absolute path.@@ -1242,7 +1242,7 @@ -- - if the path is already an absolute one, just return it -- - if it's a relative path, prepend the current directory to it toAbs :: Path b -> IO (Path Abs)-toAbs (MkPath bs) = do+toAbs (Path bs) = do let mabs = parseAbs bs :: Maybe (Path Abs) case mabs of Just a -> return a@@ -1260,7 +1260,7 @@ -- -- - `PathParseException` if the bytestring could neither be parsed as -- relative or absolute Path-withRawFilePath :: MonadThrow m => ByteString -> (Path a -> m b) -> m b+withRawFilePath :: MonadThrow m => ByteString -> (Either (Path Abs) (Path Rel) -> m b) -> m b withRawFilePath bs action = do path <- parseAny bs action path@@ -1276,7 +1276,7 @@ -- relative or absolute Path withHandle :: ByteString -> SPI.OpenMode- -> ((SIO.Handle, Path a) -> IO a)+ -> ((SIO.Handle, Either (Path Abs) (Path Rel)) -> IO a) -> IO a withHandle bs mode action = do path <- parseAny bs
src/HPath/IO/Errors.hs view
@@ -81,10 +81,6 @@ IOErrorType ) import HPath-import HPath.Internal- (- Path(..)- ) import {-# SOURCE #-} HPath.IO ( canonicalizePath@@ -175,7 +171,7 @@ -- |Throws `AlreadyExists` `IOError` if file exists. throwFileDoesExist :: Path b -> IO ()-throwFileDoesExist fp@(MkPath bs) =+throwFileDoesExist fp@(Path bs) = whenM (doesFileExist fp) (ioError . mkIOError alreadyExistsErrorType@@ -187,7 +183,7 @@ -- |Throws `AlreadyExists` `IOError` if directory exists. throwDirDoesExist :: Path b -> IO ()-throwDirDoesExist fp@(MkPath bs) =+throwDirDoesExist fp@(Path bs) = whenM (doesDirectoryExist fp) (ioError . mkIOError alreadyExistsErrorType@@ -201,7 +197,7 @@ throwSameFile :: Path b1 -> Path b2 -> IO ()-throwSameFile fp1@(MkPath bs1) fp2@(MkPath bs2) =+throwSameFile fp1@(Path bs1) fp2@(Path bs2) = whenM (sameFile fp1 fp2) (throwIO $ SameFile bs1 bs2) @@ -209,7 +205,7 @@ -- |Check if the files are the same by examining device and file id. -- This follows symbolic links. sameFile :: Path b1 -> Path b2 -> IO Bool-sameFile (MkPath fp1) (MkPath fp2) =+sameFile (Path fp1) (Path fp2) = handleIOError (\_ -> return False) $ do fs1 <- getFileStatus fp1 fs2 <- getFileStatus fp2@@ -229,7 +225,7 @@ -> Path b2 -- ^ full destination, @dirname dest@ -- must exist -> IO ()-throwDestinationInSource (MkPath sbs) dest@(MkPath dbs) = do+throwDestinationInSource (Path sbs) dest@(Path dbs) = do destAbs <- toAbs dest dest' <- (\x -> maybe x (\y -> x </> y) $ basename dest) <$> (canonicalizePath $ dirname destAbs)