-
Notifications
You must be signed in to change notification settings - Fork 10k
/
TemplatePackageInstaller.cs
148 lines (128 loc) · 5.98 KB
/
TemplatePackageInstaller.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Internal;
using Microsoft.Extensions.CommandLineUtils;
using Xunit;
using Xunit.Abstractions;
namespace Templates.Test.Helpers;
internal static class TemplatePackageInstaller
{
private static bool _haveReinstalledTemplatePackages;
private static readonly string[] _templatePackages = new[]
{
"Microsoft.DotNet.Common.ItemTemplates",
"Microsoft.DotNet.Common.ProjectTemplates.2.1",
"Microsoft.DotNet.Test.ProjectTemplates.2.1",
"Microsoft.DotNet.Web.Client.ItemTemplates",
"Microsoft.DotNet.Web.ItemTemplates",
"Microsoft.DotNet.Web.ProjectTemplates.1.x",
"Microsoft.DotNet.Web.ProjectTemplates.2.0",
"Microsoft.DotNet.Web.ProjectTemplates.2.1",
"Microsoft.DotNet.Web.ProjectTemplates.2.2",
"Microsoft.DotNet.Web.ProjectTemplates.3.0",
"Microsoft.DotNet.Web.ProjectTemplates.3.1",
"Microsoft.DotNet.Web.ProjectTemplates.5.0",
"Microsoft.DotNet.Web.ProjectTemplates.6.0",
"Microsoft.DotNet.Web.ProjectTemplates.7.0",
"Microsoft.DotNet.Web.ProjectTemplates.8.0",
"Microsoft.DotNet.Web.ProjectTemplates.9.0",
"Microsoft.DotNet.Web.ProjectTemplates.10.0",
"Microsoft.AspNetCore.Blazor.Templates",
};
public static string CustomHivePath { get; } = Path.GetFullPath((string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix")))
? typeof(TemplatePackageInstaller)
.Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.Single(s => s.Key == "CustomTemplateHivePath").Value
: Path.Combine("Hives", ".templateEngine"));
public static async Task EnsureTemplatingEngineInitializedAsync(ITestOutputHelper output)
{
if (!_haveReinstalledTemplatePackages)
{
if (Directory.Exists(CustomHivePath))
{
Directory.Delete(CustomHivePath, recursive: true);
}
await InstallTemplatePackages(output);
_haveReinstalledTemplatePackages = true;
}
}
public static async Task<ProcessEx> RunDotNetNew(ITestOutputHelper output, string arguments)
{
var proc = ProcessEx.Run(
output,
AppContext.BaseDirectory,
DotNetMuxer.MuxerPathOrDefault(),
//--debug:disable-sdk-templates means, don't include C:\Program Files\dotnet\templates, aka. what comes with SDK, so we don't need to uninstall
//--debug:custom-hive means, don't install templates on CI/developer machine, instead create new temporary instance
$"new {arguments} --debug:disable-sdk-templates --debug:custom-hive \"{CustomHivePath}\"");
await proc.Exited;
return proc;
}
private static async Task InstallTemplatePackages(ITestOutputHelper output)
{
string packagesDir;
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix")))
{
packagesDir = ".";
}
else
{
packagesDir = typeof(TemplatePackageInstaller).Assembly
.GetCustomAttributes<AssemblyMetadataAttribute>()
.Single(a => a.Key == "ArtifactsShippingPackagesDir").Value;
}
var builtPackages = Directory.EnumerateFiles(packagesDir, "*Templates*.nupkg")
.Where(p => _templatePackages.Any(t => Path.GetFileName(p).StartsWith(t, StringComparison.OrdinalIgnoreCase)))
.ToArray();
if (builtPackages.Length == 0)
{
throw new InvalidOperationException($"Failed to find required templates in {packagesDir}. Please ensure the *Templates*.nupkg have been built.");
}
Assert.Equal(3, builtPackages.Length);
await VerifyCannotFindTemplateAsync(output, "web");
await VerifyCannotFindTemplateAsync(output, "webapp");
await VerifyCannotFindTemplateAsync(output, "webapi");
await VerifyCannotFindTemplateAsync(output, "mvc");
foreach (var packagePath in builtPackages)
{
output.WriteLine($"Installing templates package {packagePath}...");
var result = await RunDotNetNew(output, $"install \"{packagePath}\"");
Assert.True(result.ExitCode == 0, result.GetFormattedOutput());
}
await VerifyCanFindTemplate(output, "webapp");
await VerifyCanFindTemplate(output, "web");
await VerifyCanFindTemplate(output, "webapi");
}
private static async Task VerifyCanFindTemplate(ITestOutputHelper output, string templateName)
{
var proc = await RunDotNetNew(output, $"--list");
if (!(proc.Output.Contains($" {templateName} ") || proc.Output.Contains($",{templateName}") || proc.Output.Contains($"{templateName},")))
{
throw new InvalidOperationException($"Couldn't find {templateName} as an option in {proc.Output}.");
}
}
private static async Task VerifyCannotFindTemplateAsync(ITestOutputHelper output, string templateName)
{
// Verify we really did remove the previous templates
var tempDir = Path.Combine(AppContext.BaseDirectory, Path.GetRandomFileName(), Guid.NewGuid().ToString("D"));
Directory.CreateDirectory(tempDir);
try
{
var proc = await RunDotNetNew(output, $"\"{templateName}\"");
if (!proc.Error.Contains("No templates or subcommands found matching:"))
{
throw new InvalidOperationException($"Failed to uninstall previous templates. The template '{templateName}' could still be found.");
}
}
finally
{
Directory.Delete(tempDir, recursive: true);
}
}
}