internal async Task OnRestoreInfoChangedAsync(IProjectVersionedValue <IVsProjectRestoreInfo2> e)
            {
                // 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, e.Value))
                {
                    return;
                }

                // No configurations - likely during project close
                if (e.Value == null)
                {
                    return;
                }

                _latestValue = e.Value;

                JoinableTask joinableTask = JoinableFactory.RunAsync(() =>
                {
                    return(NominateProjectRestoreAsync(e.Value, _projectAsynchronousTasksService.UnloadCancellationToken));
                });

                _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask,
                                                                   ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename,
                                                                   registerFaultHandler: true);

                // Prevent overlap until Restore completes
                await joinableTask;
            }
        public ProjectRestoreUpdate(ProjectConfiguration projectConfiguration, IVsProjectRestoreInfo2 restoreInfo)
        {
            Requires.NotNull(projectConfiguration, nameof(projectConfiguration));
            Requires.NotNull(restoreInfo, nameof(restoreInfo));

            ProjectConfiguration = projectConfiguration;
            RestoreInfo          = restoreInfo;
        }
        private static void AssertNoItems(IVsProjectRestoreInfo2 result)
        {
            Assert.Empty(result.ToolReferences);
            Assert.Equal(1, result.TargetFrameworks.Count);

            var targetFramework = result.TargetFrameworks.Item(0);

            Assert.Empty(targetFramework.FrameworkReferences);
            Assert.Empty(targetFramework.PackageDownloads);
            Assert.Empty(targetFramework.PackageReferences);
            Assert.Empty(targetFramework.ProjectReferences);
        }
Пример #4
0
            private async Task NominateProjectRestoreAsync(IVsProjectRestoreInfo2 restoreInfo, CancellationToken cancellationToken)
            {
                RestoreLogger.BeginNominateRestore(_logger, _project.FullPath, restoreInfo);

                // Nominate NuGet with the restore data. This will complete when we're guaranteed
                // that the  assets files *at least* contains the changes that we pushed to it.
                await _solutionRestoreService.NominateProjectAsync(_project.FullPath, restoreInfo, cancellationToken);

                CodeMarkers.Instance.CodeMarker(CodeMarkerTimerId.PerfPackageRestoreEnd);

                RestoreLogger.EndNominateRestore(_logger, _project.FullPath);
            }
Пример #5
0
        public async Task OnRestoreInfoChangedAsync_PushesRestoreInfoToRestoreService()
        {
            IVsProjectRestoreInfo2 result = null;
            var solutionRestoreService    = IVsSolutionRestoreServiceFactory.ImplementNominateProjectAsync((projectFile, info, cancellationToken) => { result = info; });

            var instance = await CreateInitializedInstance(solutionRestoreService : solutionRestoreService);

            var restoreInfo = IVsProjectRestoreInfo2Factory.Create();
            var value       = IProjectVersionedValueFactory.Create(restoreInfo);

            await instance.OnRestoreInfoChangedAsync(value);

            Assert.Same(restoreInfo, result);
        }
Пример #6
0
        private PackageRestoreConfiguredInput CreateRestoreInput(ConfiguredProject project, IImmutableDictionary <string, IProjectRuleSnapshot> update)
        {
            IVsProjectRestoreInfo2 restoreInfo = RestoreBuilder.ToProjectRestoreInfo(update);

            return(new PackageRestoreConfiguredInput(project, restoreInfo));
        }
