@@ -103,10 +103,11 @@ public HashSet<AssemblyLookupLocation> Restore()
103
103
compilationInfoContainer . CompilationInfos . Add ( ( "NuGet feed responsiveness checked" , checkNugetFeedResponsiveness ? "1" : "0" ) ) ;
104
104
105
105
HashSet < string > ? explicitFeeds = null ;
106
+ HashSet < string > ? allFeeds = null ;
106
107
107
108
try
108
109
{
109
- if ( checkNugetFeedResponsiveness && ! CheckFeeds ( out explicitFeeds ) )
110
+ if ( checkNugetFeedResponsiveness && ! CheckFeeds ( out explicitFeeds , out allFeeds ) )
110
111
{
111
112
// 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.
112
113
var unresponsiveMissingPackageLocation = DownloadMissingPackagesFromSpecificFeeds ( [ ] , explicitFeeds ) ;
@@ -156,7 +157,7 @@ public HashSet<AssemblyLookupLocation> Restore()
156
157
157
158
var restoredProjects = RestoreSolutions ( out var container ) ;
158
159
var projects = fileProvider . Projects . Except ( restoredProjects ) ;
159
- RestoreProjects ( projects , out var containers ) ;
160
+ RestoreProjects ( projects , allFeeds , out var containers ) ;
160
161
161
162
var dependencies = containers . Flatten ( container ) ;
162
163
@@ -260,8 +261,33 @@ private IEnumerable<string> RestoreSolutions(out DependencyContainer dependencie
260
261
/// Populates dependencies with the relative paths to the assets files generated by the restore.
261
262
/// </summary>
262
263
/// <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 )
264
265
{
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
+
265
291
var successCount = 0 ;
266
292
var nugetSourceFailures = 0 ;
267
293
ConcurrentBag < DependencyContainer > collectedDependencies = [ ] ;
@@ -276,7 +302,7 @@ private void RestoreProjects(IEnumerable<string> projects, out ConcurrentBag<Dep
276
302
foreach ( var project in projectGroup )
277
303
{
278
304
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 ) ) ;
280
306
assets . AddDependenciesRange ( res . AssetsFilePaths ) ;
281
307
lock ( sync )
282
308
{
@@ -680,10 +706,42 @@ private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount,
680
706
return ( timeoutMilliSeconds , tryCount ) ;
681
707
}
682
708
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 )
684
743
{
685
- logger . LogInfo ( "Checking Nuget feeds..." ) ;
686
- ( explicitFeeds , var allFeeds ) = GetAllFeeds ( ) ;
744
+ logger . LogInfo ( "Checking that Nuget feeds are reachable..." ) ;
687
745
688
746
var excludedFeeds = EnvironmentVariables . GetURLs ( EnvironmentVariableNames . ExcludedNugetFeedsFromResponsivenessCheck )
689
747
. ToHashSet ( ) ;
@@ -695,7 +753,7 @@ private bool CheckFeeds(out HashSet<string> explicitFeeds)
695
753
696
754
var ( initialTimeout , tryCount ) = GetFeedRequestSettings ( isFallback : false ) ;
697
755
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 ) ) ;
699
757
if ( ! allFeedsReachable )
700
758
{
701
759
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)
710
768
}
711
769
compilationInfoContainer . CompilationInfos . Add ( ( "All Nuget feeds reachable" , allFeedsReachable ? "1" : "0" ) ) ;
712
770
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
-
721
771
return allFeedsReachable ;
722
772
}
723
773
@@ -766,23 +816,33 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
766
816
}
767
817
768
818
// 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 =>
778
826
{
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
+ }
786
846
787
847
logger . LogInfo ( $ "Found { allFeeds . Count } Nuget feeds (with inherited ones) in nuget.config files: { string . Join ( ", " , allFeeds . OrderBy ( f => f ) ) } ") ;
788
848
0 commit comments