generate wrong path when a file within a folder with space
newbienewbie opened this issue · comments
Describe the bug
A post folder path that contains a space character (or non-ascii char) will cause an error of System.Collections.Generic.KeyNotFoundException
To Reproduce
Steps to reproduce the behaviour:
- Run
fornax new
- create a markdown file with path of "posts/subdir/a sub folder with space/post3 with space and 你好.md" :
├─ posts/
│ └─ subdir/
│ └─ a sub folder with space/
| └─ post3 with space and 你好.md
- Run
fornax watch
. Now we get an error :
An unexpected error happend: System.IO.DirectoryNotFoundException: Could not find a part of the path 'F:\Playground\Fornax\posts\subdir\a%20sub%20folder%20with%20space\post3%20with%20space%20and%20%E4%BD%A0%E5%A5%BD.md'.
at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.StreamReader.ValidateArgsAndOpenPath(String path, Encoding encoding, Int32 bufferSize)
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks)
at System.IO.File.InternalReadAllText(String path, Encoding encoding)
at System.IO.File.ReadAllText(String path)
at FSI_0001.Config.postPredicate(String projectRoot, String page)
at FSI_0001.Config.config@37.Invoke(Tuple2 tupledArg) at Microsoft.FSharp.Collections.ListModule.TryFind[T](FSharpFunc
2 predicate, FSharpList`1 list) in F:\workspace_work\1\s\src\fsharp\FSharp.Core\list.fs:line 391
at Generator.pickGenerator(Config cfg, SiteContents siteContent, String projectRoot, String page) in F:\Source Code Study\Fornax\src\Fornax\Generator.fs:line 302
at Generator.generate(FsiEvaluationSession fsi, Config cfg, SiteContents siteContent, String projectRoot, String page) in F:\Source Code Study\Fornax\src\Fornax\Generator.fs:line 333
at Generator.action@1-3(String projectRoot, FsiEvaluationSession fsi, Config config, SiteContents sc, String filePath) in F:\Source Code Study\Fornax\src\Fornax\Generator.fs:line 496
at Generator.generateFolder(String projectRoot, Boolean isWatch) in F:\Source Code Study\Fornax\src\Fornax\Generator.fs:line 495
at Fornax.guardedGenerate@226(String cwd, Unit unitVar0) in F:\Source Code Study\Fornax\src\Fornax\Fornax.fs:line 228
Expected behaviour
The static files will be generated and the HTTP server will run flawlessly.
Screenshots
Environment (please complete the following information):
- OS: win10-x64, 10.0.19042
- Ionide version: v5.7.3
- VSCode version: 1.61.0
- dotnet SDK version: 5.0.102
- mono / .Net Framework version: -
Additional context
the relative function calculates the relative path by using the MakeRelativeUri
method:
let relative toPath fromPath =
let toUri = Uri(toPath)
let fromUri = Uri(fromPath)
toUri.MakeRelativeUri(fromUri).OriginalString
However, when a directory path contains an space char, the result will not be decoded, and then causes an Exception of :
An unexpected error happend: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. System.Collections.Generic.KeyNotFoundException
Actually, this exception also occurs when having any directory that uses non-ascii encodings. For example, if we have a post with path of posts/subdir/中文 目录-带空格和非URL字符/post 带空格3.md
, the relative
funtion will return:
posts/subdir/%E4%B8%AD%E6%96%87%20%E7%9B%AE%E5%BD%95-%E5%B8%A6%E7%A9%BA%E6%A0%BC%E5%92%8C%E9%9D%9EURL%E5%AD%97%E7%AC%A6/post%20%E5%B8%A6%E7%A9%BA%E6%A0%BC3.md
And the above path will be passed to the generate
function as a file path. However, the encoded url is not the original path.
A quick fix is to use the Path.GetRelativePath
as below :
let relative toPath fromPath =
Path.GetRelativePath(toPath, fromPath).Replace("\\","/")