[commit: packages/directory] master: Fix trailing path sep behavior of canonicalizePath and makeAbsolute (67c18f0)
git at git.haskell.org
git at git.haskell.org
Sun Feb 14 22:19:11 UTC 2016
Repository : ssh://git@git.haskell.org/directory
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/67c18f0be0f3f94d0deed1aa13a4423e816fb13d/directory
>---------------------------------------------------------------
commit 67c18f0be0f3f94d0deed1aa13a4423e816fb13d
Author: Phil Ruffwind <rf at rufflewind.com>
Date: Mon Feb 8 06:54:53 2016 -0500
Fix trailing path sep behavior of canonicalizePath and makeAbsolute
It used to be that `canonicalizePath "."` returned a path without a
trailing slash, but now it does. This is due to the use of `normalise`
in `makeAbsolute`, which adds extra slashes whenever `.` gets stripped
out at the end. This commit restores the original behavior for
`canonicalizePath`, and also affects `makeAbsolute` in a similar manner.
Fixes #42.
>---------------------------------------------------------------
67c18f0be0f3f94d0deed1aa13a4423e816fb13d
System/Directory.hs | 41 ++++++++++++++++++++++++++++-------------
changelog.md | 10 ++++++++++
directory.cabal | 2 +-
tests/CanonicalizePath.hs | 5 ++++-
4 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/System/Directory.hs b/System/Directory.hs
index d67a249..0c6e830 100644
--- a/System/Directory.hs
+++ b/System/Directory.hs
@@ -828,13 +828,13 @@ canonicalizePath = \ path ->
modifyIOError ((`ioeSetLocation` "canonicalizePath") .
(`ioeSetFileName` path)) $
-- normalise does more stuff, like upper-casing the drive letter
- normalise <$> (transform =<< makeAbsolute path)
+ normalise <$> (transform =<< prependCurrentDirectory path)
where
#if defined(mingw32_HOST_OS)
transform path = Win32.getFullPathName path
`catchIOError` \ _ -> return path
#else
- transform path = copySlash path <$> do
+ transform path = matchTrailingSeparator path <$> do
encoding <- getFileSystemEncoding
realpathPrefix encoding (reverse (zip prefixes suffixes)) path
where segments = splitPath path
@@ -856,25 +856,40 @@ canonicalizePath = \ path ->
doesPathExist path = (Posix.getFileStatus path >> return True)
`catchIOError` \ _ -> return False
-
- -- make sure trailing slash is preserved
- copySlash path | hasTrailingPathSeparator path = addTrailingPathSeparator
- | otherwise = id
#endif
--- | Make a path absolute by prepending the current directory (if it isn't
--- already absolute) and applying 'normalise' to the result.
+-- | Convert a (possibly) relative path into an absolute path. This is nearly
+-- equivalent to prepending the current directory (if the path isn't already
+-- absolute) and then applying 'normalise' to the result. The trailing path
+-- separator, if any, is preserved during the process.
--
-- If the path is already absolute, the operation never fails. Otherwise, the
-- operation may fail with the same exceptions as 'getCurrentDirectory'.
--
-- @since 1.2.2.0
makeAbsolute :: FilePath -> IO FilePath
-makeAbsolute = (normalise <$>) . absolutize
- where absolutize path -- avoid the call to `getCurrentDirectory` if we can
- | isRelative path = (</> path) . addTrailingPathSeparator <$>
- getCurrentDirectory
- | otherwise = return path
+makeAbsolute path =
+ modifyIOError ((`ioeSetLocation` "makeAbsolute") .
+ (`ioeSetFileName` path)) $
+ matchTrailingSeparator path . normalise <$> prependCurrentDirectory path
+
+prependCurrentDirectory :: FilePath -> IO FilePath
+prependCurrentDirectory path =
+ modifyIOError ((`ioeSetLocation` "prependCurrentDirectory") .
+ (`ioeSetFileName` path)) $
+ case path of
+ "" -> -- avoid trailing path separator
+ prependCurrentDirectory "."
+ _ -- avoid the call to `getCurrentDirectory` if we can
+ | isRelative path ->
+ (</> path) . addTrailingPathSeparator <$> getCurrentDirectory
+ | otherwise ->
+ return path
+
+matchTrailingSeparator :: FilePath -> FilePath -> FilePath
+matchTrailingSeparator path
+ | hasTrailingPathSeparator path = addTrailingPathSeparator
+ | otherwise = dropTrailingPathSeparator
-- | 'makeRelative' the current directory.
makeRelativeToCurrentDirectory :: FilePath -> IO FilePath
diff --git a/changelog.md b/changelog.md
index 13b6af3..6e9e984 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,16 @@
Changelog for the [`directory`][1] package
==========================================
+## 1.2.5.1 (February 2015)
+
+ * Fix the behavior of trailing path separators in `canonicalizePath` as well
+ as `makeAbsolute` when applied to the current directory; they should now
+ match the behavior of `canonicalizePath` prior to 1.2.3.0 (when the bug
+ was introduced)
+ ([#42](https://github.com/haskell/directory/issues/42))
+
+ * Set the location in IO errors from `makeAbsolute`.
+
## 1.2.5.0 (December 2015)
* Add `listDirectory`, which is similar to `getDirectoryContents`
diff --git a/directory.cabal b/directory.cabal
index d112a77..5a58dcf 100644
--- a/directory.cabal
+++ b/directory.cabal
@@ -1,5 +1,5 @@
name: directory
-version: 1.2.5.0
+version: 1.2.5.1
-- NOTE: Don't forget to update ./changelog.md
license: BSD3
license-file: LICENSE
diff --git a/tests/CanonicalizePath.hs b/tests/CanonicalizePath.hs
index 4d05198..e9d3672 100644
--- a/tests/CanonicalizePath.hs
+++ b/tests/CanonicalizePath.hs
@@ -2,13 +2,16 @@
module CanonicalizePath where
#include "util.inl"
import System.Directory
-import System.FilePath ((</>), normalise)
+import System.FilePath ((</>), hasTrailingPathSeparator, normalise)
main :: TestEnv -> IO ()
main _t = do
+ dot' <- canonicalizePath "./"
dot <- canonicalizePath "."
nul <- canonicalizePath ""
T(expectEq) () dot nul
+ T(expect) dot (not (hasTrailingPathSeparator dot))
+ T(expect) dot' (hasTrailingPathSeparator dot')
writeFile "bar" ""
bar <- canonicalizePath "bar"
More information about the ghc-commits
mailing list