filepath-bytestring 1.4.2.1.3 → 1.4.2.1.4
raw patch · 6 files changed
+68/−22 lines, 6 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ System.FilePath.Posix.ByteString: getSearchPath :: IO [RawFilePath]
+ System.FilePath.Posix.ByteString: splitSearchPath :: ByteString -> [RawFilePath]
+ System.FilePath.Windows.ByteString: getSearchPath :: IO [RawFilePath]
+ System.FilePath.Windows.ByteString: splitSearchPath :: ByteString -> [RawFilePath]
Files
- CHANGELOG +8/−0
- System/FilePath/Internal.hs +26/−18
- TODO +2/−2
- filepath-bytestring.cabal +1/−1
- tests/TestEquiv.hs +6/−1
- tests/TestGen.hs +25/−0
CHANGELOG view
@@ -1,3 +1,11 @@+filepath-bytestring (1.4.2.1.4) unstable; urgency=medium++ * Added splitSearchPath and getSearchPath.+ * Fix bug in makeRelative, caught by test suite.+ * Added quickcheck tests for equalFilePath and makeRelative.++ -- Joey Hess <id@joeyh.name> Wed, 01 Jan 2020 11:58:31 -0400+ filepath-bytestring (1.4.2.1.3) unstable; urgency=medium * Added equalFilePath.
System/FilePath/Internal.hs view
@@ -100,7 +100,7 @@ extSeparator, isExtSeparator, -- * @$PATH@ methods- --splitSearchPath, getSearchPath,+ splitSearchPath, getSearchPath, -- * Extension functions splitExtension,@@ -146,6 +146,7 @@ import qualified GHC.IO.Encoding as Encoding import System.IO.Unsafe (unsafePerformIO) #endif+import System.Environment (getEnv) import Data.Semigroup import Prelude @@ -270,7 +271,6 @@ isExtSeparator :: Word8 -> Bool isExtSeparator = (== extSeparator) -{- --------------------------------------------------------------------- -- Path methods (environment $PATH)@@ -282,28 +282,36 @@ -- Follows the recommendations in -- <http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html> ----- > untested Posix: splitSearchPath "File1:File2:File3" == ["File1","File2","File3"]--- > untested Posix: splitSearchPath "File1::File2:File3" == ["File1",".","File2","File3"]--- > untested Windows: splitSearchPath "File1;File2;File3" == ["File1","File2","File3"]--- > untested Windows: splitSearchPath "File1;;File2;File3" == ["File1","File2","File3"]--- > untested Windows: splitSearchPath "File1;\"File2\";File3" == ["File1","File2","File3"]-splitSearchPath :: String -> [FilePath]+-- > Posix: splitSearchPath "File1:File2:File3" == ["File1","File2","File3"]+-- > Posix: splitSearchPath "File1::File2:File3" == ["File1",".","File2","File3"]+-- > Windows: splitSearchPath "File1;File2;File3" == ["File1","File2","File3"]+-- > Windows: splitSearchPath "File1;;File2;File3" == ["File1","File2","File3"]+-- > Windows: splitSearchPath "File1;\"File2\";File3" == ["File1","File2","File3"]+splitSearchPath :: ByteString -> [RawFilePath] splitSearchPath = f where- f xs = case break isSearchPathSeparator xs of- (pre, [] ) -> g pre- (pre, _:post) -> g pre ++ f post+ f x = case B.break isSearchPathSeparator x of+ (pre, post)+ | B.null post -> g pre+ | otherwise -> g pre ++ f (B.drop 1 post) g "" = ["." | isPosix]- g ('\"':x@(_:_)) | isWindows && last x == '\"' = [init x]- g x = [x]+ g x+ | isWindows = case B.uncons x of+ Just (q, x') | q == quote ->+ case B.unsnoc x' of+ Just (x'', q') | q' == quote -> [x'']+ _ -> [x]+ _ -> [x]+ | otherwise = [x]+ + quote = fromIntegral (ord '"') --- | Get a list of 'FilePath's in the $PATH variable.-getSearchPath :: IO [FilePath]-getSearchPath = fmap splitSearchPath (getEnv "PATH")+-- | Get a list of 'RawFilePath's in the $PATH variable.+getSearchPath :: IO [RawFilePath]+getSearchPath = fmap (splitSearchPath . encodeFilePath) (getEnv "PATH") --} --------------------------------------------------------------------- -- Extension methods@@ -947,7 +955,7 @@ takeAbs x | hasLeadingPathSeparator x && not (hasDrive x) = B.singleton pathSeparator -- A Windows drive letter is an ascii character, so it's safe to -- operate on the ByteString containing it using B8.- takeAbs x = B8.map toLower $ takeDrive x+ takeAbs x = B8.map (\y -> if isPathSeparator (fromIntegral (ord y)) then chr (fromIntegral pathSeparator) else toLower y) $ takeDrive x -- | Normalise a file --
TODO view
@@ -1,3 +1,3 @@ * Some functions have not been ported from FilePath and are commented out:- splitSearchPath, getSearchPath,- makeValid. Implementations would be accepted if you need any of these.+ makeValid+ Implementations would be accepted if you need any of these.
filepath-bytestring.cabal view
@@ -1,6 +1,6 @@ cabal-version: >= 1.18 name: filepath-bytestring-version: 1.4.2.1.3+version: 1.4.2.1.4 -- NOTE: Don't forget to update CHANGELOG and the filepath version below license: BSD3 license-file: LICENSE
tests/TestEquiv.hs view
@@ -1,7 +1,6 @@ -- GENERATED CODE: See ../Generate.hs module TestEquiv(equivtests) where import TestUtil-import System.FilePath.ByteString (RawFilePath) import qualified System.FilePath.Windows.ByteString as OurWindows import qualified System.FilePath.Windows as TheirWindows import qualified System.FilePath.Posix.ByteString as OurPosix@@ -45,6 +44,9 @@ ,("equiv Posix.addTrailingPathSeparator", equiv_1 OurPosix.addTrailingPathSeparator TheirPosix.addTrailingPathSeparator) ,("equiv Posix.dropTrailingPathSeparator", equiv_1 OurPosix.dropTrailingPathSeparator TheirPosix.dropTrailingPathSeparator) ,("equiv Posix.normalise", equiv_1 OurPosix.normalise TheirPosix.normalise)+ ,("equiv Posix.equalFilePath", equiv_2 OurPosix.equalFilePath TheirPosix.equalFilePath)+ ,("equiv Posix.makeRelative", equiv_2 OurPosix.makeRelative TheirPosix.makeRelative)+ ,("equiv Posix.splitSearchPath", equiv_1 OurPosix.splitSearchPath TheirPosix.splitSearchPath) ,("equiv Windows.isPathSeparator", equiv_0 OurWindows.isPathSeparator TheirWindows.isPathSeparator) ,("equiv Windows.isSearchPathSeparator", equiv_0 OurWindows.isSearchPathSeparator TheirWindows.isSearchPathSeparator) ,("equiv Windows.isExtSeparator", equiv_0 OurWindows.isExtSeparator TheirWindows.isExtSeparator)@@ -82,4 +84,7 @@ ,("equiv Windows.addTrailingPathSeparator", equiv_1 OurWindows.addTrailingPathSeparator TheirWindows.addTrailingPathSeparator) ,("equiv Windows.dropTrailingPathSeparator", equiv_1 OurWindows.dropTrailingPathSeparator TheirWindows.dropTrailingPathSeparator) ,("equiv Windows.normalise", equiv_1 OurWindows.normalise TheirWindows.normalise)+ ,("equiv Windows.equalFilePath", equiv_2 OurWindows.equalFilePath TheirWindows.equalFilePath)+ ,("equiv Windows.makeRelative", equiv_2 OurWindows.makeRelative TheirWindows.makeRelative)+ ,("equiv Windows.splitSearchPath", equiv_1 OurWindows.splitSearchPath TheirWindows.splitSearchPath) ]
tests/TestGen.hs view
@@ -28,6 +28,11 @@ ,("W.extSeparator == fromIntegral (ord '.')", property $ W.extSeparator == fromIntegral (ord '.')) ,("P.isExtSeparator a == (a == P.extSeparator)", property $ \a -> P.isExtSeparator a == (a == P.extSeparator)) ,("W.isExtSeparator a == (a == W.extSeparator)", property $ \a -> W.isExtSeparator a == (a == W.extSeparator))+ ,("P.splitSearchPath \"File1:File2:File3\" == [\"File1\", \"File2\", \"File3\"]", property $ P.splitSearchPath "File1:File2:File3" == ["File1", "File2", "File3"])+ ,("P.splitSearchPath \"File1::File2:File3\" == [\"File1\", \".\", \"File2\", \"File3\"]", property $ P.splitSearchPath "File1::File2:File3" == ["File1", ".", "File2", "File3"])+ ,("W.splitSearchPath \"File1;File2;File3\" == [\"File1\", \"File2\", \"File3\"]", property $ W.splitSearchPath "File1;File2;File3" == ["File1", "File2", "File3"])+ ,("W.splitSearchPath \"File1;;File2;File3\" == [\"File1\", \"File2\", \"File3\"]", property $ W.splitSearchPath "File1;;File2;File3" == ["File1", "File2", "File3"])+ ,("W.splitSearchPath \"File1;\\\"File2\\\";File3\" == [\"File1\", \"File2\", \"File3\"]", property $ W.splitSearchPath "File1;\"File2\";File3" == ["File1", "File2", "File3"]) ,("P.splitExtension \"/directory/path.ext\" == (\"/directory/path\", \".ext\")", property $ P.splitExtension "/directory/path.ext" == ("/directory/path", ".ext")) ,("W.splitExtension \"/directory/path.ext\" == (\"/directory/path\", \".ext\")", property $ W.splitExtension "/directory/path.ext" == ("/directory/path", ".ext")) ,("uncurry (<>) (P.splitExtension x) == x", property $ \(QFilePath vx) -> let x = toRawFilePath vx in uncurry (<>) (P.splitExtension x) == x)@@ -361,6 +366,26 @@ ,("not (P.equalFilePath \"foo\" \"FOO\")", property $ not (P.equalFilePath "foo" "FOO")) ,("W.equalFilePath \"foo\" \"FOO\"", property $ W.equalFilePath "foo" "FOO") ,("not (W.equalFilePath \"C:\" \"C:/\")", property $ not (W.equalFilePath "C:" "C:/"))+ ,("P.makeRelative \"/directory\" \"/directory/file.ext\" == \"file.ext\"", property $ P.makeRelative "/directory" "/directory/file.ext" == "file.ext")+ ,("W.makeRelative \"/directory\" \"/directory/file.ext\" == \"file.ext\"", property $ W.makeRelative "/directory" "/directory/file.ext" == "file.ext")+ ,("P.makeRelative (P.takeDirectory x) x `P.equalFilePath` P.takeFileName x", property $ \(QFilePathValidP vx) -> let x = toRawFilePath vx in P.makeRelative (P.takeDirectory x) x `P.equalFilePath` P.takeFileName x)+ ,("W.makeRelative (W.takeDirectory x) x `W.equalFilePath` W.takeFileName x", property $ \(QFilePathValidW vx) -> let x = toRawFilePath vx in W.makeRelative (W.takeDirectory x) x `W.equalFilePath` W.takeFileName x)+ ,("P.makeRelative x x == \".\"", property $ \(QFilePath vx) -> let x = toRawFilePath vx in P.makeRelative x x == ".")+ ,("W.makeRelative x x == \".\"", property $ \(QFilePath vx) -> let x = toRawFilePath vx in W.makeRelative x x == ".")+ ,("P.equalFilePath x y || (P.isRelative x && P.makeRelative y x == x) || P.equalFilePath (y P.</> P.makeRelative y x) x", property $ \(QFilePathValidP vx) (QFilePathValidP vy) -> let y = toRawFilePath vy in let x = toRawFilePath vx in P.equalFilePath x y || (P.isRelative x && P.makeRelative y x == x) || P.equalFilePath (y P.</> P.makeRelative y x) x)+ ,("W.equalFilePath x y || (W.isRelative x && W.makeRelative y x == x) || W.equalFilePath (y W.</> W.makeRelative y x) x", property $ \(QFilePathValidW vx) (QFilePathValidW vy) -> let y = toRawFilePath vy in let x = toRawFilePath vx in W.equalFilePath x y || (W.isRelative x && W.makeRelative y x == x) || W.equalFilePath (y W.</> W.makeRelative y x) x)+ ,("W.makeRelative \"C:\\\\Home\" \"c:\\\\home\\\\bob\" == \"bob\"", property $ W.makeRelative "C:\\Home" "c:\\home\\bob" == "bob")+ ,("W.makeRelative \"C:\\\\Home\" \"c:/home/bob\" == \"bob\"", property $ W.makeRelative "C:\\Home" "c:/home/bob" == "bob")+ ,("W.makeRelative \"C:\\\\Home\" \"D:\\\\Home\\\\Bob\" == \"D:\\\\Home\\\\Bob\"", property $ W.makeRelative "C:\\Home" "D:\\Home\\Bob" == "D:\\Home\\Bob")+ ,("W.makeRelative \"C:\\\\Home\" \"C:Home\\\\Bob\" == \"C:Home\\\\Bob\"", property $ W.makeRelative "C:\\Home" "C:Home\\Bob" == "C:Home\\Bob")+ ,("W.makeRelative \"/Home\" \"/home/bob\" == \"bob\"", property $ W.makeRelative "/Home" "/home/bob" == "bob")+ ,("W.makeRelative \"/\" \"//\" == \"//\"", property $ W.makeRelative "/" "//" == "//")+ ,("P.makeRelative \"/Home\" \"/home/bob\" == \"/home/bob\"", property $ P.makeRelative "/Home" "/home/bob" == "/home/bob")+ ,("P.makeRelative \"/home/\" \"/home/bob/foo/bar\" == \"bob/foo/bar\"", property $ P.makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar")+ ,("P.makeRelative \"/fred\" \"bob\" == \"bob\"", property $ P.makeRelative "/fred" "bob" == "bob")+ ,("P.makeRelative \"/file/test\" \"/file/test/fred\" == \"fred\"", property $ P.makeRelative "/file/test" "/file/test/fred" == "fred")+ ,("P.makeRelative \"/file/test\" \"/file/test/fred/\" == \"fred/\"", property $ P.makeRelative "/file/test" "/file/test/fred/" == "fred/")+ ,("P.makeRelative \"some/path\" \"some/path/a/b/c\" == \"a/b/c\"", property $ P.makeRelative "some/path" "some/path/a/b/c" == "a/b/c") ,("P.normalise \"/file/\\\\test////\" == \"/file/\\\\test/\"", property $ P.normalise "/file/\\test////" == "/file/\\test/") ,("P.normalise \"/file/./test\" == \"/file/test\"", property $ P.normalise "/file/./test" == "/file/test") ,("P.normalise \"/test/file/../bob/fred/\" == \"/test/file/../bob/fred/\"", property $ P.normalise "/test/file/../bob/fred/" == "/test/file/../bob/fred/")