public async Task <bool> RestoreAsync(string entryProjectFilePath, IDictionary <string, string> globalProperties, IReadOnlyDictionary <string, string> options)
        {
            var dependencyGraphSpec = GetDependencyGraphSpec(entryProjectFilePath, globalProperties);

            // If the dependency graph spec is null, something went wrong evaluating the projects, so return false
            if (dependencyGraphSpec == null)
            {
                return(false);
            }

            try
            {
                return(await BuildTasksUtility.RestoreAsync(
                           dependencyGraphSpec : dependencyGraphSpec,
                           interactive : IsOptionTrue(nameof(RestoreTaskEx.Interactive), options),
                           recursive : IsOptionTrue(nameof(RestoreTaskEx.Recursive), options),
                           noCache : IsOptionTrue(nameof(RestoreTaskEx.NoCache), options),
                           ignoreFailedSources : IsOptionTrue(nameof(RestoreTaskEx.IgnoreFailedSources), options),
                           disableParallel : IsOptionTrue(nameof(RestoreTaskEx.DisableParallel), options),
                           force : IsOptionTrue(nameof(RestoreTaskEx.Force), options),
                           forceEvaluate : IsOptionTrue(nameof(RestoreTaskEx.ForceEvaluate), options),
                           hideWarningsAndErrors : IsOptionTrue(nameof(RestoreTaskEx.HideWarningsAndErrors), options),
                           restorePC : IsOptionTrue(nameof(RestoreTaskEx.RestorePackagesConfig), options),
                           log : MSBuildLogger,
                           cancellationToken : CancellationToken.None));
            }
            catch (Exception e)
            {
                LoggingQueue.TaskLoggingHelper.LogErrorFromException(e, showStackTrace: true);

                return(false);
            }
        }
 /// <summary>
 /// Gets the package sources of the specified project.
 /// </summary>
 /// <param name="project">An <see cref="IMSBuildItem" /> representing the project..</param>
 /// <param name="innerNodes">An <see cref="IReadOnlyCollection{IMSBuildItem}" /> containing the inner nodes of the project if its targets multiple frameworks.</param>
 /// <param name="settings">The <see cref="ISettings" /> of the specified project.</param>
 /// <returns>A <see cref="List{PackageSource}" /> object containing the packages sources for the specified project.</returns>
 internal static List <PackageSource> GetSources(IMSBuildProject project, IReadOnlyCollection <IMSBuildProject> innerNodes, ISettings settings)
 {
     return(BuildTasksUtility.GetSources(
                project.Directory,
                project.SplitPropertyValueOrNull("RestoreSources"),
                project.SplitPropertyValueOrNull("RestoreSourcesOverride"),
                innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectSources"))),
                settings)
            .Select(i => new PackageSource(i))
            .ToList());
 }
