예제 #1
0
        public void ReportStatus(IReadOnlyList <RestoreSummary> restoreSummaries)
        {
            _failedProjects.Clear();

            foreach (var summary in restoreSummaries)
            {
                if (summary.Success)
                {
                    var packageSpec = _cachedDependencyGraphSpec.GetProjectSpec(summary.InputPath);
                    GetOutputFilePaths(packageSpec, out string assetsFilePath, out string cacheFilePath, out string targetsFilePath, out string propsFilePath, out string lockFilePath);

                    _outputWriteTimes[summary.InputPath] = new RestoreOutputData()
                    {
                        _lastAssetsFileWriteTime          = GetLastWriteTime(assetsFilePath),
                        _lastCacheFileWriteTime           = GetLastWriteTime(cacheFilePath),
                        _lastTargetsFileWriteTime         = GetLastWriteTime(targetsFilePath),
                        _lastPropsFileWriteTime           = GetLastWriteTime(propsFilePath),
                        _lastLockFileWriteTime            = GetLastWriteTime(lockFilePath),
                        _globalPackagesFolderCreationTime = GetCreationTime(packageSpec.RestoreMetadata.PackagesPath)
                    };
                }
                else
                {
                    _failedProjects.Add(summary.InputPath);
                }
            }
        }
예제 #2
0
        private RestoreSummaryRequest Create(
            string projectNameToRestore,
            ExternalProjectReference project,
            HashSet <ExternalProjectReference> projectReferenceClosure,
            RestoreArgs restoreArgs,
            DependencyGraphSpec projectDgSpec)
        {
            //fallback paths, global packages path and sources need to all be passed in the dg spec
            var fallbackPaths = projectDgSpec.GetProjectSpec(projectNameToRestore).RestoreMetadata.FallbackFolders;
            var globalPath    = GetPackagesPath(restoreArgs, projectDgSpec.GetProjectSpec(projectNameToRestore));
            var settings      = Settings.LoadSettingsGivenConfigPaths(projectDgSpec.GetProjectSpec(projectNameToRestore).RestoreMetadata.ConfigFilePaths);
            var sources       = restoreArgs.GetEffectiveSources(settings, projectDgSpec.GetProjectSpec(projectNameToRestore).RestoreMetadata.Sources);

            var sharedCache = _providerCache.GetOrCreate(
                globalPath,
                fallbackPaths.AsList(),
                sources,
                restoreArgs.CacheContext,
                restoreArgs.Log);

            var rootPath = Path.GetDirectoryName(project.PackageSpec.FilePath);

            // Create request
            var request = new RestoreRequest(
                project.PackageSpec,
                sharedCache,
                restoreArgs.CacheContext,
                restoreArgs.Log)
            {
                // Set properties from the restore metadata
                ProjectStyle               = project.PackageSpec.RestoreMetadata.ProjectStyle,
                RestoreOutputPath          = project.PackageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson ? rootPath : project.PackageSpec.RestoreMetadata.OutputPath,
                DependencyGraphSpec        = projectDgSpec,
                BaseIntermediateOutputPath = project.PackageSpec.RestoreMetadata.OutputPath
            };

            var restoreLegacyPackagesDirectory = project.PackageSpec?.RestoreMetadata?.LegacyPackagesDirectory
                                                 ?? DefaultRestoreLegacyPackagesDirectory;

            request.IsLowercasePackagesDirectory = !restoreLegacyPackagesDirectory;

            // Standard properties
            restoreArgs.ApplyStandardProperties(request);

            // Add project references
            request.ExternalProjects = projectReferenceClosure.ToList();

            // The lock file is loaded later since this is an expensive operation
            var summaryRequest = new RestoreSummaryRequest(
                request,
                project.MSBuildProjectPath,
                settings, // TODO NK - We don't need to pass the settings down here. We just need the config files
                sources);

            return(summaryRequest);
        }
        /// <summary>
        /// Write the dg file to a temp location if NUGET_PERSIST_NOOP_DG.
        /// </summary>
        /// <remarks>This is a noop if NUGET_PERSIST_NOOP_DG is not set to true.</remarks>
        private static void PersistHashedDGFileIfDebugging(DependencyGraphSpec spec, ILogger log)
        {
            if (_isPersistDGSet.Value)
            {
                string path;
                var    envPath = Environment.GetEnvironmentVariable("NUGET_PERSIST_NOOP_DG_PATH");
                if (!string.IsNullOrEmpty(envPath))
                {
                    path = envPath;
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                }
                else
                {
                    path = Path.Combine(
                        NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp),
                        "nuget-dg",
                        $"{spec.GetProjectSpec(spec.Restore.FirstOrDefault()).RestoreMetadata.ProjectName}-{DateTime.Now.ToString("yyyyMMddHHmmss")}.dg");
                    DirectoryUtility.CreateSharedDirectory(Path.GetDirectoryName(path));
                }

                log.LogMinimal($"Persisting no-op dg to {path}");

                spec.Save(path);
            }
        }
