1212
1313namespace Semmle . Extraction . CSharp . DependencyFetching
1414{
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+
1523 /// <summary>
1624 /// Main implementation of the build analysis.
1725 /// </summary>
18- public sealed partial class DependencyManager : IDisposable
26+ public sealed partial class DependencyManager : IDisposable , ICompilationInfoContainer
1927 {
2028 private readonly AssemblyCache assemblyCache ;
2129 private readonly ILogger logger ;
2230 private readonly IDiagnosticsWriter diagnosticsWriter ;
31+ private readonly NugetPackageRestorer nugetPackageRestorer ;
32+ private readonly IDotNet dotnet ;
33+ private readonly FileContent fileContent ;
34+ private readonly FileProvider fileProvider ;
2335
2436 // Only used as a set, but ConcurrentDictionary is the only concurrent set in .NET.
2537 private readonly IDictionary < string , bool > usedReferences = new ConcurrentDictionary < string , bool > ( ) ;
@@ -30,18 +42,14 @@ public sealed partial class DependencyManager : IDisposable
3042 private int conflictedReferences = 0 ;
3143 private readonly DirectoryInfo sourceDir ;
3244 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+
3846 private readonly TemporaryDirectory tempWorkingDirectory ;
39- private readonly FileProvider fileProvider ;
4047 private readonly bool cleanupTempWorkingDirectory ;
4148
4249 private readonly Lazy < Runtime > runtimeLazy ;
4350 private Runtime Runtime => runtimeLazy . Value ;
44- private readonly int threads = EnvironmentVariables . GetDefaultNumberOfThreads ( ) ;
51+
52+ internal static readonly int Threads = EnvironmentVariables . GetDefaultNumberOfThreads ( ) ;
4553
4654 /// <summary>
4755 /// Performs C# dependency fetching.
@@ -74,10 +82,6 @@ public DependencyManager(string srcDir, ILogger logger)
7482 $ "dependency-manager-{ DateTime . UtcNow : yyyyMMddHHmm} -{ Environment . ProcessId } .jsonc") ) ;
7583 this . sourceDir = new DirectoryInfo ( srcDir ) ;
7684
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-
8185 tempWorkingDirectory = new TemporaryDirectory ( FileUtils . GetTemporaryWorkingDirectory ( out cleanupTempWorkingDirectory ) ) ;
8286
8387 this . fileProvider = new FileProvider ( sourceDir , logger ) ;
@@ -112,8 +116,10 @@ void exitCallback(int ret, string msg, bool silent)
112116 throw ;
113117 }
114118
119+ nugetPackageRestorer = new NugetPackageRestorer ( fileProvider , fileContent , dotnet , diagnosticsWriter , logger , this ) ;
120+
115121 var dllLocations = fileProvider . Dlls . Select ( x => new AssemblyLookupLocation ( x ) ) . ToHashSet ( ) ;
116- RestoreNugetPackages ( dllLocations ) ;
122+ dllLocations . UnionWith ( nugetPackageRestorer . Restore ( ) ) ;
117123 // Find DLLs in the .Net / Asp.Net Framework
118124 // This needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
119125 var frameworkLocations = AddFrameworkDlls ( dllLocations ) ;
@@ -221,11 +227,7 @@ private HashSet<string> AddFrameworkDlls(HashSet<AssemblyLookupLocation> dllLoca
221227
222228 private void RemoveNugetAnalyzerReferences ( )
223229 {
224- var packageFolder = packageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
225- if ( packageFolder == null )
226- {
227- return ;
228- }
230+ var packageFolder = nugetPackageRestorer . PackageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
229231
230232 foreach ( var filename in usedReferences . Keys )
231233 {
@@ -299,7 +301,7 @@ private void AddNetFrameworkDlls(ISet<AssemblyLookupLocation> dllLocations, ISet
299301 var packagesInPrioOrder = FrameworkPackageNames . NetFrameworks ;
300302
301303 var frameworkPaths = packagesInPrioOrder
302- . Select ( ( s , index ) => ( Index : index , Path : GetPackageDirectory ( s , packageDirectory ) ) )
304+ . Select ( ( s , index ) => ( Index : index , Path : GetPackageDirectory ( s ) ) )
303305 . Where ( pair => pair . Path is not null )
304306 . ToArray ( ) ;
305307
@@ -330,11 +332,7 @@ private void AddNetFrameworkDlls(ISet<AssemblyLookupLocation> dllLocations, ISet
330332 if ( runtimeLocation is null )
331333 {
332334 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 ( ) ;
338336 }
339337 }
340338
@@ -354,12 +352,7 @@ private void AddNetFrameworkDlls(ISet<AssemblyLookupLocation> dllLocations, ISet
354352
355353 private void RemoveNugetPackageReference ( string packagePrefix , ISet < AssemblyLookupLocation > dllLocations )
356354 {
357- var packageFolder = packageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
358- if ( packageFolder == null )
359- {
360- return ;
361- }
362-
355+ var packageFolder = nugetPackageRestorer . PackageDirectory . DirInfo . FullName . ToLowerInvariant ( ) ;
363356 var packagePathPrefix = Path . Combine ( packageFolder , packagePrefix . ToLowerInvariant ( ) ) ;
364357 var toRemove = dllLocations . Where ( s => s . Path . StartsWith ( packagePathPrefix , StringComparison . InvariantCultureIgnoreCase ) ) ;
365358 foreach ( var path in toRemove )
@@ -382,7 +375,7 @@ private void AddAspNetCoreFrameworkDlls(ISet<AssemblyLookupLocation> dllLocation
382375 }
383376
384377 // 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 )
386379 {
387380 SelectNewestFrameworkPath ( aspNetCorePackage , "ASP.NET Core" , dllLocations , frameworkLocations ) ;
388381 return ;
@@ -398,15 +391,20 @@ private void AddAspNetCoreFrameworkDlls(ISet<AssemblyLookupLocation> dllLocation
398391
399392 private void AddMicrosoftWindowsDesktopDlls ( ISet < AssemblyLookupLocation > dllLocations , ISet < string > frameworkLocations )
400393 {
401- if ( GetPackageDirectory ( FrameworkPackageNames . WindowsDesktopFramework , packageDirectory ) is string windowsDesktopApp )
394+ if ( GetPackageDirectory ( FrameworkPackageNames . WindowsDesktopFramework ) is string windowsDesktopApp )
402395 {
403396 SelectNewestFrameworkPath ( windowsDesktopApp , "Windows Desktop App" , dllLocations , frameworkLocations ) ;
404397 }
405398 }
406399
407- private string ? GetPackageDirectory ( string packagePrefix , TemporaryDirectory root )
400+ private string ? GetPackageDirectory ( string packagePrefix )
408401 {
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 )
410408 . EnumerateDirectories ( packagePrefix + "*" , new EnumerationOptions { MatchCasing = MatchCasing . CaseInsensitive , RecurseSubdirectories = false } )
411409 . FirstOrDefault ( ) ?
412410 . FullName ;
@@ -495,22 +493,6 @@ private void GenerateSourceFilesFromWebViews()
495493 }
496494 }
497495
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-
514496 /// <summary>
515497 /// Creates a temporary directory with the given subfolder name.
516498 /// 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)
634616
635617 private void AnalyseSolutions ( IEnumerable < string > solutions )
636618 {
637- Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = threads } , solutionFile =>
619+ Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = Threads } , solutionFile =>
638620 {
639621 try
640622 {
@@ -683,7 +665,7 @@ private void AnalyseProject(FileInfo project)
683665 }
684666 }
685667
686- public void Dispose ( TemporaryDirectory ? dir , string name )
668+ public static void DisposeTempDirectory ( TemporaryDirectory ? dir , string name , ILogger logger )
687669 {
688670 try
689671 {
@@ -697,15 +679,13 @@ public void Dispose(TemporaryDirectory? dir, string name)
697679
698680 public void Dispose ( )
699681 {
700- Dispose ( packageDirectory , "package" ) ;
701- Dispose ( legacyPackageDirectory , "legacy package" ) ;
702- Dispose ( missingPackageDirectory , "missing package" ) ;
703682 if ( cleanupTempWorkingDirectory )
704683 {
705- Dispose ( tempWorkingDirectory , "temporary working" ) ;
684+ DisposeTempDirectory ( tempWorkingDirectory , "temporary working" , logger ) ;
706685 }
707686
708687 diagnosticsWriter ? . Dispose ( ) ;
688+ nugetPackageRestorer ? . Dispose ( ) ;
709689 }
710690 }
711691}
0 commit comments