packages feed

filepath 1.4.102.0 → 1.4.200.0

raw patch · 13 files changed

+50/−92 lines, 13 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- System.OsPath.Encoding.Internal: isAsyncException :: Exception e => e -> Bool
- System.OsPath.Encoding.Internal: trySafe :: Exception e => IO a -> IO (Either e a)

Files

System/FilePath/Internal.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE TypeApplications #-}-{-# LANGUAGE MultiWayIf #-}  -- This template expects CPP definitions for: --     MODULE_NAME = Posix | Windows@@ -130,10 +129,9 @@ #define FILEPATH FilePath #else import Prelude (fromIntegral)-import Control.Exception ( SomeException, evaluate, displayException )+import Control.Exception ( SomeException, evaluate, try, displayException ) import Control.DeepSeq (force) import GHC.IO (unsafePerformIO)-import System.OsPath.Encoding.Internal (trySafe) import qualified Data.Char as C #ifdef WINDOWS import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )@@ -604,7 +602,6 @@ -- > Posix:   splitFileName "/" == ("/","") -- > Windows: splitFileName "c:" == ("c:","") -- > Windows: splitFileName "\\\\?\\A:\\fred" == ("\\\\?\\A:\\","fred")--- > Windows: splitFileName "\\\\?\\A:" == ("\\\\?\\A:","") splitFileName :: FILEPATH -> (STRING, STRING) splitFileName x = if null path     then (dotSlash, file)@@ -647,43 +644,20 @@   -- or UNC location "\\?\UNC\foo", where path separator is a part of the drive name.   -- We can test this by trying dropDrive and falling back to splitDrive.   | isWindows-  = case uncons2 dirSlash of-    Just (s1, s2, bs')-      | isPathSeparator s1-      -- If bs' is empty, then s2 as the last character of dirSlash must be a path separator,-      -- so we are in the middle of shared drive.-      -- Otherwise, since s1 is a path separator, we might be in the middle of UNC path.-      , null bs' || maybe False isIncompleteUNC (readDriveUNC dirSlash)-      -> (fp, mempty)-      -- This handles inputs like "//?/A:" and "//?/A:foo"-      | isPathSeparator s1-      , isPathSeparator s2-      , Just (s3, s4, bs'') <- uncons2 bs'-      , s3 == _question-      , isPathSeparator s4-      , null bs''-      , Just (drive, rest) <- readDriveLetter file-      -> (dirSlash <> drive, rest)-    _ -> (dirSlash, file)+  , Just (s1, _s2, bs') <- uncons2 dirSlash+  , isPathSeparator s1+  -- If bs' is empty, then s2 as the last character of dirSlash must be a path separator,+  -- so we are in the middle of shared drive.+  -- Otherwise, since s1 is a path separator, we might be in the middle of UNC path.+  , null bs' || maybe False isIncompleteUNC (readDriveUNC dirSlash)+  = (fp, mempty)   | otherwise-    = (dirSlash, file)+  = (dirSlash, file)   where     (dirSlash, file) = breakEnd isPathSeparator fp-    dropExcessTrailingPathSeparators x-      | hasTrailingPathSeparator x-      , let x' = dropWhileEnd isPathSeparator x-      , otherwise = if | null x' -> singleton (last x)-                       | otherwise -> addTrailingPathSeparator x'-      | otherwise = x -    -- an "incomplete" UNC is one without a path (but potentially a drive)     isIncompleteUNC (pref, suff) = null suff && not (hasPenultimateColon pref)--    -- e.g. @//?/a:/@ or @//?/a://@, but not @//?/a:@-    hasPenultimateColon pref-      | hasTrailingPathSeparator pref-      = maybe False (maybe False ((== _colon) . snd) . unsnoc . fst) . unsnoc . dropExcessTrailingPathSeparators $ pref-      | otherwise = False+    hasPenultimateColon = maybe False (maybe False ((== _colon) . snd) . unsnoc . fst) . unsnoc  -- | Set the filename. --@@ -1274,12 +1248,12 @@ #ifdef WINDOWS fromString :: P.String -> STRING fromString str = P.either (P.error . P.show) P.id $ unsafePerformIO $ do-  r <- trySafe @SomeException $ GHC.withCStringLen (mkUTF16le ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr+  r <- try @SomeException $ GHC.withCStringLen (mkUTF16le ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr   evaluate $ force $ first displayException r #else fromString :: P.String -> STRING fromString str = P.either (P.error . P.show) P.id $ unsafePerformIO $ do-  r <- trySafe @SomeException $ GHC.withCStringLen (mkUTF8 ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr+  r <- try @SomeException $ GHC.withCStringLen (mkUTF8 ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr   evaluate $ force $ first displayException r #endif 
System/OsPath/Data/ByteString/Short.hs view
@@ -23,7 +23,9 @@ -- -- > import qualified Data.ByteString.Short as B.Short ---module System.OsPath.Data.ByteString.Short (+module System.OsPath.Data.ByteString.Short {-# DEPRECATED "Use System.OsString.Data.ByteString.Short from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-}++ (      -- * The @ShortByteString@ type 
System/OsPath/Data/ByteString/Short/Internal.hs view
@@ -17,7 +17,7 @@ -- -- Internal low-level utilities mostly for 'System.OsPath.Data.ByteString.Short.Word16', -- such as byte-array operations and other stuff not meant to be exported from Word16 module.-module System.OsPath.Data.ByteString.Short.Internal where+module System.OsPath.Data.ByteString.Short.Internal {-# DEPRECATED "Use System.OsString.Data.ByteString.Short.Internal from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-} where  import Control.Monad.ST import Control.Exception (assert, throwIO)@@ -164,9 +164,13 @@       action buf   where l = length bs --- | /O(n) construction./ Use a @ShortByteString@ with a function requiring a @CStringLen@.--- As for @useAsCString@ this function makes a copy of the original @ShortByteString@.+-- | /O(n) construction./ Use a @ShortByteString@ with a function requiring a 'CStringLen'.+-- As for 'useAsCString' this function makes a copy of the original @ShortByteString@. -- It must not be stored or used after the subcomputation finishes.+--+-- Beware that this function does not add a terminating @\NUL@ byte at the end of 'CStringLen'.+-- If you need to construct a pointer to a null-terminated sequence, use 'useAsCString'+-- (and measure length independently if desired). -- -- @since 0.10.10.0 useAsCStringLen :: ShortByteString -> (CStringLen -> IO a) -> IO a
System/OsPath/Data/ByteString/Short/Word16.hs view
@@ -29,7 +29,7 @@ -- -- All functions will error out if the input string is not a valid UTF16 stream (uneven number of bytes). -- So use this module with caution.-module System.OsPath.Data.ByteString.Short.Word16 (+module System.OsPath.Data.ByteString.Short.Word16 {-# DEPRECATED "Use System.OsString.Data.ByteString.Short.Word16 from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-} (     -- * The @ShortByteString@ type and representation     ShortByteString(..), 
System/OsPath/Encoding/Internal.hs view
@@ -6,7 +6,7 @@ {-# OPTIONS_GHC  -funbox-strict-fields #-}  -module System.OsPath.Encoding.Internal where+module System.OsPath.Encoding.Internal {-# DEPRECATED "Use System.OsString.Encoding.Internal from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-} where  import qualified System.OsPath.Data.ByteString.Short as BS8 import qualified System.OsPath.Data.ByteString.Short.Word16 as BS16@@ -19,7 +19,7 @@ import GHC.IO.Encoding.Failure import GHC.IO.Encoding.Types import Data.Bits-import Control.Exception (SomeException, SomeAsyncException(..), Exception (displayException), evaluate, catch, throwIO, toException, fromException)+import Control.Exception (SomeException, try, Exception (displayException), evaluate) import qualified GHC.Foreign as GHC import Data.Either (Either) import GHC.IO (unsafePerformIO)@@ -31,7 +31,7 @@ import Foreign.C (CStringLen) import Data.Char (chr) import Foreign-import Prelude (FilePath, Either(..))+import Prelude (FilePath) import GHC.IO.Encoding (getFileSystemEncoding)  -- -----------------------------------------------------------------------------@@ -277,13 +277,13 @@ -- | Decode with the given 'TextEncoding'. decodeWithTE :: TextEncoding -> BS8.ShortByteString -> Either EncodingException String decodeWithTE enc ba = unsafePerformIO $ do-  r <- trySafe @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen enc fp+  r <- try @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen enc fp   evaluate $ force $ first (flip EncodingError Nothing . displayException) r  -- | Encode with the given 'TextEncoding'. encodeWithTE :: TextEncoding -> String -> Either EncodingException BS8.ShortByteString encodeWithTE enc str = unsafePerformIO $ do-  r <- trySafe @SomeException $ GHC.withCStringLen enc str $ \cstr -> BS8.packCStringLen cstr+  r <- try @SomeException $ GHC.withCStringLen enc str $ \cstr -> BS8.packCStringLen cstr   evaluate $ force $ first (flip EncodingError Nothing . displayException) r  -- -----------------------------------------------------------------------------@@ -347,25 +347,3 @@  wNUL :: Word16 wNUL = 0x00---- -------------------------------------------------------------------------------- Exceptions------- | Like 'try', but rethrows async exceptions.-trySafe :: Exception e => IO a -> IO (Either e a)-trySafe ioA = catch action eHandler- where-  action = do-    v <- ioA-    return (Right v)-  eHandler e-    | isAsyncException e = throwIO e-    | otherwise = return (Left e)--isAsyncException :: Exception e => e -> Bool-isAsyncException e =-    case fromException (toException e) of-        Just (SomeAsyncException _) -> True-        Nothing -> False-
System/OsString.hs view
@@ -14,7 +14,7 @@ -- -- It captures the notion of syscall specific encoding (or the lack thereof) to avoid roundtrip issues -- and memory fragmentation by using unpinned byte arrays. Bytes are not touched or interpreted.-module System.OsString+module System.OsString {-# DEPRECATED "Use System.OsString from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-}   (   -- * String types     OsString
System/OsString/Common.hs view
@@ -11,7 +11,7 @@ #define POSIX_DOC #endif -module System.OsString.MODULE_NAME+module System.OsString.MODULE_NAME {-# DEPRECATED "Use System.OsString.MODULE_NAME from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-}   (   -- * Types #ifdef WINDOWS@@ -60,7 +60,7 @@ import Data.ByteString.Internal     ( ByteString ) import Control.Exception-    ( SomeException, displayException )+    ( SomeException, try, displayException ) import Control.DeepSeq ( force ) import Data.Bifunctor ( first ) import GHC.IO@@ -73,7 +73,6 @@   import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )-import System.OsPath.Encoding.Internal (trySafe) #ifdef WINDOWS import System.OsPath.Encoding import System.IO@@ -117,10 +116,10 @@            -> Either EncodingException PLATFORM_STRING encodeWith enc str = unsafePerformIO $ do #ifdef WINDOWS-  r <- trySafe @SomeException $ GHC.withCStringLen enc str $ \cstr -> WindowsString <$> BS8.packCStringLen cstr+  r <- try @SomeException $ GHC.withCStringLen enc str $ \cstr -> WindowsString <$> BS8.packCStringLen cstr   evaluate $ force $ first (flip EncodingError Nothing . displayException) r #else-  r <- trySafe @SomeException $ GHC.withCStringLen enc str $ \cstr -> PosixString <$> BS.packCStringLen cstr+  r <- try @SomeException $ GHC.withCStringLen enc str $ \cstr -> PosixString <$> BS.packCStringLen cstr   evaluate $ force $ first (flip EncodingError Nothing . displayException) r #endif @@ -177,7 +176,7 @@            -> PLATFORM_STRING            -> Either EncodingException String decodeWith winEnc (WindowsString ba) = unsafePerformIO $ do-  r <- trySafe @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen winEnc fp+  r <- try @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen winEnc fp   evaluate $ force $ first (flip EncodingError Nothing . displayException) r #else -- | Decode a 'PosixString' with the specified encoding.@@ -187,7 +186,7 @@        -> PLATFORM_STRING        -> Either EncodingException String decodeWith unixEnc (PosixString ba) = unsafePerformIO $ do-  r <- trySafe @SomeException $ BS.useAsCStringLen ba $ \fp -> GHC.peekCStringLen unixEnc fp+  r <- try @SomeException $ BS.useAsCStringLen ba $ \fp -> GHC.peekCStringLen unixEnc fp   evaluate $ force $ first (flip EncodingError Nothing . displayException) r #endif 
System/OsString/Internal.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE UnliftedFFITypes #-} -module System.OsString.Internal where+module System.OsString.Internal {-# DEPRECATED "Use System.OsString.Internal from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-} where  import System.OsString.Internal.Types 
System/OsString/Internal/Types.hs view
@@ -8,7 +8,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE PatternSynonyms #-} -module System.OsString.Internal.Types+module System.OsString.Internal.Types {-# DEPRECATED "Use System.OsString.Internal.Types from os-string >= 2.0.0 package instead. This module will be removed in filepath >= 1.5." #-}   (     WindowsString(..)   , pattern WS
changelog.md view
@@ -2,13 +2,9 @@  _Note: below all `FilePath` values are unquoted, so `\\` really means two backslashes._ -## 1.4.102.0 *Nov 2024*--* Don't catch async exceptions in internal functions wrt https://github.com/haskell/os-string/issues/22--## 1.4.101.0 *Jan 2024*+## 1.4.200.0 *Jul 2023* -* Backport bugfix for [`splitFileName`](https://github.com/haskell/filepath/issues/219) on windows+* deprecate `OsString` modules  ## 1.4.100.4 *Jul 2023* 
filepath.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               filepath-version:            1.4.102.0+version:            1.4.200.0  -- NOTE: Don't forget to update ./changelog.md license:            BSD-3-Clause@@ -103,7 +103,7 @@    default-language: Haskell2010   build-depends:-    , base              >=4.9      && <4.22+    , base              >=4.9      && <4.20     , bytestring        >=0.11.3.0     , deepseq     , exceptions
tests/filepath-equivalent-tests/TestEquiv.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE TypeApplications #-}  module Main where @@ -11,6 +10,7 @@ import qualified System.FilePath.Posix as P import qualified Legacy.System.FilePath.Windows as LW import qualified Legacy.System.FilePath.Posix as LP+import Data.Char (isAsciiLower, isAsciiUpper)   main :: IO ()@@ -189,7 +189,14 @@     )     ,     ( "normalise (windows)"-    , property $ \p -> W.normalise p == LW.normalise p+    , property $ \p -> case p of+                         (l:':':rs)+                           -- new filepath normalises "a:////////" to "A:\\"+                           -- see https://github.com/haskell/filepath/commit/cb4890aa03a5ee61f16f7a08dd2d964fffffb385+                           | isAsciiLower l || isAsciiUpper l+                           , let (seps, path) = span LW.isPathSeparator rs+                           , length seps > 1 -> let np = l : ':' : LW.pathSeparator : path in W.normalise np == LW.normalise np+                         _ -> W.normalise p == LW.normalise p     )     ,     ( "equalFilePath (windows)"
tests/filepath-tests/TestGen.hs view
@@ -458,8 +458,6 @@     ,("AFP_W.splitFileName (\"c:\") == ((\"c:\"), (\"\"))", property $ AFP_W.splitFileName ("c:") == (("c:"), ("")))     ,("W.splitFileName \"\\\\\\\\?\\\\A:\\\\fred\" == (\"\\\\\\\\?\\\\A:\\\\\", \"fred\")", property $ W.splitFileName "\\\\?\\A:\\fred" == ("\\\\?\\A:\\", "fred"))     ,("AFP_W.splitFileName (\"\\\\\\\\?\\\\A:\\\\fred\") == ((\"\\\\\\\\?\\\\A:\\\\\"), (\"fred\"))", property $ AFP_W.splitFileName ("\\\\?\\A:\\fred") == (("\\\\?\\A:\\"), ("fred")))-    ,("W.splitFileName \"\\\\\\\\?\\\\A:\" == (\"\\\\\\\\?\\\\A:\", \"\")", property $ W.splitFileName "\\\\?\\A:" == ("\\\\?\\A:", ""))-    ,("AFP_W.splitFileName (\"\\\\\\\\?\\\\A:\") == ((\"\\\\\\\\?\\\\A:\"), (\"\"))", property $ AFP_W.splitFileName ("\\\\?\\A:") == (("\\\\?\\A:"), ("")))     ,("P.replaceFileName \"/directory/other.txt\" \"file.ext\" == \"/directory/file.ext\"", property $ P.replaceFileName "/directory/other.txt" "file.ext" == "/directory/file.ext")     ,("W.replaceFileName \"/directory/other.txt\" \"file.ext\" == \"/directory/file.ext\"", property $ W.replaceFileName "/directory/other.txt" "file.ext" == "/directory/file.ext")     ,("AFP_P.replaceFileName (\"/directory/other.txt\") (\"file.ext\") == (\"/directory/file.ext\")", property $ AFP_P.replaceFileName ("/directory/other.txt") ("file.ext") == ("/directory/file.ext"))