Пример #7
0
        /// <summary>
        /// This is where the nominate calls for the IVs1 and IVS3 APIs combine. The reason for this method is to avoid duplication and potential issues
        /// The issue with this method is that it has some weird custom logging to ensure backward compatibility. It's on the implementer to ensure these calls are correct.
        /// <param name="projectUniqueName">projectUniqueName</param>
        /// <param name="projectRestoreInfo">projectRestoreInfo. Can be null</param>
        /// <param name="projectRestoreInfo2">proectRestoreInfo2. Can be null</param>
        /// <param name="token"></param>
        /// <remarks>Exactly one of projectRestoreInfos has to null.</remarks>
        /// <returns>The task that scheduled restore</returns>
        private Task <bool> NominateProjectAsync(string projectUniqueName, IVsProjectRestoreInfo projectRestoreInfo, IVsProjectRestoreInfo2 projectRestoreInfo2, CancellationToken token)
        {
            if (string.IsNullOrEmpty(projectUniqueName))
            {
                throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(projectUniqueName));
            }

            if (projectRestoreInfo == null && projectRestoreInfo2 == null)
            {
                throw new ArgumentNullException(nameof(projectRestoreInfo));
            }

            if (projectRestoreInfo != null && projectRestoreInfo2 != null)
            {
                throw new ArgumentException($"Internal error: Both {nameof(projectRestoreInfo)} and {nameof(projectRestoreInfo2)} cannot have values. Please file an issue at NuGet/Home if you see this exception.");
            }

            if (projectRestoreInfo != null)
            {
                if (projectRestoreInfo.TargetFrameworks == null)
                {
                    throw new InvalidOperationException("TargetFrameworks cannot be null.");
                }
            }
            else
            {
                if (projectRestoreInfo2.TargetFrameworks == null)
                {
                    throw new InvalidOperationException("TargetFrameworks cannot be null.");
                }
            }

            try
            {
                _logger.LogInformation(
                    $"The nominate API is called for '{projectUniqueName}'.");

                var projectNames = ProjectNames.FromFullProjectPath(projectUniqueName);
                DependencyGraphSpec dgSpec;
                IReadOnlyList <IAssetsLogMessage> nominationErrors = null;
                try
                {
                    dgSpec = ToDependencyGraphSpec(projectNames, projectRestoreInfo, projectRestoreInfo2);
                }
                catch (Exception e)
                {
                    var restoreLogMessage = RestoreLogMessage.CreateError(NuGetLogCode.NU1105, string.Format(Resources.NU1105, projectNames.ShortName, e.Message));
                    restoreLogMessage.LibraryId = projectUniqueName;

                    nominationErrors = new List <IAssetsLogMessage>()
                    {
                        AssetsLogMessage.Create(restoreLogMessage)
                    };

                    var    projectDirectory        = Path.GetDirectoryName(projectUniqueName);
                    string projectIntermediatePath = projectRestoreInfo == null
                        ? projectRestoreInfo2.BaseIntermediatePath
                        : projectRestoreInfo.BaseIntermediatePath;
                    var dgSpecOutputPath = GetProjectOutputPath(projectDirectory, projectIntermediatePath);
                    dgSpec = CreateMinimalDependencyGraphSpec(projectUniqueName, dgSpecOutputPath);
                }

                _projectSystemCache.AddProjectRestoreInfo(projectNames, dgSpec, nominationErrors);

                // returned task completes when scheduled restore operation completes.
                var restoreTask = _restoreWorker.ScheduleRestoreAsync(
                    SolutionRestoreRequest.OnUpdate(),
                    token);

                return(restoreTask);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                _logger.LogError(e.ToString());
                TelemetryUtility.EmitException(nameof(VsSolutionRestoreService), nameof(NominateProjectAsync), e);
                return(Task.FromResult(false));
            }
        }
Пример #8
0
 public Task <bool> NominateProjectAsync(string projectUniqueName, IVsProjectRestoreInfo2 projectRestoreInfo, CancellationToken token)
 {
     return(NominateProjectAsync(projectUniqueName, null, projectRestoreInfo, token));
 }
Пример #9
0
        private static DependencyGraphSpec ToDependencyGraphSpec(ProjectNames projectNames, IVsProjectRestoreInfo projectRestoreInfo, IVsProjectRestoreInfo2 projectRestoreInfo2)
        {
            var dgSpec = new DependencyGraphSpec();

            var packageSpec = projectRestoreInfo != null?
                              ToPackageSpec(projectNames, projectRestoreInfo.TargetFrameworks, projectRestoreInfo.OriginalTargetFrameworks, projectRestoreInfo.BaseIntermediatePath) :
                                  ToPackageSpec(projectNames, projectRestoreInfo2.TargetFrameworks, projectRestoreInfo2.OriginalTargetFrameworks, projectRestoreInfo2.BaseIntermediatePath);

            dgSpec.AddRestore(packageSpec.RestoreMetadata.ProjectUniqueName);
            dgSpec.AddProject(packageSpec);

            if (projectRestoreInfo != null && projectRestoreInfo.ToolReferences != null)
            {
                VSNominationUtilities.ProcessToolReferences(projectNames, projectRestoreInfo.TargetFrameworks, projectRestoreInfo.ToolReferences, dgSpec);
            }
            else if (projectRestoreInfo2 != null && projectRestoreInfo2.ToolReferences != null)
            {
                VSNominationUtilities.ProcessToolReferences(projectNames, projectRestoreInfo2.TargetFrameworks, projectRestoreInfo2.ToolReferences, dgSpec);
            }

            return(dgSpec);
        }
