From 23f3e44fa1d37407308186af75c5af3a749ca55b Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 7 Jul 2023 13:49:28 +0200 Subject: [PATCH] C#: Use `nuget.config` file for `dotnet restore` fallback logic --- .../BuildAnalysis.cs | 32 ++++++++++++++----- .../DotNet.cs | 4 ++- .../ProgressMonitor.cs | 10 ++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs index ad501c9e758..d4a0956c82a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs @@ -133,9 +133,9 @@ namespace Semmle.BuildAnalyser DateTime.Now - startTime); } - private IEnumerable GetFiles(string pattern) + private IEnumerable GetFiles(string pattern, bool recurseSubdirectories = true) { - return sourceDir.GetFiles(pattern, SearchOption.AllDirectories) + return sourceDir.GetFiles(pattern, new EnumerationOptions { RecurseSubdirectories = recurseSubdirectories, MatchCasing = MatchCasing.CaseInsensitive }) .Select(d => d.FullName) .Where(d => !options.ExcludesFile(d)); } @@ -318,16 +318,16 @@ namespace Semmle.BuildAnalyser } - private bool Restore(string target) + private bool Restore(string target, string? pathToNugetConfig = null) { - return dotnet.RestoreToDirectory(target, packageDirectory.DirInfo.FullName); + return dotnet.RestoreToDirectory(target, packageDirectory.DirInfo.FullName, pathToNugetConfig); } - private void Restore(IEnumerable targets) + private void Restore(IEnumerable targets, string? pathToNugetConfig = null) { foreach (var target in targets) { - Restore(target); + Restore(target, pathToNugetConfig); } } @@ -336,7 +336,23 @@ namespace Semmle.BuildAnalyser var alreadyDownloadedPackages = Directory.GetDirectories(packageDirectory.DirInfo.FullName).Select(d => Path.GetFileName(d).ToLowerInvariant()).ToHashSet(); var notYetDownloadedPackages = new HashSet(); - var allFiles = GetFiles("*.*").ToArray(); + var nugetConfigs = GetFiles("nuget.config", recurseSubdirectories: true).ToArray(); + string? nugetConfig = null; + if (nugetConfigs.Length > 1) + { + progressMonitor.MultipleNugetConfig(nugetConfigs); + nugetConfig = GetFiles("nuget.config", recurseSubdirectories: false).FirstOrDefault(); + if (nugetConfig == null) + { + progressMonitor.NoTopLevelNugetConfig(); + } + } + else + { + nugetConfig = nugetConfigs.FirstOrDefault(); + } + + var allFiles = GetFiles("*.*"); foreach (var file in allFiles) { try @@ -390,7 +406,7 @@ namespace Semmle.BuildAnalyser continue; } - success = Restore(tempDir.DirInfo.FullName); + success = Restore(tempDir.DirInfo.FullName, nugetConfig); // TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package. diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs index dbe3b2c4a1e..5cc507c94d2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs @@ -45,9 +45,11 @@ namespace Semmle.BuildAnalyser return true; } - public bool RestoreToDirectory(string projectOrSolutionFile, string packageDirectory) + public bool RestoreToDirectory(string projectOrSolutionFile, string packageDirectory, string? pathToNugetConfig = null) { var args = $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true"; + if (pathToNugetConfig != null) + args += $" --configfile \"{pathToNugetConfig}\""; return RunCommand(args); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs index de1c5274c37..233ba969fea 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs @@ -118,5 +118,15 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Info, $"Failed to read file {file}"); logger.Log(Severity.Debug, $"Failed to read file {file}, exception: {ex}"); } + + public void MultipleNugetConfig(string[] nugetConfigs) + { + logger.Log(Severity.Info, $"Found multiple nuget.config files: {string.Join(", ", nugetConfigs)}."); + } + + internal void NoTopLevelNugetConfig() + { + logger.Log(Severity.Info, $"Could not find a top-level nuget.config file."); + } } }