anchor.diff:  | Disk
   
   let hashRegex = Text.RegularExpressions.Regex("(?<script>.+)_(?<hash>[a-zA-Z0-9]+\.dll$)", System.Text.RegularExpressions.RegexOptions.Compiled)
  -/// Run the given FAKE script with fsi.exe at the given working directory. Provides full access to Fsi options and args. Redirect output and error messages.
  -let internal runFAKEScriptWithFsiArgsAndRedirectMessages printDetails (FsiArgs(fsiOptions, scriptPath, scriptArgs)) env onErrMsg onOutMsg useCache cleanCache =
  -
  -    if printDetails then traceFAKE "Running Buildscript: %s" scriptPath
  -
  -    // Add arguments to the Environment
  -    for (k,v) in env do
  -      Environment.SetEnvironmentVariable(k, v, EnvironmentVariableTarget.Process)
  -
  -    // Create an env var that only contains the build script args part from the --fsiargs (or "").
  -    Environment.SetEnvironmentVariable("fsiargs-buildscriptargs", String.Join(" ", scriptArgs))
  -
  -    let fsiConfig = FsiEvaluationSession.GetDefaultConfiguration()
  -
  -    let options =
  -        [ "fsi.exe"; "--noninteractive" ] @ fsiOptions
  -        |> List.toArray
  -
  -    let sbOut = Text.StringBuilder()
  -    let sbErr = Text.StringBuilder()
  -    let handleMessages() =
  -        let handleMessagesFrom (sb:Text.StringBuilder) onMsg =
  -            let s = sb.ToString()
  -            if not <| String.IsNullOrEmpty s
  -                then onMsg s
  -        handleMessagesFrom sbOut onOutMsg
  -        handleMessagesFrom sbErr onErrMsg
  -    let handleException (ex : Exception) = 
  -        onErrMsg (ex.ToString())
  -
  -    use outStream = new StringWriter(sbOut)
  -    use errStream = new StringWriter(sbErr)
  -    use stdin = new StreamReader(Stream.Null)
  -
  -    let scriptPath =
  -        if Path.IsPathRooted scriptPath then
  -            scriptPath
  -        else
  -            Path.Combine(Directory.GetCurrentDirectory(), scriptPath)
  -        
  +
  +type private CacheInfo =
  +  {
  +    ScriptFileName : string
  +    AssemblyPath : string
  +    AssemblyWarningsPath : string
  +    CacheConfigPath : string
  +    CacheConfig : Lazy<Cache.CacheConfig>
  +    IsValid : bool
  +  }
  +
  +let private getCacheInfoFromScript printDetails fsiOptions scriptPath =
       let allScriptContents = getAllScripts scriptPath
       let scriptHash = lazy (getScriptHash allScriptContents fsiOptions)
       //TODO this is only calculating the hash for the input file, not anything #load-ed
       
  -    let scriptFileName = lazy(Path.GetFileName(scriptPath))
  -    let hashPath = lazy("./.fake/" + scriptFileName.Value + "_" + scriptHash.Value)
  -    let assemblyPath = lazy(hashPath.Value + ".dll")
  -    let cacheConfigPath = lazy(hashPath.Value + "_config.xml")
  -    let cacheConfig = lazy(Cache.read cacheConfigPath.Value)
  -    let cacheValid = lazy (
  +    let scriptFileName = Path.GetFileName(scriptPath)
  +    let hashPath = "./.fake/" + scriptFileName + "_" + scriptHash.Value
  +    let assemblyPath = hashPath + ".dll"
  +    let assemblyWarningsPath = hashPath + "_warnings.txt"
  +    let cacheConfigPath = hashPath + "_config.xml"
  +    let cacheConfig = lazy Cache.read cacheConfigPath
  +    let cacheValid =
           let cacheFilesExist = 
  -            System.IO.File.Exists(assemblyPath.Value) &&
  -            System.IO.File.Exists(cacheConfigPath.Value) 
  +            File.Exists(assemblyPath) &&
  +            File.Exists(cacheConfigPath) &&
  +            File.Exists(assemblyWarningsPath)
           if cacheFilesExist then
               let loadedAssemblies =
                   cacheConfig.Value.Assemblies
  
positive.code:             assemVersionValidCount = Seq.length cacheConfig.Value.Assemblies
          else
              false
      )
  
      let getScriptAndHash fileName =
          let matched = hashRegex.Match(fileName)
          matched.Groups.Item("script").Value, matched.Groups.Item("hash").Value
  
      if useCache && cacheValid.Value then
          
          if printDetails then trace "Using cache"
          let noExtension = Path.GetFileNameWithoutExtension(scriptFileName.Value)
          let fullName = 
              sprintf "<StartupCode$FSI_0001>.$FSI_0001_%s%s$%s" 
                  (noExtension.Substring(0, 1).ToUpper())
                  (noExtension.Substring(1))
                  (Path.GetExtension(scriptFileName.Value).Substring(1))
  
          let assembly = Reflection.Assembly.LoadFrom(assemblyPath.Value)
  
          let mainModule = assembly.GetType(fullName)
          
          try
              let _result = 
                  mainModule.InvokeMember(
                      "main@",
                      BindingFlags.InvokeMethod ||| BindingFlags.Public ||| BindingFlags.Static, 
                      null, null, [||])
              true
          with
          | ex ->
              handleException ex
              false
      else
          let cacheDir = DirectoryInfo(Path.Combine(".",".fake"))
          if useCache then
  
negative.code: open System.Threading
  open System.Text.RegularExpressions
  open System.Xml.Linq
  open Yaaf.FSharp.Scripting
  
  let private FSIPath = @".\tools\FSharp\;.\lib\FSharp\;[ProgramFilesX86]\Microsoft SDKs\F#\4.0\Framework\v4.0;[ProgramFilesX86]\Microsoft SDKs\F#\3.1\Framework\v4.0;[ProgramFilesX86]\Microsoft SDKs\F#\3.0\Framework\v4.0;[ProgramFiles]\Microsoft F#\v4.0\;[ProgramFilesX86]\Microsoft F#\v4.0\;[ProgramFiles]\FSharp-2.0.0.0\bin\;[ProgramFilesX86]\FSharp-2.0.0.0\bin\;[ProgramFiles]\FSharp-1.9.9.9\bin\;[ProgramFilesX86]\FSharp-1.9.9.9\bin\"
  
  