예제 #4
0
        /// <summary>
        /// Updates the project Id in packageSpec.
        /// </summary>
        /// <param name="nuGetProject">NuGetProject containing the project Id.</param>
        /// <param name="projectUniqueName">Project unique name used to get the package spec from the dgSpec.</param>
        /// <param name="projectRestoreInfo">DgSpec of containing the packageSpec for the project.</param>
        private void UpdateProjectIdInPackageSpec(NuGetProject nuGetProject, string projectUniqueName, DependencyGraphSpec projectRestoreInfo)
        {
            var packageSpec = projectRestoreInfo.GetProjectSpec(projectUniqueName);

            if (packageSpec != null &&
                nuGetProject != null &&
                string.IsNullOrEmpty(packageSpec.ProjectId))
            {
                packageSpec.ProjectId = nuGetProject.GetProjectId();
            }
        }
            public override Task <(IReadOnlyList <PackageSpec> dgSpecs, IReadOnlyList <IAssetsLogMessage> additionalMessages)> GetPackageSpecsAndAdditionalMessagesAsync(DependencyGraphCacheContext context)
            {
                DependencyGraphSpec dgSpec = DependencyGraphSpecTestUtilities.CreateMinimalDependencyGraphSpec(ProjectFullPath, MSBuildProjectPath);

                List <PackageSpec> packageSpecs = new List <PackageSpec>();

                packageSpecs.Add(dgSpec.GetProjectSpec(ProjectFullPath));

                (IReadOnlyList <PackageSpec>, IReadOnlyList <IAssetsLogMessage>)result = (packageSpecs, null);
                return(Task.FromResult(result));
            }
        public void SaveRestoreStatus(IReadOnlyList <RestoreSummary> restoreSummaries)
        {
            if (restoreSummaries == null)
            {
                throw new ArgumentNullException(nameof(restoreSummaries));
            }

            _failedProjects.Clear();

            foreach (var summary in restoreSummaries)
            {
                if (summary.Success)
                {
                    var packageSpec = _cachedDependencyGraphSpec.GetProjectSpec(summary.InputPath);
                    GetOutputFilePaths(packageSpec, out string assetsFilePath, out string cacheFilePath, out string targetsFilePath, out string propsFilePath, out string lockFilePath);
                    var messages = !packageSpec.RestoreSettings.HideWarningsAndErrors && summary.Errors.Count > 0 ?
                                   summary.Errors :
                                   null;

                    _restoreData[summary.InputPath] = new RestoreData()
                    {
                        _lastAssetsFileWriteTime          = GetLastWriteTime(assetsFilePath),
                        _lastCacheFileWriteTime           = GetLastWriteTime(cacheFilePath),
                        _lastTargetsFileWriteTime         = GetLastWriteTime(targetsFilePath),
                        _lastPropsFileWriteTime           = GetLastWriteTime(propsFilePath),
                        _lastLockFileWriteTime            = GetLastWriteTime(lockFilePath),
                        _globalPackagesFolderCreationTime = GetCreationTime(packageSpec.RestoreMetadata.PackagesPath),
                        _messages = messages
                    };
                }
                else
                {
                    _failedProjects.Add(summary.InputPath);
                }
            }
        }
        async Task <PackageSpec> CreateProjectPackageSpec(DependencyGraphCacheContext context)
        {
            DependencyGraphSpec dependencySpec = await MSBuildPackageSpecCreator.GetDependencyGraphSpec(project, configuration, context?.Logger);

            context.AddToCache(dependencySpec);

            PackageSpec spec = dependencySpec.GetProjectSpec(project.FileName);

            if (spec != null)
            {
                return(spec);
            }

            throw new InvalidOperationException(GettextCatalog.GetString("Unable to create package spec for project. '{0}'", project.FileName));
        }
