`prependCurrentDirectory` strips trailing whitespace on Windows
type: x-intended-behavior
Hello,
I encountered the following surprising (to me) behavior. Consider:
```haskell
{-# LANGUAGE QuasiQuotes #-}
module Main (main)
import System.OsPath (OsPath, osp, (</>))
import System.Directory.Internal qualified as IDir
main :: IO ()
main = putStrLn . show =<< IDir.prependCurrentDirectory relOsPath
-- "a/rel/path "
relOsPath :: OsPath
relOsPath = [osp|a|] </> [osp|rel|] </> [osp|path |]
```
This prints:
```
"/<root-path>/a/rel/path " -- unix
"/<root-path>/a/rel/path" -- windows
```
This is the latest `directory-1.3.9.0` and `filepath-1.5.4.0`.
I discovered this when a property test expected a filename to be preserved after calling [`makeAbsolute`](https://hackage.haskell.org/package/directory-1.3.9.0/docs/System-Directory-OsPath.html#v:makeAbsolute) (which calls [`prependCurrentDirectory`](https://hackage.haskell.org/package/directory-1.3.9.0/docs/System-Directory-Internal.html#v:prependCurrentDirectory)). On unix this test passed, but on windows it failed because the generated path had its trailing whitespace stripped.
My question, is this expected? I don't understand windows paths well enough to know what's going on here. The [docs](https://learn.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/file-folder-name-whitespace-characters) mention that some applications will strip whitespace when actually saving files, but it's not clear to me what part of `directory`'s API is doing this. I attempted to investigate this [here](https://github.com/tbidne/dir-abs-whitespace/blob/main/app/Main.hs), though I was not able to pinpoint an exact cause (I do not have a windows machine, so I am relying on github's CI).
The examples are essentially:
```haskell
Rel: print "a/rel/path "
Rel normalise: print (OsP.normalise "a/rel/path ")
Rel simplify: print (Internal.simplify "a/rel/path ")
/ </> (root </> a/rel/path ): print ("/" </> ("root" </> "a/rel/path "))
/root </> a/rel/path : print (("/" </> "root") </> "a/rel/path ")
Abs: print "/a/rel/path "
Abs normalise: print (OsP.normalise "/a/rel/path ")
Abs simplify: print (Internal.simplify "/a/rel/path ")
Manual prepend: print ((</> "a/rel/path ") <$> Internal.getCurrentDirectoryInternal)
My prepend: print (myPrependCurrentDirectory "a/rel/path ")
Dir prepend: print (Internal.prependCurrentDirectory "a/rel/path ")
Abs: print (Dir.makeAbsolute "a/rel/path ")
```
And the output is (with links to CI output, though they're probably not publicly available):
```
-- ubuntu: https://github.com/tbidne/dir-abs-whitespace/actions/runs/13776102934/job/38525559164
Rel: "a/rel/path "
Rel normalise: "a/rel/path "
Rel simplify: "a/rel/path "
/ </> (root </> a/rel/path ): "/root/a/rel/path "
/root </> a/rel/path : "/root/a/rel/path "
Abs: "/a/rel/path "
Abs normalise: "/a/rel/path "
Abs simplify: "/a/rel/path "
Manual prepend: "/home/runner/work/dir-abs-whitespace/dir-abs-whitespace/a/rel/path "
My prepend: "/home/runner/work/dir-abs-whitespace/dir-abs-whitespace/a/rel/path "
Dir prepend: "/home/runner/work/dir-abs-whitespace/dir-abs-whitespace/a/rel/path "
Abs: "/home/runner/work/dir-abs-whitespace/dir-abs-whitespace/a/rel/path "
```
```
-- windows: https://github.com/tbidne/dir-abs-whitespace/actions/runs/13776102934/job/38525559428
Rel: "a\rel\path "
Rel normalise: "a\rel\path "
Rel simplify: "a\rel\path "
/ </> (root </> a/rel/path ): "\root\a\rel\path "
/root </> a/rel/path : "\root\a\rel\path "
Abs: "\a\rel\path "
Abs normalise: "\a\rel\path "
Abs simplify: "\a\rel\path "
Manual prepend: "D:\a\dir-abs-whitespace\dir-abs-whitespace\a\rel\path "
My prepend: "D:\a\dir-abs-whitespace\dir-abs-whitespace\a\rel\path "
Dir prepend: "D:\a\dir-abs-whitespace\dir-abs-whitespace\a\rel\path"
Abs: "D:\a\dir-abs-whitespace\dir-abs-whitespace\a\rel\path"
```
Even more bizarre, the "My prepend" example is just directory's `Internal.prependCurrentDirectory` directly copied, so I'm not sure where the discrepancy is. This code for this is [here](https://github.com/tbidne/dir-abs-whitespace/blob/main/app/Main.hs).
Thanks!
关闭于 2026-01-03 2 条评论