ITADN

`prependCurrentDirectory` strips trailing whitespace on Windows

#199Closedtbidne 创建于 2025-03-10
type: x-intended-behavior
T
tbidnecommented
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 条评论