@@ -40,9 +40,9 @@ public class NuGetPackageManager
4040
4141 public Configuration . ISettings Settings { get ; }
4242
43- private IDictionary < string , bool > _buildIntegratedProjectsUpdateDict ;
43+ private HashSet < string > _buildIntegratedProjectsUpdateSet ;
4444
45- private DependencyGraphSpec _buildIntegratedProjectsCache ;
45+ private DependencyGraphSpec _buildIntegratedProjectsCache ;
4646
4747 private RestoreCommandProvidersCache _restoreProviderCache ;
4848
@@ -2054,52 +2054,90 @@ public async Task ExecuteNuGetProjectActionsAsync(IEnumerable<NuGetProject> nuGe
20542054 {
20552055 var projects = nuGetProjects . ToList ( ) ;
20562056
2057- // find out build integrated projects so that we can arrange them in reverse dependency order
2057+ // find out build integrated projects
20582058 var buildIntegratedProjectsToUpdate = projects . OfType < BuildIntegratedNuGetProject > ( ) . ToList ( ) ;
20592059
2060- // order won't matter for other type of projects so just add rest of the projects in result
2061- var sortedProjectsToUpdate = projects . Except ( buildIntegratedProjectsToUpdate ) . ToList ( ) ;
2062-
2063- if ( buildIntegratedProjectsToUpdate . Count > 0 )
2060+ if ( buildIntegratedProjectsToUpdate . Any ( ) )
20642061 {
2065- var logger = new ProjectContextLogger ( nuGetProjectContext ) ;
2066- var referenceContext = new DependencyGraphCacheContext ( logger , Settings ) ;
2067- _buildIntegratedProjectsUpdateDict = new Dictionary < string , bool > ( StringComparer . OrdinalIgnoreCase ) ;
2068-
2069- var projectUniqueNamesForBuildIntToUpdate
2070- = buildIntegratedProjectsToUpdate . ToDictionary ( ( project ) => project . MSBuildProjectPath ) ;
2071-
2072- var dgFile = await DependencyGraphRestoreUtility . GetSolutionRestoreSpec ( SolutionManager , referenceContext ) ;
2073- _buildIntegratedProjectsCache = dgFile ;
2074- var allSortedProjects = DependencyGraphSpec . SortPackagesByDependencyOrder ( dgFile . Projects ) ;
2062+ _buildIntegratedProjectsUpdateSet = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
2063+ _buildIntegratedProjectsUpdateSet . AddRange (
2064+ buildIntegratedProjectsToUpdate . Select ( child => child . MSBuildProjectPath ) ) ;
20752065
2076- foreach ( var projectUniqueName in allSortedProjects . Select ( e => e . RestoreMetadata . ProjectUniqueName ) )
2066+ // execute buildintegrated nuget project actions, if any.
2067+ foreach ( var project in buildIntegratedProjectsToUpdate )
20772068 {
2078- BuildIntegratedNuGetProject project ;
2079- if ( projectUniqueNamesForBuildIntToUpdate . TryGetValue ( projectUniqueName , out project ) )
2080- {
2081- sortedProjectsToUpdate . Add ( project ) ;
2082- }
2083- }
2069+ var nugetActions = nuGetProjectActions . Where ( action => action . Project . Equals ( project ) ) ;
20842070
2085- // cache these projects which will be used to avoid duplicate restore as part of parent projects
2086- _buildIntegratedProjectsUpdateDict . AddRange (
2087- buildIntegratedProjectsToUpdate . Select ( child => new KeyValuePair < string , bool > ( child . MSBuildProjectPath , false ) ) ) ;
2071+ await ExecuteBuildIntegratedNuGetProjectActionsAsync ( project , nugetActions , nuGetProjectContext , token ) ;
2072+ }
20882073 }
20892074
2090- // execute all nuget project actions
2091- foreach ( var project in sortedProjectsToUpdate )
2075+ var otherProjects = projects . Except ( buildIntegratedProjectsToUpdate ) . ToList ( ) ;
2076+
2077+ // execute non-buildintegrated nuget project actions
2078+ foreach ( var project in otherProjects )
20922079 {
20932080 var nugetActions = nuGetProjectActions . Where ( action => action . Project . Equals ( project ) ) ;
2081+
20942082 await ExecuteNuGetProjectActionsAsync ( project , nugetActions , nuGetProjectContext , sourceCacheContext , token ) ;
20952083 }
20962084
20972085 // clear cache which could temper with other updates
2098- _buildIntegratedProjectsUpdateDict ? . Clear ( ) ;
2099- _buildIntegratedProjectsCache = null ;
21002086 _restoreProviderCache = null ;
21012087 }
21022088
2089+ /// <summary>
2090+ /// Executes the list of <paramref name="nuGetProjectActions" /> on <paramref name="buildIntegratedProject" />
2091+ /// </summary>
2092+ /// <param name="buildIntegratedProject"></param>
2093+ /// <param name="nuGetProjectActions"></param>
2094+ /// <param name="nuGetProjectContext"></param>
2095+ /// <param name="token"></param>
2096+ /// <returns></returns>
2097+ internal async Task ExecuteBuildIntegratedNuGetProjectActionsAsync ( BuildIntegratedNuGetProject buildIntegratedProject ,
2098+ IEnumerable < NuGetProjectAction > nuGetProjectActions ,
2099+ INuGetProjectContext nuGetProjectContext ,
2100+ CancellationToken token )
2101+ {
2102+ if ( buildIntegratedProject == null )
2103+ {
2104+ throw new ArgumentNullException ( nameof ( buildIntegratedProject ) ) ;
2105+ }
2106+
2107+ if ( nuGetProjectActions == null )
2108+ {
2109+ throw new ArgumentNullException ( nameof ( nuGetProjectActions ) ) ;
2110+ }
2111+
2112+ if ( nuGetProjectContext == null )
2113+ {
2114+ throw new ArgumentNullException ( nameof ( nuGetProjectContext ) ) ;
2115+ }
2116+
2117+ token . ThrowIfCancellationRequested ( ) ;
2118+
2119+ var stopWatch = Stopwatch . StartNew ( ) ;
2120+
2121+ // DNU: Find the closure before executing the actions
2122+ await ExecuteBuildIntegratedProjectActionsAsync ( buildIntegratedProject ,
2123+ nuGetProjectActions ,
2124+ nuGetProjectContext ,
2125+ token ) ;
2126+
2127+ // calculate total time taken to execute all nuget actions
2128+ stopWatch . Stop ( ) ;
2129+ nuGetProjectContext . Log (
2130+ MessageLevel . Info , Strings . NugetActionsTotalTime ,
2131+ DatetimeUtility . ToReadableTimeFormat ( stopWatch . Elapsed ) ) ;
2132+
2133+ // emit resolve actions telemetry event
2134+ var actionTelemetryEvent = new ActionTelemetryStepEvent (
2135+ nuGetProjectContext . OperationId . ToString ( ) ,
2136+ TelemetryConstants . ExecuteActionStepName , stopWatch . Elapsed . TotalSeconds ) ;
2137+
2138+ TelemetryActivity . EmitTelemetryEvent ( actionTelemetryEvent ) ;
2139+ }
2140+
21032141 /// <summary>
21042142 /// Executes the list of <paramref name="nuGetProjectActions" /> on <paramref name="nuGetProject" /> , which is
21052143 /// likely obtained by calling into
@@ -2804,30 +2842,8 @@ await buildIntegratedProject.UninstallPackageAsync(
28042842 var now = DateTime . UtcNow ;
28052843 void cacheContextModifier ( SourceCacheContext c ) => c . MaxAge = now ;
28062844
2807- // Check if current project is there in update cache and needs revaluation
2808- var isProjectUpdated = false ;
2809- if ( _buildIntegratedProjectsUpdateDict != null &&
2810- _buildIntegratedProjectsUpdateDict . TryGetValue (
2811- buildIntegratedProject . MSBuildProjectPath ,
2812- out isProjectUpdated ) &&
2813- isProjectUpdated )
2814- {
2815- await DependencyGraphRestoreUtility . RestoreProjectAsync (
2816- SolutionManager ,
2817- buildIntegratedProject ,
2818- referenceContext ,
2819- GetRestoreProviderCache ( ) ,
2820- cacheContextModifier ,
2821- projectAction . Sources ,
2822- nuGetProjectContext . OperationId ,
2823- logger ,
2824- token ) ;
2825- }
2826- else
2827- {
2828- // Write out the lock file
2829- await RestoreRunner . CommitAsync ( projectAction . RestoreResultPair , token ) ;
2830- }
2845+ // Write out the lock file
2846+ await RestoreRunner . CommitAsync ( projectAction . RestoreResultPair , token ) ;
28312847
28322848 // add packages lock file into project
28332849 if ( PackagesLockFileUtilities . IsNuGetLockFileEnabled ( projectAction . RestoreResult . LockFile . PackageSpec ) )
@@ -2895,13 +2911,9 @@ await BuildIntegratedRestoreUtility.ExecuteInitPs1ScriptsAsync(
28952911
28962912 foreach ( var parent in parents )
28972913 {
2898- // if this parent exists in update cache, then update it's entry to be re-evaluated
2899- if ( _buildIntegratedProjectsUpdateDict != null &&
2900- _buildIntegratedProjectsUpdateDict . ContainsKey ( parent . MSBuildProjectPath ) )
2901- {
2902- _buildIntegratedProjectsUpdateDict [ parent . MSBuildProjectPath ] = true ;
2903- }
2904- else
2914+ // if this parent not in current target projects list, it's not evaluated project.
2915+ if ( _buildIntegratedProjectsUpdateSet == null ||
2916+ _buildIntegratedProjectsUpdateSet . Contains ( parent . MSBuildProjectPath ) )
29052917 {
29062918 // Mark project for restore
29072919 dgSpecForParents . AddRestore ( parent . MSBuildProjectPath ) ;
0 commit comments