예제 #8
0
        public void AddProject_DoesNotClone(bool cpvmEnabled)
        {
            // Arrange
            var dependencyFoo = new LibraryDependency()
            {
                LibraryRange = new LibraryRange("foo", versionRange: cpvmEnabled ? null : VersionRange.Parse("1.0.0"), LibraryDependencyTarget.Package),
            };

            var centralVersions = cpvmEnabled
                ? new List <CentralPackageVersion>()
            {
                new CentralPackageVersion("foo", VersionRange.Parse("1.0.0"))
            }
                : new List <CentralPackageVersion>();

            var tfi = CreateTargetFrameworkInformation(
                new List <LibraryDependency>()
            {
                dependencyFoo
            },
                centralVersions);

            var packageSpec = new PackageSpec(new List <TargetFrameworkInformation>()
            {
                tfi
            });

            packageSpec.RestoreMetadata = new ProjectRestoreMetadata()
            {
                ProjectUniqueName             = "a",
                CentralPackageVersionsEnabled = cpvmEnabled
            };

            var dgSpec = new DependencyGraphSpec();

            dgSpec.AddRestore("a");
            dgSpec.AddProject(packageSpec);

            // Act
            var packageSpecFromDGSpec = dgSpec.GetProjectSpec("a");

            // Assert
            Assert.True(packageSpec.Equals(packageSpecFromDGSpec));
        }
예제 #9
0
        private void DumpProjectRestoreInfo(string projectUniqueName, DependencyGraphSpec projectRestoreInfo)
        {
            try
            {
                var packageSpec = projectRestoreInfo.GetProjectSpec(projectUniqueName);
                var outputPath  = packageSpec.RestoreMetadata.OutputPath;
                if (!Directory.Exists(outputPath))
                {
                    Directory.CreateDirectory(outputPath);
                }

                var dgPath = Path.Combine(outputPath, $"{Guid.NewGuid()}.dg");
                projectRestoreInfo.Save(dgPath);
            }
            catch (Exception e)
            {
                _logger.LogError(e.ToString());
            }
        }
예제 #10
0
        // recursive
        static void ReportProjectReferences(ProjectReferenceNode source, PackageSpec project, NuGetFramework rootNuGetFramework,
                                            DependencyGraphSpec dependencyGraph, int indentLevel, HashSet <Node> vertices, HashSet <Edge> edges)
        {
            const int INDENT_SIZE = 2;

            NuGetFramework nearest = project.GetNearestFrameworkMatching(rootNuGetFramework);

            // TODO: This is done be caller....delete
            //var projectReference = new ProjectReferenceNode(project.FilePath, project.Version.ToString(), nearest);
            //projects.Add(projectReference);

            // indent shows levels of the graph
            Console.Write(new string(' ', indentLevel * INDENT_SIZE));
            Console.WriteLine($"{project.RestoreMetadata.ProjectUniqueName}, v{project.Version}, ({nearest.GetShortFolderName()})");

            ProjectRestoreMetadataFrameworkInfo resolvedTargetFramework =
                project.RestoreMetadata.TargetFrameworks.Single(tf => nearest.Equals(tf.FrameworkName));

            // project references of a targetFramework
            foreach (ProjectRestoreReference projectRestoreReference in resolvedTargetFramework.ProjectReferences)
            {
                // TODO: PrivateAssets, ExcludeAssets, IncludeAssets
                //dependency.ProjectPath
                //dependency.ProjectUniqueName
                PackageSpec projectDependency = dependencyGraph.GetProjectSpec(projectRestoreReference.ProjectUniqueName);

                var projectDependencyReference = new ProjectReferenceNode(
                    projectDependency.FilePath,
                    projectDependency.Version.ToString(),
                    projectDependency.GetNearestFrameworkMatching(rootNuGetFramework));

                vertices.Add(projectDependencyReference);

                edges.Add(new Edge(source, projectDependencyReference));

                //Console.WriteLine($"({projectDependency.Name}, {Path.GetFileName(projectDependency.FilePath)}) is a project reference of ({project.Name}, {Path.GetFileName(project.FilePath)}");

                // recursive
                ReportProjectReferences(projectDependencyReference, projectDependency, rootNuGetFramework,
                                        dependencyGraph, indentLevel + 1, vertices, edges);
            }
        }
