AddMetapackageReferences.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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.Linq;
  5. using System.Xml;
  6. using Microsoft.Build.Framework;
  7. using Microsoft.Build.Utilities;
  8. using NuGet.Versioning;
  9. using RepoTasks.Utilities;
  10. namespace RepoTasks
  11. {
  12. public class AddMetapackageReferences : Task
  13. {
  14. [Required]
  15. public string ReferencePackagePath { get; set; }
  16. [Required]
  17. public string MetapackageReferenceType { get; set; }
  18. [Required]
  19. public string DependencyVersionRangeType { get; set; }
  20. // MSBuild doesn't allow binding to enums directly.
  21. private enum VersionRangeType
  22. {
  23. Minimum, // [1.1.1, )
  24. MajorMinor, // [1.1.1, 1.2.0)
  25. }
  26. [Required]
  27. public ITaskItem[] PackageArtifacts { get; set; }
  28. [Required]
  29. public ITaskItem[] ExternalDependencies { get; set; }
  30. public override bool Execute()
  31. {
  32. if (!Enum.TryParse<VersionRangeType>(DependencyVersionRangeType, out var dependencyVersionType))
  33. {
  34. Log.LogError("Unexpected value {0} for DependencyVersionRangeType", DependencyVersionRangeType);
  35. return false;
  36. }
  37. // Parse input
  38. var metapackageArtifacts = PackageArtifacts.Where(p => p.GetMetadata(MetapackageReferenceType) == "true");
  39. var externalArtifacts = ExternalDependencies.Where(p => p.GetMetadata(MetapackageReferenceType) == "true");
  40. var xmlDoc = new XmlDocument();
  41. xmlDoc.Load(ReferencePackagePath);
  42. // Project
  43. var projectElement = xmlDoc.FirstChild;
  44. // Items
  45. var itemGroupElement = xmlDoc.CreateElement("ItemGroup");
  46. Log.LogMessage(MessageImportance.High, $"{MetapackageReferenceType} will include the following packages");
  47. foreach (var package in metapackageArtifacts)
  48. {
  49. var packageName = package.ItemSpec;
  50. var packageVersion = package.GetMetadata("Version");
  51. if (string.IsNullOrEmpty(packageVersion))
  52. {
  53. Log.LogError("Missing version information for package {0}", packageName);
  54. continue;
  55. }
  56. var packageVersionValue = GetDependencyVersion(dependencyVersionType, packageName, packageVersion);
  57. Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersionValue}");
  58. var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
  59. packageReferenceElement.SetAttribute("Include", packageName);
  60. packageReferenceElement.SetAttribute("Version", packageVersionValue);
  61. packageReferenceElement.SetAttribute("PrivateAssets", "None");
  62. itemGroupElement.AppendChild(packageReferenceElement);
  63. }
  64. foreach (var package in externalArtifacts)
  65. {
  66. var packageName = package.ItemSpec;
  67. var packageVersion = package.GetMetadata("Version");
  68. if (string.IsNullOrEmpty(packageVersion))
  69. {
  70. Log.LogError("Missing version information for package {0}", packageName);
  71. continue;
  72. }
  73. var packageVersionValue =
  74. Enum.TryParse<VersionRangeType>(package.GetMetadata("MetapackageVersionRangeType"), out var packageVersionType)
  75. ? GetDependencyVersion(packageVersionType, packageName, packageVersion)
  76. : GetDependencyVersion(dependencyVersionType, packageName, packageVersion);
  77. Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersionValue}");
  78. var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
  79. packageReferenceElement.SetAttribute("Include", packageName);
  80. packageReferenceElement.SetAttribute("Version", packageVersionValue);
  81. packageReferenceElement.SetAttribute("PrivateAssets", "None");
  82. itemGroupElement.AppendChild(packageReferenceElement);
  83. }
  84. projectElement.AppendChild(itemGroupElement);
  85. // Save updated file
  86. xmlDoc.AppendChild(projectElement);
  87. xmlDoc.Save(ReferencePackagePath);
  88. return !Log.HasLoggedErrors;
  89. }
  90. private string GetDependencyVersion(VersionRangeType dependencyVersionType, string packageName, string packageVersion)
  91. {
  92. switch (dependencyVersionType)
  93. {
  94. case VersionRangeType.MajorMinor:
  95. if (!NuGetVersion.TryParse(packageVersion, out var nugetVersion))
  96. {
  97. Log.LogError("Invalid NuGet version '{0}' for package {1}", packageVersion, packageName);
  98. return null;
  99. }
  100. return $"[{packageVersion}, {nugetVersion.Major}.{nugetVersion.Minor + 1}.0)";
  101. case VersionRangeType.Minimum:
  102. return packageVersion;
  103. default:
  104. throw new NotImplementedException();
  105. }
  106. }
  107. }
  108. }