filepath 1.4.1.2 → 1.4.2
raw patch · 6 files changed
+54/−11 lines, 6 filesdep ~QuickCheckdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: QuickCheck, base
API changes (from Hackage documentation)
+ System.FilePath.Posix: isExtensionOf :: String -> FilePath -> Bool
+ System.FilePath.Windows: isExtensionOf :: String -> FilePath -> Bool
Files
- LICENSE +1/−1
- README.md +14/−0
- System/FilePath/Internal.hs +15/−3
- changelog.md +6/−2
- filepath.cabal +5/−5
- tests/TestGen.hs +13/−0
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2005-2017.+Copyright Neil Mitchell 2005-2018. All rights reserved. Redistribution and use in source and binary forms, with or without
README.md view
@@ -17,3 +17,17 @@ * Often it is useful to represent invalid files, e.g. `/foo/*.txt` probably isn't an actual file, but a glob pattern. Other programs use `foo//bar` for globs, which is definitely not a file, but might want to be stored as a `FilePath`. * Some programs use syntactic non-semantic details of the `FilePath` to change their behaviour. For example, `foo`, `foo/` and `foo/.` are all similar, and refer to the same location on disk, but may behave differently when passed to command-line tools. * A useful step to introducing an abstract `FilePath` is to reduce the amount of manipulating `FilePath` values like lists. This library hopes to help in that effort.++### Developer notes++Most of the code is in `System/FilePath/Internal.hs` which is `#include`'d into both `System/FilePath/Posix.hs` and `System/FilePath/Windows.hs` with the `IS_WINDOWS` CPP define set to either `True` or `False`. This Internal module is a bit weird in that it isn't really a Haskell module, but is more an include file.++The library has extensive doc tests. Anything starting with `-- >` is transformed into a doc test as a predicate that must evaluate to `True`. These tests follow a few rules:++* Tests prefixed with `Windows:` or `Posix:` are only tested against that specific implementation - otherwise tests are run against both implementations.+* Any single letter variable, e.g. `x`, is considered universal quantification, and is checked with `QuickCheck`.+* If `Valid x =>` appears at the start of a doc test, that means the property will only be tested with `x` passing the `isValid` predicate.++The tests can be generated by `Generate.hs` in the root of the repo, and will be placed in `tests/TestGen.hs`. The `TestGen.hs` file is checked into the repo, and the CI scripts check that `TestGen.hs` is in sync with what would be generated a fresh - if you don't regenerate `TestGen.hs` the CI will fail.++The `.ghci` file is set up to allow you to type `ghci` to open the library, then `:go` will regenerate the tests and run them.
System/FilePath/Internal.hs view
@@ -53,7 +53,7 @@ -- /Example 2:/ Download a file from @url@ and save it to disk: -- -- @do let file = 'makeValid' url--- System.IO.createDirectoryIfMissing True ('takeDirectory' file)@+-- System.Directory.createDirectoryIfMissing True ('takeDirectory' file)@ -- -- /Example 3:/ Compile a Haskell file, putting the @.hi@ file under @interface@: --@@ -75,7 +75,7 @@ -- * Extension functions splitExtension, takeExtension, replaceExtension, (-<.>), dropExtension, addExtension, hasExtension, (<.>),- splitExtensions, dropExtensions, takeExtensions, replaceExtensions,+ splitExtensions, dropExtensions, takeExtensions, replaceExtensions, isExtensionOf, stripExtension, -- * Filename\/directory functions@@ -105,7 +105,7 @@ import Data.Char(toLower, toUpper, isAsciiLower, isAsciiUpper) import Data.Maybe(isJust)-import Data.List(stripPrefix)+import Data.List(stripPrefix, isSuffixOf) import System.Environment(getEnv) @@ -312,6 +312,18 @@ hasExtension :: FilePath -> Bool hasExtension = any isExtSeparator . takeFileName ++-- | Does the given filename have the specified extension?+--+-- > "png" `isExtensionOf` "/directory/file.png" == True+-- > ".png" `isExtensionOf` "/directory/file.png" == True+-- > ".tar.gz" `isExtensionOf` "bar/foo.tar.gz" == True+-- > "ar.gz" `isExtensionOf` "bar/foo.tar.gz" == False+-- > "png" `isExtensionOf` "/directory/file.png.jpg" == False+-- > "csv/table.csv" `isExtensionOf` "/data/csv/table.csv" == False+isExtensionOf :: String -> FilePath -> Bool+isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions+isExtensionOf ext = isSuffixOf ('.':ext) . takeExtensions -- | Drop the given extension from a FilePath, and the @\".\"@ preceding it. -- Returns 'Nothing' if the FilePath does not have the given extension, or
changelog.md view
@@ -2,6 +2,12 @@ _Note: below all `FilePath` values are unquoted, so `\\` really means two backslashes._ +## 1.4.2 *Jan 2018*++ * Bundled with GHC 8.4.1++ * Add `isExtensionOf` function.+ ## 1.4.1.2 *Feb 2017* * Bundled with GHC 8.2.1@@ -11,8 +17,6 @@ * Bundled with GHC 8.0.2 * Documentation improvements-- * Allow QuickCheck-2.9 ## 1.4.1.0 *Dec 2015*
filepath.cabal view
@@ -1,18 +1,18 @@ cabal-version: >= 1.18 name: filepath-version: 1.4.1.2+version: 1.4.2 -- NOTE: Don't forget to update ./changelog.md license: BSD3 license-file: LICENSE author: Neil Mitchell <ndmitchell@gmail.com> maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2005-2017+copyright: Neil Mitchell 2005-2018 bug-reports: https://github.com/haskell/filepath/issues homepage: https://github.com/haskell/filepath#readme category: System build-type: Simple synopsis: Library for manipulating FilePaths in a cross platform way.-tested-with: GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2+tested-with: GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 description: This package provides functionality for manipulating @FilePath@ values, and is shipped with both <https://www.haskell.org/ghc/ GHC> and the <https://www.haskell.org/platform/ Haskell Platform>. It provides three modules: .@@ -48,7 +48,7 @@ System.FilePath.Windows build-depends:- base >= 4 && < 4.11+ base >= 4 && < 4.12 ghc-options: -Wall @@ -64,4 +64,4 @@ build-depends: filepath, base,- QuickCheck >= 2.7 && < 2.10+ QuickCheck >= 2.7 && < 2.12
tests/TestGen.hs view
@@ -3,6 +3,7 @@ import TestUtil import qualified System.FilePath.Windows as W import qualified System.FilePath.Posix as P+{-# ANN module "HLint: ignore" #-} tests :: [(String, Property)] tests = [("W.pathSeparator == '\\\\'", property $ W.pathSeparator == '\\')@@ -107,6 +108,18 @@ ,("W.hasExtension \"/directory/path\" == False", property $ W.hasExtension "/directory/path" == False) ,("null (P.takeExtension x) == not (P.hasExtension x)", property $ \(QFilePath x) -> null (P.takeExtension x) == not (P.hasExtension x)) ,("null (W.takeExtension x) == not (W.hasExtension x)", property $ \(QFilePath x) -> null (W.takeExtension x) == not (W.hasExtension x))+ ,("\"png\" `P.isExtensionOf` \"/directory/file.png\" == True", property $ "png" `P.isExtensionOf` "/directory/file.png" == True)+ ,("\"png\" `W.isExtensionOf` \"/directory/file.png\" == True", property $ "png" `W.isExtensionOf` "/directory/file.png" == True)+ ,("\".png\" `P.isExtensionOf` \"/directory/file.png\" == True", property $ ".png" `P.isExtensionOf` "/directory/file.png" == True)+ ,("\".png\" `W.isExtensionOf` \"/directory/file.png\" == True", property $ ".png" `W.isExtensionOf` "/directory/file.png" == True)+ ,("\".tar.gz\" `P.isExtensionOf` \"bar/foo.tar.gz\" == True", property $ ".tar.gz" `P.isExtensionOf` "bar/foo.tar.gz" == True)+ ,("\".tar.gz\" `W.isExtensionOf` \"bar/foo.tar.gz\" == True", property $ ".tar.gz" `W.isExtensionOf` "bar/foo.tar.gz" == True)+ ,("\"ar.gz\" `P.isExtensionOf` \"bar/foo.tar.gz\" == False", property $ "ar.gz" `P.isExtensionOf` "bar/foo.tar.gz" == False)+ ,("\"ar.gz\" `W.isExtensionOf` \"bar/foo.tar.gz\" == False", property $ "ar.gz" `W.isExtensionOf` "bar/foo.tar.gz" == False)+ ,("\"png\" `P.isExtensionOf` \"/directory/file.png.jpg\" == False", property $ "png" `P.isExtensionOf` "/directory/file.png.jpg" == False)+ ,("\"png\" `W.isExtensionOf` \"/directory/file.png.jpg\" == False", property $ "png" `W.isExtensionOf` "/directory/file.png.jpg" == False)+ ,("\"csv/table.csv\" `P.isExtensionOf` \"/data/csv/table.csv\" == False", property $ "csv/table.csv" `P.isExtensionOf` "/data/csv/table.csv" == False)+ ,("\"csv/table.csv\" `W.isExtensionOf` \"/data/csv/table.csv\" == False", property $ "csv/table.csv" `W.isExtensionOf` "/data/csv/table.csv" == False) ,("P.stripExtension \"hs.o\" \"foo.x.hs.o\" == Just \"foo.x\"", property $ P.stripExtension "hs.o" "foo.x.hs.o" == Just "foo.x") ,("W.stripExtension \"hs.o\" \"foo.x.hs.o\" == Just \"foo.x\"", property $ W.stripExtension "hs.o" "foo.x.hs.o" == Just "foo.x") ,("P.stripExtension \"hi.o\" \"foo.x.hs.o\" == Nothing", property $ P.stripExtension "hi.o" "foo.x.hs.o" == Nothing)