@@ -103,10 +103,11 @@ public HashSet<AssemblyLookupLocation> Restore()
103103 compilationInfoContainer . CompilationInfos . Add ( ( "NuGet feed responsiveness checked" , checkNugetFeedResponsiveness ? "1" : "0" ) ) ;
104104
105105 HashSet < string > ? explicitFeeds = null ;
106+ HashSet < string > ? allFeeds = null ;
106107
107108 try
108109 {
109- if ( checkNugetFeedResponsiveness && ! CheckFeeds ( out explicitFeeds ) )
110+ if ( checkNugetFeedResponsiveness && ! CheckFeeds ( out explicitFeeds , out allFeeds ) )
110111 {
111112 // todo: we could also check the reachability of the inherited nuget feeds, but to use those in the fallback we would need to handle authentication too.
112113 var unresponsiveMissingPackageLocation = DownloadMissingPackagesFromSpecificFeeds ( [ ] , explicitFeeds ) ;
@@ -156,7 +157,7 @@ public HashSet<AssemblyLookupLocation> Restore()
156157
157158 var restoredProjects = RestoreSolutions ( out var container ) ;
158159 var projects = fileProvider . Projects . Except ( restoredProjects ) ;
159- RestoreProjects ( projects , out var containers ) ;
160+ RestoreProjects ( projects , allFeeds , out var containers ) ;
160161
161162 var dependencies = containers . Flatten ( container ) ;
162163
@@ -260,8 +261,33 @@ private IEnumerable<string> RestoreSolutions(out DependencyContainer dependencie
260261 /// Populates dependencies with the relative paths to the assets files generated by the restore.
261262 /// </summary>
262263 /// <param name="projects">A list of paths to project files.</param>
263- private void RestoreProjects ( IEnumerable < string > projects , out ConcurrentBag < DependencyContainer > dependencies )
264+ private void RestoreProjects ( IEnumerable < string > projects , HashSet < string > ? configuredSources , out ConcurrentBag < DependencyContainer > dependencies )
264265 {
266+ // Conservatively, we only set this to a non-null value if a Dependabot proxy is enabled.
267+ // This ensures that we continue to get the old behaviour where feeds are taken from
268+ // `nuget.config` files instead of the command-line arguments.
269+ string ? extraArgs = null ;
270+
271+ if ( this . dependabotProxy is not null )
272+ {
273+ // If the Dependabot proxy is configured, then our main goal is to make `dotnet` aware
274+ // of the private registry feeds. However, since providing them as command-line arguments
275+ // to `dotnet` ignores other feeds that may be configured, we also need to add the feeds
276+ // we have discovered from analysing `nuget.config` files.
277+ var sources = configuredSources ?? new ( ) ;
278+ this . dependabotProxy . RegistryURLs . ForEach ( url => sources . Add ( url ) ) ;
279+
280+ // Add package sources. If any are present, they override all sources specified in
281+ // the configuration file(s).
282+ var feedArgs = new StringBuilder ( ) ;
283+ foreach ( string source in sources )
284+ {
285+ feedArgs . Append ( $ " -s { source } ") ;
286+ }
287+
288+ extraArgs = feedArgs . ToString ( ) ;
289+ }
290+
265291 var successCount = 0 ;
266292 var nugetSourceFailures = 0 ;
267293 ConcurrentBag < DependencyContainer > collectedDependencies = [ ] ;
@@ -276,7 +302,7 @@ private void RestoreProjects(IEnumerable<string> projects, out ConcurrentBag<Dep
276302 foreach ( var project in projectGroup )
277303 {
278304 logger . LogInfo ( $ "Restoring project { project } ...") ;
279- var res = dotnet . Restore ( new ( project , PackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : true , TargetWindows : isWindows ) ) ;
305+ var res = dotnet . Restore ( new ( project , PackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : true , extraArgs , TargetWindows : isWindows ) ) ;
280306 assets . AddDependenciesRange ( res . AssetsFilePaths ) ;
281307 lock ( sync )
282308 {
@@ -680,10 +706,42 @@ private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount,
680706 return ( timeoutMilliSeconds , tryCount ) ;
681707 }
682708
683- private bool CheckFeeds ( out HashSet < string > explicitFeeds )
709+ /// <summary>
710+ /// Checks that we can connect to all Nuget feeds that are explicitly configured in configuration files
711+ /// as well as any private package registry feeds that are configured.
712+ /// </summary>
713+ /// <param name="explicitFeeds">Outputs the set of explicit feeds.</param>
714+ /// <param name="allFeeds">Outputs the set of all feeds (explicit and inherited).</param>
715+ /// <returns>True if all feeds are reachable or false otherwise.</returns>
716+ private bool CheckFeeds ( out HashSet < string > explicitFeeds , out HashSet < string > allFeeds )
717+ {
718+ ( explicitFeeds , allFeeds ) = GetAllFeeds ( ) ;
719+ HashSet < string > feedsToCheck = explicitFeeds ;
720+
721+ // If private package registries are configured for C#, then check those
722+ // in addition to the ones that are configured in `nuget.config` files.
723+ this . dependabotProxy ? . RegistryURLs . ForEach ( url => feedsToCheck . Add ( url ) ) ;
724+
725+ var allFeedsReachable = this . CheckSpecifiedFeeds ( feedsToCheck ) ;
726+
727+ var inheritedFeeds = allFeeds . Except ( explicitFeeds ) . ToHashSet ( ) ;
728+ if ( inheritedFeeds . Count > 0 )
729+ {
730+ logger . LogInfo ( $ "Inherited Nuget feeds (not checked for reachability): { string . Join ( ", " , inheritedFeeds . OrderBy ( f => f ) ) } ") ;
731+ compilationInfoContainer . CompilationInfos . Add ( ( "Inherited Nuget feed count" , inheritedFeeds . Count . ToString ( ) ) ) ;
732+ }
733+
734+ return allFeedsReachable ;
735+ }
736+
737+ /// <summary>
738+ /// Checks that we can connect to the specified Nuget feeds.
739+ /// </summary>
740+ /// <param name="feeds">The set of package feeds to check.</param>
741+ /// <returns>True if all feeds are reachable or false otherwise.</returns>
742+ private bool CheckSpecifiedFeeds ( HashSet < string > feeds )
684743 {
685- logger . LogInfo ( "Checking Nuget feeds..." ) ;
686- ( explicitFeeds , var allFeeds ) = GetAllFeeds ( ) ;
744+ logger . LogInfo ( "Checking that Nuget feeds are reachable..." ) ;
687745
688746 var excludedFeeds = EnvironmentVariables . GetURLs ( EnvironmentVariableNames . ExcludedNugetFeedsFromResponsivenessCheck )
689747 . ToHashSet ( ) ;
@@ -695,7 +753,7 @@ private bool CheckFeeds(out HashSet<string> explicitFeeds)
695753
696754 var ( initialTimeout , tryCount ) = GetFeedRequestSettings ( isFallback : false ) ;
697755
698- var allFeedsReachable = explicitFeeds . All ( feed => excludedFeeds . Contains ( feed ) || IsFeedReachable ( feed , initialTimeout , tryCount ) ) ;
756+ var allFeedsReachable = feeds . All ( feed => excludedFeeds . Contains ( feed ) || IsFeedReachable ( feed , initialTimeout , tryCount ) ) ;
699757 if ( ! allFeedsReachable )
700758 {
701759 logger . LogWarning ( "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis." ) ;
@@ -710,14 +768,6 @@ private bool CheckFeeds(out HashSet<string> explicitFeeds)
710768 }
711769 compilationInfoContainer . CompilationInfos . Add ( ( "All Nuget feeds reachable" , allFeedsReachable ? "1" : "0" ) ) ;
712770
713-
714- var inheritedFeeds = allFeeds . Except ( explicitFeeds ) . ToHashSet ( ) ;
715- if ( inheritedFeeds . Count > 0 )
716- {
717- logger . LogInfo ( $ "Inherited Nuget feeds (not checked for reachability): { string . Join ( ", " , inheritedFeeds . OrderBy ( f => f ) ) } ") ;
718- compilationInfoContainer . CompilationInfos . Add ( ( "Inherited Nuget feed count" , inheritedFeeds . Count . ToString ( ) ) ) ;
719- }
720-
721771 return allFeedsReachable ;
722772 }
723773
@@ -766,23 +816,33 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
766816 }
767817
768818 // todo: this could be improved.
769- // We don't have to get the feeds from each of the folders from below, it would be enought to check the folders that recursively contain the others.
770- var allFeeds = nugetConfigs
771- . Select ( config =>
772- {
773- try
774- {
775- return new FileInfo ( config ) . Directory ? . FullName ;
776- }
777- catch ( Exception exc )
819+ HashSet < string > ? allFeeds = null ;
820+
821+ if ( nugetConfigs . Count > 0 )
822+ {
823+ // We don't have to get the feeds from each of the folders from below, it would be enought to check the folders that recursively contain the others.
824+ allFeeds = nugetConfigs
825+ . Select ( config =>
778826 {
779- logger . LogWarning ( $ "Failed to get directory of '{ config } ': { exc } ") ;
780- }
781- return null ;
782- } )
783- . Where ( folder => folder != null )
784- . SelectMany ( folder => GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( folder ! ) ) )
785- . ToHashSet ( ) ;
827+ try
828+ {
829+ return new FileInfo ( config ) . Directory ? . FullName ;
830+ }
831+ catch ( Exception exc )
832+ {
833+ logger . LogWarning ( $ "Failed to get directory of '{ config } ': { exc } ") ;
834+ }
835+ return null ;
836+ } )
837+ . Where ( folder => folder != null )
838+ . SelectMany ( folder => GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( folder ! ) ) )
839+ . ToHashSet ( ) ;
840+ }
841+ else
842+ {
843+ // If we haven't found any `nuget.config` files, then obtain a list of feeds from the root source directory.
844+ allFeeds = GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( this . fileProvider . SourceDir . FullName ) ) . ToHashSet ( ) ;
845+ }
786846
787847 logger . LogInfo ( $ "Found { allFeeds . Count } Nuget feeds (with inherited ones) in nuget.config files: { string . Join ( ", " , allFeeds . OrderBy ( f => f ) ) } ") ;
788848
0 commit comments