예제 #11
0
        public static IReadOnlyList <PackageSpec> GetProjectSpecs(this DependencyGraphSpec dependencySpec, string projectPath)
        {
            var mainProjectSpec = dependencySpec.GetProjectSpec(projectPath);

            if (mainProjectSpec == null)
            {
                return(null);
            }

            var specs = new List <PackageSpec> ();

            specs.Add(mainProjectSpec);

            // Look for any DotNetCliTools
            foreach (var spec in dependencySpec.Projects)
            {
                if (spec.IsDotNetCliToolPackageSpecForProject(projectPath))
                {
                    specs.Add(spec);
                }
            }

            return(specs);
        }
예제 #12
0
        private RestoreSummaryRequest Create(
            string projectNameToRestore,
            ExternalProjectReference project,
            HashSet <ExternalProjectReference> projectReferenceClosure,
            RestoreArgs restoreArgs,
            DependencyGraphSpec projectDgSpec,
            SettingsLoadingContext settingsLoadingContext)
        {
            var projectPackageSpec = projectDgSpec.GetProjectSpec(projectNameToRestore);
            //fallback paths, global packages path and sources need to all be passed in the dg spec
            var fallbackPaths       = projectPackageSpec.RestoreMetadata.FallbackFolders;
            var globalPath          = GetPackagesPath(restoreArgs, projectPackageSpec);
            var settings            = Settings.LoadImmutableSettingsGivenConfigPaths(projectPackageSpec.RestoreMetadata.ConfigFilePaths, settingsLoadingContext);
            var sources             = restoreArgs.GetEffectiveSources(settings, projectPackageSpec.RestoreMetadata.Sources);
            var clientPolicyContext = ClientPolicyContext.GetClientPolicy(settings, restoreArgs.Log);

            var sharedCache = _providerCache.GetOrCreate(
                globalPath,
                fallbackPaths.AsList(),
                sources,
                restoreArgs.CacheContext,
                restoreArgs.Log);

            var rootPath = Path.GetDirectoryName(project.PackageSpec.FilePath);

            // Create request
            var request = new RestoreRequest(
                project.PackageSpec,
                sharedCache,
                restoreArgs.CacheContext,
                clientPolicyContext,
                restoreArgs.Log)
            {
                // Set properties from the restore metadata
                ProjectStyle = project.PackageSpec.RestoreMetadata.ProjectStyle,
                //  Project.json is special cased to put assets file and generated .props and targets in the project folder
                RestoreOutputPath            = project.PackageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson ? rootPath : project.PackageSpec.RestoreMetadata.OutputPath,
                DependencyGraphSpec          = projectDgSpec,
                MSBuildProjectExtensionsPath = projectPackageSpec.RestoreMetadata.OutputPath
            };

            var restoreLegacyPackagesDirectory = project.PackageSpec?.RestoreMetadata?.LegacyPackagesDirectory
                                                 ?? DefaultRestoreLegacyPackagesDirectory;

            request.IsLowercasePackagesDirectory = !restoreLegacyPackagesDirectory;

            // Standard properties
            restoreArgs.ApplyStandardProperties(request);

            // Add project references
            request.ExternalProjects = projectReferenceClosure.ToList();

            // The lock file is loaded later since this is an expensive operation
            var summaryRequest = new RestoreSummaryRequest(
                request,
                project.MSBuildProjectPath,
                settings.GetConfigFilePaths(),
                sources);

            return(summaryRequest);
        }
        /// <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);
        }