|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
if (args.Length != 22)
{
for (var i = 0; i < args.Length; i++)
{
Console.WriteLine($"Arg {i}: {args[i]}");
}
}
string nuspecFile = args[0];
string assetsDir = args[1];
string projectDir = args[2];
string configuration = args[3];
string[] tfms = args[4].Split(';');
var metadataList = args[5].Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var fileList = args[6].Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var readmeFile = args[7];
var folderList = args[8].Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var assemblyList = args[9].Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var dependencyList = args[10].Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var libraryList = args[11].Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var rulesetsDir = args[12];
var editorconfigsDir = args[13];
var artifactsBinDir = args[14];
var analyzerDocumentationFileDir = args[15];
var analyzerDocumentationFileName = args[16];
var analyzerSarifFileDir = args[17];
var analyzerSarifFileName = args[18];
var analyzerConfigurationFileDir = args[19];
var analyzerConfigurationFileName = args[20];
var globalAnalyzerConfigsDir = args[21];
var result = new StringBuilder();
result.AppendLine(@"<?xml version=""1.0""?>");
result.AppendLine(@"<package xmlns=""http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"">");
result.AppendLine(@" <metadata>");
string version = string.Empty;
string repositoryType = string.Empty;
string repositoryUrl = string.Empty;
string repositoryCommit = string.Empty;
string readmePackageLocation = string.Empty;
foreach (string entry in metadataList)
{
int equals = entry.IndexOf('=');
string name = entry[..equals];
string value = entry[(equals + 1)..];
switch (name)
{
case "repositoryType": repositoryType = value; continue;
case "repositoryUrl": repositoryUrl = value; continue;
case "repositoryCommit": repositoryCommit = value; continue;
case "license": result.AppendLine($" <license type=\"expression\">{value}</license>"); continue;
case "readme": readmePackageLocation = value; break;
}
if (value.Length > 0)
{
result.AppendLine($" <{name}>{value}</{name}>");
}
if (name == "version")
{
version = value;
}
}
if (!string.IsNullOrEmpty(repositoryType))
{
result.AppendLine($@" <repository type=""{repositoryType}"" url=""{repositoryUrl}"" commit=""{repositoryCommit}""/>");
}
if (dependencyList.Length > 0)
{
result.AppendLine(@" <dependencies>");
foreach (var dependency in dependencyList)
{
result.AppendLine($@" <dependency id=""{dependency}"" version=""{version}"" />");
}
result.AppendLine(@" </dependencies>");
}
result.AppendLine(@" </metadata>");
result.AppendLine(@" <files>");
result.AppendLine(@" $CommonFileElements$");
if (fileList.Length > 0 || assemblyList.Length > 0 || libraryList.Length > 0 || folderList.Length > 0 || readmePackageLocation.Length > 0)
{
const string csName = "CSharp";
const string vbName = "VisualBasic";
const string csTarget = @"analyzers\dotnet\cs";
const string vbTarget = @"analyzers\dotnet\vb";
const string agnosticTarget = @"analyzers\dotnet";
var allTargets = new List<string>();
if (assemblyList.Any(assembly => assembly.Contains(csName, StringComparison.Ordinal)))
{
allTargets.Add(csTarget);
}
if (assemblyList.Any(assembly => assembly.Contains(vbName, StringComparison.Ordinal)))
{
allTargets.Add(vbTarget);
}
if (allTargets.Count == 0)
{
allTargets.Add(agnosticTarget);
}
foreach (string assembly in assemblyList)
{
IEnumerable<string> targets;
if (assembly.Contains(csName, StringComparison.Ordinal))
{
targets = new[] { csTarget };
}
else if (assembly.Contains(vbName, StringComparison.Ordinal))
{
targets = new[] { vbTarget };
}
else
{
targets = allTargets;
}
string assemblyNameWithoutExtension = Path.GetFileNameWithoutExtension(assembly);
foreach (var tfm in tfms)
{
string assemblyFolder = Path.Combine(artifactsBinDir, assemblyNameWithoutExtension, configuration, tfm);
string assemblyPathForNuspec = Path.Combine(assemblyFolder, assembly);
foreach (string target in targets)
{
result.AppendLine(FileElement(assemblyPathForNuspec, target));
if (Directory.Exists(assemblyFolder))
{
string resourceAssemblyName = assemblyNameWithoutExtension + ".resources.dll";
foreach (var directory in Directory.EnumerateDirectories(assemblyFolder))
{
var resourceAssemblyFullPath = Path.Combine(directory, resourceAssemblyName);
if (File.Exists(resourceAssemblyFullPath))
{
var directoryName = Path.GetFileName(directory);
string resourceAssemblyPathForNuspec = Path.Combine(artifactsBinDir, assemblyNameWithoutExtension, configuration, tfm, directoryName, resourceAssemblyName);
string targetForNuspec = Path.Combine(target, directoryName);
result.AppendLine(FileElement(resourceAssemblyPathForNuspec, targetForNuspec));
}
}
}
}
}
}
foreach (string file in fileList)
{
var fileWithPath = Path.IsPathRooted(file) ? file : Path.Combine(projectDir, file);
result.AppendLine(FileElement(fileWithPath, "buildTransitive"));
}
if (readmePackageLocation.Length > 0)
{
readmeFile = Path.IsPathRooted(readmeFile) ? readmeFile : Path.GetFullPath(Path.Combine(projectDir, readmeFile));
var directoryName = Path.GetDirectoryName(readmePackageLocation) ?? string.Empty;
result.AppendLine(FileElement(readmeFile, directoryName));
}
foreach (string file in libraryList)
{
foreach (var tfm in tfms)
{
var fileWithPath = Path.Combine(artifactsBinDir, Path.GetFileNameWithoutExtension(file), configuration, tfm, file);
// For multi-tfm case, file may not exist for all tfms.
if (File.Exists(fileWithPath))
{
result.AppendLine(FileElement(fileWithPath, Path.Combine("lib", tfm)));
}
}
}
// Skip packaging certain well-known third-party assemblies that ship within Microsoft.CodeAnalysis.Features package.
var fileNamesToExclude = new List<string>() { "Humanizer.dll", "MessagePack.dll", "MessagePack.Annotations.dll" };
foreach (string folder in folderList)
{
foreach (var tfm in tfms)
{
string folderPath = Path.Combine(artifactsBinDir, folder, configuration, tfm);
foreach (var file in Directory.EnumerateFiles(folderPath))
{
var fileExtension = Path.GetExtension(file);
if (fileExtension is ".exe" or ".dll" or ".config" or ".xml")
{
var fileName = Path.GetFileName(file);
if (fileNamesToExclude.Contains(fileName, StringComparer.OrdinalIgnoreCase))
continue;
var fileWithPath = Path.Combine(folderPath, file);
var targetPath = tfms.Length > 1 ? Path.Combine(folder, tfm) : folder;
result.AppendLine(FileElement(fileWithPath, targetPath));
}
}
}
}
result.AppendLine(FileElement(Path.Combine(assetsDir, "Install.ps1"), "tools"));
result.AppendLine(FileElement(Path.Combine(assetsDir, "Uninstall.ps1"), "tools"));
}
if (rulesetsDir.Length > 0 && Directory.Exists(rulesetsDir))
{
foreach (string ruleset in Directory.EnumerateFiles(rulesetsDir))
{
if (Path.GetExtension(ruleset) == ".ruleset")
{
result.AppendLine(FileElement(Path.Combine(rulesetsDir, ruleset), "rulesets"));
}
}
}
if (editorconfigsDir.Length > 0 && Directory.Exists(editorconfigsDir))
{
foreach (string directory in Directory.EnumerateDirectories(editorconfigsDir))
{
var directoryName = new DirectoryInfo(directory).Name;
foreach (string editorconfig in Directory.EnumerateFiles(directory))
{
result.AppendLine(FileElement(Path.Combine(directory, editorconfig), $"editorconfig\\{directoryName}"));
}
}
}
if (globalAnalyzerConfigsDir.Length > 0 && Directory.Exists(globalAnalyzerConfigsDir))
{
foreach (string globalconfig in Directory.EnumerateFiles(globalAnalyzerConfigsDir))
{
if (Path.GetExtension(globalconfig) == ".globalconfig")
{
result.AppendLine(FileElement(Path.Combine(globalAnalyzerConfigsDir, globalconfig), $"buildTransitive\\config"));
}
else
{
throw new InvalidDataException($"Encountered a file with unexpected extension: {globalconfig}");
}
}
}
if (analyzerDocumentationFileDir.Length > 0 && Directory.Exists(analyzerDocumentationFileDir) && analyzerDocumentationFileName.Length > 0)
{
var fileWithPath = Path.Combine(analyzerDocumentationFileDir, analyzerDocumentationFileName);
if (File.Exists(fileWithPath))
{
result.AppendLine(FileElement(fileWithPath, "documentation"));
}
}
if (analyzerSarifFileDir.Length > 0 && Directory.Exists(analyzerSarifFileDir) && analyzerSarifFileName.Length > 0)
{
var fileWithPath = Path.Combine(analyzerSarifFileDir, analyzerSarifFileName);
if (File.Exists(fileWithPath))
{
result.AppendLine(FileElement(fileWithPath, "documentation"));
}
}
if (analyzerConfigurationFileDir.Length > 0 && Directory.Exists(analyzerConfigurationFileDir) && analyzerConfigurationFileName.Length > 0)
{
var fileWithPath = Path.Combine(analyzerConfigurationFileDir, analyzerConfigurationFileName);
if (File.Exists(fileWithPath))
{
result.AppendLine(FileElement(fileWithPath, "documentation"));
}
}
result.AppendLine(FileElement(Path.Combine(assetsDir, "ThirdPartyNotices.txt"), ""));
result.AppendLine(@" </files>");
result.AppendLine(@"</package>");
File.WriteAllText(nuspecFile, result.ToString());
static string FileElement(string file, string target) => $@" <file src=""{file}"" target=""{target}""/>";
|