GeneratePackageVersionPropsFile.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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.Linq;
  6. using System.IO;
  7. using System.Xml;
  8. using System.Xml.Linq;
  9. using Microsoft.Build.Framework;
  10. using Microsoft.Build.Utilities;
  11. using RepoTasks.ProjectModel;
  12. using RepoTasks.Utilities;
  13. using System.Text;
  14. namespace RepoTasks
  15. {
  16. public class GeneratePackageVersionPropsFile : Task
  17. {
  18. [Required]
  19. public ITaskItem[] Packages { get; set; }
  20. [Required]
  21. public string OutputPath { get; set; }
  22. public override bool Execute()
  23. {
  24. OutputPath = OutputPath.Replace('\\', '/');
  25. Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
  26. var props = new XElement("PropertyGroup");
  27. var root = new XElement("Project", props);
  28. var doc = new XDocument(root);
  29. props.Add(new XElement("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)"));
  30. var varNames = new HashSet<string>();
  31. var versionElements = new List<XElement>();
  32. foreach (var pkg in Packages)
  33. {
  34. var packageVersion = pkg.GetMetadata("Version");
  35. if (string.IsNullOrEmpty(packageVersion))
  36. {
  37. Log.LogError("Package {0} is missing the Version metadata", pkg.ItemSpec);
  38. continue;
  39. }
  40. string packageVarName;
  41. if (!string.IsNullOrEmpty(pkg.GetMetadata("VariableName")))
  42. {
  43. packageVarName = pkg.GetMetadata("VariableName");
  44. if (!packageVarName.EndsWith("Version", StringComparison.Ordinal))
  45. {
  46. Log.LogError("VariableName for {0} must end in 'Version'", pkg.ItemSpec);
  47. continue;
  48. }
  49. }
  50. else
  51. {
  52. packageVarName = GetVariableName(pkg.ItemSpec);
  53. }
  54. var packageTfm = pkg.GetMetadata("TargetFramework");
  55. var key = $"{packageVarName}/{packageTfm}";
  56. if (varNames.Contains(key))
  57. {
  58. Log.LogError("Multiple packages would produce {0} in the generated dependencies.props file. Set VariableName to differentiate the packages manually", key);
  59. continue;
  60. }
  61. varNames.Add(key);
  62. var elem = new XElement(packageVarName, packageVersion);
  63. if (!string.IsNullOrEmpty(packageTfm))
  64. {
  65. elem.Add(new XAttribute("Condition", $" '$(TargetFramework)' == '{packageTfm}' "));
  66. }
  67. versionElements.Add(elem);
  68. }
  69. foreach (var item in versionElements.OrderBy(p => p.Name.ToString()))
  70. {
  71. props.Add(item);
  72. }
  73. var settings = new XmlWriterSettings
  74. {
  75. OmitXmlDeclaration = true,
  76. Indent = true,
  77. };
  78. using (var writer = XmlWriter.Create(OutputPath, settings))
  79. {
  80. Log.LogMessage(MessageImportance.Normal, $"Generate {OutputPath}");
  81. doc.Save(writer);
  82. }
  83. return !Log.HasLoggedErrors;
  84. }
  85. private string GetVariableName(string packageId)
  86. {
  87. var sb = new StringBuilder();
  88. var first = true;
  89. foreach (var ch in packageId)
  90. {
  91. if (ch == '.')
  92. {
  93. first = true;
  94. continue;
  95. }
  96. if (first)
  97. {
  98. first = false;
  99. sb.Append(char.ToUpperInvariant(ch));
  100. }
  101. else
  102. {
  103. sb.Append(ch);
  104. }
  105. }
  106. sb.Append("PackageVersion");
  107. return sb.ToString();
  108. }
  109. }
  110. }