Refactor normalise: simplify propSep
authorThomas Miedema <thomasmiedema@gmail.com>
Sun, 14 Sep 2014 22:20:52 +0000 (00:20 +0200)
committerThomas Miedema <thomasmiedema@gmail.com>
Sun, 26 Oct 2014 20:50:20 +0000 (21:50 +0100)
Only when a path on Windows starts with a leading forward slash does propSep
need to do something, all others path separators are properly taken care of by
joinPath.

Add 2 tests to show that splitDirectories can handle superfluous
pathSeparators, and a test to show that (this new version of) propSep is
indeed needed to normalise relative-to-root paths on Windows.

System/FilePath/Internal.hs

index 7256991..8b67fb2 100644 (file)
@@ -642,6 +642,8 @@ splitPath x = [drive | drive /= ""] ++ f path
 -- > Windows: splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"]
 -- > Valid x => joinPath (splitDirectories x) `equalFilePath` x
 -- > splitDirectories "" == []
+-- > Windows: splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"]
+-- >          splitDirectories "/test///file" == ["/","test","file"]
 splitDirectories :: FilePath -> [FilePath]
 splitDirectories path =
         if hasDrive path then head pathComponents : f (tail pathComponents)
@@ -751,6 +753,7 @@ makeRelative root path
 -- > Windows: normalise "\\\\server\\test" == "\\\\server\\test"
 -- > Windows: normalise "//server/test" == "\\\\server\\test"
 -- > Windows: normalise "c:/file" == "C:\\file"
+-- > Windows: normalise "/file" == "\\file"
 -- > Windows: normalise "\\" == "\\"
 -- >          normalise "." == "."
 -- > Posix:   normalise "./" == "./"
@@ -769,13 +772,10 @@ normalise path = joinDrive' (normaliseDrive drv) (f pth)
         isDirPath xs = hasTrailingPathSeparator xs
             || not (null xs) && last xs == '.' && hasTrailingPathSeparator (init xs)
 
-        f = joinPath . dropDots . splitDirectories . propSep
+        f = joinPath . dropDots . propSep . splitDirectories
 
-        propSep (a:b:xs)
-         | isPathSeparator a && isPathSeparator b = propSep (a:xs)
-        propSep (a:xs)
-         | isPathSeparator a = pathSeparator : propSep xs
-        propSep (x:xs) = x : propSep xs
+        propSep (x:xs) | all isPathSeparator x = [pathSeparator] : xs
+                       | otherwise = x : xs
         propSep [] = []
 
         dropDots = filter ("." /=)