29 Commits
0.2.0 ... 0.5.3

Author SHA1 Message Date
Chris Done
28c4f7fe21 Bump to 0.5.3 2015-11-21 19:54:59 +01:00
Chris Done
95fab22567 Merge pull request #7 from mrkkrp/master
Various improvements
2015-11-21 19:53:16 +01:00
mrkkrp
00fabad1f4 Add type-safe synonyms of ‘toFilePath’
This helps to “double check” programmers' assumptions about what kind of
path he is converting into ‘FilePath’. Without these synonyms it's
possible to silently convert wrong type of path into ‘FilePath’.
2015-11-21 16:15:34 +06:00
mrkkrp
733fa04ac3 Write ‘isPrefixOf’ and friends in infix form 2015-11-21 16:14:54 +06:00
mrkkrp
339f7587a3 Remove unused language pragmas 2015-11-21 16:13:52 +06:00
mrkkrp
0476db8ebc Add ‘.stack-work’ to ‘.gitignore’ 2015-11-21 16:12:12 +06:00
Chris Done
57e886b71f Merge pull request #6 from mgsloan/properties-doc-fix
Improve a few property definitions
2015-10-08 09:13:13 -07:00
Michael Sloan
1841d7451c Improve a few property definitions
The properties for stripDir and parent used the name 'parent' as a
variable.

The properties for filename and dirname seemed to be wrong and also used
'parent' as a variable.
2015-10-08 03:00:50 -07:00
Chris Done
62278a77e6 Merge pull request #5 from glasserc/rel-file-tests
test: missing case for parseRelFile
2015-07-09 03:07:35 +02:00
Ethan Glasser-Camp
a4ed4cd504 test: missing case for parseRelFile 2015-07-08 20:28:15 -04:00
Chris Done
c637893aa8 Bump to 0.5.2 2015-06-21 12:19:11 +02:00
Chris Done
09996f1605 Merge pull request #4 from bergmark/no-derivegeneric
Remove unused DeriveGeneric extension, fixes GHC 7.0 build
2015-06-21 12:18:07 +02:00
Adam Bergmark
9f229ecef3 Remove unused DeriveGeneric extension, fixes GHC 7.0 build 2015-06-21 02:29:25 +02:00
Chris Done
44d9e02cc2 Add note in docs about dropTrailingPathSeparator 2015-06-18 08:58:01 +02:00
Chris Done
94a5252ff5 Bump to 0.5.1 2015-06-17 18:45:43 +02:00
Chris Done
df1e191517 Fix syntax error 2015-06-17 18:45:34 +02:00
Chris Done
30890ad3c2 Merge pull request #3 from snoyberg/master
Handle parent directory checks on Windows
2015-06-17 18:43:01 +02:00
Michael Snoyman
9ca83d66b8 Handle parent directory checks on Windows 2015-06-17 19:21:45 +03:00
Chris Done
4e1816392a Fix stripDir p p /= Nothing bug 2015-05-27 17:08:03 +02:00
Chris Done
8f3b169760 Bump to 0.4.0 2015-05-22 11:35:52 +02:00
Chris Done
ffdf4af243 Generalize stripDir to MonadThrow 2015-05-22 11:35:52 +02:00
Chris Done
87a56a93b8 Disallow .. 2015-05-22 11:35:52 +02:00
Chris Done
cb6f472524 Merge pull request #2 from kraai/patch-2
Add source repository information
2015-05-14 17:54:33 +02:00
Chris Done
bff31277e3 Merge pull request #1 from kraai/patch-1
Add ellipsis
2015-05-14 17:48:11 +02:00
kraai
b06a8c9528 Add source repository information 2015-05-14 15:47:04 +00:00
kraai
0c1dd7e493 Add ellipsis 2015-05-14 15:44:41 +00:00
Chris Done
5613ba1dfa Bump for hackage 2015-05-14 08:02:19 +02:00
Chris Done
07aa83ca19 Remove Generic 2015-05-14 08:01:14 +02:00
Chris Done
a68b46b060 Update test suite 2015-05-11 19:01:35 +02:00
6 changed files with 122 additions and 27 deletions

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@ cabal-dev/
TAGS
tags
*.tag
.stack-work/

View File

@@ -1,4 +1,20 @@
0.5.3:
* Added conversion functions.
0.2.0:
* Rename parentAbs to simply parent.
* Add dirname.
0.3.0:
* Removed Generic instance.
0.4.0:
* Implemented stricter parsing, disabling use of "..".
* Made stripDir generic over MonadThrow
0.5.0:
* Fix stripDir p p /= Nothing bug.
0.5.2:
* Removed unused DeriveGeneric.

View File

