|
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Commands;
using NuGet.LibraryModel;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.ProjectManagement;
using NuGet.ProjectManagement.Projects;
using NuGet.ProjectModel;
using NuGet.Shared;
namespace NuGet.PackageManagement
{
/// <summary>
/// Helper class for calling the RestoreCommand
/// </summary>
public static class BuildIntegratedRestoreUtility
{
public static async Task ExecuteInitPs1ScriptsAsync(
BuildIntegratedNuGetProject project,
IEnumerable<PackageIdentity> packages,
FallbackPackagePathResolver pathResolver,
INuGetProjectContext projectContext,
CancellationToken token)
{
// Find all dependencies in sorted order
var sortedPackages = await BuildIntegratedProjectUtility.GetOrderedProjectPackageDependencies(project);
// Keep track of the packages that need to be executed.
var packagesToExecute = new HashSet<PackageIdentity>(packages, PackageIdentity.Comparer);
// Use the ordered packages to run init.ps1 for the specified packages.
foreach (var package in sortedPackages)
{
if (packagesToExecute.Remove(package))
{
var packageInstallPath = pathResolver.GetPackageDirectory(package.Id, package.Version);
if (packageInstallPath == null)
{
continue;
}
await project
.ProjectServices
.ScriptService
.ExecutePackageInitScriptAsync(
package,
packageInstallPath,
projectContext,
throwOnFailure: false,
token: token);
}
}
}
/// <summary>
/// Find all packages added to <paramref name="updatedLockFile"/>.
/// </summary>
public static IReadOnlyList<PackageIdentity> GetAddedPackages(
LockFile originalLockFile,
LockFile updatedLockFile)
{
IEnumerable<PackageIdentity> updatedPackages;
if (updatedLockFile != null)
{
updatedPackages = updatedLockFile
.Targets
.SelectMany(target => target.Libraries)
.Where(library => library.Type == LibraryType.Package)
.Select(library => new PackageIdentity(library.Name, library.Version));
}
else
{
updatedPackages = Enumerable.Empty<PackageIdentity>();
}
IEnumerable<PackageIdentity> originalPackages;
if (originalLockFile != null)
{
originalPackages = originalLockFile
.Targets
.SelectMany(target => target.Libraries)
.Where(library => library.Type == LibraryType.Package)
.Select(library => new PackageIdentity(library.Name, library.Version));
}
else
{
originalPackages = Enumerable.Empty<PackageIdentity>();
}
var results = updatedPackages
.Except(originalPackages, PackageIdentity.Comparer)
.ToList();
return results;
}
/// <summary>
/// Find the list of parent projects which directly or indirectly reference the child project.
/// </summary>
public static IReadOnlyList<BuildIntegratedNuGetProject> GetParentProjectsInClosure(
IReadOnlyList<BuildIntegratedNuGetProject> projects,
BuildIntegratedNuGetProject target,
DependencyGraphSpec cache)
{
if (projects == null)
{
throw new ArgumentNullException(nameof(projects));
}
if (target == null)
{
throw new ArgumentNullException(nameof(target));
}
if (cache == null)
{
throw new ArgumentNullException(nameof(cache));
}
var listOfParents = cache.GetParents(target.MSBuildProjectPath);
var parentNuGetprojects = new HashSet<BuildIntegratedNuGetProject>();
foreach (var parent in listOfParents)
{
// do not count the target as a parent
var nugetProject = projects.FirstOrDefault(r => r.MSBuildProjectPath == parent);
if (nugetProject != null && !nugetProject.Equals(target))
{
parentNuGetprojects.Add(nugetProject);
}
}
// sort parents by path to make this more deterministic during restores
return parentNuGetprojects
.OrderBy(parent => parent.MSBuildProjectPath, StringComparer.Ordinal)
.ToList();
}
public static void UpdatePackageReferenceMetadata(
LockFile lockFile,
FallbackPackagePathResolver pathResolver,
PackageIdentity package)
{
var info = pathResolver.GetPackageInfo(package.Id, package.Version);
if (info == null)
{
// don't do anything if package was not resolved on disk
return;
}
var nuspecFilePath = info.PathResolver.GetManifestFilePath(package.Id, package.Version);
var nuspecReader = new NuspecReader(nuspecFilePath);
var developmentDependency = nuspecReader.GetDevelopmentDependency();
if (developmentDependency)
{
for (var i = 0; i < lockFile.PackageSpec.TargetFrameworks.Count; i++)
{
var frameworkInfo = lockFile.PackageSpec.TargetFrameworks[i];
var index = frameworkInfo.Dependencies.FirstIndex(dep => dep.Name.Equals(package.Id, StringComparison.OrdinalIgnoreCase));
var dependency = frameworkInfo.Dependencies[index];
if (dependency.SuppressParent == LibraryIncludeFlagUtils.DefaultSuppressParent &&
dependency.IncludeType == LibraryIncludeFlags.All)
{
var includeType = LibraryIncludeFlags.All & ~LibraryIncludeFlags.Compile;
dependency = new LibraryDependency(dependency)
{
IncludeType = includeType,
SuppressParent = LibraryIncludeFlags.All
};
var newDependencies = frameworkInfo.Dependencies.SetItem(index, dependency);
lockFile.PackageSpec.TargetFrameworks[i] = new TargetFrameworkInformation(frameworkInfo) { Dependencies = newDependencies };
// update lock file target libraries
foreach (var target in lockFile.Targets
.Where(t => EqualityUtility.EqualsWithNullCheck(t.TargetFramework, frameworkInfo.FrameworkName)))
{
var targetLibrary = target.GetTargetLibrary(package.Id);
if (targetLibrary != null)
{
LockFileUtils.ExcludeItems(targetLibrary, includeType);
}
}
}
}
}
}
}
}
|