in src/NuGet.Clients/NuGet.SolutionRestoreManager/SolutionRestoreJob.cs [408:561]
private async Task RestorePackageSpecProjectsAsync(
List<IDependencyGraphProject> projects,
bool forceRestore,
bool isSolutionAvailable,
RestoreOperationSource restoreSource,
IntervalTracker intervalTracker,
CancellationToken token)
{
// Only continue if there are some build integrated type projects.
if (!(projects.Any(project => project is BuildIntegratedNuGetProject)))
{
return;
}
if (_packageRestoreConsent.IsGranted)
{
if (!isSolutionAvailable)
{
var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(_settings);
if (!Path.IsPathRooted(globalPackagesFolder))
{
var message = string.Format(
CultureInfo.CurrentCulture,
Resources.RelativeGlobalPackagesFolder,
globalPackagesFolder);
await _logger.WriteLineAsync(VerbosityLevel.Quiet, message);
// Cannot restore packages since globalPackagesFolder is a relative path
// and the solution is not available
return;
}
}
DependencyGraphCacheContext cacheContext;
DependencyGraphSpec originalDgSpec;
DependencyGraphSpec dgSpec;
IReadOnlyList<IAssetsLogMessage> additionalMessages;
using (intervalTracker.Start(RestoreTelemetryEvent.SolutionDependencyGraphSpecCreation))
{
// Cache p2ps discovered from DTE
cacheContext = new DependencyGraphCacheContext(_logger, _settings);
var pathContext = NuGetPathContext.Create(_settings);
// Get full dg spec
(originalDgSpec, additionalMessages) = await DependencyGraphRestoreUtility.GetSolutionRestoreSpecAndAdditionalMessages(_solutionManager, cacheContext);
}
using (intervalTracker.Start(RestoreTelemetryEvent.SolutionUpToDateCheck))
{
// Run solution based up to date check.
var projectsNeedingRestore = _solutionUpToDateChecker.PerformUpToDateCheck(originalDgSpec, _logger).AsList();
var specialReferencesCount = originalDgSpec.Projects
.Count(x => x.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference && x.RestoreMetadata.ProjectStyle != ProjectStyle.PackagesConfig && x.RestoreMetadata.ProjectStyle != ProjectStyle.ProjectJson);
dgSpec = originalDgSpec;
// Only use the optimization results if the restore is not `force`.
// Still run the optimization check anyways to prep the cache.
if (!forceRestore)
{
// Update the dg spec.
dgSpec = originalDgSpec.WithoutRestores();
foreach (var uniqueProjectId in projectsNeedingRestore)
{
dgSpec.AddRestore(uniqueProjectId); // Fill DGSpec copy only with restore-needed projects
}
// Calculate the number of up to date projects
_upToDateProjectCount = originalDgSpec.Restore.Count - specialReferencesCount - projectsNeedingRestore.Count;
_noOpProjectsCount = _upToDateProjectCount;
}
}
using (intervalTracker.Start(RestoreTelemetryEvent.PackageReferenceRestoreDuration))
{
// Avoid restoring if all the projects are up to date, or the solution does not have build integrated projects.
if (DependencyGraphRestoreUtility.IsRestoreRequired(dgSpec))
{
await _logger.RunWithProgressAsync(
async (logger, _, token) =>
{
// Display the restore opt out message if it has not been shown yet
await logger.WriteHeaderAsync();
var sources = _sourceRepositoryProvider
.GetRepositories()
.ToList();
var providerCache = new RestoreCommandProvidersCache();
Action<SourceCacheContext> cacheModifier = (cache) => { };
var isRestoreOriginalAction = true;
var isRestoreSucceeded = true;
var projectList = dgSpec.Projects.Select(e => e.FilePath).ToList();
IReadOnlyList<RestoreSummary> restoreSummaries = null;
try
{
_nuGetProgressReporter.StartSolutionRestore(projectList);
restoreSummaries = await DependencyGraphRestoreUtility.RestoreAsync(
dgSpec,
cacheContext,
providerCache,
cacheModifier,
sources,
_nuGetProjectContext.OperationId,
forceRestore,
isRestoreOriginalAction,
additionalMessages,
_nuGetProgressReporter,
logger,
token);
_packageCount += restoreSummaries.Sum(summary => summary.InstallCount);
isRestoreSucceeded = restoreSummaries.All(summary => summary.Success == true);
_noOpProjectsCount += restoreSummaries.Count(summary => summary.NoOpRestore == true);
_solutionUpToDateChecker.SaveRestoreStatus(restoreSummaries);
_didNewAuditCheckRun = true;
_solutionHasVulnerabilities |= AnyProjectHasVulnerablePackageWarning(restoreSummaries);
}
catch
{
isRestoreSucceeded = false;
throw;
}
finally
{
if (isRestoreSucceeded)
{
if (_noOpProjectsCount < restoreSummaries.Count)
{
_status = NuGetOperationStatus.Succeeded;
}
else
{
_status = NuGetOperationStatus.NoOp;
}
}
else
{
_status = NuGetOperationStatus.Failed;
}
_nuGetProgressReporter.EndSolutionRestore(projectList);
}
},
token);
}
}
}
else if (restoreSource == RestoreOperationSource.Explicit)
{
await _logger.ShowErrorAsync(Resources.PackageRefNotRestoredBecauseOfNoConsent);
}
}