@@ -10,13 +10,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
1010{
1111 internal sealed partial class FeedManager : IDisposable
1212 {
13- internal const string PublicNugetOrgFeed = "https://api.nuget.org/v3/index.json" ;
13+ private const string PublicNugetOrg = "nuget.org" ;
14+ private const string PublicDotNugetOrg = $ ".{ PublicNugetOrg } ";
15+ internal const string PublicApiNugetOrgFeed = $ "https://api{ PublicDotNugetOrg } /v3/index.json";
1416
1517 private readonly ILogger logger ;
1618 private readonly IDotNet dotnet ;
1719 private readonly IFileProvider fileProvider ;
1820 private readonly DependencyDirectory emptyPackageDirectory ;
1921 private readonly ImmutableHashSet < string > privateRegistryFeeds ;
22+ private readonly bool hasPrivateRegistryBaseFeeds ;
23+ private readonly ImmutableHashSet < string > privateRegistryBaseFeeds ;
2024 private readonly IFeedManagerIO feedManagerIo ;
2125
2226 /// <summary>
@@ -72,14 +76,33 @@ internal sealed partial class FeedManager : IDisposable
7276 /// </summary>
7377 public ImmutableHashSet < string > ReachableFallbackFeeds => lazyReachableFallbackFeeds . Value ;
7478
79+ private readonly Lazy < ImmutableHashSet < string > > lazyReachableDefaultFeeds ;
80+
81+ /// <summary>
82+ /// Gets the list of default NuGet feeds that are configured in the environment.
83+ /// This is either the public NuGet feed or a set of feeds specified by the environment.
84+ /// </summary>
85+ public ImmutableHashSet < string > DefaultFeeds { get ; init ; }
86+
87+ /// <summary>
88+ /// Gets the list of reachable default NuGet feeds.
89+ /// </summary>
90+ public ImmutableHashSet < string > ReachableDefaultFeeds => lazyReachableDefaultFeeds . Value ;
91+
7592 public FeedManager ( ILogger logger , IDotNet dotnet , IDependabotProxy ? dependabotProxy , IFileProvider fileProvider , IFeedManagerIO feedManagerIo )
7693 {
7794 this . logger = logger ;
7895 this . dotnet = dotnet ;
7996 this . fileProvider = fileProvider ;
8097 this . feedManagerIo = feedManagerIo ;
81- privateRegistryFeeds = dependabotProxy ? . RegistryURLs . ToImmutableHashSet ( ) ?? [ ] ;
98+ privateRegistryFeeds = dependabotProxy ? . RegistryURLs ?? [ ] ;
8299 HasPrivateRegistryFeeds = privateRegistryFeeds . Count > 0 ;
100+ privateRegistryBaseFeeds = dependabotProxy ? . RegistryBaseURLs ?? [ ] ;
101+ hasPrivateRegistryBaseFeeds = privateRegistryBaseFeeds . Count > 0 ;
102+
103+ DefaultFeeds = hasPrivateRegistryBaseFeeds
104+ ? privateRegistryBaseFeeds
105+ : [ PublicApiNugetOrgFeed ] ;
83106 emptyPackageDirectory = new DependencyDirectory ( "empty" , "empty package" , logger ) ;
84107
85108 lazyExplicitFeeds = new Lazy < ImmutableHashSet < string > > ( GetExplicitFeeds ) ;
@@ -96,13 +119,28 @@ public FeedManager(ILogger logger, IDotNet dotnet, IDependabotProxy? dependabotP
96119 var reachableFallbackFeeds = GetReachableFallbackNugetFeeds ( ) ;
97120 return reachableFallbackFeeds . ToImmutableHashSet ( ) ;
98121 } ) ;
122+ lazyReachableDefaultFeeds = new Lazy < ImmutableHashSet < string > > ( ( ) => CheckSpecifiedFeeds ( DefaultFeeds ) ) ;
99123 }
100124
101125 public FeedManager ( ILogger logger , IDotNet dotnet , IDependabotProxy ? dependabotProxy , IFileProvider fileProvider )
102126 : this ( logger , dotnet , dependabotProxy , fileProvider , new FeedManagerIO ( logger , dependabotProxy ) )
103127 {
104128 }
105129
130+ private bool IsNugetOrgFeed ( string url )
131+ {
132+ try
133+ {
134+ var uri = new Uri ( url ) ;
135+ return uri . Host . EndsWith ( PublicDotNugetOrg , StringComparison . InvariantCultureIgnoreCase ) ||
136+ string . Equals ( uri . Host , PublicNugetOrg , StringComparison . InvariantCultureIgnoreCase ) ;
137+ }
138+ catch ( UriFormatException )
139+ {
140+ return false ;
141+ }
142+ }
143+
106144 private IEnumerable < string > GetFeeds ( Func < IList < string > > getNugetFeeds )
107145 {
108146 var results = getNugetFeeds ( ) ;
@@ -124,18 +162,26 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
124162 continue ;
125163 }
126164
127- if ( ! string . IsNullOrWhiteSpace ( url ) )
165+ if ( hasPrivateRegistryBaseFeeds && IsNugetOrgFeed ( url ) )
128166 {
129- yield return url ;
167+ // Use private registry base feeds.
168+ foreach ( var feed in privateRegistryBaseFeeds )
169+ {
170+ logger . LogDebug ( $ "Using private registry base feed '{ feed } '.") ;
171+ yield return feed ;
172+ }
173+ continue ;
130174 }
175+
176+ yield return url ;
131177 }
132178 }
133179
134180 private IEnumerable < string > GetFeedsFromFolder ( string folderPath ) =>
135181 GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( folderPath ) ) ;
136182
137183 private IEnumerable < string > GetFeedsFromNugetConfig ( string nugetConfigPath ) =>
138- GetFeeds ( ( ) => dotnet . GetNugetFeeds ( nugetConfigPath ) ) ;
184+ GetFeeds ( ( ) => dotnet . GetNugetFeedsFromConfig ( nugetConfigPath ) ) ;
139185
140186 /// <summary>
141187 /// Constructs the NuGet sources argument for the restore command based on the given feeds.
@@ -266,22 +312,6 @@ private ImmutableHashSet<string> CheckSpecifiedFeeds(ImmutableHashSet<string> fe
266312 return reachable . Union ( feeds . Where ( feed => excludedFeeds . Contains ( feed ) ) ) . ToImmutableHashSet ( ) ;
267313 }
268314
269- /// <summary>
270- /// Return true if the default NuGet feed is reachable, false otherwise.
271- /// If the reachability check is disabled, this method will always return true.
272- /// </summary>
273- /// <returns>True if the default NuGet feed is reachable, false otherwise.</returns>
274- public bool IsDefaultFeedReachable ( )
275- {
276- if ( CheckNugetFeedResponsiveness )
277- {
278- var ( initialTimeout , tryCount ) = GetFeedRequestSettings ( isFallback : false ) ;
279- return feedManagerIo . IsFeedReachable ( PublicNugetOrgFeed , initialTimeout , tryCount ) ;
280- }
281-
282- return true ;
283- }
284-
285315 /// <summary>
286316 /// Tests which of the feeds given by <paramref name="feedsToCheck"/> are reachable.
287317 /// </summary>
@@ -315,8 +345,8 @@ private List<string> GetReachableFallbackNugetFeeds()
315345 var fallbackFeeds = EnvironmentVariables . GetURLs ( EnvironmentVariableNames . FallbackNugetFeeds ) . ToHashSet ( ) ;
316346 if ( fallbackFeeds . Count == 0 )
317347 {
318- fallbackFeeds . Add ( PublicNugetOrgFeed ) ;
319- logger . LogInfo ( $ "No fallback NuGet feeds specified. Adding default feed : { PublicNugetOrgFeed } ") ;
348+ fallbackFeeds . UnionWith ( DefaultFeeds ) ;
349+ logger . LogInfo ( $ "No fallback NuGet feeds specified. Adding default feeds : { string . Join ( ", " , DefaultFeeds . OrderBy ( f => f ) ) } ") ;
320350
321351 var shouldAddNugetConfigFeeds = EnvironmentVariables . GetBooleanOptOut ( EnvironmentVariableNames . AddNugetConfigFeedsToFallback ) ;
322352 logger . LogInfo ( $ "Adding feeds from nuget.config to fallback restore: { shouldAddNugetConfigFeeds } ") ;
@@ -329,6 +359,10 @@ private List<string> GetReachableFallbackNugetFeeds()
329359 logger . LogInfo ( $ "Using NuGet feeds from nuget.config files as fallback feeds: { string . Join ( ", " , ExplicitFeeds . OrderBy ( f => f ) ) } ") ;
330360 }
331361 }
362+ else
363+ {
364+ logger . LogInfo ( $ "Using fallback NuGet feeds from environment variable '{ EnvironmentVariableNames . FallbackNugetFeeds } '.") ;
365+ }
332366
333367 return GetReachableNuGetFeeds ( fallbackFeeds , isFallback : true ) ;
334368 }
0 commit comments