@@ -28,15 +28,13 @@ internal sealed partial class NugetPackageRestorer : IDisposable
2828 private readonly IDiagnosticsWriter diagnosticsWriter ;
2929 private readonly DependencyDirectory legacyPackageDirectory ;
3030 private readonly DependencyDirectory missingPackageDirectory ;
31- private readonly DependencyDirectory emptyPackageDirectory ;
3231 private readonly ILogger logger ;
3332 private readonly ICompilationInfoContainer compilationInfoContainer ;
34- private readonly bool checkNugetFeedResponsiveness = EnvironmentVariables . GetBooleanOptOut ( EnvironmentVariableNames . CheckNugetFeedResponsiveness ) ;
35- private readonly ImmutableHashSet < string > privateRegistryFeeds ;
36- private readonly bool hasPrivateRegistryFeeds ;
33+ private readonly FeedManager feedManager ;
3734
3835 public DependencyDirectory PackageDirectory { get ; }
3936
37+
4038 public NugetPackageRestorer (
4139 FileProvider fileProvider ,
4240 FileContent fileContent ,
@@ -50,16 +48,14 @@ public NugetPackageRestorer(
5048 this . fileContent = fileContent ;
5149 this . dotnet = dotnet ;
5250 this . dependabotProxy = dependabotProxy ;
53- this . privateRegistryFeeds = dependabotProxy ? . RegistryURLs . ToImmutableHashSet ( ) ?? [ ] ;
54- this . hasPrivateRegistryFeeds = privateRegistryFeeds . Count > 0 ;
5551 this . diagnosticsWriter = diagnosticsWriter ;
5652 this . logger = logger ;
5753 this . compilationInfoContainer = compilationInfoContainer ;
5854
5955 PackageDirectory = new DependencyDirectory ( "packages" , "package" , logger ) ;
6056 legacyPackageDirectory = new DependencyDirectory ( "legacypackages" , "legacy package" , logger ) ;
6157 missingPackageDirectory = new DependencyDirectory ( "missingpackages" , "missing package" , logger ) ;
62- emptyPackageDirectory = new DependencyDirectory ( "empty" , "empty package" , logger ) ;
58+ feedManager = new FeedManager ( logger , dotnet , dependabotProxy ) ;
6359 }
6460
6561 public string ? TryRestore ( string package )
@@ -118,8 +114,8 @@ public DirectoryInfo[] GetOrderedPackageVersionSubDirectories(string packagePath
118114 public HashSet < AssemblyLookupLocation > Restore ( )
119115 {
120116 var assemblyLookupLocations = new HashSet < AssemblyLookupLocation > ( ) ;
121- logger . LogInfo ( $ "Checking NuGet feed responsiveness: { checkNugetFeedResponsiveness } ") ;
122- compilationInfoContainer . CompilationInfos . Add ( ( "NuGet feed responsiveness checked" , checkNugetFeedResponsiveness ? "1" : "0" ) ) ;
117+ logger . LogInfo ( $ "Checking NuGet feed responsiveness: { feedManager . CheckNugetFeedResponsiveness } ") ;
118+ compilationInfoContainer . CompilationInfos . Add ( ( "NuGet feed responsiveness checked" , feedManager . CheckNugetFeedResponsiveness ? "1" : "0" ) ) ;
123119
124120 HashSet < string > explicitFeeds = [ ] ;
125121 HashSet < string > reachableFeeds = [ ] ;
@@ -131,7 +127,7 @@ public HashSet<AssemblyLookupLocation> Restore()
131127 // (including inherited ones) from other locations on the host outside of the working directory.
132128 ( explicitFeeds , var allFeeds ) = GetAllFeeds ( ) ;
133129
134- if ( checkNugetFeedResponsiveness )
130+ if ( feedManager . CheckNugetFeedResponsiveness )
135131 {
136132 var inheritedFeeds = allFeeds . Except ( explicitFeeds ) . ToHashSet ( ) ;
137133
@@ -215,7 +211,7 @@ public HashSet<AssemblyLookupLocation> Restore()
215211
216212 var usedPackageNames = GetAllUsedPackageDirNames ( dependencies ) ;
217213
218- var missingPackageLocation = checkNugetFeedResponsiveness
214+ var missingPackageLocation = feedManager . CheckNugetFeedResponsiveness
219215 ? DownloadMissingPackagesFromSpecificFeeds ( usedPackageNames , explicitFeeds )
220216 : DownloadMissingPackages ( usedPackageNames ) ;
221217
@@ -264,7 +260,7 @@ private List<string> GetReachableNuGetFeeds(HashSet<string> feedsToCheck, bool i
264260
265261 private bool IsDefaultFeedReachable ( )
266262 {
267- if ( checkNugetFeedResponsiveness )
263+ if ( feedManager . CheckNugetFeedResponsiveness )
268264 {
269265 var ( initialTimeout , tryCount ) = GetFeedRequestSettings ( isFallback : false ) ;
270266 return IsFeedReachable ( PublicNugetOrgFeed , initialTimeout , tryCount , out var _ ) ;
@@ -321,7 +317,7 @@ private IEnumerable<string> RestoreSolutions(HashSet<string> reachableFeeds, out
321317 var projects = fileProvider . Solutions . SelectMany ( solution =>
322318 {
323319 logger . LogInfo ( $ "Restoring solution { solution } ...") ;
324- var nugetSources = MakeRestoreSourcesArgument ( solution , reachableFeeds ) ;
320+ var nugetSources = feedManager . MakeRestoreSourcesArgument ( solution , reachableFeeds ) ;
325321 var res = dotnet . Restore ( new ( solution , PackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : true , NugetSources : nugetSources , TargetWindows : isWindows ) ) ;
326322 if ( res . Success )
327323 {
@@ -346,57 +342,6 @@ private IEnumerable<string> RestoreSolutions(HashSet<string> reachableFeeds, out
346342 return projects ;
347343 }
348344
349- private string FeedsToRestoreArgument ( IEnumerable < string > feeds )
350- {
351- // If there are no feeds, we want to override any default feeds that `dotnet restore` would use by passing a dummy source argument.
352- if ( ! feeds . Any ( ) )
353- {
354- return $ " -s \" { emptyPackageDirectory . DirInfo . FullName } \" ";
355- }
356-
357- // Add package sources. If any are present, they override all sources specified in
358- // the configuration file(s).
359- var feedArgs = new StringBuilder ( ) ;
360- foreach ( var feed in feeds )
361- {
362- feedArgs . Append ( $ " -s \" { feed } \" ") ;
363- }
364-
365- return feedArgs . ToString ( ) ;
366- }
367-
368- /// <summary>
369- /// Constructs the list of NuGet sources to use for this restore.
370- /// (1) Use the feeds we get from `dotnet nuget list source`
371- /// (2) Use private registries, if they are configured
372- /// </summary>
373- /// <param name="path">Path to project/solution</param>
374- /// <param name="reachableFeeds">The set of reachable NuGet feeds.</param>
375- /// <returns>A string representing the NuGet sources argument for the restore command.</returns>
376- private string ? MakeRestoreSourcesArgument ( string path , HashSet < string > reachableFeeds )
377- {
378- // Do not construct an set of explicit NuGet sources to use for restore.
379- if ( ! checkNugetFeedResponsiveness && ! hasPrivateRegistryFeeds )
380- {
381- return null ;
382- }
383-
384- // Find the path specific feeds.
385- var folder = GetDirectoryName ( path ) ;
386- var feedsToConsider = folder is not null ? GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( folder ) ) . ToHashSet ( ) : [ ] ;
387-
388- if ( hasPrivateRegistryFeeds )
389- {
390- feedsToConsider . UnionWith ( privateRegistryFeeds ) ;
391- }
392-
393- var feedsToUse = checkNugetFeedResponsiveness
394- ? feedsToConsider . Where ( reachableFeeds . Contains )
395- : feedsToConsider ;
396-
397- return FeedsToRestoreArgument ( feedsToUse ) ;
398- }
399-
400345 /// <summary>
401346 /// Executes `dotnet restore` on all projects in projects.
402347 /// This is done in parallel for performance reasons.
@@ -421,7 +366,7 @@ private void RestoreProjects(IEnumerable<string> projects, HashSet<string> reach
421366 foreach ( var project in projectGroup )
422367 {
423368 logger . LogInfo ( $ "Restoring project { project } ...") ;
424- var nugetSources = MakeRestoreSourcesArgument ( project , reachableFeeds ) ;
369+ var nugetSources = feedManager . MakeRestoreSourcesArgument ( project , reachableFeeds ) ;
425370 var res = dotnet . Restore ( new ( project , PackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : true , NugetSources : nugetSources , TargetWindows : isWindows ) ) ;
426371 assets . AddDependenciesRange ( res . AssetsFilePaths ) ;
427372 lock ( sync )
@@ -899,47 +844,6 @@ private void EmitUnreachableFeedsDiagnostics(bool allFeedsReachable)
899844 compilationInfoContainer . CompilationInfos . Add ( ( "All NuGet feeds reachable" , allFeedsReachable ? "1" : "0" ) ) ;
900845 }
901846
902- private IEnumerable < string > GetFeeds ( Func < IList < string > > getNugetFeeds )
903- {
904- var results = getNugetFeeds ( ) ;
905- var regex = EnabledNugetFeed ( ) ;
906- foreach ( var result in results )
907- {
908- var match = regex . Match ( result ) ;
909- if ( ! match . Success )
910- {
911- logger . LogError ( $ "Failed to parse feed from '{ result } '") ;
912- continue ;
913- }
914-
915- var url = match . Groups [ 1 ] . Value ;
916- if ( ! url . StartsWith ( "https://" , StringComparison . InvariantCultureIgnoreCase ) &&
917- ! url . StartsWith ( "http://" , StringComparison . InvariantCultureIgnoreCase ) )
918- {
919- logger . LogInfo ( $ "Skipping feed '{ url } ' as it is not a valid URL.") ;
920- continue ;
921- }
922-
923- if ( ! string . IsNullOrWhiteSpace ( url ) )
924- {
925- yield return url ;
926- }
927- }
928- }
929-
930- private string ? GetDirectoryName ( string path )
931- {
932- try
933- {
934- return new FileInfo ( path ) . Directory ? . FullName ;
935- }
936- catch ( Exception exc )
937- {
938- logger . LogWarning ( $ "Failed to get directory of '{ path } ': { exc } ") ;
939- }
940- return null ;
941- }
942-
943847 private ( HashSet < string > explicitFeeds , HashSet < string > allFeeds ) GetAllFeeds ( )
944848 {
945849 var nugetConfigs = fileProvider . NugetConfigs ;
@@ -981,7 +885,7 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
981885
982886 // Find feeds that are explicitly configured in the NuGet configuration files that we found.
983887 var explicitFeeds = nugetConfigs
984- . SelectMany ( config => GetFeeds ( ( ) => dotnet . GetNugetFeeds ( config ) ) )
888+ . SelectMany ( config => feedManager . GetFeedsFromNugetConfig ( config ) )
985889 . ToHashSet ( ) ;
986890
987891 if ( explicitFeeds . Count > 0 )
@@ -995,10 +899,10 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
995899
996900 // If private package registries are configured for C#, then consider those
997901 // in addition to the ones that are configured in `nuget.config` files.
998- if ( hasPrivateRegistryFeeds )
902+ if ( feedManager . HasPrivateRegistryFeeds )
999903 {
1000- logger . LogInfo ( $ "Found { privateRegistryFeeds . Count } private registry feeds configured for C#: { string . Join ( ", " , privateRegistryFeeds . OrderBy ( f => f ) ) } ") ;
1001- explicitFeeds . UnionWith ( privateRegistryFeeds ) ;
904+ logger . LogInfo ( $ "Found { feedManager . PrivateRegistryFeeds . Count } private registry feeds configured for C#: { string . Join ( ", " , feedManager . PrivateRegistryFeeds . OrderBy ( f => f ) ) } ") ;
905+ explicitFeeds . UnionWith ( feedManager . PrivateRegistryFeeds ) ;
1002906 }
1003907
1004908 HashSet < string > allFeeds = [ ] ;
@@ -1008,15 +912,15 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
1008912
1009913 // Obtain the list of feeds from the root source directory.
1010914 // If a NuGet file is present it will be respected, otherwise we will just get the machine/environment specific feeds.
1011- var nugetFeedsFromRoot = GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( fileProvider . SourceDir . FullName ) ) ;
915+ var nugetFeedsFromRoot = feedManager . GetFeedsFromFolder ( fileProvider . SourceDir . FullName ) ;
1012916 allFeeds . UnionWith ( nugetFeedsFromRoot ) ;
1013917
1014918 if ( nugetConfigs . Count > 0 )
1015919 {
1016920 var nugetConfigFeeds = nugetConfigs
1017- . Select ( GetDirectoryName )
921+ . Select ( path => FileUtils . GetDirectoryName ( path , logger ) )
1018922 . Where ( folder => folder != null )
1019- . SelectMany ( folder => GetFeeds ( ( ) => dotnet . GetNugetFeedsFromFolder ( folder ! ) ) )
923+ . SelectMany ( folder => feedManager . GetFeedsFromFolder ( folder ! ) )
1020924 . ToHashSet ( ) ;
1021925
1022926 allFeeds . UnionWith ( nugetConfigFeeds ) ;
@@ -1036,15 +940,12 @@ private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
1036940 [ GeneratedRegex ( @"^(.+)\.(\d+\.\d+\.\d+(-(.+))?)$" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
1037941 private static partial Regex LegacyNugetPackage ( ) ;
1038942
1039- [ GeneratedRegex ( @"^E\s(.*)$" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
1040- private static partial Regex EnabledNugetFeed ( ) ;
1041-
1042943 public void Dispose ( )
1043944 {
1044945 PackageDirectory ? . Dispose ( ) ;
1045946 legacyPackageDirectory ? . Dispose ( ) ;
1046947 missingPackageDirectory ? . Dispose ( ) ;
1047- emptyPackageDirectory ? . Dispose ( ) ;
948+ feedManager . Dispose ( ) ;
1048949 }
1049950
1050951 /// <summary>
0 commit comments