Skip to content

Commit 670a165

Browse files
committed
C#: Use feed management for more package download flows.
1 parent 85af2ec commit 670a165

2 files changed

Lines changed: 47 additions & 42 deletions

File tree

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FeedManager.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,20 @@ public string FeedsToRestoreArgument(IEnumerable<string> feeds, string sourceArg
164164
return feedArgs.ToString();
165165
}
166166

167+
private IEnumerable<string> FeedsToUseAux(HashSet<string> feedsToConsider)
168+
{
169+
if (HasPrivateRegistryFeeds)
170+
{
171+
feedsToConsider.UnionWith(privateRegistryFeeds);
172+
}
173+
174+
var feedsToUse = CheckNugetFeedResponsiveness
175+
? feedsToConsider.Where(ReachableFeeds.Contains)
176+
: feedsToConsider;
177+
178+
return feedsToUse;
179+
}
180+
167181
/// <summary>
168182
/// Constructs the list of NuGet sources to use for this restore.
169183
/// (1) Use the feeds we get from `dotnet nuget list source`
@@ -177,16 +191,19 @@ public IEnumerable<string> FeedsToUse(string path)
177191
var folder = GetDirectoryName(path);
178192
var feedsToConsider = folder is not null ? GetFeedsFromFolder(folder).ToHashSet() : new HashSet<string>();
179193

180-
if (HasPrivateRegistryFeeds)
181-
{
182-
feedsToConsider.UnionWith(privateRegistryFeeds);
183-
}
194+
return FeedsToUseAux(feedsToConsider);
195+
}
184196

185-
var feedsToUse = CheckNugetFeedResponsiveness
186-
? feedsToConsider.Where(ReachableFeeds.Contains)
187-
: feedsToConsider;
197+
public IEnumerable<string> FeedsToUseFromConfig(string config)
198+
{
199+
var feedsToConsider = GetFeedsFromNugetConfig(config).ToHashSet();
188200

189-
return feedsToUse;
201+
return FeedsToUseAux(feedsToConsider);
202+
}
203+
204+
public string FeedsToDotnetRestoreArgument(IEnumerable<string> feeds)
205+
{
206+
return FeedsToRestoreArgument(feeds, "-s");
190207
}
191208

192209
/// <summary>
@@ -206,7 +223,7 @@ public IEnumerable<string> FeedsToUse(string path)
206223

207224
var feedsToUse = FeedsToUse(path);
208225

209-
return FeedsToRestoreArgument(feedsToUse, "-s");
226+
return FeedsToDotnetRestoreArgument(feedsToUse);
210227
}
211228

212229
private (int initialTimeout, int tryCount) GetFeedRequestSettings(bool isFallback)

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,18 @@ private void RestoreProjects(IEnumerable<string> projects, out ConcurrentBag<Dep
350350
}
351351

352352
logger.LogInfo($"Found {notYetDownloadedPackages.Count} packages that are not yet restored");
353-
using var tempDir = new TemporaryDirectory(ComputeTempDirectoryPath("nugetconfig"), "generated nuget config", logger);
354-
var nugetConfig = fallbackNugetFeeds is null
355-
? GetNugetConfig()
356-
: CreateFallbackNugetConfig(fallbackNugetFeeds, tempDir.DirInfo.FullName);
353+
354+
IEnumerable<string> feeds = [];
355+
if (fallbackNugetFeeds is not null)
356+
{
357+
feeds = fallbackNugetFeeds;
358+
}
359+
else if (GetNugetConfig() is string config)
360+
{
361+
feeds = feedManager.FeedsToUseFromConfig(config);
362+
}
363+
364+
var nugetSources = feedManager.FeedsToDotnetRestoreArgument(feeds);
357365

358366
compilationInfoContainer.CompilationInfos.Add(("Fallback nuget restore", notYetDownloadedPackages.Count.ToString()));
359367

