packages feed

system-filepath 0.4.2 → 0.4.3

raw patch · 11 files changed

+334/−116 lines, 11 filesdep +deepseqdep ~text

Dependencies added: deepseq

Dependency ranges changed: text

Files

lib/Filesystem/Path.hs view
@@ -132,11 +132,8 @@ dirname :: FilePath -> FilePath dirname p = case reverse (pathDirectories p) of 	[] -> FilePath Nothing [] Nothing []-	(d:_) -> let-		d':exts = T.split (== '.') (chunkText d)-		chunk txt = d { chunkText = txt }-		in FilePath Nothing [] (Just (chunk d')) (map chunk exts)-+	(d:_) -> case parseFilename d of+		(base, exts) -> FilePath Nothing [] base exts  -- | Retrieve a 'FilePath'&#x2019;s basename component. --@@ -183,7 +180,7 @@ 	directories = xDirectories ++ pathDirectories y 	xDirectories = (pathDirectories x ++) $ if null (filename x) 		then []-		else [filenameChunk True x]+		else [filenameText x]  -- | An alias for 'append'. (</>) :: FilePath -> FilePath -> FilePath@@ -285,7 +282,7 @@  -- | Get a 'FilePath'&#x2019;s full extension list. extensions :: FilePath -> [T.Text]-extensions = map chunkText . pathExtensions+extensions = map unescape' . pathExtensions  -- | Get whether a 'FilePath'&#x2019;s last extension is the predicate. hasExtension :: FilePath -> T.Text -> Bool@@ -298,8 +295,7 @@ -- | Append many extensions to the end of a 'FilePath'. addExtensions :: FilePath -> [T.Text] -> FilePath addExtensions p exts = p { pathExtensions = newExtensions } where-	newExtensions = pathExtensions p ++ chunks-	chunks = map (\e -> Chunk e True) exts+	newExtensions = pathExtensions p ++ exts  -- | An alias for 'addExtension'. (<.>) :: FilePath -> T.Text -> FilePath
lib/Filesystem/Path/CurrentOS.hs view
@@ -41,7 +41,7 @@ import qualified Filesystem.Path as F import qualified Filesystem.Path.Rules as R -#if defined(CABAL_OS_WINDOWS)+#if defined(CABAL_OS_WINDOWS) || defined(CABAL_OS_DARWIN) #define PLATFORM_PATH_FORMAT T.Text #else #define PLATFORM_PATH_FORMAT B.ByteString@@ -50,6 +50,12 @@ currentOS :: R.Rules PLATFORM_PATH_FORMAT #if defined(CABAL_OS_WINDOWS) currentOS = R.windows+#elif defined(CABAL_OS_DARWIN)+#if __GLASGOW_HASKELL__ >= 702+currentOS = R.darwin_ghc702+#else+currentOS = R.darwin+#endif #else #if __GLASGOW_HASKELL__ >= 702 currentOS = R.posix_ghc702
lib/Filesystem/Path/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-}  -- |@@ -12,29 +13,27 @@  import           Prelude hiding (FilePath) +import           Control.DeepSeq (NFData, rnf)+import qualified Control.Exception as Exc+import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8+import           Data.Char (chr, ord) import           Data.Data (Data) import           Data.List (intersperse)+import           Data.Ord (comparing) import qualified Data.Text as T import qualified Data.Text.Encoding as TE+import           Data.Text.Encoding.Error (UnicodeException) import           Data.Typeable (Typeable)+import           System.IO.Unsafe (unsafePerformIO)  ------------------------------------------------------------------------------- -- File Paths ------------------------------------------------------------------------------- -data Chunk = Chunk-	{ chunkText :: T.Text-	, chunkGood :: Bool-	}-	deriving (Ord, Data, Typeable)--instance Eq Chunk where-	(Chunk x _) == (Chunk y _) = x == y--type Directory = Chunk-type Basename = Chunk-type Extension = Chunk+type Directory = T.Text+type Basename = T.Text+type Extension = T.Text  data Root 	= RootPosix@@ -48,34 +47,42 @@ 	, pathBasename :: Maybe Basename 	, pathExtensions :: [Extension] 	}-	deriving (Eq, Ord, Data, Typeable)+	deriving (Data, Typeable) +instance Eq FilePath where+	x == y = compare x y == EQ++instance Ord FilePath where+	compare = comparing (\p ->+		(pathRoot p+		, fmap unescape' (pathDirectories p)+		, fmap unescape' (pathBasename p)+		, fmap unescape' (pathExtensions p)+		))++instance NFData Root where+	rnf (RootWindowsVolume c) = rnf c+	rnf _ = ()++instance NFData FilePath where+	rnf p = rnf (pathRoot p) `seq` rnf (pathDirectories p) `seq` rnf (pathBasename p) `seq` rnf (pathExtensions p)+ -- | A file path with no root, directory, or filename empty :: FilePath empty = FilePath Nothing [] Nothing [] -dot :: Chunk-dot = Chunk (T.pack ".") True+dot :: T.Text+dot = T.pack "." -dots :: Chunk-dots = Chunk (T.pack "..") True+dots :: T.Text+dots = T.pack ".." -filenameChunk :: Bool -> FilePath -> Chunk-filenameChunk strict p = Chunk (T.concat texts) allGood where-	name = maybe (Chunk T.empty True) id (pathBasename p)+filenameText :: FilePath -> T.Text+filenameText p = T.concat (name:exts) where+	name = maybe T.empty id (pathBasename p) 	exts = case pathExtensions p of 		[] -> []-		exts' -> intersperse dot ((Chunk T.empty True):exts')-	chunks = name:exts-	-	texts = map chunkText' chunks-	allGood = and (map chunkGood chunks)-	-	chunkText' c = if chunkGood c-		then if allGood || not strict-			then chunkText c-			else T.pack (B8.unpack (TE.encodeUtf8 (chunkText c)))-		else chunkText c+		exts' -> intersperse dot (T.empty:exts')  ------------------------------------------------------------------------------- -- Rules@@ -157,3 +164,52 @@ instance Show (Rules a) where 	showsPrec d r = showParen (d > 10) 		(showString "Rules " . shows (rulesName r))++textSplitBy :: (Char -> Bool) -> T.Text -> [T.Text]+#if MIN_VERSION_text(0,11,0)+textSplitBy = T.split+#else+textSplitBy = T.splitBy+#endif++unescape :: T.Text -> (T.Text, Bool)+unescape t = if T.any (\c -> ord c >= 0xEF00 && ord c <= 0xEFFF) t+	then (T.map (\c -> if ord c >= 0xEF00 && ord c <= 0xEFFF+		then chr (ord c - 0xEF00)+		else c) t, False)+	else (t, True)++unescape' :: T.Text -> T.Text+unescape' = fst . unescape++unescapeBytes' :: T.Text -> B8.ByteString+unescapeBytes' t = B8.concat (map (\c -> if ord c >= 0xEF00 && ord c <= 0xEFFF+	then B8.singleton (chr (ord c - 0xEF00))+	else TE.encodeUtf8 (T.singleton c)) (T.unpack t))++parseFilename :: T.Text -> (Maybe Basename, [Extension])+parseFilename filename = parsed where+	parsed = if T.null filename+		then (Nothing, [])+		else case textSplitBy (== '.') filename of+			[] -> (Nothing, [])+			(name':exts') -> (Just (checkChunk name'), map checkChunk exts')+	+	checkChunk t = if chunkGood t+		then t+		else case maybeDecodeUtf8 (unescapeBytes' t) of+			Just text -> text+			Nothing -> t+	+	chunkGood t = not (T.any (\c -> ord c >= 0xEF00 && ord c <= 0xEFFF) t)++maybeDecodeUtf8 :: B.ByteString -> Maybe T.Text+maybeDecodeUtf8 = excToMaybe . TE.decodeUtf8 where+	excToMaybe :: a -> Maybe a+	excToMaybe x = unsafePerformIO $ Exc.catch+		(fmap Just (Exc.evaluate x))+		unicodeError+	+	unicodeError :: UnicodeException -> IO (Maybe a)+	unicodeError _ = return Nothing+
lib/Filesystem/Path/Rules.hs view
@@ -11,6 +11,8 @@ 	, posix 	, posix_ghc702 	, windows+	, darwin+	, darwin_ghc702 	 	-- * Type conversions 	, toText@@ -28,16 +30,13 @@ import           Prelude hiding (FilePath, null) import qualified Prelude as P -import qualified Control.Exception as Exc import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8-import           Data.Char (toUpper, chr)+import           Data.Char (toUpper, chr, ord) import           Data.List (intersperse) import qualified Data.Text as T import qualified Data.Text.Encoding as TE-import           Data.Text.Encoding.Error (UnicodeException) import           System.IO ()-import           System.IO.Unsafe (unsafePerformIO)  import           Filesystem.Path hiding (root, filename, basename) import           Filesystem.Path.Internal@@ -52,24 +51,14 @@ 	RootWindowsVolume c -> c : ":\\" 	RootWindowsCurrentVolume -> "\\" -directoryChunks :: Bool -> FilePath -> [Chunk]-directoryChunks strict path = pathDirectories path ++ [filenameChunk strict path]--maybeDecodeUtf8 :: B.ByteString -> Maybe T.Text-maybeDecodeUtf8 = excToMaybe . TE.decodeUtf8 where-	excToMaybe :: a -> Maybe a-	excToMaybe x = unsafePerformIO $ Exc.catch-		(fmap Just (Exc.evaluate x))-		unicodeError-	-	unicodeError :: UnicodeException -> IO (Maybe a)-	unicodeError _ = return Nothing+directoryChunks :: FilePath -> [T.Text]+directoryChunks path = pathDirectories path ++ [filenameText path]  ------------------------------------------------------------------------------- -- POSIX ------------------------------------------------------------------------------- --- | Linux, BSD, OS X, and other UNIX or UNIX-like operating systems.+-- | Linux, BSD, and other UNIX or UNIX-like operating systems. posix :: Rules B.ByteString posix = Rules 	{ rulesName = T.pack "POSIX"@@ -83,75 +72,78 @@ 	, decodeString = posixFromBytes . B8.pack 	} --- | Linux, BSD, OS X, and other UNIX or UNIX-like operating systems.+-- | Linux, BSD, and other UNIX or UNIX-like operating systems. ----- This variant is for use with GHC 7.2 or later, which tries to decode--- file paths in its IO computations.+-- This is a variant of 'posix' for use with GHC 7.2 or later, which tries to+-- decode file paths in its IO computations.+--+-- Since: 0.3.3 posix_ghc702 :: Rules B.ByteString posix_ghc702 = posix-	{ encodeString = T.unpack . either id id . posixToText-	, decodeString = posixFromText . T.pack+	{ rulesName = T.pack "POSIX (GHC 7.2)"+	, encodeString = posixToGhcString+	, decodeString = posixFromGhcString 	}  posixToText :: FilePath -> Either T.Text T.Text posixToText p = if good then Right text else Left text where-	good = and (map chunkGood chunks)-	text = T.concat (root : map chunkText chunks)+	good = and (map snd chunks)+	text = T.concat (root : map fst chunks) 	 	root = rootText (pathRoot p)-	chunks = intersperse (Chunk (T.pack "/") True) (directoryChunks False p)+	chunks = intersperse (T.pack "/", True) (map unescape (directoryChunks p)) -posixFromChunks :: [Chunk] -> FilePath+posixFromChunks :: [T.Text] -> FilePath posixFromChunks chunks = FilePath root directories basename exts where-	(root, pastRoot) = if T.null (chunkText (head chunks))+	(root, pastRoot) = if T.null (head chunks) 		then (Just RootPosix, tail chunks) 		else (Nothing, chunks) 	 	(directories, filename)-		| P.null pastRoot = ([], Chunk T.empty True)+		| P.null pastRoot = ([], T.empty) 		| otherwise = case last pastRoot of-			fn | fn == dot -> (goodDirs pastRoot, Chunk T.empty True)-			fn | fn == dots -> (goodDirs pastRoot, Chunk T.empty True)+			fn | fn == dot -> (goodDirs pastRoot, T.empty)+			fn | fn == dots -> (goodDirs pastRoot, T.empty) 			fn -> (goodDirs (init pastRoot), fn) 	-	goodDirs = filter (not . T.null . chunkText)-	-	(basename, exts) = if T.null (chunkText filename)-		then (Nothing, [])-		else case T.split (== '.') (chunkText filename) of-			[] -> (Nothing, [])-			(name':exts') -> if chunkGood filename-				then (Just (Chunk name' True), map (\e -> Chunk e True) exts')-				else (Just (checkChunk name'), map checkChunk exts')+	goodDirs = filter (not . T.null) 	-	checkChunk raw = case maybeDecodeUtf8 (B8.pack (T.unpack raw)) of-		Just text -> Chunk text True-		Nothing -> Chunk raw False+	(basename, exts) = parseFilename filename  posixFromText :: T.Text -> FilePath posixFromText text = if T.null text 	then empty-	else posixFromChunks (map (\t -> Chunk t True) (T.split (== '/') text))+	else posixFromChunks (textSplitBy (== '/') text)  posixToBytes :: FilePath -> B.ByteString posixToBytes p = B.concat (root : chunks) where 	root = TE.encodeUtf8 (rootText (pathRoot p))-	chunks = intersperse (B8.pack "/") (map chunkBytes (directoryChunks True p))-	chunkBytes c = if chunkGood c-		then TE.encodeUtf8 (chunkText c)-		else B8.pack (T.unpack (chunkText c))+	chunks = intersperse (B8.pack "/") (map chunkBytes (directoryChunks p))+	chunkBytes t = if T.any (\c -> ord c >= 0xEF00 && ord c <= 0xEFFF) t+		then unescapeBytes' t+		else TE.encodeUtf8 t  posixFromBytes :: B.ByteString -> FilePath posixFromBytes bytes = if B.null bytes 	then empty 	else posixFromChunks $ flip map (B.split 0x2F bytes) $ \b -> case maybeDecodeUtf8 b of-		Just text -> Chunk text True-		Nothing -> Chunk (T.pack (B8.unpack b)) False+		Just text -> text+		Nothing -> T.pack (map (\c -> if ord c >= 0x80+			then chr (ord c + 0xEF00)+			else c) (B8.unpack b)) +posixToGhcString :: FilePath -> String+posixToGhcString p = P.concat (root : chunks) where+	root = T.unpack (rootText (pathRoot p))+	chunks = intersperse "/" (map T.unpack (directoryChunks p))++posixFromGhcString :: String -> FilePath+posixFromGhcString = posixFromText . T.pack+ posixValid :: FilePath -> Bool posixValid p = validRoot && validDirectories where-	validDirectories = all validChunk (directoryChunks True p)-	validChunk ch = not (T.any (\c -> c == '\0' || c == '/') (chunkText ch))+	validDirectories = all validChunk (directoryChunks p)+	validChunk ch = not (T.any (\c -> c == '\0' || c == '/') ch) 	validRoot = case pathRoot p of 		Nothing -> True 		Just RootPosix -> True@@ -162,6 +154,57 @@ 	normSearch bytes = if B.null bytes then B8.pack "." else bytes  -------------------------------------------------------------------------------+-- Darwin+-------------------------------------------------------------------------------++-- | Darwin and Mac OS X.+--+-- This is almost identical to 'posix', but with a native path type of 'T.Text'+-- rather than 'B.ByteString'.+--+-- Since: 0.3.4+darwin :: Rules T.Text+darwin = Rules+	{ rulesName = T.pack "Darwin"+	, valid = posixValid+	, splitSearchPath = darwinSplitSearch+	, toText = Right . darwinToText+	, fromText = posixFromText+	, encode = darwinToText+	, decode = posixFromText+	, encodeString = darwinToString+	, decodeString = darwinFromString+	}++-- | Darwin and Mac OS X.+--+-- This is a variant of 'darwin' for use with GHC 7.2 or later, which tries to+-- decode file paths in its IO computations.+--+-- Since: 0.3.4+darwin_ghc702 :: Rules T.Text+darwin_ghc702 = darwin+	{ rulesName = T.pack "Darwin (GHC 7.2)"+	, encodeString = T.unpack . darwinToText+	, decodeString = posixFromText . T.pack+	}++darwinToText :: FilePath -> T.Text+darwinToText p = T.concat (root : chunks) where+	root = rootText (pathRoot p)+	chunks = intersperse (T.pack "/") (directoryChunks p)++darwinToString :: FilePath -> String+darwinToString = B8.unpack . TE.encodeUtf8 . darwinToText++darwinFromString :: String -> FilePath+darwinFromString = posixFromText . TE.decodeUtf8 . B8.pack++darwinSplitSearch :: T.Text -> [FilePath]+darwinSplitSearch = map (posixFromText . normSearch) . textSplitBy (== ':') where+	normSearch text = if T.null text then T.pack "." else text++------------------------------------------------------------------------------- -- Windows ------------------------------------------------------------------------------- @@ -182,13 +225,13 @@ winToText :: FilePath -> T.Text winToText p = T.concat (root : chunks) where 	root = rootText (pathRoot p)-	chunks = intersperse (T.pack "\\") (map chunkText (directoryChunks False p))+	chunks = intersperse (T.pack "\\") (directoryChunks p)  winFromText :: T.Text -> FilePath winFromText text = if T.null text then empty else path where 	path = FilePath root directories basename exts 	-	split = T.split (\c -> c == '/' || c == '\\') text+	split = textSplitBy (\c -> c == '/' || c == '\\') text 	 	(root, pastRoot) = let 		head' = head split@@ -204,17 +247,13 @@ 	(directories, filename) 		| P.null pastRoot = ([], T.empty) 		| otherwise = case last pastRoot of-			fn | fn == chunkText dot -> (goodDirs pastRoot, T.empty)-			fn | fn == chunkText dots -> (goodDirs pastRoot, T.empty)+			fn | fn == dot -> (goodDirs pastRoot, T.empty)+			fn | fn == dots -> (goodDirs pastRoot, T.empty) 			fn -> (goodDirs (init pastRoot), fn) 	-	goodDirs = map (\t -> Chunk t True) . filter (not . T.null)+	goodDirs = filter (not . T.null) 	-	(basename, exts) = if T.null filename-		then (Nothing, [])-		else case T.split (== '.') filename of-			[] -> (Nothing, [])-			(name':exts') -> (Just (Chunk name' True), map (\e -> Chunk e True) exts')+	(basename, exts) = parseFilename filename  winValid :: FilePath -> Bool winValid p = validRoot && noReserved && validCharacters where@@ -233,11 +272,11 @@ 		_ -> False 	 	noExt = p { pathExtensions = [] }-	noReserved = flip all (directoryChunks False noExt)-		$ \fn -> notElem (T.toUpper (chunkText fn)) reservedNames+	noReserved = flip all (directoryChunks noExt)+		$ \fn -> notElem (T.toUpper fn) reservedNames 	-	validCharacters = flip all (directoryChunks False p)-		$ not . T.any (`elem` reservedChars) . chunkText+	validCharacters = flip all (directoryChunks p)+		$ not . T.any (`elem` reservedChars)  winSplit :: T.Text -> [FilePath]-winSplit = map winFromText . filter (not . T.null) . T.split (== ';')+winSplit = map winFromText . filter (not . T.null) . textSplitBy (== ';')
+ scripts/common.bash view
@@ -0,0 +1,23 @@+PATH="$PATH:$PWD/cabal-dev/bin/"++VERSION=$(awk '/^version:/{print $2}' system-filepath.cabal)++CABAL_DEV=$(which cabal-dev)+XZ=$(which xz)++require_cabal_dev()+{+	if [ -z "$CABAL_DEV" ]; then+		echo "Can't find 'cabal-dev' executable; make sure it exists on your "'$PATH'+		echo "Cowardly refusing to fuck with the global package database"+		exit 1+	fi+}++clean_dev_install()+{+	require_cabal_dev+	+	rm -rf dist+	$CABAL_DEV install || exit 1+}
+ scripts/run-benchmarks view
@@ -0,0 +1,21 @@+#!/bin/bash+if [ ! -f 'system-filepath.cabal' ]; then+	echo -n "Can't find system-filepath.cabal; please run this script as"+	echo -n " ./scripts/run-benchmarks from within the system-filepath source"+	echo " directory"+	exit 1+fi++. scripts/common.bash++require_cabal_dev++rm -rf dist+cabal-dev install || exit 1++pushd benchmarks+rm -rf dist+$CABAL_DEV -s ../cabal-dev install || exit 1+popd++cabal-dev/bin/system-filepath_benchmarks $@
+ scripts/run-coverage view
@@ -0,0 +1,21 @@+#!/bin/bash+if [ ! -f 'system-filepath.cabal' ]; then+	echo -n "Can't find system-filepath.cabal; please run this script as"+	echo -n " ./scripts/run-coverage from within the system-filepath source"+	echo " directory"+	exit 1+fi++. scripts/common.bash++require_cabal_dev++pushd tests+$CABAL_DEV -s ../cabal-dev install --flags="coverage" || exit 1+popd++rm -f system-filepath_tests.tix+cabal-dev/bin/system-filepath_tests $@++hpc markup --srcdir=src --srcdir=tests/ system-filepath_tests.tix --destdir=hpc-markup --exclude=Main+hpc report --srcdir=src --srcdir=tests/ system-filepath_tests.tix --exclude=Main
+ scripts/run-tests view
@@ -0,0 +1,17 @@+#!/bin/bash+if [ ! -f 'system-filepath.cabal' ]; then+	echo -n "Can't find system-filepath.cabal; please run this script as"+	echo -n " ./scripts/run-tests from within the system-filepath source"+	echo " directory"+	exit 1+fi++. scripts/common.bash++require_cabal_dev++pushd tests+$CABAL_DEV -s ../cabal-dev install || exit 1+popd++cabal-dev/bin/system-filepath_tests $@
system-filepath.cabal view
@@ -1,5 +1,5 @@ name: system-filepath-version: 0.4.2+version: 0.4.3 synopsis: High-level, byte-based file and directory path manipulations license: MIT license-file: license.txt@@ -14,6 +14,11 @@ bug-reports: mailto:jmillikin@gmail.com  extra-source-files:+  scripts/common.bash+  scripts/run-benchmarks+  scripts/run-coverage+  scripts/run-tests+  --   tests/system-filepath-tests.cabal   tests/Tests.hs @@ -24,7 +29,7 @@ source-repository this   type: bzr   location: https://john-millikin.com/branches/hs-filepath/0.4/-  tag: system-filepath_0.4.2+  tag: system-filepath_0.4.3  library   ghc-options: -Wall -O2@@ -33,10 +38,14 @@   build-depends:       base >= 3 && < 5     , bytestring >= 0.9 && < 0.10-    , text >= 0.3 && < 0.12+    , deepseq >= 1.1 && < 1.3+    , text >= 0.7.1 && < 0.12    if os(windows)     cpp-options: -DCABAL_OS_WINDOWS++  if os(darwin)+    cpp-options: -DCABAL_OS_DARWIN    exposed-modules:     Filesystem.Path
tests/Tests.hs view
@@ -5,8 +5,8 @@  import           Prelude hiding (FilePath) -import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8+import           Data.Char (toUpper) import           Data.List (intercalate) import qualified Data.Text as T import           Data.Text (Text)@@ -64,6 +64,7 @@ 	, test_EncodeString 	, test_DecodeString 	, test_EqualsIgnoresPosixEncoding+	, test_ShowRules 	]  test_Empty :: Suite@@ -137,7 +138,7 @@ 	$expect $ equal (dirnameExts "foo.d/bar") ["d"] 	 	-- reparsing preserves good/bad encoding state-	$expect $ equal (dirnameExts "foo.\xB1.\xDD\xAA/bar") ["\xB1", "\xDD\xAA"]+	$expect $ equal (dirnameExts "foo.\xB1.\xDD\xAA/bar") ["\xB1", "\x76A"]  test_Basename :: Suite test_Basename = assertions "basename" $ do@@ -201,7 +202,7 @@ 	$expect $ equal (toText posix (p "\xF0\x9D\x84\x9E/\xED\xA0\x80")) (Left (T.pack "\x1D11E/\xED\xA0\x80")) 	$expect $ equal (toText posix (p "\xED.\xF0\x9D\x84\x9E.\xA0\x80")) (Left (T.pack "\xED.\x1D11E.\xA0\x80")) 	$expect $ equal (toText posix (p "\xB1.\xDD\xAA")) (Left (T.pack "\xB1.\x76A"))-	$expect $ equal (toText posix (p "\xB1.\xDD\xAA" </> p "foo")) (Left (T.pack "\xB1.\xDD\xAA/foo"))+	$expect $ equal (toText posix (p "\xB1.\xDD\xAA" </> p "foo")) (Left (T.pack "\xB1.\x76A/foo"))  test_FromText :: Suite test_FromText = assertions "fromText" $ do@@ -384,8 +385,8 @@ test_EncodeString_Posix_Ghc702 = assertions "posix_ghc702" $ do 	let enc = encodeString posix_ghc702 	$expect $ equal (enc (fromChar8 "test")) "test"-	$expect $ equal (enc (fromChar8 "test\xA1\xA2")) "test\xA1\xA2"-	$expect $ equal (enc (fromChar8 "\xC2\xA1\xC2\xA2/test\xA1\xA2")) "\xA1\xA2/test\xA1\xA2"+	$expect $ equal (enc (fromChar8 "test\xA1\xA2")) "test\xEFA1\xEFA2"+	$expect $ equal (enc (fromChar8 "\xC2\xA1\xC2\xA2/test\xA1\xA2")) "\xA1\xA2/test\xEFA1\xEFA2" 	$expect $ equal (enc (fromText posix_ghc702 "test\xA1\xA2")) "test\xA1\xA2"  test_EncodeString_Win32 :: Suite@@ -399,6 +400,8 @@ test_DecodeString = suite "decodeString" 	[ test_DecodeString_Posix 	, test_DecodeString_Posix_Ghc702+	, test_DecodeString_Darwin+	, test_DecodeString_Darwin_Ghc702 	, test_DecodeString_Win32 	] @@ -417,7 +420,25 @@ 	$expect $ equal (dec r "test") (fromText r "test") 	$expect $ equal (dec r "test\xC2\xA1\xC2\xA2") (fromText r "test\xC2\xA1\xC2\xA2") 	$expect $ equal (dec r "test\xA1\xA2") (fromText r "test\xA1\xA2")+	$expect $ equal (dec r "test\xEFA1\xEFA2") (fromChar8 "test\xA1\xA2")+	$expect $ equal+		(toText r (dec r "test\xEFA1\xEFA2"))+		(Left "test\xA1\xA2") +test_DecodeString_Darwin :: Suite+test_DecodeString_Darwin = assertions "darwin" $ do+	let r = darwin+	let dec = decodeString+	$expect $ equal (dec r "test\xC2\xA1\xC2\xA2") (fromText r "test\xA1\xA2")++test_DecodeString_Darwin_Ghc702 :: Suite+test_DecodeString_Darwin_Ghc702 = assertions "darwin_ghc702" $ do+	let r = darwin_ghc702+	let dec = decodeString+	$expect $ equal (dec r "test\xC2\xA1\xC2\xA2") (fromText r "test\xC2\xA1\xC2\xA2")+	$expect $ equal (dec r "test\xA1\xA2") (fromText r "test\xA1\xA2")+	$expect $ equal (dec r "test\xEFA1\xEFA2") (fromChar8 "test\xA1\xA2")+ test_DecodeString_Win32 :: Suite test_DecodeString_Win32 = assertions "windows" $ do 	let r = windows@@ -432,6 +453,14 @@ 		(fromChar8 "test\xA1\xA2") 		(fromText posix "test\xA1\xA2") +test_ShowRules :: Suite+test_ShowRules = assertions "show-rules" $ do+	$expect $ equal (showsPrec 11 darwin "") "(Rules \"Darwin\")"+	$expect $ equal (showsPrec 11 darwin_ghc702 "") "(Rules \"Darwin (GHC 7.2)\")"+	$expect $ equal (showsPrec 11 posix "") "(Rules \"POSIX\")"+	$expect $ equal (showsPrec 11 posix_ghc702 "") "(Rules \"POSIX (GHC 7.2)\")"+	$expect $ equal (showsPrec 11 windows "") "(Rules \"Windows\")"+ posixPaths :: Gen FilePath posixPaths = sized $ fmap merge . genComponents where 	merge = fromChar8 . intercalate "/"@@ -458,7 +487,7 @@ 		, "LPT7", "LPT8", "LPT9", "NUL", "PRN" 		] 	validChar c = not (elem c reserved)-	validComponent c = not (elem c reservedNames)+	validComponent c = not (elem (map toUpper c) reservedNames) 	component = do 		size <- choose (0, 10) 		vectorOf size $ arbitrary `suchThat` validChar
tests/system-filepath-tests.cabal view
@@ -20,5 +20,6 @@     , bytestring     , chell >= 0.2 && < 0.3     , chell-quickcheck >= 0.1 && < 0.2+    , deepseq >= 1.1 && < 1.3     , QuickCheck     , text