From 9cacf87d541fb8e92655228b21de926b96139bdd Mon Sep 17 00:00:00 2001 From: Thomas Miedema Date: Sat, 25 Oct 2014 23:38:17 +0200 Subject: [PATCH 1/3] Bug fix: normalize "\\" == "\\" --- System/FilePath/Internal.hs | 3 ++- changelog.md | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/System/FilePath/Internal.hs b/System/FilePath/Internal.hs index f85e6351..3abebe9d 100644 --- a/System/FilePath/Internal.hs +++ b/System/FilePath/Internal.hs @@ -750,6 +750,7 @@ makeRelative root path -- > Windows: normalise "c:\\" == "C:\\" -- > Windows: normalise "\\\\server\\test" == "\\\\server\\test" -- > Windows: normalise "c:/file" == "C:\\file" +-- > Windows: normalise "\\" == "\\" -- > normalise "." == "." -- > Posix: normalise "./" == "./" -- > Posix: normalise "./." == "./" @@ -757,7 +758,7 @@ makeRelative root path -- > Posix: normalise "bob/fred/." == "bob/fred/" normalise :: FilePath -> FilePath normalise path = joinDrive' (normaliseDrive drv) (f pth) - ++ [pathSeparator | isDirPath pth] + ++ [pathSeparator | isDirPath pth && length pth > 1] where (drv,pth) = splitDrive path diff --git a/changelog.md b/changelog.md index 13dad0e2..81d832ad 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,9 @@ * Bug fix: on Windows, `dropTrailingPathSeparator "/"` now returns `"/"` unchanged, instead of the normalised `"\\"`. + * Bug fix: on Windows, `normalise "\\"` now retuns `"\\"` unchanged, + instead of `"\\\\"`. + ## 1.3.0.2 *Mar 2014* * Bundled with GHC 7.8.1 From 645d2972ec3929d1e22975879082e3afcae516c8 Mon Sep 17 00:00:00 2001 From: Thomas Miedema Date: Sun, 26 Oct 2014 21:19:39 +0100 Subject: [PATCH 2/3] Bug fix: normalise "//server/test" == "\\\\server\\test" When drive represents a network share, slashes were not being normalised properly. --- System/FilePath/Internal.hs | 3 ++- changelog.md | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/System/FilePath/Internal.hs b/System/FilePath/Internal.hs index 3abebe9d..72569912 100644 --- a/System/FilePath/Internal.hs +++ b/System/FilePath/Internal.hs @@ -749,6 +749,7 @@ makeRelative root path -- > Windows: normalise "c:\\file/bob\\" == "C:\\file\\bob\\" -- > Windows: normalise "c:\\" == "C:\\" -- > Windows: normalise "\\\\server\\test" == "\\\\server\\test" +-- > Windows: normalise "//server/test" == "\\\\server\\test" -- > Windows: normalise "c:/file" == "C:\\file" -- > Windows: normalise "\\" == "\\" -- > normalise "." == "." @@ -783,7 +784,7 @@ normaliseDrive :: FilePath -> FilePath normaliseDrive drive | isPosix = drive normaliseDrive drive = if isJust $ readDriveLetter x2 then map toUpper x2 - else drive + else x2 where x2 = map repSlash drive diff --git a/changelog.md b/changelog.md index 81d832ad..3e87a9cf 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,9 @@ * Bug fix: on Windows, `normalise "\\"` now retuns `"\\"` unchanged, instead of `"\\\\"`. + * Bug fix: on Windows, `normalise "//server/test"` now retuns + `"\\\\server\\test"`, instead of `"//server/test"` unchanged. + ## 1.3.0.2 *Mar 2014* * Bundled with GHC 7.8.1 From eca255a41c6e6cf427f22f468f5c051ecad3d4e3 Mon Sep 17 00:00:00 2001 From: Thomas Miedema Date: Mon, 15 Sep 2014 00:20:52 +0200 Subject: [PATCH 3/3] Refactor normalise: simplify propSep 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 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/System/FilePath/Internal.hs b/System/FilePath/Internal.hs index 72569912..8b67fb2d 100644 --- a/System/FilePath/Internal.hs +++ b/System/FilePath/Internal.hs @@ -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 ("." /=)