Пример #10
0
        public static void BeginNominateRestore(IProjectDiagnosticOutputService logger, string fullPath, IVsProjectRestoreInfo2 projectRestoreInfo)
        {
            if (logger.IsEnabled)
            {
                using var batch = new BatchLogger(logger);
                batch.WriteLine();
                batch.WriteLine("------------------------------------------");
                batch.WriteLine($"BEGIN Nominate Restore for {fullPath}");
                batch.IndentLevel++;

                batch.WriteLine($"MSBuildProjectExtensionsPath:     {projectRestoreInfo.BaseIntermediatePath}");
                batch.WriteLine($"OriginalTargetFrameworks:         {projectRestoreInfo.OriginalTargetFrameworks}");
                LogTargetFrameworks(batch, projectRestoreInfo.TargetFrameworks);
                LogReferenceItems(batch, "Tool References", projectRestoreInfo.ToolReferences);

                batch.IndentLevel--;
                batch.WriteLine();
            }
        }
        /// <summary>
        /// This is where the nominate calls for the IVs1 and IVS3 APIs combine. The reason for this method is to avoid duplication and potential issues
        /// The issue with this method is that it has some weird custom logging to ensure backward compatibility. It's on the implementer to ensure these calls are correct.
        /// <param name="projectUniqueName">projectUniqueName</param>
        /// <param name="projectRestoreInfo">projectRestoreInfo. Can be null</param>
        /// <param name="projectRestoreInfo2">proectRestoreInfo2. Can be null</param>
        /// <param name="token"></param>
        /// <remarks>Exactly one of projectRestoreInfos has to null.</remarks>
        /// <returns>The task that scheduled restore</returns>
        private Task <bool> NominateProjectAsync(string projectUniqueName, IVsProjectRestoreInfo projectRestoreInfo, IVsProjectRestoreInfo2 projectRestoreInfo2, CancellationToken token)
        {
            if (string.IsNullOrEmpty(projectUniqueName))
            {
                throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(projectUniqueName));
            }

            if (projectRestoreInfo == null && projectRestoreInfo2 == null)
            {
                throw new ArgumentNullException(nameof(projectRestoreInfo));
            }

            if (projectRestoreInfo != null && projectRestoreInfo2 != null)
            {
                throw new ArgumentException($"Internal error: Both {nameof(projectRestoreInfo)} and {nameof(projectRestoreInfo2)} cannot have values. Please file an issue at NuGet/Home if you see this exception.");
            }

            if (projectRestoreInfo != null)
            {
                if (projectRestoreInfo.TargetFrameworks == null)
                {
                    throw new InvalidOperationException("TargetFrameworks cannot be null.");
                }
            }
            else
            {
                if (projectRestoreInfo2.TargetFrameworks == null)
                {
                    throw new InvalidOperationException("TargetFrameworks cannot be null.");
                }
            }

            try
            {
                _logger.LogInformation(
                    $"The nominate API is called for '{projectUniqueName}'.");

                var projectNames = ProjectNames.FromFullProjectPath(projectUniqueName);

                var dgSpec = ToDependencyGraphSpec(projectNames, projectRestoreInfo, projectRestoreInfo2);

                _projectSystemCache.AddProjectRestoreInfo(projectNames, dgSpec);

                // returned task completes when scheduled restore operation completes.
                var restoreTask = _restoreWorker.ScheduleRestoreAsync(
                    SolutionRestoreRequest.OnUpdate(),
                    token);

                return(restoreTask);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                _logger.LogError(e.ToString());
                return(Task.FromResult(false));
            }
        }
Пример #12
0
        private ProjectRestoreUpdate CreateRestoreUpdate(ProjectConfiguration projectConfiguration, IImmutableDictionary <string, IProjectRuleSnapshot> update)
        {
            IVsProjectRestoreInfo2 restoreInfo = RestoreBuilder.ToProjectRestoreInfo(update);

            return(new ProjectRestoreUpdate(projectConfiguration, restoreInfo));
        }
 public PackageRestoreConfiguredInput(ConfiguredProject project, IVsProjectRestoreInfo2 restoreInfo)
 {
     Project     = project;
     RestoreInfo = restoreInfo;
 }