fsprojects / FAKE

FAKE - F# Make
https://fake.build
Other
1.28k stars 585 forks source link

Cannot find Results.xml output file if current directory is changed. #1295

Closed theprash closed 8 years ago

theprash commented 8 years ago

Description

Changing the current working directory breaks XML logging.

Repro steps

The log message is added to the file in the original location, regardless of the current directory.

Actual behavior

Throws:

System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\xxx\xxx\output\Results.xml'

Notes

The stack trace points here. xmlOutputFile comes from a parameter that defaults to a relative path. Turning this into an absolute path early on should fix the problem.

theprash commented 8 years ago

My proposed fix above does seem to work. I'll make a PR soon.

theprash commented 8 years ago

After making my fix I was still getting another error:

Error: System.IO.IOException: The process cannot access the file 'C:\temp\fake-test\output\Results.xml' because it is being used by another process.

I found out that this was because TraceListener.fs was being loaded twice. That is, there were two separate points where a stack trace contained:

at <StartupCode$FakeLib>.$Fake.TraceListener..cctor() in C:\Users\Prash\dev\FAKE\src\app\FakeLib\TraceListener.fs:line 151

So all of the top level actions and definitions in TraceListener.fs, were being evaluated twice and their side-effects executed twice. So the line if hasBuildParam "logfile" || buildServer = CCNet then addXmlListener xmlOutputFile was adding two XML listeners on the same file, causing the IOException.

I found that this only happened in Debug mode and everything was fine in Release mode. Is this a known thing? It doesn't affect my original reported bug or the fix so I'll submit a PR.

theprash commented 8 years ago

My test setup to reproduce this:

fake-test.fsx:

#r @"C:\Users\Prash\dev\FAKE\build\FakeLib.dll"

open Fake
open System.IO

buildServer |> printfn "%A"

Target "Testing" (fun _ ->
    trace "1"
    let orig = Directory.GetCurrentDirectory()
    Directory.SetCurrentDirectory @"C:\"
    trace "2"
    Directory.SetCurrentDirectory orig
)

RunTargetOrDefault "Testing"

run.ps1:

$env:CCNETLABEL = 1
C:\Users\Prash\dev\FAKE\build\FAKE.exe fake-test.fsx