This repository has been archived by the owner on Nov 20, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Drop use of MSBuild API directly and use indirect project evaluation
- Loading branch information
Nate McMaster
committed
Oct 11, 2016
1 parent
ef63762
commit 27fc53e
Showing
17 changed files
with
414 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ project.lock.json | |
.testPublish/ | ||
.build/ | ||
/.vs/ | ||
.vscode/ | ||
testWorkDir/ | ||
*.nuget.props | ||
*.nuget.targets |
6 changes: 6 additions & 0 deletions
6
src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<Import Project="$(Project)" /> | ||
<Target Name="_FindUserSecretsProperty"> | ||
<WriteLinesToFile File="$(OutputFile)" Lines="$(UserSecretsId)" /> | ||
</Target> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 0 additions & 26 deletions
26
src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulProjectFinder.cs
This file was deleted.
Oops, something went wrong.
61 changes: 61 additions & 0 deletions
61
src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using Microsoft.DotNet.Cli.Utils; | ||
|
||
namespace Microsoft.Extensions.SecretManager.Tools.Internal | ||
{ | ||
internal class MsBuildProjectFinder | ||
{ | ||
private readonly string _directory; | ||
|
||
public MsBuildProjectFinder(string directory) | ||
{ | ||
if (string.IsNullOrEmpty(directory)) | ||
{ | ||
throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(directory)); | ||
} | ||
|
||
_directory = directory; | ||
} | ||
|
||
public string FindMsBuildProject(string project) | ||
{ | ||
var projectPath = project ?? _directory; | ||
|
||
if (!Path.IsPathRooted(projectPath)) | ||
{ | ||
projectPath = Path.Combine(_directory, projectPath); | ||
} | ||
|
||
if (Directory.Exists(projectPath)) | ||
{ | ||
var projects = Directory.EnumerateFileSystemEntries(projectPath, "*.*proj", SearchOption.TopDirectoryOnly) | ||
.Where(f => !".xproj".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase)) | ||
.ToList(); | ||
|
||
if (projects.Count > 1) | ||
{ | ||
throw new GracefulException(Resources.FormatError_MultipleProjectsFound(projectPath)); | ||
} | ||
|
||
if (projects.Count == 0) | ||
{ | ||
throw new GracefulException(Resources.FormatError_NoProjectsFound(projectPath)); | ||
} | ||
|
||
return projects[0]; | ||
} | ||
|
||
if (!File.Exists(projectPath)) | ||
{ | ||
throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); | ||
} | ||
|
||
return projectPath; | ||
} | ||
} | ||
} |
23 changes: 0 additions & 23 deletions
23
src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectContextExtensions.cs
This file was deleted.
Oops, something went wrong.
130 changes: 130 additions & 0 deletions
130
src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using Microsoft.DotNet.Cli.Utils; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Microsoft.Extensions.SecretManager.Tools.Internal | ||
{ | ||
public class ProjectIdResolver : IDisposable | ||
{ | ||
private const string TargetsFileName = "FindUserSecretsProperty.targets"; | ||
private readonly ILogger _logger; | ||
private readonly string _workingDirectory; | ||
private readonly List<string> _tempFiles = new List<string>(); | ||
|
||
public ProjectIdResolver(ILogger logger, string workingDirectory) | ||
{ | ||
_workingDirectory = workingDirectory; | ||
_logger = logger; | ||
} | ||
|
||
public string Resolve(string project, string configuration = Constants.DefaultConfiguration) | ||
{ | ||
var finder = new MsBuildProjectFinder(_workingDirectory); | ||
var projectFile = finder.FindMsBuildProject(project); | ||
|
||
_logger.LogDebug(Resources.Message_Project_File_Path, projectFile); | ||
|
||
var targetFile = GetTargetFile(); | ||
var outputFile = Path.GetTempFileName(); | ||
_tempFiles.Add(outputFile); | ||
|
||
var commandOutput = new List<string>(); | ||
var commandResult = Command.CreateDotNet("msbuild", | ||
new[] { | ||
targetFile, | ||
"/nologo", | ||
"/t:_FindUserSecretsProperty", | ||
$"/p:Project={projectFile}", | ||
$"/p:OutputFile={outputFile}", | ||
$"/p:Configuration={configuration}" | ||
}) | ||
.CaptureStdErr() | ||
.CaptureStdOut() | ||
.OnErrorLine(l => commandOutput.Add(l)) | ||
.OnOutputLine(l => commandOutput.Add(l)) | ||
.Execute(); | ||
|
||
if (commandResult.ExitCode != 0) | ||
{ | ||
_logger.LogDebug(string.Join(Environment.NewLine, commandOutput)); | ||
throw new GracefulException(Resources.FormatError_ProjectFailedToLoad(projectFile)); | ||
} | ||
|
||
var id = File.ReadAllText(outputFile)?.Trim(); | ||
if (string.IsNullOrEmpty(id)) | ||
{ | ||
throw new GracefulException(Resources.FormatError_ProjectMissingId(projectFile)); | ||
} | ||
|
||
return id; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
foreach (var file in _tempFiles) | ||
{ | ||
TryDelete(file); | ||
} | ||
} | ||
|
||
private string GetTargetFile() | ||
{ | ||
var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); | ||
|
||
// targets should be in one of these locations, depending on test setup and tools installation | ||
var searchPaths = new[] | ||
{ | ||
AppContext.BaseDirectory, | ||
assemblyDir, // next to assembly | ||
Path.Combine(assemblyDir, "../../tools"), // inside the nupkg | ||
}; | ||
|
||
var foundFile = searchPaths | ||
.Select(dir => Path.Combine(dir, TargetsFileName)) | ||
.Where(File.Exists) | ||
.FirstOrDefault(); | ||
|
||
if (foundFile != null) | ||
{ | ||
return foundFile; | ||
} | ||
|
||
// This should only really happen during testing. Current build system doesn't give us a good way to ensure the | ||
// test project has an always-up to date version of the targets file. | ||
// TODO cleanup after we switch to an MSBuild system in which can specify "CopyToOutputDirectory: Always" to resolve this issue | ||
var outputPath = Path.GetTempFileName(); | ||
using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(TargetsFileName)) | ||
using (var stream = new FileStream(outputPath, FileMode.Create)) | ||
{ | ||
resource.CopyTo(stream); | ||
} | ||
|
||
// cleanup | ||
_tempFiles.Add(outputPath); | ||
|
||
return outputPath; | ||
} | ||
|
||
private static void TryDelete(string file) | ||
{ | ||
try | ||
{ | ||
if (File.Exists(file)) | ||
{ | ||
File.Delete(file); | ||
} | ||
} | ||
catch | ||
{ | ||
// whatever | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.