-
Notifications
You must be signed in to change notification settings - Fork 10.2k
/
Copy pathCreateFrameworkListFile.cs
129 lines (108 loc) · 4.83 KB
/
CreateFrameworkListFile.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 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.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace RepoTasks
{
public class CreateFrameworkListFile : Task
{
/// <summary>
/// Files to extract basic information from and include in the list.
/// </summary>
[Required]
public ITaskItem[] Files { get; set; }
[Required]
public string TargetFile { get; set; }
/// <summary>
/// Extra attributes to place on the root node.
///
/// %(Identity): Attribute name.
/// %(Value): Attribute value.
/// </summary>
public ITaskItem[] RootAttributes { get; set; }
public override bool Execute()
{
XAttribute[] rootAttributes = RootAttributes
?.Select(item => new XAttribute(item.ItemSpec, item.GetMetadata("Value")))
.ToArray();
var frameworkManifest = new XElement("FileList", rootAttributes);
var usedFileProfiles = new HashSet<string>();
foreach (var f in Files
.Select(item => new
{
Item = item,
Filename = Path.GetFileName(item.ItemSpec),
AssemblyName = FileUtilities.GetAssemblyName(item.ItemSpec),
FileVersion = FileUtilities.GetFileVersion(item.ItemSpec),
IsNative = item.GetMetadata("IsNativeImage") == "true",
IsSymbolFile = item.GetMetadata("IsSymbolFile") == "true",
PackagePath = item.GetMetadata("PackagePath")
})
.Where(f =>
!f.IsSymbolFile &&
(f.Filename.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || f.IsNative))
.OrderBy(f => f.Filename, StringComparer.Ordinal))
{
string path = Path.Combine(f.PackagePath, f.Filename).Replace('\\', '/');
string type = f.IsNative ? "Native" : "Managed";
var element = new XElement("File", new XAttribute("Path", path));
if (path.StartsWith("analyzers/", StringComparison.Ordinal))
{
type = "Analyzer";
if (path.EndsWith(".resources.dll", StringComparison.Ordinal))
{
// omit analyzer resources
continue;
}
var pathParts = path.Split('/');
if (pathParts.Length < 3 || !pathParts[1].Equals("dotnet", StringComparison.Ordinal) || pathParts.Length > 4)
{
Log.LogError($"Unexpected analyzer path format {path}. Expected 'analyzers/dotnet(/language)/analyzer.dll");
}
// Check if we have enough parts for language directory and include it
if (pathParts.Length > 3)
{
element.Add(new XAttribute("Language", pathParts[2]));
}
}
element.Add(new XAttribute("Type", type));
if (f.AssemblyName != null)
{
byte[] publicKeyToken = f.AssemblyName.GetPublicKeyToken();
string publicKeyTokenHex;
if (publicKeyToken != null)
{
publicKeyTokenHex = BitConverter.ToString(publicKeyToken)
.ToLowerInvariant()
.Replace("-", "");
}
else
{
Log.LogError($"No public key token found for assembly {f.Item.ItemSpec}");
publicKeyTokenHex = "";
}
element.Add(
new XAttribute("AssemblyName", f.AssemblyName.Name),
new XAttribute("PublicKeyToken", publicKeyTokenHex),
new XAttribute("AssemblyVersion", f.AssemblyName.Version));
}
else if (!f.IsNative)
{
// This file isn't managed and isn't native. Leave it off the list.
continue;
}
element.Add(new XAttribute("FileVersion", f.FileVersion));
frameworkManifest.Add(element);
}
Directory.CreateDirectory(Path.GetDirectoryName(TargetFile));
File.WriteAllText(TargetFile, frameworkManifest.ToString());
return !Log.HasLoggedErrors;
}
}
}