filepath-bytestring 1.4.2.1.2 → 1.4.2.1.3
raw patch · 5 files changed
+64/−47 lines, 5 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ System.FilePath.Posix.ByteString: equalFilePath :: RawFilePath -> RawFilePath -> Bool
+ System.FilePath.Posix.ByteString: makeRelative :: RawFilePath -> RawFilePath -> RawFilePath
+ System.FilePath.Windows.ByteString: equalFilePath :: RawFilePath -> RawFilePath -> Bool
+ System.FilePath.Windows.ByteString: makeRelative :: RawFilePath -> RawFilePath -> RawFilePath
Files
- CHANGELOG +7/−0
- System/FilePath/Internal.hs +40/−45
- TODO +1/−1
- filepath-bytestring.cabal +1/−1
- tests/TestGen.hs +15/−0
CHANGELOG view
@@ -1,3 +1,10 @@+filepath-bytestring (1.4.2.1.3) unstable; urgency=medium++ * Added equalFilePath.+ * Added makeRelative.++ -- Joey Hess <id@joeyh.name> Mon, 30 Dec 2019 13:07:31 -0400+ filepath-bytestring (1.4.2.1.2) unstable; urgency=medium * Fix build with ghc 8.0 (pre-Semigroup Monoid transition)
System/FilePath/Internal.hs view
@@ -126,8 +126,8 @@ dropTrailingPathSeparator, -- * File name manipulations- normalise, --equalFilePath,- --makeRelative,+ normalise, equalFilePath,+ makeRelative, isRelative, isAbsolute, isValid, --makeValid )@@ -136,7 +136,7 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8-import Data.Char(ord, chr, toUpper, isAsciiLower, isAsciiUpper)+import Data.Char(ord, chr, toUpper, toLower, isAsciiLower, isAsciiUpper) import Data.Maybe(isJust) import Data.Word(Word8) #ifdef mingw32_HOST_OS@@ -796,7 +796,7 @@ -- > Posix: "/directory" </> "file.ext" == "/directory/file.ext" -- > Windows: "/directory" </> "file.ext" == "/directory\\file.ext" -- > "directory" </> "/file.ext" == "/file.ext"--- > untested Valid x => (takeDirectory x </> takeFileName x) `equalFilePath` x+-- > Valid x => (takeDirectory x </> takeFileName x) `equalFilePath` x -- -- Combined: --@@ -859,7 +859,7 @@ -- > splitDirectories "test/file" == ["test","file"] -- > splitDirectories "/test/file" == ["/","test","file"] -- > Windows: splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"]--- > untested Valid x => joinPath (splitDirectories x) `equalFilePath` x+-- > Valid x => joinPath (splitDirectories x) `equalFilePath` x -- > splitDirectories "" == [] -- > Windows: splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"] -- > splitDirectories "/test///file" == ["/","test","file"]@@ -877,8 +877,6 @@ -- Note that this definition on c:\\c:\\, join then split will give c:\\. joinPath = foldr combine mempty -{-- --------------------------------------------------------------------- -- File name manipulators @@ -887,24 +885,21 @@ -- first this has a much better chance of working. -- Note that this doesn't follow symlinks or DOSNAM~1s. ----- > untested x == y ==> equalFilePath x y--- > untested normalise x == normalise y ==> equalFilePath x y--- > untested equalFilePath "foo" "foo/"--- > untested not (equalFilePath "foo" "/foo")--- > untested Posix: not (equalFilePath "foo" "FOO")--- > untested Windows: equalFilePath "foo" "FOO"--- > untested Windows: not (equalFilePath "C:" "C:/")+-- > x == y ==> equalFilePath x y+-- > normalise x == normalise y ==> equalFilePath x y+-- > equalFilePath "foo" "foo/"+-- > not (equalFilePath "foo" "/foo")+-- > Posix: not (equalFilePath "foo" "FOO")+-- > Windows: equalFilePath "foo" "FOO"+-- > Windows: not (equalFilePath "C:" "C:/") equalFilePath :: RawFilePath -> RawFilePath -> Bool equalFilePath a b = f a == f b where--- FIXME: B8.map will not lower-case non-ascii characters. f x- | isWindows = dropTrailingPathSeparator $ B8.map toLower $ normalise x+ | isWindows = dropTrailingPathSeparator $ encodeFilePath $+ map toLower $ decodeFilePath $ normalise x | otherwise = dropTrailingPathSeparator $ normalise x--} -{-- -- | Contract a filename, based on a relative path. Note that the resulting path -- will never introduce @..@ paths, as the presence of symlinks means @..\/b@ -- may not reach @a\/b@ if it starts from @a\/c@. For a worked example see@@ -913,46 +908,46 @@ -- The corresponding @makeAbsolute@ function can be found in -- @System.Directory@. ----- > untested makeRelative "/directory" "/directory/file.ext" == "file.ext"--- > untested Valid x => makeRelative (takeDirectory x) x `equalFilePath` takeFileName x--- > untested makeRelative x x == "."--- > untested Valid x y => equalFilePath x y || (isRelative x && makeRelative y x == x) || equalFilePath (y </> makeRelative y x) x--- > untested Windows: makeRelative "C:\\Home" "c:\\home\\bob" == "bob"--- > untested Windows: makeRelative "C:\\Home" "c:/home/bob" == "bob"--- > untested Windows: makeRelative "C:\\Home" "D:\\Home\\Bob" == "D:\\Home\\Bob"--- > untested Windows: makeRelative "C:\\Home" "C:Home\\Bob" == "C:Home\\Bob"--- > untested Windows: makeRelative "/Home" "/home/bob" == "bob"--- > untested Windows: makeRelative "/" "//" == "//"--- > untested Posix: makeRelative "/Home" "/home/bob" == "/home/bob"--- > untested Posix: makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar"--- > untested Posix: makeRelative "/fred" "bob" == "bob"--- > untested Posix: makeRelative "/file/test" "/file/test/fred" == "fred"--- > untested Posix: makeRelative "/file/test" "/file/test/fred/" == "fred/"--- > untested Posix: makeRelative "some/path" "some/path/a/b/c" == "a/b/c"-makeRelative :: FilePath -> FilePath -> FilePath+-- > makeRelative "/directory" "/directory/file.ext" == "file.ext"+-- > Valid x => makeRelative (takeDirectory x) x `equalFilePath` takeFileName x+-- > makeRelative x x == "."+-- > Valid x y => equalFilePath x y || (isRelative x && makeRelative y x == x) || equalFilePath (y </> makeRelative y x) x+-- > Windows: makeRelative "C:\\Home" "c:\\home\\bob" == "bob"+-- > Windows: makeRelative "C:\\Home" "c:/home/bob" == "bob"+-- > Windows: makeRelative "C:\\Home" "D:\\Home\\Bob" == "D:\\Home\\Bob"+-- > Windows: makeRelative "C:\\Home" "C:Home\\Bob" == "C:Home\\Bob"+-- > Windows: makeRelative "/Home" "/home/bob" == "bob"+-- > Windows: makeRelative "/" "//" == "//"+-- > Posix: makeRelative "/Home" "/home/bob" == "/home/bob"+-- > Posix: makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar"+-- > Posix: makeRelative "/fred" "bob" == "bob"+-- > Posix: makeRelative "/file/test" "/file/test/fred" == "fred"+-- > Posix: makeRelative "/file/test" "/file/test/fred/" == "fred/"+-- > Posix: makeRelative "some/path" "some/path/a/b/c" == "a/b/c"+makeRelative :: RawFilePath -> RawFilePath -> RawFilePath makeRelative root path | equalFilePath root path = "." | takeAbs root /= takeAbs path = path | otherwise = f (dropAbs root) (dropAbs path) where- f "" y = dropWhile isPathSeparator y+ f "" y = B.dropWhile isPathSeparator y f x y = let (x1,x2) = g x (y1,y2) = g y in if equalFilePath x1 y1 then f x2 y2 else path - g x = (dropWhile isPathSeparator a, dropWhile isPathSeparator b)+ g x = (B.dropWhile isPathSeparator a, B.dropWhile isPathSeparator b) where- (a,b) = break isPathSeparator $ dropWhile isPathSeparator x+ (a,b) = B.break isPathSeparator $ B.dropWhile isPathSeparator x -- on windows, need to drop '/' which is kind of absolute, but not a drive- dropAbs x | hasLeadingPathSeparator x && not (hasDrive x) = tail x+ dropAbs x | hasLeadingPathSeparator x && not (hasDrive x) = B.tail x dropAbs x = dropDrive x - takeAbs x | hasLeadingPathSeparator x && not (hasDrive x) = [pathSeparator]- takeAbs x = map (\y -> if isPathSeparator y then pathSeparator else toLower y) $ takeDrive x---}+ 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 -- | Normalise a file --@@ -1074,7 +1069,7 @@ not (isJust (readDriveUNC x1) && not (hasTrailingPathSeparator x1)) where (x1,x2) = splitDrive path- f x = map toUpper (B8.unpack $ dropWhileEnd (== 32) $ dropExtensions x) `elem` badElements+ f x = map toUpper (decodeFilePath $ dropWhileEnd (== 32) $ dropExtensions x) `elem` badElements {-
TODO view
@@ -1,3 +1,3 @@ * Some functions have not been ported from FilePath and are commented out:- splitSearchPath, getSearchPath, normalise, equalFilePath, makeRelative,+ splitSearchPath, getSearchPath, 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.2+version: 1.4.2.1.3 -- NOTE: Don't forget to update CHANGELOG and the filepath version below license: BSD3 license-file: LICENSE
tests/TestGen.hs view
@@ -303,6 +303,8 @@ ,("\"/directory\" W.</> \"file.ext\" == \"/directory\\\\file.ext\"", property $ "/directory" W.</> "file.ext" == "/directory\\file.ext") ,("\"directory\" P.</> \"/file.ext\" == \"/file.ext\"", property $ "directory" P.</> "/file.ext" == "/file.ext") ,("\"directory\" W.</> \"/file.ext\" == \"/file.ext\"", property $ "directory" W.</> "/file.ext" == "/file.ext")+ ,("(P.takeDirectory x P.</> P.takeFileName x) `P.equalFilePath` x", property $ \(QFilePathValidP vx) -> let x = toRawFilePath vx in (P.takeDirectory x P.</> P.takeFileName x) `P.equalFilePath` x)+ ,("(W.takeDirectory x W.</> W.takeFileName x) `W.equalFilePath` x", property $ \(QFilePathValidW vx) -> let x = toRawFilePath vx in (W.takeDirectory x W.</> W.takeFileName x) `W.equalFilePath` x) ,("\"/\" P.</> \"test\" == \"/test\"", property $ "/" P.</> "test" == "/test") ,("\"home\" P.</> \"bob\" == \"home/bob\"", property $ "home" P.</> "bob" == "home/bob") ,("\"x:\" P.</> \"foo\" == \"x:/foo\"", property $ "x:" P.</> "foo" == "x:/foo")@@ -334,6 +336,8 @@ ,("P.splitDirectories \"/test/file\" == [\"/\", \"test\", \"file\"]", property $ P.splitDirectories "/test/file" == ["/", "test", "file"]) ,("W.splitDirectories \"/test/file\" == [\"/\", \"test\", \"file\"]", property $ W.splitDirectories "/test/file" == ["/", "test", "file"]) ,("W.splitDirectories \"C:\\\\test\\\\file\" == [\"C:\\\\\", \"test\", \"file\"]", property $ W.splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"])+ ,("P.joinPath (P.splitDirectories x) `P.equalFilePath` x", property $ \(QFilePathValidP vx) -> let x = toRawFilePath vx in P.joinPath (P.splitDirectories x) `P.equalFilePath` x)+ ,("W.joinPath (W.splitDirectories x) `W.equalFilePath` x", property $ \(QFilePathValidW vx) -> let x = toRawFilePath vx in W.joinPath (W.splitDirectories x) `W.equalFilePath` x) ,("P.splitDirectories \"\" == []", property $ P.splitDirectories "" == []) ,("W.splitDirectories \"\" == []", property $ W.splitDirectories "" == []) ,("W.splitDirectories \"C:\\\\test\\\\\\\\\\\\file\" == [\"C:\\\\\", \"test\", \"file\"]", property $ W.splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"])@@ -346,6 +350,17 @@ ,("P.joinPath [] == \"\"", property $ P.joinPath [] == "") ,("W.joinPath [] == \"\"", property $ W.joinPath [] == "") ,("P.joinPath [\"test\", \"file\", \"path\"] == \"test/file/path\"", property $ P.joinPath ["test", "file", "path"] == "test/file/path")+ ,("x == y ==> P.equalFilePath x y", property $ \(QFilePath vx) (QFilePath vy) -> let y = toRawFilePath vy in let x = toRawFilePath vx in x == y ==> P.equalFilePath x y)+ ,("x == y ==> W.equalFilePath x y", property $ \(QFilePath vx) (QFilePath vy) -> let y = toRawFilePath vy in let x = toRawFilePath vx in x == y ==> W.equalFilePath x y)+ ,("P.normalise x == P.normalise y ==> P.equalFilePath x y", property $ \(QFilePath vx) (QFilePath vy) -> let y = toRawFilePath vy in let x = toRawFilePath vx in P.normalise x == P.normalise y ==> P.equalFilePath x y)+ ,("W.normalise x == W.normalise y ==> W.equalFilePath x y", property $ \(QFilePath vx) (QFilePath vy) -> let y = toRawFilePath vy in let x = toRawFilePath vx in W.normalise x == W.normalise y ==> W.equalFilePath x y)+ ,("P.equalFilePath \"foo\" \"foo/\"", property $ P.equalFilePath "foo" "foo/")+ ,("W.equalFilePath \"foo\" \"foo/\"", property $ W.equalFilePath "foo" "foo/")+ ,("not (P.equalFilePath \"foo\" \"/foo\")", property $ not (P.equalFilePath "foo" "/foo"))+ ,("not (W.equalFilePath \"foo\" \"/foo\")", property $ not (W.equalFilePath "foo" "/foo"))+ ,("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.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/")