@@ -1,5 +1,5 @@
name: path
version: 0.2.0
version: 0.5.3
synopsis: Path
description: Path
license: BSD3
@@ -10,6 +10,7 @@ copyright: 2015 FP Complete
category: Filesystem
build-type: Simple
cabal-version: >=1.8
extra-source-files: README.md, CHANGELOG
library
hs-source-dirs: src/
@@ -29,3 +30,7 @@ test-suite test
, hspec
, mtl
, path
source-repository head
type: git
location: https://github.com/chrisdone/path.git

View File

@@ -1,5 +1,4 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE EmptyDataDecls #-}
@@ -32,6 +31,10 @@ module Path
,dirname
-- * Conversion
,toFilePath
,fromAbsDir
,fromRelDir
,fromAbsFile
,fromRelFile
)
where
@@ -65,6 +68,7 @@ data PathParseException
| InvalidRelDir FilePath
| InvalidAbsFile FilePath
| InvalidRelFile FilePath
| Couldn'tStripPrefixDir FilePath FilePath
deriving (Show,Typeable)
instance Exception PathParseException
@@ -81,7 +85,8 @@ parseAbsDir :: MonadThrow m
parseAbsDir filepath =
if FilePath.isAbsolute filepath &&
not (null (normalizeDir filepath)) &&
not (isPrefixOf "~/" filepath)
not ("~/" `isPrefixOf` filepath) &&
not (hasParentDir filepath)
then return (Path (normalizeDir filepath))
else throwM (InvalidAbsDir filepath)
@@ -95,8 +100,10 @@ parseRelDir :: MonadThrow m
parseRelDir filepath =
if not (FilePath.isAbsolute filepath) &&
not (null filepath) &&
not (isPrefixOf "~/" filepath) &&
not (null (normalizeDir filepath))
not ("~/" `isPrefixOf` filepath) &&
not (hasParentDir filepath) &&
not (null (normalizeDir filepath)) &&
filepath /= ".."
then return (Path (normalizeDir filepath))
else throwM (InvalidRelDir filepath)
@@ -109,8 +116,10 @@ parseAbsFile :: MonadThrow m
parseAbsFile filepath =
if FilePath.isAbsolute filepath &&
not (FilePath.hasTrailingPathSeparator filepath) &&
not (isPrefixOf "~/" filepath) &&
not (null (normalizeFile filepath))
not ("~/" `isPrefixOf` filepath) &&
not (hasParentDir filepath) &&
not (null (normalizeFile filepath)) &&
filepath /= ".."
then return (Path (normalizeFile filepath))
else throwM (InvalidAbsFile filepath)
@@ -121,13 +130,29 @@ parseAbsFile filepath =
parseRelFile :: MonadThrow m
=> FilePath -> m (Path Rel File)
parseRelFile filepath =
if not (FilePath.isAbsolute filepath || FilePath.hasTrailingPathSeparator filepath) &&
if not (FilePath.isAbsolute filepath ||
FilePath.hasTrailingPathSeparator filepath) &&
not (null filepath) &&
not (isPrefixOf "~/" filepath) &&
not (null (normalizeFile filepath))
not ("~/" `isPrefixOf` filepath) &&
not (hasParentDir filepath) &&
not (null (normalizeFile filepath)) &&
filepath /= ".."
then return (Path (normalizeFile filepath))
else throwM (InvalidRelFile filepath)
-- | Helper function: check if the filepath has any parent directories in it.
-- This handles the logic of checking for different path separators on Windows.
hasParentDir :: FilePath -> Bool
hasParentDir filepath' =
("/.." `isSuffixOf` filepath) ||
("/../" `isInfixOf` filepath) ||
("../" `isPrefixOf` filepath)
where
filepath =
case FilePath.pathSeparator of
'/' -> filepath'
x -> map (\y -> if x == y then '/' else y) filepath'
--------------------------------------------------------------------------------
-- Constructors
@@ -175,9 +200,29 @@ mkRelFile s =
-- Conversion
-- | Convert to a 'FilePath' type.
--
-- All directories have a trailing slash, so if you want no trailing
-- slash, you can use 'System.FilePath.dropTrailingPathSeparator' from
-- the filepath package.
toFilePath :: Path b t -> FilePath
toFilePath (Path l) = l
-- | Convert absolute path to directory to 'FilePath' type.
fromAbsDir :: Path Abs Dir -> FilePath
fromAbsDir = toFilePath
-- | Convert relative path to directory to 'FilePath' type.
fromRelDir :: Path Rel Dir -> FilePath
fromRelDir = toFilePath
-- | Convert absolute path to file to 'FilePath' type.
fromAbsFile :: Path Abs File -> FilePath
fromAbsFile = toFilePath
-- | Convert relative path to file to 'FilePath' type.
fromRelFile :: Path Rel File -> FilePath
fromRelFile = toFilePath
--------------------------------------------------------------------------------
-- Operations
@@ -211,19 +256,25 @@ toFilePath (Path l) = l
--
-- The following properties hold:
--
-- @stripDir parent (parent \<\/> child) = child@
-- @stripDir x (x \<\/> y) = y@
--
-- Cases which are proven not possible:
--
-- @stripDir (a :: Path Abs …) (b :: Path Rel …)@
--
-- @stripDir (a :: Path Rel) (b :: Path Abs …)@
-- @stripDir (a :: Path Rel) (b :: Path Abs …)@
--
-- In other words the bases must match.
--
stripDir :: Path b Dir -> Path b t -> Maybe (Path Rel t)
-- Throws: 'Couldn'tStripPrefixDir'
--
stripDir :: MonadThrow m
=> Path b Dir -> Path b t -> m (Path Rel t)
stripDir (Path p) (Path l) =
fmap Path (stripPrefix p l)
case stripPrefix p l of
Nothing -> throwM (Couldn'tStripPrefixDir p l)
Just "" -> throwM (Couldn'tStripPrefixDir p l)
Just ok -> return (Path ok)
-- | Is p a parent of the given location? Implemented in terms of
-- 'stripDir'. The bases must match.
@@ -235,7 +286,7 @@ isParentOf p l =
--
-- The following properties hold:
--
-- @parent (parent \<\/> child) == parent@
-- @parent (x \<\/> y) == x@
--
-- On the root, getting the parent is idempotent:
--
@@ -249,7 +300,7 @@ parent (Path fp) =
--
-- The following properties hold:
--
-- @filename (parent \<\/> filename a) == a@
-- @filename (p \<\/> a) == filename a@
--
filename :: Path b File -> Path Rel File
filename (Path l) =
@@ -259,7 +310,7 @@ filename (Path l) =
--
-- The following properties hold:
--
-- @dirname (parent \<\/> dirname a) == a@
-- @dirname (p \<\/> a) == dirname a@
--
dirname :: Path b Dir -> Path Rel Dir
dirname (Path l) =

View File

@@ -1,7 +1,4 @@
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- | Internal types and functions.
@@ -10,7 +7,6 @@ module Path.Internal
where
import Data.Data
import GHC.Generics
-- | Path of some base and type.
--
@@ -22,7 +18,7 @@ import GHC.Generics
-- All directories end in a trailing separator. There are no duplicate
-- path separators @\/\/@, no @..@, no @.\/@, no @~\/@, etc.
newtype Path b t = Path FilePath
deriving (Typeable,Generic)
deriving (Typeable)
-- | String equality.
--

View File

@@ -4,6 +4,9 @@
module Main where
import Control.Applicative
import Control.Monad
import Data.Maybe
import Data.Monoid
import Path
import Path.Internal
@@ -23,8 +26,27 @@ spec =
describe "Operations: (</>)" operationAppend
describe "Operations: stripDir" operationStripDir
describe "Operations: isParentOf" operationIsParentOf
describe "Operations: parentAbs" operationParentAbs
describe "Operations: parent" operationParent
describe "Operations: filename" operationFilename
describe "Restrictions" restrictions
-- | Restricting the input of any tricks.
restrictions :: Spec
restrictions =
do parseFails "~/"
parseFails "~/foo"
parseFails "~/foo/bar"
parseFails "../"
parseFails ".."
parseFails "/.."
parseFails "/foo/../bar/"
parseFails "/foo/bar/.."
where parseFails x =
it (show x ++ " should be rejected")
(isNothing (void (parseAbsDir x) <|>
void (parseRelDir x) <|>
void (parseAbsFile x) <|>
void (parseRelFile x)))
-- | The 'filename' operation.
operationFilename :: Spec
@@ -38,10 +60,10 @@ operationFilename =
filename $(mkRelFile "bar.txt")) ==
$(mkRelFile "bar.txt"))
-- | The 'parentAbs' operation.
operationParentAbs :: Spec
operationParentAbs =
do it "parentAbs (parent </> child) == parent"
-- | The 'parent' operation.
operationParent :: Spec
operationParent =
do it "parent (parent </> child) == parent"
(parent ($(mkAbsDir "/foo") </>
$(mkRelDir "bar")) ==
$(mkAbsDir "/foo"))
@@ -79,6 +101,10 @@ operationStripDir =
($(mkRelDir "bar/") </>
$(mkRelFile "bob/foo.txt")) ==
Just $(mkRelFile "bob/foo.txt"))
it "stripDir parent parent = _|_"
(stripDir $(mkAbsDir "/home/chris/foo")
$(mkAbsDir "/home/chris/foo") ==
Nothing)
-- | The '</>' operation.
operationAppend :: Spec