-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfunctions.cake
326 lines (263 loc) · 12.7 KB
/
functions.cake
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml.Linq;
public class ProjectTaskConfigurationManager
{
readonly IDictionary<string, HashSet<string>> _taskConfigLookup = new Dictionary<string, HashSet<string>>()
{
{ "Clean" , new HashSet<string>(new string[] { "App", "Package", "Test" }) },
{ "Build" , new HashSet<string>(new string[] { "App", "Package", "Test" }) },
{ "Test" , new HashSet<string>(new string[] { "Test" }) },
{ "Pack" , new HashSet<string>(new string[] { "App", "Package" }) },
{ "Publish" , new HashSet<string>(new string[] { "App", "Package" }) },
};
bool CanDoTask(string taskName, string projectType) => _taskConfigLookup[taskName].Contains(projectType);
public bool CanClean(ProjectConfigDescriptor projectConfig) => CanDoTask("Clean", projectConfig.Type);
public bool CanBuild(ProjectConfigDescriptor projectConfig) => CanDoTask("Build", projectConfig.Type);
public bool CanTest(ProjectConfigDescriptor projectConfig) => CanDoTask("Test", projectConfig.Type);
public bool CanPack(ProjectConfigDescriptor projectConfig) => CanDoTask("Pack", projectConfig.Type);
public bool CanPublish(ProjectConfigDescriptor projectConfig) => CanDoTask("Publish", projectConfig.Type);
}
public static class ProjectLoader
{
public static ProjectContainerDescriptor Load(ICakeContext context, string configFilePath, string basePath, string configuration)
{
var configLookup = context.DeserializeYamlFromFile<IDictionary<string, IDictionary<string, string>>>(configFilePath);
var container = new ProjectContainerDescriptor();
foreach(var projectPair in configLookup)
{
var configDescriptor = ProjectConfigDescriptor.Create(projectPair.Key, projectPair.Value[nameof(ProjectConfigDescriptor.Type)]);
var projectFilePath = context.BuildProjectFilePath(basePath, configDescriptor);
var documentDescriptor = context.ParseProject(projectFilePath, configuration);
var projectDescriptor = ProjectDescriptor.New()
.WithConfigDescriptor(configDescriptor)
.WithDocumentDescriptor(documentDescriptor);
container.Projects.Add(projectDescriptor);
}
return container;
}
}
public class ProjectContainerDescriptor
{
public ProjectContainerDescriptor()
{
Projects = new List<ProjectDescriptor>();
}
public IList<ProjectDescriptor> Projects { get; }
public void Add(ProjectDescriptor projectDescriptor) => Projects.Add(projectDescriptor);
}
public class ProjectDescriptor
{
private ProjectDescriptor() {}
public ProjectConfigDescriptor Config { get; private set; }
public ProjectDocumentDescriptor Document { get; private set; }
public static ProjectDescriptor New() => new ProjectDescriptor();
public ProjectDescriptor WithConfigDescriptor(ProjectConfigDescriptor config)
{
Config = config;
return this;
}
public ProjectDescriptor WithDocumentDescriptor(ProjectDocumentDescriptor document)
{
Document = document;
return this;
}
}
public class ProjectConfigDescriptor
{
protected ProjectConfigDescriptor(string name, string type)
{
Name = name;
Type = type;
}
public string Name { get; }
public string Type { get; }
public static ProjectConfigDescriptor Create(string name, string type) => new ProjectConfigDescriptor(name, type);
}
public static string BuildProjectFilePath(this ICakeContext context, string basePath, ProjectConfigDescriptor projectConfig) =>
$"{basePath}/{projectConfig.Name}/{projectConfig.Name}.csproj";
public static string BuildProjectDirPath(this ICakeContext context, string basePath, ProjectConfigDescriptor projectConfig) =>
$"{basePath}/{projectConfig.Name}";
public static string BuildNugetPackagePath(this ICakeContext context, DirectoryPath artifactsPath, ProjectDescriptor project, string version) =>
$"{context.MakeAbsolute(artifactsPath).FullPath}/{project.Document.DotNet.PackageId}.{version}.nupkg";
/////// Start Project Document Descriptor Code via: https://github.com/cake-contrib/Cake.Incubator/blob/develop/src/Cake.Incubator/Project/ProjectParserExtensions.cs ///////
public static ProjectDocumentDescriptor ParseProject(this ICakeContext context, FilePath project, string configuration)
{
return context.ParseProject(project, configuration, "AnyCPU");
}
public static ProjectDocumentDescriptor ParseProject(this ICakeContext context, FilePath project, string configuration, string platform)
{
if (project.IsRelative)
{
project = project.MakeAbsolute(context.Environment);
}
var projectFile = context.FileSystem.GetProjectFile(project);
var result = projectFile.ParseProjectFile(configuration, platform);
return result;
}
public static ProjectDocumentDescriptor ParseProjectFile(this IFile projectFile, string configuration, string platform = "AnyCPU")
{
var document = projectFile.LoadXml();
return document.ParseSdkProjectFile(projectFile, configuration, platform);
}
public class ProjectDocumentDescriptor
{
public XDocument ProjectXml { get; set; }
public string AssemblyName { get; set; }
public string ProjectFileFullPath { get; set; }
public FilePath ProjectFilePath { get; set; }
public string[] TargetFrameworkVersions { get; set; }
public bool IsNetCore { get; set; }
public bool IsNetFramework { get; set; }
public bool IsNetStandard { get; set; }
public DotNetProjectDescriptor DotNet { get; set; }
}
public class DotNetProjectDescriptor
{
public string AssemblyTitle { get; set; }
public bool IsPackable { get; set; } = true;
public bool IsTool { get; set; }
public bool IsWeb { get; set; }
public string NetStandardImplicitPackageVersion { get; set; }
public string PackageId { get; set; }
public string Sdk { get; set; }
public string[] TargetFrameworks { get; set; }
public bool PackAsTool { get; set; }
}
// internal static class ProjectParserExtensions
// {
static readonly Regex NetCoreTargetFrameworkRegex = new Regex("([Nn][Ee][Tt])([Cc])\\w+", RegexOptions.Compiled);
static readonly Regex NetStandardTargetFrameworkRegex = new Regex("([Nn][Ee][Tt])([Ss])\\w+", RegexOptions.Compiled);
static readonly Regex NetFrameworkTargetFrameworkRegex = new Regex("([Nn][Ee][Tt][0-9*])\\w+", RegexOptions.Compiled);
public static ProjectDocumentDescriptor ParseSdkProjectFile(this XDocument document, IFile projectFile, string config, string platform)
{
var sdk = document.GetSdk();
var projectName = projectFile.Path.GetFilenameWithoutExtension().ToString();
var targetFramework = document.GetFirstElementValue(ProjectXElement.TargetFramework);
var targetFrameworks =
document.GetFirstElementValue(ProjectXElement.TargetFrameworks)?.SplitIgnoreEmpty(';') ??
(targetFramework != null ? new[] { targetFramework } : new string[0]);
var assemblyName = document.GetFirstElementValue(ProjectXElement.AssemblyName) ?? projectName;
var packageId = document.GetFirstElementValue(ProjectXElement.PackageId) ?? assemblyName;
var netstandardVersion = document.GetFirstElementValue(ProjectXElement.NetStandardImplicitPackageVersion);
if (!bool.TryParse(document.GetFirstElementValue(ProjectXElement.IsPackable), out var isPackable))
{
isPackable = true;
}
bool.TryParse(document.GetFirstElementValue(ProjectXElement.IsTool), out var isTool);
bool.TryParse(document.GetFirstElementValue(ProjectXElement.PackAsTool), out var packAsTool);
var isNetCore = targetFrameworks.Any(x => NetCoreTargetFrameworkRegex.IsMatch(x));
var isNetStandard = targetFrameworks.Any(x => NetStandardTargetFrameworkRegex.IsMatch(x));
var isNetFramework = targetFrameworks.Any(x => NetFrameworkTargetFrameworkRegex.IsMatch(x));
return new ProjectDocumentDescriptor
{
ProjectXml = document,
ProjectFilePath = projectFile.Path,
ProjectFileFullPath = projectFile.Path.FullPath,
AssemblyName = assemblyName,
TargetFrameworkVersions = targetFrameworks,
IsNetCore = isNetCore,
IsNetStandard = isNetStandard,
IsNetFramework = isNetFramework,
DotNet = new DotNetProjectDescriptor
{
IsPackable = isPackable,
IsTool = isTool,
PackAsTool = packAsTool,
IsWeb = sdk.EqualsIgnoreCase("Microsoft.NET.Sdk.Web"),
NetStandardImplicitPackageVersion = netstandardVersion,
PackageId = packageId,
Sdk = sdk,
TargetFrameworks = targetFrameworks
}
};
}
// }
// internal static class XDocumentExtensions
// {
internal static bool IsDotNetSdk(this XDocument document) => document.GetSdk() != null;
internal static string GetSdk(this XDocument document) => document.Root?.Attribute("Sdk", true)?.Value;
internal static string GetFirstElementValue(this XDocument document, XName elementName, string config = null, string platform = "AnyCPU")
{
var elements = document.Descendants(elementName);
if (!elements.Any()) return null;
if (string.IsNullOrEmpty(config))
return elements.FirstOrDefault(x => !x.WithConfigCondition())?.Value;
return elements.FirstOrDefault(x => x.WithConfigCondition(config, platform))
?.Value ?? elements.FirstOrDefault(x => !x.WithConfigCondition())?.Value;
}
// }
// internal static class XElementExtensions
// {
internal static bool WithConfigCondition(this XElement element, string config = null, string platform = null)
{
var configAttribute = element.Attribute("Condition")?.Value.HasConfigPlatformCondition(config, platform);
if(!configAttribute.HasValue) configAttribute = element.Parent?.Attribute("Condition")?.Value.HasConfigPlatformCondition(config, platform);
return configAttribute ?? false;
}
internal static XAttribute Attribute(this XElement element, XName name, bool ignoreCase)
{
var el = element.Attribute(name);
if (el != null)
return el;
if (!ignoreCase)
return null;
var attributes = element.Attributes().Where(e => e.Name.LocalName.EqualsIgnoreCase(name.ToString()));
return !attributes.Any() ? null : attributes.First();
}
// }
// internal static class FileExtensions
// {
public static XDocument LoadXml(this IFile xmlFile)
{
XDocument document;
using (var stream = xmlFile.OpenRead())
{
document = XDocument.Load(stream);
}
return document;
}
// }
// internal static class FileSystemExtensions
// {
internal static IFile GetProjectFile(this IFileSystem fs, FilePath projectPath)
{
var file = fs.GetFile(projectPath);
if (!file.Exists)
{
const string format = "Project file '{0}' does not exist.";
var message = string.Format(CultureInfo.InvariantCulture, format, projectPath.FullPath);
throw new CakeException(message);
}
if (!file.Path.HasExtension)
{
throw new CakeException("Project file type could not be determined by extension.");
}
return file;
}
// }
// internal static class StringExtensions
// {
private const string ConfigPlatformCondition = "'$(Configuration)|$(Platform)'==";
public static bool IsNullOrEmpty(this string value) => string.IsNullOrEmpty(value);
public static bool EqualsIgnoreCase(this string source, string value) =>
source.Equals(value, StringComparison.OrdinalIgnoreCase);
public static string[] SplitIgnoreEmpty(this string value, params char[] separator) =>
value.IsNullOrEmpty() ? new string[0] : value.Split(separator, StringSplitOptions.RemoveEmptyEntries);
internal static bool HasConfigPlatformCondition(this string condition, string config = null, string platform = null) =>
config.IsNullOrEmpty()
? condition.StartsWith(ConfigPlatformCondition)
: condition.EqualsIgnoreCase($"{ConfigPlatformCondition}'{config}|{platform}'");
// }
internal static class ProjectXElement
{
internal const string AssemblyName = "AssemblyName";
internal const string IsPackable = "IsPackable";
internal const string IsTool = "IsTool";
internal const string NetStandardImplicitPackageVersion = "NetStandardImplicitPackageVersion";
internal const string PackAsTool = "PackAsTool";
internal const string PackageId = "PackageId";
internal const string TargetFramework = "TargetFramework";
internal const string TargetFrameworks = "TargetFrameworks";
}
/////// End Project Document Descriptor Code ///////