Ejemplo n.º 3
0
        public void GetSources_WithRestoreSourcesGlobal_Property_ResolvesAgainstWorkingDirectory()
        {
            using (var testDir = TestDirectory.CreateInTemp())
            {
                // Arrange
                var startupDirectory = Path.Combine(testDir, "startup");
                var projectDirectory = Path.Combine(testDir, "project");
                var relativePath     = "relativeSource";

                // Act
                var effectiveSources = BuildTasksUtility.GetSources(
                    startupDirectory: startupDirectory,
                    projectDirectory: projectDirectory,
                    sources: new string[] { relativePath },
                    sourcesOverride: new string[] { relativePath },
                    additionalProjectSources: Array.Empty <string>(),
                    settings: NullSettings.Instance
                    );

                // Assert
                effectiveSources.ShouldBeEquivalentTo(new[] { Path.Combine(startupDirectory, relativePath) });
            }
        }
        /// <summary>
        /// Gets the restore metadata and target framework information for the specified project.
        /// </summary>
        /// <param name="project">An <see cref="IMSBuildProject" /> representing the project.</param>
        /// <param name="projectsByTargetFramework">A <see cref="IReadOnlyDictionary{NuGetFramework,IMSBuildProject}" /> containing the inner nodes by target framework.</param>
        /// <param name="settings">The <see cref="ISettings" /> of the specified project.</param>
        /// <returns>A <see cref="Tuple" /> containing the <see cref="ProjectRestoreMetadata" /> and <see cref="List{TargetFrameworkInformation}" /> for the specified project.</returns>
        private (ProjectRestoreMetadata RestoreMetadata, List <TargetFrameworkInformation> TargetFrameworkInfos) GetProjectRestoreMetadataAndTargetFrameworkInformation(IMSBuildProject project, IReadOnlyDictionary <NuGetFramework, IMSBuildProject> projectsByTargetFramework, ISettings settings)
        {
            var projectName = GetProjectName(project);

            var outputPath = GetRestoreOutputPath(project);

            var targetFrameworkInfos = GetTargetFrameworkInfos(projectsByTargetFramework);

            var projectStyleResult = BuildTasksUtility.GetProjectRestoreStyle(
                restoreProjectStyle: project.GetProperty("RestoreProjectStyle"),
                hasPackageReferenceItems: targetFrameworkInfos.Any(i => i.Dependencies.Any()),
                projectJsonPath: project.GetProperty("_CurrentProjectJsonPath"),
                projectDirectory: project.Directory,
                projectName: project.GetProperty("MSBuildProjectName"),
                log: MSBuildLogger);

            var projectStyle = projectStyleResult.ProjectStyle;

            var innerNodes = projectsByTargetFramework.Values.ToList();

            ProjectRestoreMetadata restoreMetadata;

            if (projectStyle == ProjectStyle.PackagesConfig)
            {
                restoreMetadata = new PackagesConfigProjectRestoreMetadata
                {
                    PackagesConfigPath = projectStyleResult.PackagesConfigFilePath,
                    RepositoryPath     = GetRepositoryPath(project, settings)
                };
            }
            else
            {
                restoreMetadata = new ProjectRestoreMetadata
                {
                    CrossTargeting  = (projectStyle == ProjectStyle.PackageReference || projectStyle == ProjectStyle.DotnetToolReference) && projectsByTargetFramework.Count > 1,
                    FallbackFolders = BuildTasksUtility.GetFallbackFolders(
                        project.Directory,
                        project.SplitPropertyValueOrNull("RestoreFallbackFolders"),
                        project.SplitPropertyValueOrNull("RestoreFallbackFoldersOverride"),
                        innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectFallbackFolders"))),
                        innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectFallbackFoldersExcludes"))),
                        settings),
                    SkipContentFileWrite  = IsLegacyProject(project),
                    ValidateRuntimeAssets = project.IsPropertyTrue("ValidateRuntimeIdentifierCompatibility")
                };
            }

            restoreMetadata.CacheFilePath                = NoOpRestoreUtilities.GetProjectCacheFilePath(outputPath, project.FullPath);
            restoreMetadata.ConfigFilePaths              = settings.GetConfigFilePaths();
            restoreMetadata.OutputPath                   = outputPath;
            restoreMetadata.OriginalTargetFrameworks     = GetOriginalTargetFrameworks(project, projectsByTargetFramework.Keys.ToList());
            restoreMetadata.PackagesPath                 = GetPackagesPath(project, settings);
            restoreMetadata.ProjectName                  = projectName;
            restoreMetadata.ProjectPath                  = project.FullPath;
            restoreMetadata.ProjectStyle                 = projectStyle;
            restoreMetadata.ProjectUniqueName            = project.FullPath;
            restoreMetadata.ProjectWideWarningProperties = WarningProperties.GetWarningProperties(project.GetProperty("TreatWarningsAsErrors"), project.GetProperty("WarningsAsErrors"), project.GetProperty("NoWarn"));
            restoreMetadata.RestoreLockProperties        = new RestoreLockProperties(project.GetProperty("RestorePackagesWithLockFile"), project.GetProperty("NuGetLockFilePath"), project.IsPropertyTrue("RestoreLockedMode"));
            restoreMetadata.Sources          = GetSources(project, innerNodes, settings);
            restoreMetadata.TargetFrameworks = GetProjectRestoreMetadataFrameworkInfos(projectsByTargetFramework);

            return(restoreMetadata, targetFrameworkInfos);
        }
        /// <summary>
        /// Gets a <see cref="DependencyGraphSpec" /> for the specified project.
        /// </summary>
        /// <param name="entryProjectPath">The full path to a project or Visual Studio Solution File.</param>
        /// <param name="globalProperties">An <see cref="IDictionary{String,String}" /> containing the global properties to use when evaluation MSBuild projects.</param>
        /// <returns>A <see cref="DependencyGraphSpec" /> for the specified project if they could be loaded, otherwise <code>null</code>.</returns>
        private DependencyGraphSpec GetDependencyGraphSpec(string entryProjectPath, IDictionary <string, string> globalProperties)
        {
            try
            {
                // TODO: Use a localized resource from https://github.com/NuGet/NuGet.Client/pull/3111
                MSBuildLogger.LogMinimal("Determining projects to restore...");

                var entryProjects = GetProjectGraphEntryPoints(entryProjectPath, globalProperties);

                // Load the projects via MSBuild and create an array of them since Parallel.ForEach is optimized for arrays
                var projects = LoadProjects(entryProjects)?.ToArray();

                // If no projects were loaded, return null indicating that the projects could not be loaded.
                if (projects == null || projects.Length == 0)
                {
                    return(null);
                }

                var sw = Stopwatch.StartNew();

                var dependencyGraphSpec = new DependencyGraphSpec(isReadOnly: true);

                // Unique names created by the MSBuild restore target are project paths, these
                // can be different on case-insensitive file systems for the same project file.
                // To workaround this unique names should be compared based on the OS.
                var uniqueNameComparer = PathUtility.GetStringComparerBasedOnOS();
                var projectPathLookup  = new ConcurrentDictionary <string, string>(uniqueNameComparer);

                try
                {
                    // Get the PackageSpecs in parallel because creating each one is relatively expensive so parallelism speeds things up
                    Parallel.ForEach(projects, new ParallelOptions {
                        MaxDegreeOfParallelism = Environment.ProcessorCount
                    }, project =>
                    {
                        var packageSpec = GetPackageSpec(project.OuterProject, project);

                        if (packageSpec != null)
                        {
                            // Keep track of all project path casings
                            var uniqueName = packageSpec.RestoreMetadata.ProjectUniqueName;
                            if (uniqueName != null && !projectPathLookup.ContainsKey(uniqueName))
                            {
                                projectPathLookup.TryAdd(uniqueName, uniqueName);
                            }

                            var projectPath = packageSpec.RestoreMetadata.ProjectPath;
                            if (projectPath != null && !projectPathLookup.ContainsKey(projectPath))
                            {
                                projectPathLookup.TryAdd(projectPath, projectPath);
                            }

                            // TODO: Remove this lock once https://github.com/NuGet/Home/issues/9002 is fixed
                            lock (dependencyGraphSpec)
                            {
                                dependencyGraphSpec.AddProject(packageSpec);
                            }
                        }
                    });
                }
                catch (AggregateException e)
                {
                    // Log exceptions thrown while creating PackageSpec objects
                    foreach (var exception in e.Flatten().InnerExceptions)
                    {
                        LoggingQueue.TaskLoggingHelper.LogErrorFromException(exception);
                    }

                    return(null);
                }

                // Fix project reference casings to match the original project on case insensitive file systems.
                MSBuildRestoreUtility.NormalizePathCasings(projectPathLookup, dependencyGraphSpec);

                // Add all entry projects if they support restore.  In most cases this is just a single project but if the entry
                // project is a solution, then all projects in the solution are added (if they support restore)
                foreach (var entryPoint in entryProjects)
                {
                    PackageSpec project = dependencyGraphSpec.GetProjectSpec(entryPoint.ProjectFile);

                    if (project != null && BuildTasksUtility.DoesProjectSupportRestore(project))
                    {
                        dependencyGraphSpec.AddRestore(entryPoint.ProjectFile);
                    }
                }

                sw.Stop();

                MSBuildLogger.LogDebug(string.Format(CultureInfo.CurrentCulture, Strings.CreatedDependencyGraphSpec, sw.ElapsedMilliseconds));

                return(dependencyGraphSpec);
            }
            catch (Exception e)
            {
                LoggingQueue.TaskLoggingHelper.LogErrorFromException(e, showStackTrace: true);
            }

            return(null);
        }