@@ -362,7 +370,7 @@ private void RestoreProjects(IEnumerable<string> projects, out ConcurrentBag<Dep
362370

363371
Parallel.ForEach(notYetDownloadedPackages, new ParallelOptions { MaxDegreeOfParallelism = DependencyManager.Threads }, package =>
364372
{
365-
var success = TryRestorePackageManually(package.Name, nugetConfig, package.PackageReferenceSource, tryWithoutNugetConfig: fallbackNugetFeeds is null);
373+
var success = TryRestorePackageManually(package.Name, nugetSources, package.PackageReferenceSource, tryWithoutNugetConfig: fallbackNugetFeeds is null);
366374
if (!success)
367375
{
368376
return;
@@ -379,27 +387,6 @@ private void RestoreProjects(IEnumerable<string> projects, out ConcurrentBag<Dep
379387
return missingPackageDirectory.DirInfo.FullName;
380388
}
381389

382-
private string? CreateFallbackNugetConfig(IEnumerable<string> fallbackNugetFeeds, string folderPath)
383-
{
384-
var sb = new StringBuilder();
385-
fallbackNugetFeeds.ForEach((feed, index) => sb.AppendLine($"<add key=\"feed{index}\" value=\"{feed}\" />"));
386-
387-
var nugetConfigPath = Path.Join(folderPath, "nuget.config");
388-
logger.LogInfo($"Creating fallback nuget.config file {nugetConfigPath}.");
389-
File.WriteAllText(nugetConfigPath,
390-
$"""
391-
<?xml version="1.0" encoding="utf-8"?>
392-
<configuration>
393-
<packageSources>
394-
<clear />
395-
{sb}
396-
</packageSources>
397-
</configuration>
398-
""");
399-
400-
return nugetConfigPath;
401-
}
402-
403390
private string? GetNugetConfig()
404391
{
405392
var nugetConfigs = fileProvider.NugetConfigs;
@@ -415,6 +402,7 @@ private void RestoreProjects(IEnumerable<string> projects, out ConcurrentBag<Dep
415402
}
416403
else
417404
{
405+
// TODO: This could cause non-deterministic behaviror, if the first config file is different between runs.
418406
nugetConfig = nugetConfigs.FirstOrDefault();
419407
}
420408

@@ -489,7 +477,7 @@ private static IEnumerable<string> GetRestoredPackageDirectoryNames(DirectoryInf
489477
.Select(d => Path.GetFileName(d).ToLowerInvariant());
490478
}
491479

492-
private bool TryRestorePackageManually(string package, string? nugetConfig = null, PackageReferenceSource packageReferenceSource = PackageReferenceSource.SdkCsProj,
480+
private bool TryRestorePackageManually(string package, string? nugetSources = null, PackageReferenceSource packageReferenceSource = PackageReferenceSource.SdkCsProj,
493481
bool tryWithoutNugetConfig = true, bool tryPrereleaseVersion = true)
494482
{
495483
logger.LogInfo($"Restoring package {package}...");
@@ -512,17 +500,17 @@ private bool TryRestorePackageManually(string package, string? nugetConfig = nul
512500
return false;
513501
}
514502

515-
var res = TryRestorePackageManually(package, nugetConfig, tempDir, tryPrereleaseVersion);
503+
var res = TryRestorePackageManually(package, nugetSources, tempDir, tryPrereleaseVersion);
516504
if (res.Success)
517505
{
518506
return true;
519507
}
520508

521-
if (tryWithoutNugetConfig && res.HasNugetPackageSourceError && nugetConfig is not null)
509+
if (tryWithoutNugetConfig && res.HasNugetPackageSourceError && nugetSources is not null && !feedManager.CheckNugetFeedResponsiveness)
522510
{
523511
logger.LogDebug($"Trying to restore '{package}' without nuget.config.");
524512
// Restore could not be completed because the listed source is unavailable. Try without the nuget.config:
525-
res = TryRestorePackageManually(package, nugetConfig: null, tempDir, tryPrereleaseVersion);
513+
res = TryRestorePackageManually(package, nugetSources: null, tempDir, tryPrereleaseVersion);
526514
if (res.Success)
527515
{
528516
return true;
@@ -533,16 +521,16 @@ private bool TryRestorePackageManually(string package, string? nugetConfig = nul
533521
return false;
534522
}
535523

536-
private RestoreResult TryRestorePackageManually(string package, string? nugetConfig, TemporaryDirectory tempDir, bool tryPrereleaseVersion)
524+
private RestoreResult TryRestorePackageManually(string package, string? nugetSources, TemporaryDirectory tempDir, bool tryPrereleaseVersion)
537525
{
538-
var res = dotnet.Restore(new(tempDir.DirInfo.FullName, missingPackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: false, PathToNugetConfig: nugetConfig, ForceReevaluation: true));
526+
var res = dotnet.Restore(new(tempDir.DirInfo.FullName, missingPackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: false, NugetSources: nugetSources, ForceReevaluation: true));
539527

540528
if (!res.Success && tryPrereleaseVersion && res.HasNugetNoStablePackageVersionError)
541529
{
542530
logger.LogDebug($"Failed to restore nuget package {package} because no stable version was found.");
543531
TryChangePackageVersion(tempDir.DirInfo, "*-*");
544532

545-
res = dotnet.Restore(new(tempDir.DirInfo.FullName, missingPackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: false, PathToNugetConfig: nugetConfig, ForceReevaluation: true));
533+
res = dotnet.Restore(new(tempDir.DirInfo.FullName, missingPackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: false, NugetSources: nugetSources, ForceReevaluation: true));
546534
if (!res.Success)
547535
{
548536
TryChangePackageVersion(tempDir.DirInfo, "*");

0 commit comments

Comments
 (0)