5
5
using System . Collections . Generic ;
6
6
using System . Diagnostics ;
7
7
using System . IO ;
8
- using System . Linq ;
9
8
using System . Reflection ;
10
9
using Microsoft . Extensions . Tools . Internal ;
11
10
12
11
namespace Microsoft . Extensions . SecretManager . Tools . Internal
13
12
{
14
- public class ProjectIdResolver : IDisposable
13
+ public class ProjectIdResolver
15
14
{
16
- private const string TargetsFileName = "FindUserSecretsProperty.targets" ;
17
15
private const string DefaultConfig = "Debug" ;
18
16
private readonly IReporter _reporter ;
19
17
private readonly string _workingDirectory ;
20
- private readonly List < string > _tempFiles = new List < string > ( ) ;
21
18
22
19
public ProjectIdResolver ( IReporter reporter , string workingDirectory )
23
20
{
@@ -29,83 +26,82 @@ public string Resolve(string project, string configuration)
29
26
{
30
27
var finder = new MsBuildProjectFinder ( _workingDirectory ) ;
31
28
var projectFile = finder . FindMsBuildProject ( project ) ;
29
+ EnsureProjectExtensionTargetsExist ( projectFile ) ;
32
30
33
31
_reporter . Verbose ( Resources . FormatMessage_Project_File_Path ( projectFile ) ) ;
34
32
35
- var targetFile = GetTargetFile ( ) ;
36
- var outputFile = Path . GetTempFileName ( ) ;
37
- _tempFiles . Add ( outputFile ) ;
38
-
39
33
configuration = ! string . IsNullOrEmpty ( configuration )
40
34
? configuration
41
35
: DefaultConfig ;
42
36
43
- var args = new [ ]
44
- {
45
- "msbuild" ,
46
- targetFile ,
47
- "/nologo" ,
48
- "/t:_FindUserSecretsProperty" ,
49
- $ "/p:Project={ projectFile } ",
50
- $ "/p:OutputFile={ outputFile } ",
51
- $ "/p:Configuration={ configuration } "
52
- } ;
53
- var psi = new ProcessStartInfo
37
+ var outputFile = Path . GetTempFileName ( ) ;
38
+ try
54
39
{
55
- FileName = DotNetMuxer . MuxerPathOrDefault ( ) ,
56
- Arguments = ArgumentEscaper . EscapeAndConcatenate ( args ) ,
57
- RedirectStandardOutput = true ,
58
- RedirectStandardError = true
59
- } ;
40
+ var args = new [ ]
41
+ {
42
+ "msbuild" ,
43
+ projectFile ,
44
+ "/nologo" ,
45
+ "/t:_ExtractUserSecretsMetadata" , // defined in ProjectIdResolverTargets.xml
46
+ $ "/p:_UserSecretsMetadataFile={ outputFile } ",
47
+ $ "/p:Configuration={ configuration } "
48
+ } ;
49
+ var psi = new ProcessStartInfo
50
+ {
51
+ FileName = DotNetMuxer . MuxerPathOrDefault ( ) ,
52
+ Arguments = ArgumentEscaper . EscapeAndConcatenate ( args ) ,
53
+ RedirectStandardOutput = true ,
54
+ RedirectStandardError = true
55
+ } ;
60
56
61
57
#if DEBUG
62
- _reporter . Verbose ( $ "Invoking '{ psi . FileName } { psi . Arguments } '") ;
58
+ _reporter . Verbose ( $ "Invoking '{ psi . FileName } { psi . Arguments } '") ;
63
59
#endif
64
60
65
- var process = Process . Start ( psi ) ;
66
- process . WaitForExit ( ) ;
61
+ var process = Process . Start ( psi ) ;
62
+ process . WaitForExit ( ) ;
67
63
68
- if ( process . ExitCode != 0 )
69
- {
70
- _reporter . Verbose ( process . StandardOutput . ReadToEnd ( ) ) ;
71
- _reporter . Verbose ( process . StandardError . ReadToEnd ( ) ) ;
72
- throw new InvalidOperationException ( Resources . FormatError_ProjectFailedToLoad ( projectFile ) ) ;
73
- }
74
-
75
- var id = File . ReadAllText ( outputFile ) ? . Trim ( ) ;
76
- if ( string . IsNullOrEmpty ( id ) )
77
- {
78
- throw new InvalidOperationException ( Resources . FormatError_ProjectMissingId ( projectFile ) ) ;
79
- }
80
-
81
- return id ;
82
- }
64
+ if ( process . ExitCode != 0 )
65
+ {
66
+ _reporter . Verbose ( process . StandardOutput . ReadToEnd ( ) ) ;
67
+ _reporter . Verbose ( process . StandardError . ReadToEnd ( ) ) ;
68
+ throw new InvalidOperationException ( Resources . FormatError_ProjectFailedToLoad ( projectFile ) ) ;
69
+ }
83
70
84
- private string GetTargetFile ( )
85
- {
86
- var assemblyDir = Path . GetDirectoryName ( GetType ( ) . GetTypeInfo ( ) . Assembly . Location ) ;
71
+ var id = File . ReadAllText ( outputFile ) ? . Trim ( ) ;
72
+ if ( string . IsNullOrEmpty ( id ) )
73
+ {
74
+ throw new InvalidOperationException ( Resources . FormatError_ProjectMissingId ( projectFile ) ) ;
75
+ }
76
+ return id ;
87
77
88
- // targets should be in one of these locations, depending on test setup and tools installation
89
- var searchPaths = new [ ]
78
+ }
79
+ finally
90
80
{
91
- AppContext . BaseDirectory ,
92
- assemblyDir , // next to assembly
93
- Path . Combine ( assemblyDir , "../../toolassets" ) , // inside the nupkg
94
- Path . Combine ( assemblyDir , "toolassets" ) , // for local builds
95
- Path . Combine ( AppContext . BaseDirectory , "../../toolassets" ) , // relative to packaged deps.json
96
- } ;
97
-
98
- return searchPaths
99
- . Select ( dir => Path . Combine ( dir , TargetsFileName ) )
100
- . Where ( File . Exists )
101
- . First ( ) ;
81
+ TryDelete ( outputFile ) ;
82
+ }
102
83
}
103
84
104
- public void Dispose ( )
85
+ private void EnsureProjectExtensionTargetsExist ( string projectFile )
105
86
{
106
- foreach ( var file in _tempFiles )
87
+ // relies on MSBuildProjectExtensionsPath and Microsoft.Common.targets to import this file
88
+ // into the target project
89
+ var projectExtensionsPath = Path . Combine (
90
+ Path . GetDirectoryName ( projectFile ) ,
91
+ "obj" ,
92
+ $ "{ Path . GetFileName ( projectFile ) } .usersecrets.targets") ;
93
+
94
+ Directory . CreateDirectory ( Path . GetDirectoryName ( projectExtensionsPath ) ) ;
95
+
96
+ // should overwrite the file always. Hypothetically, another version of the user-secrets tool
97
+ // could have already put a file here. We want to ensure the target file matches the currently
98
+ // running tool
99
+ using ( var resource = GetType ( ) . GetTypeInfo ( ) . Assembly . GetManifestResourceStream ( "ProjectIdResolverTargets.xml" ) )
100
+ using ( var stream = new FileStream ( projectExtensionsPath , FileMode . Create ) )
101
+ using ( var writer = new StreamWriter ( stream ) )
107
102
{
108
- TryDelete ( file ) ;
103
+ writer . WriteLine ( "<!-- Auto-generated by dotnet-user-secrets. This file can be deleted and should not be commited to source control. -->" ) ;
104
+ resource . CopyTo ( stream ) ;
109
105
}
110
106
}
111
107
0 commit comments