First step to ingest template engine (#5065)

* First step to ingest template engine

Please do not merge yet
@piotrp @seancpeters @livarocc

* Localization

* Attempt to get a build going

Rename program.cs to New3Command.cs
Move TableFormatter into its own file
Consume template engine packages version 1.0.0-beta1-20161218-24
Temporarily add MyGet templating feed so that package restore will work

* Update ExtendedCommandParser

Make short form args prefer longer runs of characters in the source
parameter before falling back to p:shortname syntax
Change scoping for a few methods to get rid of inconsistent visiblity
errors

* Fix package installation wildcards

* Cleanup New3Command, fix review issue, bump version, sorting for template list

* Installation, loc fix, help formatting

* Use latest TemplateEngine packages

* New3 unit tests

* Fixed formatting on csproj files

* Add the build steps to add templates to the layout

* Change tests slightly to make comparisons easier

Also fixes the wrong flag getting passed to set language

* Fixes for 127, 128, 130, 131 - help display

* Sync to latest TemplateEngine version

Absorbs new search logic

* All tests passing

Cleaner New3Command
Support for project/item template contexts

* Try to make tests more durable

* Disable test parallelization for dotnet-new tests

* Update web SDK and template engine versions

* Remove AI package feed

* Simplify CLI interface to Template Engine

* Fix host identifier and update to latest packages

* Update template engine & Web SDK versions

* Fix template engine version

* Remove UsingTask and redeclaration of property
This commit is contained in:
Mike Lorbetske 2017-01-06 14:48:27 -08:00 committed by Piotr Puszkiewicz
parent 5e7b946ad7
commit decec5f8da
15 changed files with 328 additions and 5 deletions

View file

@ -3,6 +3,7 @@
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="templating" value="https://dotnet.myget.org/F/templating/api/v3/index.json" />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="cli-deps" value="https://dotnet.myget.org/F/cli-deps/api/v3/index.json" />
<add key="roslyn" value="https://dotnet.myget.org/f/roslyn/api/v3/index.json" />

View file

@ -0,0 +1,39 @@
<Project ToolsVersion="15.0" DefaultTargets="CopyTemplateToOutput">
<!-- workaround for https://github.com/Microsoft/msbuild/issues/885 -->
<!-- renaming the property because the original property is a global property and therefore
cannot be redefined at runtime. -->
<Import Project="Microsoft.DotNet.Cli.tasks" />
<Target Name="CopyTemplateToOutput"
DependsOnTargets="PrepareBundledTemplateProps;
EnsureTemplateRestored;
GetTemplateItemsToCopy"
Inputs="@(TemplateContent)"
Outputs="@(TemplateContent->'$(TemplateLayoutDirectory)/%(RecursiveDir)%(FileName)%(Extension)')">
<Copy SourceFiles="@(TemplateContent)"
DestinationFiles="@(TemplateContent->'$(TemplateLayoutDirectory)/%(RecursiveDir)%(FileName)%(Extension)')" />
<Message Text="Copied template $(TemplatePackageName) from $(TemplateNuPkgPath) to $(TemplateLayoutDirectory)."
Importance="High" />
</Target>
<Target Name="GetTemplateItemsToCopy">
<ItemGroup>
<TemplateContent Include="$(TemplateNuPkgPath)/$(TemplatePackageName.ToLower()).$(TemplatePackageVersion.ToLower()).nupkg" />
</ItemGroup>
</Target>
<Target Name="EnsureTemplateRestored"
Condition="!Exists('$(TemplateNuPkgPath)/$(TemplatePackageName.ToLower()).nuspec')">
<DotNetRestore ToolPath="$(Stage0Directory)"
ProjectPath="$(MSBuildThisFileDirectory)/templates/templates.csproj"
AdditionalParameters="/p:TemplatePackageName=$(TemplatePackageName) /p:TemplatePackageVersion=$(TemplatePackageVersion)" />
</Target>
<Target Name="PrepareBundledTemplateProps">
<PropertyGroup>
<TemplateNuPkgPath>$(NuGetPackagesDir)/$(TemplatePackageName.ToLower())/$(TemplatePackageVersion.ToLower())</TemplateNuPkgPath>
</PropertyGroup>
</Target>
</Project>

View file

@ -0,0 +1,10 @@
<Project ToolsVersion="15.0">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<BundledTemplate Include="Microsoft.DotNet.Common.ItemTemplates" Version="$(TemplateEngineVersion)" />
<BundledTemplate Include="Microsoft.DotNet.Common.ProjectTemplates" Version="$(TemplateEngineVersion)" />
<BundledTemplate Include="Microsoft.DotNet.Test.ProjectTemplates" Version="$(TemplateEngineVersion)" />
<BundledTemplate Include="Microsoft.DotNet.Web.ProjectTemplates" Version="$(TemplateEngineVersion)" />
</ItemGroup>
</Project>

View file

@ -18,6 +18,7 @@
SetupStage;
CompileStage;
PublishSdks;
PublishTemplates;
BuildProjectsForNuGetPackages;
GetNuGetPackagesArchive;" />
@ -263,4 +264,25 @@
Projects="@(SdksToBundle)">
</MSBuild>
</Target>
<Target Name="PublishTemplates"
DependsOnTargets="Prepare">
<ItemGroup>
<TemplatesToBundle Include="build/Microsoft.DotNet.Cli.BundledTemplates.proj">
<Properties>
CLIBuildDll=$(CLIBuildDll);
NuGetPackagesDir=$(NuGetPackagesDir);
TemplateLayoutDirectory=$(SdkOutputDirectory)/Templates;
TemplatePackageName=%(BundledTemplate.Identity);
TemplatePackageVersion=%(BundledTemplate.Version);
Stage0Directory=$(Stage0Directory)
</Properties>
</TemplatesToBundle>
</ItemGroup>
<MSBuild
BuildInParallel="False"
Projects="@(TemplatesToBundle)">
</MSBuild>
</Target>
</Project>

View file

@ -4,7 +4,8 @@
<CLI_MSBuild_Version>15.1.0-preview-000503-01</CLI_MSBuild_Version>
<CLI_Roslyn_Version>2.0.0-rc3-61212-03</CLI_Roslyn_Version>
<CLI_NETSDK_Version>1.0.0-alpha-20170105-1</CLI_NETSDK_Version>
<CLI_WEBSDK_Version>1.0.0-alpha-20170104-1-189</CLI_WEBSDK_Version>
<CLI_WEBSDK_Version>1.0.0-alpha-20170106-1-203</CLI_WEBSDK_Version>
<CLI_TestPlatform_Version>15.0.0-preview-20161227-02</CLI_TestPlatform_Version>
<TemplateEngineVersion>1.0.0-beta1-20170106-79</TemplateEngineVersion>
</PropertyGroup>
</Project>

View file

@ -3,6 +3,7 @@
<Import Project="Microsoft.DotNet.Cli.tasks" />
<Import Project="prepare/CheckPrereqs.targets" />
<Import Project="Microsoft.DotNet.Cli.BundledSdks.props" />
<Import Project="Microsoft.DotNet.Cli.BundledTemplates.props" />
<Import Project="Microsoft.DotNet.Cli.DependencyVersions.props" />
<Target Name="Prepare"

View file

@ -0,0 +1,17 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="$(TemplatePackageName)">
<Version>$(TemplatePackageVersion)</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -16,6 +16,7 @@ using Microsoft.DotNet.Tools.List;
using Microsoft.DotNet.Tools.Migrate;
using Microsoft.DotNet.Tools.MSBuild;
using Microsoft.DotNet.Tools.New;
using Microsoft.DotNet.Tools.New3;
using Microsoft.DotNet.Tools.NuGet;
using Microsoft.DotNet.Tools.Pack;
using Microsoft.DotNet.Tools.Publish;
@ -42,6 +43,7 @@ namespace Microsoft.DotNet.Cli
["migrate"] = MigrateCommand.Run,
["msbuild"] = MSBuildCommand.Run,
["new"] = NewCommand.Run,
["new3"] = New3CommandShim.Run,
["nuget"] = NuGetCommand.Run,
["pack"] = PackCommand.Run,
["publish"] = PublishCommand.Run,

View file

@ -0,0 +1,71 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Cli;
using Microsoft.TemplateEngine.Edge;
using Microsoft.TemplateEngine.Orchestrator.RunnableProjects;
using Microsoft.TemplateEngine.Orchestrator.RunnableProjects.Config;
using Microsoft.TemplateEngine.Orchestrator.RunnableProjects.Macros;
using Microsoft.TemplateEngine.Utils;
namespace Microsoft.DotNet.Tools.New3
{
internal class New3CommandShim
{
private const string HostIdentifier = "dotnetcli";
private const string HostVersion = "1.0.0";
private const string CommandName = "new3";
public static int Run(string[] args)
{
return New3Command.Run(CommandName, CreateHost(), FirstRun, args);
}
private static ITemplateEngineHost CreateHost()
{
var builtIns = new Dictionary<Guid, Func<Type>>
{
{ new Guid("0C434DF7-E2CB-4DEE-B216-D7C58C8EB4B3"), () => typeof(RunnableProjectGenerator) },
{ new Guid("3147965A-08E5-4523-B869-02C8E9A8AAA1"), () => typeof(BalancedNestingConfig) },
{ new Guid("3E8BCBF0-D631-45BA-A12D-FBF1DE03AA38"), () => typeof(ConditionalConfig) },
{ new Guid("A1E27A4B-9608-47F1-B3B8-F70DF62DC521"), () => typeof(FlagsConfig) },
{ new Guid("3FAE1942-7257-4247-B44D-2DDE07CB4A4A"), () => typeof(IncludeConfig) },
{ new Guid("3D33B3BF-F40E-43EB-A14D-F40516F880CD"), () => typeof(RegionConfig) },
{ new Guid("62DB7F1F-A10E-46F0-953F-A28A03A81CD1"), () => typeof(ReplacementConfig) },
{ new Guid("370996FE-2943-4AED-B2F6-EC03F0B75B4A"), () => typeof(ConstantMacro) },
{ new Guid("BB625F71-6404-4550-98AF-B2E546F46C5F"), () => typeof(EvaluateMacro) },
{ new Guid("10919008-4E13-4FA8-825C-3B4DA855578E"), () => typeof(GuidMacro) },
{ new Guid("F2B423D7-3C23-4489-816A-41D8D2A98596"), () => typeof(NowMacro) },
{ new Guid("011E8DC1-8544-4360-9B40-65FD916049B7"), () => typeof(RandomMacro) },
{ new Guid("8A4D4937-E23F-426D-8398-3BDBD1873ADB"), () => typeof(RegexMacro) },
{ new Guid("B57D64E0-9B4F-4ABE-9366-711170FD5294"), () => typeof(SwitchMacro) },
{ new Guid("10919118-4E13-4FA9-825C-3B4DA855578E"), () => typeof(CaseChangeMacro) }
}.ToList();
var preferences = new Dictionary<string, string>
{
{ "prefs:language", "C#" }
};
return new DefaultTemplateEngineHost(HostIdentifier, HostVersion, CultureInfo.CurrentCulture.Name, preferences, builtIns);
}
private static void FirstRun(ITemplateEngineHost host, IInstaller installer)
{
var templatesDir = Path.Combine(Paths.Global.BaseDir, "Templates");
if (templatesDir.Exists())
{
var layoutIncludedPackages = host.FileSystem.EnumerateFiles(templatesDir, "*.nupkg", SearchOption.TopDirectoryOnly);
installer.InstallPackages(layoutIncludedPackages);
}
}
}
}

View file

@ -71,6 +71,8 @@
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions">
<Version>1.0.1-beta-000933</Version>
</PackageReference>
<PackageReference Include="Microsoft.TemplateEngine.Cli" Version="$(TemplateEngineVersion)" />
<PackageReference Include="Microsoft.TemplateEngine.Orchestrator.RunnableProjects" Version="$(TemplateEngineVersion)" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">

View file

@ -2,12 +2,10 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Construction;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using FluentAssertions;
using Xunit;
namespace Microsoft.DotNet.New.Tests
{

View file

@ -0,0 +1,68 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.Tools.Test.Utilities;
using System;
using System.IO;
using FluentAssertions;
using Xunit;
namespace Microsoft.DotNet.New3.Tests
{
public class GivenThatIWantANewApp : New3TestBase
{
[Fact]
public void When_dotnet_new_is_invoked_mupliple_times_it_should_fail()
{
var rootPath = TestAssetsManager.CreateTestDirectory(identifier: "new3").Path;
new TestCommand("dotnet") { WorkingDirectory = rootPath }
.Execute($"new3 console");
DateTime expectedState = Directory.GetLastWriteTime(rootPath);
var result = new TestCommand("dotnet") { WorkingDirectory = rootPath }
.ExecuteWithCapturedOutput($"new3 console");
DateTime actualState = Directory.GetLastWriteTime(rootPath);
Assert.Equal(expectedState, actualState);
result.Should().Fail();
}
[Fact]
public void RestoreDoesNotUseAnyCliProducedPackagesOnItsTemplates()
{
string[] cSharpTemplates = new[] { "console", "classlib", "mstest", "xunit", "web", "mvc", "webapi" };
var rootPath = TestAssetsManager.CreateTestDirectory(identifier: "new3").Path;
var packagesDirectory = Path.Combine(rootPath, "packages");
foreach (string cSharpTemplate in cSharpTemplates)
{
var projectFolder = Path.Combine(rootPath, cSharpTemplate + "1");
Directory.CreateDirectory(projectFolder);
CreateAndRestoreNewProject(cSharpTemplate, projectFolder, packagesDirectory);
}
Directory.EnumerateFiles(packagesDirectory, $"*.nupkg", SearchOption.AllDirectories)
.Should().NotContain(p => p.Contains("Microsoft.DotNet.Cli.Utils"));
}
private void CreateAndRestoreNewProject(
string projectType,
string projectFolder,
string packagesDirectory)
{
new TestCommand("dotnet") { WorkingDirectory = projectFolder }
.Execute($"new3 {projectType}")
.Should().Pass();
new RestoreCommand()
.WithWorkingDirectory(projectFolder)
.Execute($"--packages {packagesDirectory} /p:SkipInvalidConfigurations=true")
.Should().Pass();
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using FluentAssertions;
namespace Microsoft.DotNet.New3.Tests
{
public class GivenThatIWantANewAppWithSpecifiedType : New3TestBase
{
[Theory]
[InlineData("C#", "console", false)]
[InlineData("C#", "classlib", false)]
[InlineData("C#", "mstest", false)]
[InlineData("C#", "xunit", false)]
[InlineData("C#", "web", true)]
[InlineData("C#", "mvc", true)]
[InlineData("C#", "webapi", true)]
[InlineData("F#", "console", false)]
[InlineData("F#", "classlib", false)]
[InlineData("F#", "mstest", false)]
[InlineData("F#", "xunit", false)]
[InlineData("F#", "mvc", true)]
public void TemplateRestoresAndBuildsWithoutWarnings(
string language,
string projectType,
bool useNuGetConfigForAspNet)
{
string rootPath = TestAssetsManager.CreateTestDirectory(identifier: $"new3_{language}_{projectType}").Path;
new TestCommand("dotnet") { WorkingDirectory = rootPath }
.Execute($"new3 {projectType} -lang {language}")
.Should().Pass();
if (useNuGetConfigForAspNet)
{
File.Copy("NuGet.tempaspnetpatch.config", Path.Combine(rootPath, "NuGet.Config"));
}
new TestCommand("dotnet")
.WithWorkingDirectory(rootPath)
.Execute($"restore")
.Should().Pass();
var buildResult = new TestCommand("dotnet")
.WithWorkingDirectory(rootPath)
.ExecuteWithCapturedOutput("build")
.Should().Pass()
.And.NotHaveStdErr();
}
}
}

View file

@ -0,0 +1,36 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace Microsoft.DotNet.New3.Tests
{
public class New3TestBase : TestBase
{
private static readonly object InitializationSync = new object();
private static bool _isInitialized;
protected New3TestBase()
{
if (_isInitialized)
{
return;
}
lock (InitializationSync)
{
if (_isInitialized)
{
return;
}
//Force any previously computed configuration to be cleared
new TestCommand("dotnet").Execute("new3 --debug:reinit");
_isInitialized = true;
}
}
}
}

View file

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>