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 74
/
Copy pathProjectIdResolver.cs
130 lines (111 loc) · 4.4 KB
/
ProjectIdResolver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
}
}
}
}