RemoveSharedFrameworkDependencies.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright (c) .NET Foundation. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.IO.Compression;
  7. using System.Linq;
  8. using System.Xml;
  9. using System.Xml.Linq;
  10. using Microsoft.Build.Framework;
  11. using Microsoft.Build.Utilities;
  12. using NuGet.Frameworks;
  13. using NuGet.Packaging;
  14. using NuGet.Packaging.Core;
  15. namespace RepoTasks
  16. {
  17. // This is temporary until we can use FrameworkReference to build our own packages
  18. public class RemoveSharedFrameworkDependencies : Task
  19. {
  20. [Required]
  21. public ITaskItem[] Files { get; set; }
  22. [Required]
  23. public ITaskItem[] FrameworkOnlyPackages { get; set; }
  24. [Required]
  25. public string SharedFrameworkTargetFramework { get; set; }
  26. public override bool Execute()
  27. {
  28. Log.LogMessage("NuGet version = " + typeof(PackageArchiveReader).Assembly.GetName().Version);
  29. var dependencyToRemove = new HashSet<string>(FrameworkOnlyPackages.Select(p => p.ItemSpec), StringComparer.OrdinalIgnoreCase);
  30. foreach (var file in Files)
  31. {
  32. FilterDependencies(file.ItemSpec, dependencyToRemove);
  33. }
  34. return !Log.HasLoggedErrors;
  35. }
  36. private void FilterDependencies(string targetPath, ISet<string> dependencyToRemove)
  37. {
  38. var fileName = Path.GetFileName(targetPath);
  39. Log.LogMessage($"Updating {fileName}");
  40. using (var fileStream = File.Open(targetPath, FileMode.Open))
  41. using (var package = new ZipArchive(fileStream, ZipArchiveMode.Update))
  42. using (var packageReader = new PackageArchiveReader(fileStream, leaveStreamOpen: true))
  43. {
  44. var referencesFrameworkOnlyAssembly = false;
  45. var nuspecFile = packageReader.GetNuspecFile();
  46. using (var stream = package.OpenFile(nuspecFile))
  47. {
  48. var reader = Manifest.ReadFrom(stream, validateSchema: true);
  49. stream.Position = 0;
  50. var packageBuilder = new PackageBuilder(stream, basePath: null);
  51. var updatedGroups = new List<PackageDependencyGroup>();
  52. foreach (var group in packageBuilder.DependencyGroups)
  53. {
  54. var packages = new List<PackageDependency>();
  55. var updatedGroup = new PackageDependencyGroup(group.TargetFramework, packages);
  56. foreach (var dependency in group.Packages)
  57. {
  58. if (dependencyToRemove.Contains(dependency.Id))
  59. {
  60. referencesFrameworkOnlyAssembly = true;
  61. Log.LogMessage($" Remove dependency on '{dependency.Id}'");
  62. continue;
  63. }
  64. packages.Add(dependency);
  65. }
  66. updatedGroups.Add(updatedGroup);
  67. }
  68. if (referencesFrameworkOnlyAssembly)
  69. {
  70. packageBuilder.DependencyGroups.Clear();
  71. packageBuilder.DependencyGroups.AddRange(updatedGroups);
  72. var updatedManifest = Manifest.Create(packageBuilder);
  73. var inMemory = new MemoryStream();
  74. updatedManifest.Save(inMemory);
  75. inMemory.Position = 0;
  76. // Hack the raw nuspec to add the <frameworkReference> dependency
  77. var rawNuspec = XDocument.Load(inMemory, LoadOptions.PreserveWhitespace);
  78. var ns = rawNuspec.Root.GetDefaultNamespace();
  79. var metadata = rawNuspec.Root.Descendants(ns + "metadata").Single();
  80. metadata.Add(
  81. new XElement(ns + "frameworkReferences",
  82. new XElement(ns + "group",
  83. new XAttribute("targetFramework", NuGetFramework.Parse(SharedFrameworkTargetFramework).GetFrameworkString()),
  84. new XElement(ns + "frameworkReference", new XAttribute("name", "Microsoft.AspNetCore.App")))));
  85. stream.Position = 0;
  86. stream.SetLength(0);
  87. rawNuspec.Save(stream);
  88. Log.LogMessage(MessageImportance.High, "Added <frameworkReference> to {0}", fileName);
  89. }
  90. else
  91. {
  92. Log.LogMessage($"No changes made to {fileName}");
  93. }
  94. }
  95. }
  96. }
  97. }
  98. }