private PackageRestoreUnconfiguredInput MergeRestoreInputs(IReadOnlyCollection <PackageRestoreConfiguredInput> inputs) { // If there are no updates, we have no active configurations ProjectRestoreInfo?restoreInfo = null; if (inputs.Count != 0) { // We need to combine the snapshots from each implicitly active configuration (ie per TFM), // resolving any conflicts, which we'll report to the user. string msbuildProjectExtensionsPath = ResolveMSBuildProjectExtensionsPathConflicts(inputs); string originalTargetFrameworks = ResolveOriginalTargetFrameworksConflicts(inputs); string projectAssetsFilePath = ResolveProjectAssetsFilePathConflicts(inputs); IVsReferenceItems toolReferences = ResolveToolReferenceConflicts(inputs); IVsTargetFrameworks2 targetFrameworks = GetAllTargetFrameworks(inputs); restoreInfo = new ProjectRestoreInfo( msbuildProjectExtensionsPath, projectAssetsFilePath, originalTargetFrameworks, targetFrameworks, toolReferences); } return(new PackageRestoreUnconfiguredInput(restoreInfo, inputs)); }
public static byte[] CalculateHash(ProjectRestoreInfo restoreInfo) { Requires.NotNull(restoreInfo, nameof(restoreInfo)); using var hasher = new IncrementalHasher(); AppendProperty(hasher, nameof(restoreInfo.ProjectAssetsFilePath), restoreInfo.ProjectAssetsFilePath); AppendProperty(hasher, nameof(restoreInfo.MSBuildProjectExtensionsPath), restoreInfo.MSBuildProjectExtensionsPath); AppendProperty(hasher, nameof(restoreInfo.OriginalTargetFrameworks), restoreInfo.OriginalTargetFrameworks); foreach (IVsTargetFrameworkInfo3 framework in restoreInfo.TargetFrameworks) { AppendProperty(hasher, nameof(framework.TargetFrameworkMoniker), framework.TargetFrameworkMoniker); AppendFrameworkProperties(hasher, framework); AppendReferences(hasher, framework.ProjectReferences); AppendReferences(hasher, framework.PackageReferences); AppendReferences(hasher, framework.FrameworkReferences); AppendReferences(hasher, framework.PackageDownloads); AppendReferences(hasher, framework.CentralPackageVersions); } AppendReferences(hasher, restoreInfo.ToolReferences); return(hasher.GetHashAndReset()); }
private async Task <bool> RestoreCoreAsync(ProjectRestoreInfo restoreInfo) { // Restore service always does work regardless of whether the value we pass // them to actually contains changes, only nominate if there are any. byte[] hash = RestoreHasher.CalculateHash(restoreInfo); if (_latestHash != null && Enumerable.SequenceEqual(hash, _latestHash)) { return(true); } _latestHash = hash; JoinableTask <bool> joinableTask = JoinableFactory.RunAsync(() => { return(NominateForRestoreAsync(restoreInfo, _projectAsynchronousTasksService.UnloadCancellationToken)); }); _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask, ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); // Prevent overlap until Restore completes return(await joinableTask); }
public static IReadOnlyCollection <PackageRestoreConfiguredInput>?Create(ProjectRestoreInfo restoreInfo) { ProjectConfiguration projectConfiguration = ProjectConfigurationFactory.Create("Debug|x64"); IComparable projectVersion = (IComparable)0; return(new PackageRestoreConfiguredInput[1] { new PackageRestoreConfiguredInput(projectConfiguration, restoreInfo, projectVersion) }); }
private void HintProjectDependentFile(ProjectRestoreInfo restoreInfo) { if (restoreInfo.ProjectAssetsFilePath.Length != 0) { // Hint to CPS that the assets file "might" have changed and therefore // reevaluate if it has. It already listens to file-changed events for it, // but can miss them during periods where the buffer is overflowed when // there are lots of changes. _projectDependentFileChangeNotificationService.OnAfterDependentFilesChanged( fileFullPaths: new[] { restoreInfo.ProjectAssetsFilePath }, project: ContainingProject); } }
private RestoreData CreateRestoreData(ProjectRestoreInfo restoreInfo) { // Restore service gives us a guarantee that the assets file // will contain *at least* the changes that we pushed to it. if (restoreInfo.ProjectAssetsFilePath.Length == 0) { return(new RestoreData(string.Empty, DateTime.MinValue, succeeded: false)); } return(new RestoreData( restoreInfo.ProjectAssetsFilePath, GetLastWriteTimeUtc(restoreInfo.ProjectAssetsFilePath))); }
private async Task <bool> NominateForRestoreAsync(ProjectRestoreInfo restoreInfo, CancellationToken cancellationToken) { RestoreLogger.BeginNominateRestore(_logger, _project.FullPath, restoreInfo); try { return(await _solutionRestoreService.NominateProjectAsync(_project.FullPath, restoreInfo, cancellationToken)); } finally { CodeMarkers.Instance.CodeMarker(CodeMarkerTimerId.PerfPackageRestoreEnd); RestoreLogger.EndNominateRestore(_logger, _project.FullPath); } }
private RestoreData CreateRestoreData(ProjectRestoreInfo restoreInfo, bool succeeded) { string projectAssetsFilePath = restoreInfo.ProjectAssetsFilePath; // Restore service gives us a guarantee that the assets file // will contain *at least* the changes that we pushed to it. if (projectAssetsFilePath.Length == 0) { return(new RestoreData(string.Empty, DateTime.MinValue, succeeded: false)); } DateTime lastWriteTime = _fileSystem.GetLastFileWriteTimeOrMinValueUtc(projectAssetsFilePath); return(new RestoreData( projectAssetsFilePath, lastWriteTime, succeeded: succeeded && lastWriteTime != DateTime.MinValue)); }
private Task HintProjectDependentFileAsync(ProjectRestoreInfo restoreInfo) { // Hint to CPS that the assets file "might" have changed and therefore // reevaluate if it has. It already listens to file-changed events for it, // but can miss them during periods where the buffer is overflowed when // there are lots of changes. if (restoreInfo.ProjectAssetsFilePath.Length > 0) { return(_projectAccessor.EnterWriteLockAsync((collection, token) => { var hint = new ProjectChangeFileSystemEntityHint(ContainingProject !, ProjectChangeFileSystemEntityHint.UpdateProjectDependentFile, new[] { restoreInfo.ProjectAssetsFilePath }); return _projectChangeHintSubmissionService.Value.HintAsync(hint); })); } return(Task.CompletedTask); }
private async Task RestoreAsync(ProjectRestoreInfo restoreInfo) { // Restore service always does work regardless of whether the value we pass them to actually // contains changes, only nominate if there are any. if (RestoreComparer.RestoreInfos.Equals(_latestValue, restoreInfo)) { return; } _latestValue = restoreInfo; JoinableTask joinableTask = JoinableFactory.RunAsync(() => { return(NominateForRestoreAsync(restoreInfo, _projectAsynchronousTasksService.UnloadCancellationToken)); }); _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask, ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); // Prevent overlap until Restore completes await joinableTask; }
public PackageRestoreConfiguredInput(ProjectConfiguration projectConfiguration, ProjectRestoreInfo restoreInfo, IComparable configuredProjectVersion) { ProjectConfiguration = projectConfiguration; RestoreInfo = restoreInfo; ConfiguredProjectVersion = configuredProjectVersion; }