@@ -24,31 +24,79 @@ internal sealed partial class FeedManager : IDisposable
2424 private readonly FileProvider fileProvider ;
2525 private readonly DependabotProxy ? dependabotProxy ;
2626 private readonly DependencyDirectory emptyPackageDirectory ;
27+ private readonly ImmutableHashSet < string > privateRegistryFeeds ;
2728
28- public ImmutableHashSet < string > PrivateRegistryFeeds { get ; }
2929 public bool HasPrivateRegistryFeeds { get ; }
3030 public bool CheckNugetFeedResponsiveness { get ; } = EnvironmentVariables . GetBooleanOptOut ( EnvironmentVariableNames . CheckNugetFeedResponsiveness ) ;
3131
3232 private readonly Lazy < ImmutableHashSet < string > > lazyExplicitFeeds ;
33+
34+ /// <summary>
35+ /// Gets the list of NuGet feeds that are explicitly configured
36+ /// - NuGet configuration files.
37+ /// - Private package registries that are configured for C#.
38+ /// </summary>
3339 public ImmutableHashSet < string > ExplicitFeeds => lazyExplicitFeeds . Value ;
3440
3541 private readonly Lazy < ImmutableHashSet < string > > lazyAllFeeds ;
42+
43+ /// <summary>
44+ /// Gets the list of all NuGet feeds that are configured in the environment. That is
45+ /// - Explicit feeds
46+ /// - Inherited feeds from the machine and environment (if not explicitly disabled by a
47+ /// root directory NuGet configuration).
48+ /// </summary>
3649 public ImmutableHashSet < string > AllFeeds => lazyAllFeeds . Value ;
3750
51+ /// <summary>
52+ /// Gets the list of inherited NuGet feeds that are configured in the environment.
53+ /// </summary>
54+ public ImmutableHashSet < string > InheritedFeeds => AllFeeds . Except ( ExplicitFeeds ) . ToImmutableHashSet ( ) ;
55+
56+ private readonly Lazy < ( bool , ImmutableHashSet < string > ) > lazyReachableExplicitFeeds ;
57+
58+ /// <summary>
59+ /// Gets whether there was a timeout when checking the reachability of the explicitly configured NuGet feeds.
60+ /// </summary>
61+ public bool ExplicitFeedTimeout => lazyReachableExplicitFeeds . Value . Item1 ;
62+
63+ /// <summary>
64+ /// Gets the list of reachable NuGet feeds that are explicitly configured.
65+ /// </summary>
66+ public ImmutableHashSet < string > ReachableExplicitFeeds => lazyReachableExplicitFeeds . Value . Item2 ;
67+
68+ private readonly Lazy < ImmutableHashSet < string > > lazyReachableFeeds ;
69+ /// <summary>
70+ /// Gets the list of reachable NuGet feeds that are configured in the environment.
71+ /// </summary>
72+ public ImmutableHashSet < string > ReachableFeeds => lazyReachableFeeds . Value ;
73+
3874 public FeedManager ( ILogger logger , IDotNet dotnet , DependabotProxy ? dependabotProxy , FileProvider fileProvider )
3975 {
4076 this . logger = logger ;
4177 this . dotnet = dotnet ;
4278 this . dependabotProxy = dependabotProxy ;
4379 this . fileProvider = fileProvider ;
44- PrivateRegistryFeeds = dependabotProxy ? . RegistryURLs . ToImmutableHashSet ( ) ?? [ ] ;
45- HasPrivateRegistryFeeds = PrivateRegistryFeeds . Count > 0 ;
80+ privateRegistryFeeds = dependabotProxy ? . RegistryURLs . ToImmutableHashSet ( ) ?? [ ] ;
81+ HasPrivateRegistryFeeds = privateRegistryFeeds . Count > 0 ;
4682 emptyPackageDirectory = new DependencyDirectory ( "empty" , "empty package" , logger ) ;
4783
4884 lazyExplicitFeeds = new Lazy < ImmutableHashSet < string > > ( GetExplicitFeeds ) ;
4985 lazyAllFeeds = new Lazy < ImmutableHashSet < string > > ( GetAllFeeds ) ;
86+ lazyReachableExplicitFeeds = new Lazy < ( bool , ImmutableHashSet < string > ) > ( ( ) =>
87+ {
88+ var timeout = CheckSpecifiedFeeds ( ExplicitFeeds , out var reachableFeeds ) ;
89+ return ( timeout , reachableFeeds ) ;
90+ } ) ;
91+ lazyReachableFeeds = new Lazy < ImmutableHashSet < string > > ( ( ) =>
92+ {
93+ // Inherited feeds should only be used, if they are indeed reachable (as they may be environment specific).
94+ CheckSpecifiedFeeds ( InheritedFeeds , out var reachableInheritedFeeds ) ;
95+ return ReachableExplicitFeeds . Union ( reachableInheritedFeeds ) . ToImmutableHashSet ( ) ;
96+ } ) ;
5097 }
5198
99+
52100 private string ? GetDirectoryName ( string path )
53101 {
54102 try
@@ -124,15 +172,15 @@ public string FeedsToRestoreArgument(IEnumerable<string> feeds, string sourceArg
124172 /// <param name="path">Path to project/solution</param>
125173 /// <param name="reachableFeeds">The set of reachable NuGet feeds.</param>
126174 /// <returns>The list of NuGet feeds to use for this restore.</returns>
127- public IEnumerable < string > FeedsToUse ( string path , HashSet < string > reachableFeeds )
175+ public IEnumerable < string > FeedsToUse ( string path , ImmutableHashSet < string > reachableFeeds )
128176 {
129177 // Find the path specific feeds.
130178 var folder = GetDirectoryName ( path ) ;
131179 var feedsToConsider = folder is not null ? GetFeedsFromFolder ( folder ) . ToHashSet ( ) : new HashSet < string > ( ) ;
132180
133181 if ( HasPrivateRegistryFeeds )
134182 {
135- feedsToConsider . UnionWith ( PrivateRegistryFeeds ) ;
183+ feedsToConsider . UnionWith ( privateRegistryFeeds ) ;
136184 }
137185
138186 var feedsToUse = CheckNugetFeedResponsiveness
@@ -150,7 +198,7 @@ public IEnumerable<string> FeedsToUse(string path, HashSet<string> reachableFeed
150198 /// <param name="path">Path to project/solution</param>
151199 /// <param name="reachableFeeds">The set of reachable NuGet feeds.</param>
152200 /// <returns>A string representing the NuGet sources argument for the restore command.</returns>
153- public string ? MakeDotnetRestoreSourcesArgument ( string path , HashSet < string > reachableFeeds )
201+ public string ? MakeDotnetRestoreSourcesArgument ( string path , ImmutableHashSet < string > reachableFeeds )
154202 {
155203 // Do not construct a set of explicit NuGet sources to use for restore.
156204 if ( ! CheckNugetFeedResponsiveness && ! HasPrivateRegistryFeeds )
@@ -280,7 +328,7 @@ private HashSet<string> GetExcludedFeeds()
280328 /// True if there is a timeout when trying to reach the feeds (excluding any feeds that are configured
281329 /// to be excluded from the check) or false otherwise.
282330 /// </returns>
283- public bool CheckSpecifiedFeeds ( ImmutableHashSet < string > feeds , out HashSet < string > reachableFeeds )
331+ private bool CheckSpecifiedFeeds ( ImmutableHashSet < string > feeds , out ImmutableHashSet < string > reachableFeeds )
284332 {
285333 // Exclude any feeds from the feed check that are configured by the corresponding environment variable.
286334 // These feeds are always assumed to be reachable.
@@ -296,10 +344,10 @@ public bool CheckSpecifiedFeeds(ImmutableHashSet<string> feeds, out HashSet<stri
296344 return true ;
297345 } ) . ToHashSet ( ) ;
298346
299- reachableFeeds = GetReachableNuGetFeeds ( feedsToCheck , isFallback : false , out var isTimeout ) . ToHashSet ( ) ;
347+ var reachable = GetReachableNuGetFeeds ( feedsToCheck , isFallback : false , out var isTimeout ) ;
300348
301349 // Always consider feeds excluded for the reachability check as reachable.
302- reachableFeeds . UnionWith ( feeds . Where ( feed => excludedFeeds . Contains ( feed ) ) ) ;
350+ reachableFeeds = reachable . Union ( feeds . Where ( feed => excludedFeeds . Contains ( feed ) ) ) . ToImmutableHashSet ( ) ;
303351
304352 return isTimeout ;
305353 }
@@ -396,8 +444,8 @@ private ImmutableHashSet<string> GetExplicitFeeds()
396444 // in addition to the ones that are configured in `nuget.config` files.
397445 if ( HasPrivateRegistryFeeds )
398446 {
399- logger . LogInfo ( $ "Found { PrivateRegistryFeeds . Count } private registry feeds configured for C#: { string . Join ( ", " , PrivateRegistryFeeds . OrderBy ( f => f ) ) } ") ;
400- explicitFeeds . UnionWith ( PrivateRegistryFeeds ) ;
447+ logger . LogInfo ( $ "Found { privateRegistryFeeds . Count } private registry feeds configured for C#: { string . Join ( ", " , privateRegistryFeeds . OrderBy ( f => f ) ) } ") ;
448+ explicitFeeds . UnionWith ( privateRegistryFeeds ) ;
401449 }
402450
403451 return explicitFeeds . ToImmutableHashSet ( ) ;
0 commit comments