
#8752: System.FilePath.Windows.combine does not really check isAbsolute -------------------------------------+------------------------------------- Reporter: joeyhess | Owner: thomie Type: bug | Status: new Priority: normal | Milestone: Component: libraries | Version: 7.9 (other) | Keywords: filepath Resolution: | Architecture: Unknown/Multiple Operating System: Windows | Difficulty: Unknown Type of failure: | Blocked By: None/Unknown | Related Tickets: Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Comment (by thomie): Can you explain why the docstring I posed is confusing? It is valid for both Posix as Windows, so it's not really a caveat. Correct me if I'm wrong, but the way I understand it is that on [http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx Windows], if a filepath starts with a single slash, it is considered to be relative to the root of the current drive. The system keeps track of the current drive along with the current directory of that drive. Currently, if the second argument starts with a slash, `combine` returns it as is. The implementation is essentially: {{{ combine a b | hasDrive b || hasLeadingPathSeparator b = b | otherwise = combineAlways a b }}} I am guessing you are looking for the following behavior: {{{ combine "C:\\" "\\foo\\bar" == "C:\\foo\\bar" combine "C:\\STUFF" "\\foo\\bar" == "C:\\foo\\bar" combine ""\\\\shared" "\\foo\\bar" == "\\\\shared\\foo\\bar" combine ""\\\\shared\\stuff" "\\foo\\bar" == "\\\\shared\\foo\\bar" }}} But, since anything else doesn't make any sense: {{{ combine "home" "/bob" == "/bob" }}} So just changing the check to `isAbsolute` (or `hasDrive`, since combining with "C:foo", which isRelative, is not implemented at the moment, but that is another issue) doesn't work. An implementation that has this behavior would be: {{{ combine a b | hasDrive b || hasLeadingPathSeparator b && not (hasDrive a) = b | hasLeadingPathSeparator b = combineAlways (takeDrive a) (dropLeadingPathSeparator b) | otherwise = combineAlways a b }}} Or, an option with the same behavior as above, except: {{{ combine "C:\\STUFF" "\\foo\\bar" == "\\foo\\bar" combine ""\\\\shared\\stuff" "\\foo\\bar" == "\\foo\\bar" }}} , would be: {{{ combine a b | hasDrive b || hasLeadingPathSeparator b && not (isDrive a) = b | hasLeadingPathSeparator b = combineAlways a (dropLeadingPathSeparator b) | otherwise = combineAlways a b }}} I'm not sure which of the three is better. We have to change the docstring either way. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8752#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler