From d3d64a4033c3be76b9949e9531f33b0d19a1cd34 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Fri, 8 Apr 2016 17:07:29 -0700 Subject: [PATCH] fix the race condition when generating deps.json, and add some coverage of this scenario update reporter to verbose fix fix usings for test update the test --- .../ProjectToolsCommandResolver.cs | 66 ++++++++++++++----- .../GivenAProjectToolsCommandResolver.cs | 36 ++++++++++ 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs index 57ffb8290..49514db98 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -190,38 +190,68 @@ namespace Microsoft.DotNet.Cli.Utils depsPathRoot, toolLibrary.Name + FileNameSuffixes.DepsJson); - EnsureToolJsonDepsFileExists(toolLibrary, toolLockFile, depsJsonPath); + EnsureToolJsonDepsFileExists(toolLockFile, depsJsonPath); return depsJsonPath; } private void EnsureToolJsonDepsFileExists( - LibraryRange toolLibrary, LockFile toolLockFile, string depsPath) { if (!File.Exists(depsPath)) { - var projectContext = new ProjectContextBuilder() - .WithLockFile(toolLockFile) - .WithTargetFramework(s_toolPackageFramework.ToString()) - .Build(); + GenerateDepsJsonFile(toolLockFile, depsPath); + } + } - var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration); + // Need to unit test this, so public + public void GenerateDepsJsonFile( + LockFile toolLockFile, + string depsPath) + { + Reporter.Verbose.WriteLine($"Generating deps.json at: {depsPath}"); - var dependencyContext = new DependencyContextBuilder() - .Build(null, - null, - exporter.GetAllExports(), - true, - s_toolPackageFramework, - string.Empty); + var projectContext = new ProjectContextBuilder() + .WithLockFile(toolLockFile) + .WithTargetFramework(s_toolPackageFramework.ToString()) + .Build(); - using (var fileStream = File.Create(depsPath)) + var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration); + + var dependencyContext = new DependencyContextBuilder() + .Build(null, + null, + exporter.GetAllExports(), + true, + s_toolPackageFramework, + string.Empty); + + var tempDepsFile = Path.GetTempFileName(); + using (var fileStream = File.Open(tempDepsFile, FileMode.Open, FileAccess.Write)) + { + var dependencyContextWriter = new DependencyContextWriter(); + + dependencyContextWriter.Write(dependencyContext, fileStream); + } + + try + { + File.Copy(tempDepsFile, depsPath); + } + catch (Exception e) + { + Reporter.Verbose.WriteLine($"unable to generate deps.json, it may have been already generated: {e.Message}"); + } + finally + { + try { - var dependencyContextWriter = new DependencyContextWriter(); - - dependencyContextWriter.Write(dependencyContext, fileStream); + File.Delete(tempDepsFile); + } + catch (Exception e2) + { + Reporter.Verbose.WriteLine($"unable to delete temporary deps.json file: {e2.Message}"); } } } diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs index 63a85bfc7..0c556d181 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAProjectToolsCommandResolver.cs @@ -18,6 +18,11 @@ using FluentAssertions; using NuGet.Frameworks; using NuGet.Versioning; using NuGet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Compilation; +using NuGet.ProjectModel; + +using LockFile = Microsoft.DotNet.ProjectModel.Graph.LockFile; namespace Microsoft.DotNet.Cli.Utils.Tests { @@ -184,6 +189,37 @@ namespace Microsoft.DotNet.Cli.Utils.Tests depsJsonFile.Should().NotBeNull(); } + [Fact] + public void Generate_deps_json_method_doesnt_overwrite_when_deps_file_already_exists() + { + var context = ProjectContext.Create(Path.Combine(s_liveProjectDirectory, "project.json"), s_toolPackageFramework); + + var nugetPackagesRoot = context.PackagesDirectory; + var toolPathCalculator = new ToolPathCalculator(nugetPackagesRoot); + + var lockFilePath = toolPathCalculator.GetLockFilePath( + "dotnet-portable", + new NuGetVersion("1.0.0"), + s_toolPackageFramework); + + var lockFile = LockFileReader.Read(lockFilePath, designTime: false); + + var depsJsonFile = Path.Combine( + Path.GetDirectoryName(lockFilePath), + "dotnet-portable.deps.json"); + + if (File.Exists(depsJsonFile)) + { + File.Delete(depsJsonFile); + } + File.WriteAllText(depsJsonFile, "temp"); + + var projectToolsCommandResolver = SetupProjectToolsCommandResolver(); + projectToolsCommandResolver.GenerateDepsJsonFile(lockFile, depsJsonFile); + + File.ReadAllText(depsJsonFile).Should().Be("temp"); + } + private ProjectToolsCommandResolver SetupProjectToolsCommandResolver( IPackagedCommandSpecFactory packagedCommandSpecFactory = null) {