12
12
13
13
namespace Semmle . Extraction . CSharp . DependencyFetching
14
14
{
15
+ public interface ICompilationInfoContainer
16
+ {
17
+ /// <summary>
18
+ /// List of `(key, value)` tuples, that are stored in the DB for telemetry purposes.
19
+ /// </summary>
20
+ List < ( string , string ) > CompilationInfos { get ; }
21
+ }
22
+
15
23
/// <summary>
16
24
/// Main implementation of the build analysis.
17
25
/// </summary>
18
- public sealed partial class DependencyManager : IDisposable
26
+ public sealed partial class DependencyManager : IDisposable , ICompilationInfoContainer
19
27
{
20
28
private readonly AssemblyCache assemblyCache ;
21
29
private readonly ILogger logger ;
22
30
private readonly IDiagnosticsWriter diagnosticsWriter ;
31
+ private readonly NugetPackageRestorer nugetPackageRestorer ;
32
+ private readonly IDotNet dotnet ;
33
+ private readonly FileContent fileContent ;
34
+ private readonly FileProvider fileProvider ;
23
35
24
36
// Only used as a set, but ConcurrentDictionary is the only concurrent set in .NET.
25
37
private readonly IDictionary < string , bool > usedReferences = new ConcurrentDictionary < string , bool > ( ) ;
@@ -30,18 +42,14 @@ public sealed partial class DependencyManager : IDisposable
30
42
private int conflictedReferences = 0 ;
31
43
private readonly DirectoryInfo sourceDir ;
32
44
private string ? dotnetPath ;
33
- private readonly IDotNet dotnet ;
34
- private readonly FileContent fileContent ;
35
- private readonly TemporaryDirectory packageDirectory ;
36
- private readonly TemporaryDirectory legacyPackageDirectory ;
37
- private readonly TemporaryDirectory missingPackageDirectory ;
45
+
38
46
private readonly TemporaryDirectory tempWorkingDirectory ;
39
- private readonly FileProvider fileProvider ;
40
47
private readonly bool cleanupTempWorkingDirectory ;
41
48
42
49
private readonly Lazy < Runtime > runtimeLazy ;
43
50
private Runtime Runtime => runtimeLazy . Value ;
44
- private readonly int threads = EnvironmentVariables . GetDefaultNumberOfThreads ( ) ;
51
+
52
+ internal static readonly int Threads = EnvironmentVariables . GetDefaultNumberOfThreads ( ) ;
45
53
46
54
/// <summary>
47
55
/// Performs C# dependency fetching.
@@ -74,10 +82,6 @@ public DependencyManager(string srcDir, ILogger logger)
74
82
$ "dependency-manager-{ DateTime . UtcNow : yyyyMMddHHmm} -{ Environment . ProcessId } .jsonc") ) ;
75
83
this . sourceDir = new DirectoryInfo ( srcDir ) ;
76
84
77
- packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName , "packages" ) ) ;
78
- legacyPackageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName , "legacypackages" ) ) ;
79
- missingPackageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName , "missingpackages" ) ) ;
80
-
81
85
tempWorkingDirectory = new TemporaryDirectory ( FileUtils . GetTemporaryWorkingDirectory ( out cleanupTempWorkingDirectory ) ) ;
82
86
83
87
this . fileProvider = new FileProvider ( sourceDir , logger ) ;
@@ -112,8 +116,10 @@ void exitCallback(int ret, string msg, bool silent)
112
116
throw ;
113
117
}
114
118
119
+ nugetPackageRestorer = new NugetPackageRestorer ( fileProvider , fileContent , dotnet , diagnosticsWriter , logger , this ) ;
120
+
115
121
var dllLocations = fileProvider . Dlls . Select ( x => new AssemblyLookupLocation ( x ) ) . ToHashSet ( ) ;
116
- RestoreNugetPackages ( dllLocations ) ;
122
+ dllLocations . UnionWith ( nugetPackageRestorer . Restore ( ) ) ;
117
123
// Find DLLs in the .Net / Asp.Net Framework
118
124
// This needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
119
125
var frameworkLocations = AddFrameworkDlls ( dllLocations ) ;
@@ -221,11 +227,7 @@ private HashSet<string> AddFrameworkDlls(HashSet<AssemblyLookupLocation> dllLoca
221
227
222
228
private void RemoveNugetAnalyzerReferences ( )
223
229
{
224
- var packageFolder = packageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
225
- if ( packageFolder == null )
226
- {
227
- return ;
228
- }
230
+ var packageFolder = nugetPackageRestorer . PackageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
229
231
230
232
foreach ( var filename in usedReferences . Keys )
231
233
{
@@ -299,7 +301,7 @@ private void AddNetFrameworkDlls(ISet<AssemblyLookupLocation> dllLocations, ISet
299
301
var packagesInPrioOrder = FrameworkPackageNames . NetFrameworks ;
300
302
301
303
var frameworkPaths = packagesInPrioOrder
302
- . Select ( ( s , index ) => ( Index : index , Path : GetPackageDirectory ( s , packageDirectory ) ) )
304
+ . Select ( ( s , index ) => ( Index : index , Path : GetPackageDirectory ( s ) ) )
303
305
. Where ( pair => pair . Path is not null )
304
306
. ToArray ( ) ;
305
307
@@ -330,11 +332,7 @@ private void AddNetFrameworkDlls(ISet<AssemblyLookupLocation> dllLocations, ISet
330
332
if ( runtimeLocation is null )
331
333
{
332
334
logger . LogInfo ( "No .NET Desktop Runtime location found. Attempting to restore the .NET Framework reference assemblies manually." ) ;
333
-
334
- if ( TryRestorePackageManually ( FrameworkPackageNames . LatestNetFrameworkReferenceAssemblies ) )
335
- {
336
- runtimeLocation = GetPackageDirectory ( FrameworkPackageNames . LatestNetFrameworkReferenceAssemblies , missingPackageDirectory ) ;
337
- }
335
+ runtimeLocation = nugetPackageRestorer . TryRestoreLatestNetFrameworkReferenceAssemblies ( ) ;
338
336
}
339
337
}
340
338
@@ -354,12 +352,7 @@ private void AddNetFrameworkDlls(ISet<AssemblyLookupLocation> dllLocations, ISet
354
352
355
353
private void RemoveNugetPackageReference ( string packagePrefix , ISet < AssemblyLookupLocation > dllLocations )
356
354
{
357
- var packageFolder = packageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
358
- if ( packageFolder == null )
359
- {
360
- return ;
361
- }
362
-
355
+ var packageFolder = nugetPackageRestorer . PackageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
363
356
var packagePathPrefix = Path . Combine ( packageFolder , packagePrefix . ToLowerInvariant ( ) ) ;
364
357
var toRemove = dllLocations . Where ( s => s . Path . StartsWith ( packagePathPrefix , StringComparison . InvariantCultureIgnoreCase ) ) ;
365
358
foreach ( var path in toRemove )
@@ -382,7 +375,7 @@ private void AddAspNetCoreFrameworkDlls(ISet<AssemblyLookupLocation> dllLocation
382
375
}
383
376
384
377
// First try to find ASP.NET Core assemblies in the NuGet packages
385
- if ( GetPackageDirectory ( FrameworkPackageNames . AspNetCoreFramework , packageDirectory ) is string aspNetCorePackage )
378
+ if ( GetPackageDirectory ( FrameworkPackageNames . AspNetCoreFramework ) is string aspNetCorePackage )
386
379
{
387
380
SelectNewestFrameworkPath ( aspNetCorePackage , "ASP.NET Core" , dllLocations , frameworkLocations ) ;
388
381
return ;
@@ -398,15 +391,20 @@ private void AddAspNetCoreFrameworkDlls(ISet<AssemblyLookupLocation> dllLocation
398
391
399
392
private void AddMicrosoftWindowsDesktopDlls ( ISet < AssemblyLookupLocation > dllLocations , ISet < string > frameworkLocations )
400
393
{
401
- if ( GetPackageDirectory ( FrameworkPackageNames . WindowsDesktopFramework , packageDirectory ) is string windowsDesktopApp )
394
+ if ( GetPackageDirectory ( FrameworkPackageNames . WindowsDesktopFramework ) is string windowsDesktopApp )
402
395
{
403
396
SelectNewestFrameworkPath ( windowsDesktopApp , "Windows Desktop App" , dllLocations , frameworkLocations ) ;
404
397
}
405
398
}
406
399
407
- private string ? GetPackageDirectory ( string packagePrefix , TemporaryDirectory root )
400
+ private string ? GetPackageDirectory ( string packagePrefix )
408
401
{
409
- return new DirectoryInfo ( root . DirInfo . FullName )
402
+ return GetPackageDirectory ( packagePrefix , nugetPackageRestorer . PackageDirectory . DirInfo ) ;
403
+ }
404
+
405
+ internal static string ? GetPackageDirectory ( string packagePrefix , DirectoryInfo root )
406
+ {
407
+ return new DirectoryInfo ( root . FullName )
410
408
. EnumerateDirectories ( packagePrefix + "*" , new EnumerationOptions { MatchCasing = MatchCasing . CaseInsensitive , RecurseSubdirectories = false } )
411
409
. FirstOrDefault ( ) ?
412
410
. FullName ;
@@ -495,22 +493,6 @@ private void GenerateSourceFilesFromWebViews()
495
493
}
496
494
}
497
495
498
- /// <summary>
499
- /// Computes a unique temp directory for the packages associated
500
- /// with this source tree. Use a SHA1 of the directory name.
501
- /// </summary>
502
- /// <returns>The full path of the temp directory.</returns>
503
- private static string ComputeTempDirectory ( string srcDir , string subfolderName )
504
- {
505
- var bytes = Encoding . Unicode . GetBytes ( srcDir ) ;
506
- var sha = SHA1 . HashData ( bytes ) ;
507
- var sb = new StringBuilder ( ) ;
508
- foreach ( var b in sha . Take ( 8 ) )
509
- sb . AppendFormat ( "{0:x2}" , b ) ;
510
-
511
- return Path . Combine ( FileUtils . GetTemporaryWorkingDirectory ( out var _ ) , sb . ToString ( ) , subfolderName ) ;
512
- }
513
-
514
496
/// <summary>
515
497
/// Creates a temporary directory with the given subfolder name.
516
498
/// The created directory might be inside the repo folder, and it is deleted when the object is disposed.
@@ -634,7 +616,7 @@ private void ResolveConflicts(IEnumerable<string> frameworkPaths)
634
616
635
617
private void AnalyseSolutions ( IEnumerable < string > solutions )
636
618
{
637
- Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = threads } , solutionFile =>
619
+ Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = Threads } , solutionFile =>
638
620
{
639
621
try
640
622
{
@@ -683,7 +665,7 @@ private void AnalyseProject(FileInfo project)
683
665
}
684
666
}
685
667
686
- public void Dispose ( TemporaryDirectory ? dir , string name )
668
+ public static void DisposeTempDirectory ( TemporaryDirectory ? dir , string name , ILogger logger )
687
669
{
688
670
try
689
671
{
@@ -697,15 +679,13 @@ public void Dispose(TemporaryDirectory? dir, string name)
697
679
698
680
public void Dispose ( )
699
681
{
700
- Dispose ( packageDirectory , "package" ) ;
701
- Dispose ( legacyPackageDirectory , "legacy package" ) ;
702
- Dispose ( missingPackageDirectory , "missing package" ) ;
703
682
if ( cleanupTempWorkingDirectory )
704
683
{
705
- Dispose ( tempWorkingDirectory , "temporary working" ) ;
684
+ DisposeTempDirectory ( tempWorkingDirectory , "temporary working" , logger ) ;
706
685
}
707
686
708
687
diagnosticsWriter ? . Dispose ( ) ;
688
+ nugetPackageRestorer ? . Dispose ( ) ;
709
689
}
710
690
}
711
691
}
0 commit comments