@@ -47,9 +47,12 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
47
47
this . progressMonitor = new ProgressMonitor ( logger ) ;
48
48
this . sourceDir = new DirectoryInfo ( srcDir ) ;
49
49
50
+ packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
51
+ tempWorkingDirectory = new TemporaryDirectory ( FileUtils . GetTemporaryWorkingDirectory ( out cleanupTempWorkingDirectory ) ) ;
52
+
50
53
try
51
54
{
52
- this . dotnet = DotNet . Make ( options , progressMonitor ) ;
55
+ this . dotnet = DotNet . Make ( options , progressMonitor , tempWorkingDirectory ) ;
53
56
}
54
57
catch
55
58
{
@@ -59,8 +62,6 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
59
62
60
63
this . progressMonitor . FindingFiles ( srcDir ) ;
61
64
62
- packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
63
- tempWorkingDirectory = new TemporaryDirectory ( FileUtils . GetTemporaryWorkingDirectory ( out cleanupTempWorkingDirectory ) ) ;
64
65
65
66
var allFiles = GetAllFiles ( ) ;
66
67
var binaryFileExtensions = new HashSet < string > ( new [ ] { ".dll" , ".exe" } ) ; // TODO: add more binary file extensions.
@@ -77,21 +78,6 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
77
78
? allFiles . SelectFileNamesByExtension ( ".dll" ) . ToList ( )
78
79
: options . DllDirs . Select ( Path . GetFullPath ) . ToList ( ) ;
79
80
80
- // Find DLLs in the .Net / Asp.Net Framework
81
- if ( options . ScanNetFrameworkDlls )
82
- {
83
- var runtime = new Runtime ( dotnet ) ;
84
- var runtimeLocation = runtime . GetRuntime ( options . UseSelfContainedDotnet ) ;
85
- progressMonitor . LogInfo ( $ ".NET runtime location selected: { runtimeLocation } ") ;
86
- dllDirNames . Add ( runtimeLocation ) ;
87
-
88
- if ( fileContent . UseAspNetDlls && runtime . GetAspRuntime ( ) is string aspRuntime )
89
- {
90
- progressMonitor . LogInfo ( $ "ASP.NET runtime location selected: { aspRuntime } ") ;
91
- dllDirNames . Add ( aspRuntime ) ;
92
- }
93
- }
94
-
95
81
if ( options . UseNuGet )
96
82
{
97
83
dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
@@ -111,6 +97,26 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
111
97
DownloadMissingPackages ( allNonBinaryFiles ) ;
112
98
}
113
99
100
+ var existsNetCoreRefNugetPackage = false ;
101
+ var existsNetFrameworkRefNugetPackage = false ;
102
+
103
+ // Find DLLs in the .Net / Asp.Net Framework
104
+ // This block needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
105
+ if ( options . ScanNetFrameworkDlls )
106
+ {
107
+ existsNetCoreRefNugetPackage = IsNugetPackageAvailable ( "microsoft.netcore.app.ref" ) ;
108
+ existsNetFrameworkRefNugetPackage = IsNugetPackageAvailable ( "microsoft.netframework.referenceassemblies" ) ;
109
+
110
+ if ( existsNetCoreRefNugetPackage || existsNetFrameworkRefNugetPackage )
111
+ {
112
+ progressMonitor . LogInfo ( "Found .NET Core/Framework DLLs in NuGet packages. Not adding installation directory." ) ;
113
+ }
114
+ else
115
+ {
116
+ AddNetFrameworkDlls ( dllDirNames ) ;
117
+ }
118
+ }
119
+
114
120
assemblyCache = new AssemblyCache ( dllDirNames , progressMonitor ) ;
115
121
AnalyseSolutions ( solutions ) ;
116
122
@@ -119,7 +125,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
119
125
UseReference ( filename ) ;
120
126
}
121
127
122
- RemoveRuntimeNugetPackageReferences ( ) ;
128
+ RemoveUnnecessaryNugetPackages ( existsNetCoreRefNugetPackage , existsNetFrameworkRefNugetPackage ) ;
123
129
ResolveConflicts ( ) ;
124
130
125
131
// Output the findings
@@ -154,38 +160,158 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
154
160
DateTime . Now - startTime ) ;
155
161
}
156
162
157
- private void RemoveRuntimeNugetPackageReferences ( )
163
+ private void RemoveUnnecessaryNugetPackages ( bool existsNetCoreRefNugetPackage , bool existsNetFrameworkRefNugetPackage )
164
+ {
165
+ RemoveNugetAnalyzerReferences ( ) ;
166
+ RemoveRuntimeNugetPackageReferences ( ) ;
167
+
168
+ if ( fileContent . IsNewProjectStructureUsed
169
+ && ! fileContent . UseAspNetCoreDlls )
170
+ {
171
+ // This might have been restored by the CLI even though the project isn't an asp.net core one.
172
+ RemoveNugetPackageReference ( "microsoft.aspnetcore.app.ref" ) ;
173
+ }
174
+
175
+ if ( existsNetCoreRefNugetPackage && existsNetFrameworkRefNugetPackage )
176
+ {
177
+ // Multiple packages are available, we keep only one:
178
+ RemoveNugetPackageReference ( "microsoft.netframework.referenceassemblies." ) ;
179
+ }
180
+
181
+ // TODO: There could be multiple `microsoft.netframework.referenceassemblies` packages,
182
+ // we could keep the newest one, but this is covered by the conflict resolution logic
183
+ // (if the file names match)
184
+ }
185
+
186
+ private void RemoveNugetAnalyzerReferences ( )
158
187
{
159
188
if ( ! options . UseNuGet )
160
189
{
161
190
return ;
162
191
}
163
192
164
193
var packageFolder = packageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
165
- var runtimePackageNamePrefixes = new [ ]
194
+ if ( packageFolder == null )
195
+ {
196
+ return ;
197
+ }
198
+
199
+ foreach ( var filename in usedReferences . Keys )
166
200
{
167
- Path . Combine ( packageFolder , "microsoft.netcore.app.runtime" ) ,
168
- Path . Combine ( packageFolder , "microsoft.aspnetcore.app.runtime" ) ,
169
- Path . Combine ( packageFolder , "microsoft.windowsdesktop.app.runtime" ) ,
201
+ var lowerFilename = filename . ToLowerInvariant ( ) ;
202
+
203
+ if ( lowerFilename . StartsWith ( packageFolder ) )
204
+ {
205
+ var firstDirectorySeparatorCharIndex = lowerFilename . IndexOf ( Path . DirectorySeparatorChar , packageFolder . Length + 1 ) ;
206
+ if ( firstDirectorySeparatorCharIndex == - 1 )
207
+ {
208
+ continue ;
209
+ }
210
+ var secondDirectorySeparatorCharIndex = lowerFilename . IndexOf ( Path . DirectorySeparatorChar , firstDirectorySeparatorCharIndex + 1 ) ;
211
+ if ( secondDirectorySeparatorCharIndex == - 1 )
212
+ {
213
+ continue ;
214
+ }
215
+ var subFolderIndex = secondDirectorySeparatorCharIndex + 1 ;
216
+ var isInAnalyzersFolder = lowerFilename . IndexOf ( "analyzers" , subFolderIndex ) == subFolderIndex ;
217
+ if ( isInAnalyzersFolder )
218
+ {
219
+ usedReferences . Remove ( filename ) ;
220
+ progressMonitor . RemovedReference ( filename ) ;
221
+ }
222
+ }
223
+ }
224
+ }
225
+ private void AddNetFrameworkDlls ( List < string > dllDirNames )
226
+ {
227
+ var runtime = new Runtime ( dotnet ) ;
228
+ string ? runtimeLocation = null ;
229
+
230
+ if ( options . UseSelfContainedDotnet )
231
+ {
232
+ runtimeLocation = runtime . ExecutingRuntime ;
233
+ }
234
+ else if ( fileContent . IsNewProjectStructureUsed )
235
+ {
236
+ runtimeLocation = runtime . NetCoreRuntime ;
237
+ }
238
+ else if ( fileContent . IsLegacyProjectStructureUsed )
239
+ {
240
+ runtimeLocation = runtime . DesktopRuntime ;
241
+ }
242
+
243
+ runtimeLocation ??= runtime . ExecutingRuntime ;
244
+
245
+ progressMonitor . LogInfo ( $ ".NET runtime location selected: { runtimeLocation } ") ;
246
+ dllDirNames . Add ( runtimeLocation ) ;
247
+
248
+ if ( fileContent . IsNewProjectStructureUsed
249
+ && fileContent . UseAspNetCoreDlls
250
+ && runtime . AspNetCoreRuntime is string aspRuntime )
251
+ {
252
+ progressMonitor . LogInfo ( $ "ASP.NET runtime location selected: { aspRuntime } ") ;
253
+ dllDirNames . Add ( aspRuntime ) ;
254
+ }
255
+ }
256
+
257
+ private void RemoveRuntimeNugetPackageReferences ( )
258
+ {
259
+ var runtimePackagePrefixes = new [ ]
260
+ {
261
+ "microsoft.netcore.app.runtime" ,
262
+ "microsoft.aspnetcore.app.runtime" ,
263
+ "microsoft.windowsdesktop.app.runtime" ,
170
264
171
265
// legacy runtime packages:
172
- Path . Combine ( packageFolder , "runtime.linux-x64.microsoft.netcore.app" ) ,
173
- Path . Combine ( packageFolder , "runtime.osx-x64.microsoft.netcore.app" ) ,
174
- Path . Combine ( packageFolder , "runtime.win-x64.microsoft.netcore.app" ) ,
266
+ "runtime.linux-x64.microsoft.netcore.app" ,
267
+ "runtime.osx-x64.microsoft.netcore.app" ,
268
+ "runtime.win-x64.microsoft.netcore.app" ,
269
+
270
+ // Internal implementation packages not meant for direct consumption:
271
+ "runtime."
175
272
} ;
273
+ RemoveNugetPackageReference ( runtimePackagePrefixes ) ;
274
+ }
275
+
276
+ private void RemoveNugetPackageReference ( params string [ ] packagePrefixes )
277
+ {
278
+ if ( ! options . UseNuGet )
279
+ {
280
+ return ;
281
+ }
282
+
283
+ var packageFolder = packageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
284
+ if ( packageFolder == null )
285
+ {
286
+ return ;
287
+ }
288
+
289
+ var packagePathPrefixes = packagePrefixes . Select ( p => Path . Combine ( packageFolder , p . ToLowerInvariant ( ) ) ) ;
176
290
177
291
foreach ( var filename in usedReferences . Keys )
178
292
{
179
293
var lowerFilename = filename . ToLowerInvariant ( ) ;
180
294
181
- if ( runtimePackageNamePrefixes . Any ( prefix => lowerFilename . StartsWith ( prefix ) ) )
295
+ if ( packagePathPrefixes . Any ( prefix => lowerFilename . StartsWith ( prefix ) ) )
182
296
{
183
297
usedReferences . Remove ( filename ) ;
184
298
progressMonitor . RemovedReference ( filename ) ;
185
299
}
186
300
}
187
301
}
188
302
303
+ private bool IsNugetPackageAvailable ( string packagePrefix )
304
+ {
305
+ if ( ! options . UseNuGet )
306
+ {
307
+ return false ;
308
+ }
309
+
310
+ return new DirectoryInfo ( packageDirectory . DirInfo . FullName )
311
+ . EnumerateDirectories ( packagePrefix + "*" , new EnumerationOptions { MatchCasing = MatchCasing . CaseInsensitive , RecurseSubdirectories = false } )
312
+ . Any ( ) ;
313
+ }
314
+
189
315
private void GenerateSourceFileFromImplicitUsings ( )
190
316
{
191
317
var usings = new HashSet < string > ( ) ;
@@ -198,7 +324,7 @@ private void GenerateSourceFileFromImplicitUsings()
198
324
usings . UnionWith ( new [ ] { "System" , "System.Collections.Generic" , "System.IO" , "System.Linq" , "System.Net.Http" , "System.Threading" ,
199
325
"System.Threading.Tasks" } ) ;
200
326
201
- if ( fileContent . UseAspNetDlls )
327
+ if ( fileContent . UseAspNetCoreDlls )
202
328
{
203
329
usings . UnionWith ( new [ ] { "System.Net.Http.Json" , "Microsoft.AspNetCore.Builder" , "Microsoft.AspNetCore.Hosting" ,
204
330
"Microsoft.AspNetCore.Http" , "Microsoft.AspNetCore.Routing" , "Microsoft.Extensions.Configuration" ,
@@ -461,11 +587,11 @@ private void AnalyseProject(FileInfo project)
461
587
462
588
}
463
589
464
- private bool RestoreProject ( string project , string ? pathToNugetConfig = null ) =>
465
- dotnet . RestoreProjectToDirectory ( project , packageDirectory . DirInfo . FullName , pathToNugetConfig ) ;
590
+ private bool RestoreProject ( string project , bool forceDotnetRefAssemblyFetching , string ? pathToNugetConfig = null ) =>
591
+ dotnet . RestoreProjectToDirectory ( project , packageDirectory . DirInfo . FullName , forceDotnetRefAssemblyFetching , pathToNugetConfig ) ;
466
592
467
593
private bool RestoreSolution ( string solution , out IEnumerable < string > projects ) =>
468
- dotnet . RestoreSolutionToDirectory ( solution , packageDirectory . DirInfo . FullName , out projects ) ;
594
+ dotnet . RestoreSolutionToDirectory ( solution , packageDirectory . DirInfo . FullName , forceDotnetRefAssemblyFetching : true , out projects ) ;
469
595
470
596
/// <summary>
471
597
/// Executes `dotnet restore` on all solution files in solutions.
@@ -491,7 +617,7 @@ private void RestoreProjects(IEnumerable<string> projects)
491
617
{
492
618
Parallel . ForEach ( projects , new ParallelOptions { MaxDegreeOfParallelism = options . Threads } , project =>
493
619
{
494
- RestoreProject ( project ) ;
620
+ RestoreProject ( project , forceDotnetRefAssemblyFetching : true ) ;
495
621
} ) ;
496
622
}
497
623
@@ -536,7 +662,7 @@ private void DownloadMissingPackages(List<FileInfo> allFiles)
536
662
return ;
537
663
}
538
664
539
- success = RestoreProject ( tempDir . DirInfo . FullName , nugetConfig ) ;
665
+ success = RestoreProject ( tempDir . DirInfo . FullName , forceDotnetRefAssemblyFetching : false , pathToNugetConfig : nugetConfig ) ;
540
666
// TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
541
667
if ( ! success )
542
668
{
@@ -564,9 +690,25 @@ private void AnalyseSolutions(IEnumerable<string> solutions)
564
690
565
691
public void Dispose ( )
566
692
{
567
- packageDirectory ? . Dispose ( ) ;
693
+ try
694
+ {
695
+ packageDirectory ? . Dispose ( ) ;
696
+ }
697
+ catch ( Exception exc )
698
+ {
699
+ progressMonitor . LogInfo ( "Couldn't delete package directory: " + exc . Message ) ;
700
+ }
568
701
if ( cleanupTempWorkingDirectory )
569
- tempWorkingDirectory ? . Dispose ( ) ;
702
+ {
703
+ try
704
+ {
705
+ tempWorkingDirectory ? . Dispose ( ) ;
706
+ }
707
+ catch ( Exception exc )
708
+ {
709
+ progressMonitor . LogInfo ( "Couldn't delete temporary working directory: " + exc . Message ) ;
710
+ }
711
+ }
570
712
}
571
713
}
572
714
}
0 commit comments