diff --git a/Microsoft.TemplateEngine.sln b/Microsoft.TemplateEngine.sln
index d43c9d2404..c84b6f9616 100644
--- a/Microsoft.TemplateEngine.sln
+++ b/Microsoft.TemplateEngine.sln
@@ -45,19 +45,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.ID
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateSearch.Common.UnitTests", "test\Microsoft.TemplateSearch.Common.UnitTests\Microsoft.TemplateSearch.Common.UnitTests.csproj", "{15304624-1774-4990-A0CC-7B9DA27A8FF6}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.TemplateLocalizer", "src\Microsoft.TemplateEngine.TemplateLocalizer\Microsoft.TemplateEngine.TemplateLocalizer.csproj", "{F8C5BBAA-99E9-46BA-87C9-9FB7F388F403}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI", "src\Microsoft.TemplateEngine.Authoring.CLI\Microsoft.TemplateEngine.Authoring.CLI.csproj", "{F8C5BBAA-99E9-46BA-87C9-9FB7F388F403}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.TemplateLocalizer.Core", "src\Microsoft.TemplateEngine.TemplateLocalizer.Core\Microsoft.TemplateEngine.TemplateLocalizer.Core.csproj", "{ED5D6873-220B-4F9D-A30B-B99E950F8E26}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.TemplateLocalizer.Core.UnitTests", "test\Microsoft.TemplateEngine.TemplateLocalizer.Core.UnitTests\Microsoft.TemplateEngine.TemplateLocalizer.Core.UnitTests.csproj", "{858B2E28-1FF8-4ED2-A356-B576BD793B71}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests", "test\Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests\Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests.csproj", "{BB38681E-BBD1-4E77-BCD5-CDB6E532B2C5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests", "test\Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests\Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj", "{BB38681E-BBD1-4E77-BCD5-CDB6E532B2C5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateSearch.TemplateDiscovery.IntegrationTests", "test\Microsoft.TemplateSearch.TemplateDiscovery.IntegrationTests\Microsoft.TemplateSearch.TemplateDiscovery.IntegrationTests.csproj", "{B0330A2C-3F10-4C46-97DF-13D187564F70}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Tasks", "src\Microsoft.TemplateEngine.Tasks\Microsoft.TemplateEngine.Tasks.csproj", "{BD758B10-A47F-4159-B9A1-997723AF7349}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.Tasks", "src\Microsoft.TemplateEngine.Authoring.Tasks\Microsoft.TemplateEngine.Authoring.Tasks.csproj", "{BD758B10-A47F-4159-B9A1-997723AF7349}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Tasks.IntegrationTests", "test\Microsoft.TemplateEngine.Tasks.IntegrationTests\Microsoft.TemplateEngine.Tasks.IntegrationTests.csproj", "{2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.Tasks.IntegrationTests", "test\Microsoft.TemplateEngine.Authoring.Tasks.IntegrationTests\Microsoft.TemplateEngine.Authoring.Tasks.IntegrationTests.csproj", "{2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5186341-2064-49AA-B398-CDF4302D2823}"
ProjectSection(SolutionItems) = preProject
@@ -66,6 +66,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.targets = Directory.Build.targets
EndProjectSection
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B794BF86-4185-4DCE-AC86-C27D5D966B9B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier", "src\Microsoft.TemplateEngine.Authoring.TemplateVerifier\Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj", "{12764D81-61A7-437A-90B6-9F245E43F457}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj", "{B1DDA327-F55E-466A-AF3E-7F039B9B51A9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj", "{D478568D-CA20-4331-9019-F585B564425E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI.UnitTests", "test\Microsoft.TemplateEngine.Authoring.CLI.UnitTests\Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj", "{E8B9226E-879F-495A-BDAD-2607844D048C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -388,6 +398,54 @@ Global
{2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}.Release|x64.Build.0 = Release|Any CPU
{2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}.Release|x86.ActiveCfg = Release|Any CPU
{2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}.Release|x86.Build.0 = Release|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x64.Build.0 = Debug|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x86.Build.0 = Debug|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Release|Any CPU.Build.0 = Release|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.ActiveCfg = Release|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.Build.0 = Release|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.ActiveCfg = Release|Any CPU
+ {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.Build.0 = Release|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x64.Build.0 = Debug|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x86.Build.0 = Debug|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x64.ActiveCfg = Release|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x64.Build.0 = Release|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x86.ActiveCfg = Release|Any CPU
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x86.Build.0 = Release|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Debug|x64.Build.0 = Debug|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Debug|x86.Build.0 = Debug|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Release|x64.ActiveCfg = Release|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Release|x64.Build.0 = Release|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Release|x86.ActiveCfg = Release|Any CPU
+ {D478568D-CA20-4331-9019-F585B564425E}.Release|x86.Build.0 = Release|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x64.Build.0 = Debug|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x86.Build.0 = Debug|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x64.ActiveCfg = Release|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x64.Build.0 = Release|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x86.ActiveCfg = Release|Any CPU
+ {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -407,18 +465,22 @@ Global
{D26D7FC1-3DCD-434C-8261-63FCCEF27278} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
{C416006F-FAE9-4263-8290-81B2AA81E024} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
{4DF4A1B9-F31C-49D1-8FEB-8DB37AEBDC0B} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
- {FBEBB725-F645-40DC-856C-D1BC7FB52CF3} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
- {95D28477-05FE-4450-86B8-D7384202AB90} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
+ {FBEBB725-F645-40DC-856C-D1BC7FB52CF3} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B}
+ {95D28477-05FE-4450-86B8-D7384202AB90} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B}
{FC7516FB-7F44-4786-ADF2-589EF06C2EDE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
{0A4EBB7D-E75B-4589-9FB3-0CD6A0B47C78} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
{15304624-1774-4990-A0CC-7B9DA27A8FF6} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
- {F8C5BBAA-99E9-46BA-87C9-9FB7F388F403} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
+ {F8C5BBAA-99E9-46BA-87C9-9FB7F388F403} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B}
{ED5D6873-220B-4F9D-A30B-B99E950F8E26} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
{858B2E28-1FF8-4ED2-A356-B576BD793B71} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
{BB38681E-BBD1-4E77-BCD5-CDB6E532B2C5} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
{B0330A2C-3F10-4C46-97DF-13D187564F70} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
- {BD758B10-A47F-4159-B9A1-997723AF7349} = {7DAC892E-ADAE-4CEB-8A0C-EDC452A5826A}
+ {BD758B10-A47F-4159-B9A1-997723AF7349} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B}
{2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
+ {12764D81-61A7-437A-90B6-9F245E43F457} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B}
+ {B1DDA327-F55E-466A-AF3E-7F039B9B51A9} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
+ {D478568D-CA20-4331-9019-F585B564425E} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
+ {E8B9226E-879F-495A-BDAD-2607844D048C} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6EA1A508-6033-4538-BF98-7F71B4E297AD}
diff --git a/eng/Signing.props b/eng/Signing.props
index 586fe4875a..f233f020f2 100644
--- a/eng/Signing.props
+++ b/eng/Signing.props
@@ -2,4 +2,20 @@
true
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/ExecutableCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/ExecutableCommand.cs
similarity index 96%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/ExecutableCommand.cs
rename to src/Microsoft.TemplateEngine.Authoring.CLI/Commands/ExecutableCommand.cs
index f8005eba36..2734c2af96 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/ExecutableCommand.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/ExecutableCommand.cs
@@ -6,7 +6,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
-namespace Microsoft.TemplateEngine.TemplateLocalizer.Commands
+namespace Microsoft.TemplateEngine.Authoring.CLI.Commands
{
///
/// Represents a together with its handler.
diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs
new file mode 100644
index 0000000000..48ccef56a5
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs
@@ -0,0 +1,204 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using System.CommandLine.Binding;
+using System.CommandLine.Parsing;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+
+namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify
+{
+ internal class VerifyCommand : ExecutableCommand
+ {
+ private const string CommandName = "verify";
+
+ private readonly Argument _templateNameArgument = new("template-short-name")
+ {
+ Description = LocalizableStrings.command_verify_help_templateName_description,
+ // 0 for case where only path is specified
+ Arity = new ArgumentArity(1, 1)
+ };
+
+ private readonly Option _remainingArguments = new Option("--template-args")
+ {
+ Description = "Template specific arguments - all joined into single enquoted string. Any needed quotations of actual arguments has to be escaped.",
+ Arity = new ArgumentArity(0, 1)
+ };
+
+ private readonly Option _templatePathOption = new(new[] { "-p", "--template-path" })
+ {
+ Description = LocalizableStrings.command_verify_help_templatePath_description,
+ };
+
+ private readonly Option _newCommandPathOption = new("--new-command-assembly")
+ {
+ Description = LocalizableStrings.command_verify_help_newCommandPath_description,
+ //TODO: do we have better way of distinguishing options that might rarely be needed?
+ // if not - we should probably add a link to more detailed help in the command description (mentioning that online help has additional options)
+ IsHidden = true
+ };
+
+ private readonly Option _templateOutputPathOption = new(new[] { "-o", "--output" })
+ {
+ Description = LocalizableStrings.command_verify_help_outputPath_description,
+ };
+
+ private readonly Option _expectationsDirectoryOption = new(new[] { "-d", "--expectations-directory" })
+ {
+ Description = LocalizableStrings.command_verify_help_expectationsDirPath_description,
+ };
+
+ private readonly Option _disableDiffToolOption = new("--disable-diff-tool")
+ {
+ Description = LocalizableStrings.command_verify_help_disableDiffTool_description,
+ };
+
+ private readonly Option _disableDefaultExcludePatternsOption = new("--disable-default-exclude-patterns")
+ {
+ Description = LocalizableStrings.command_verify_help_disableDefaultExcludes_description,
+ };
+
+ private readonly Option> _excludePatternOption = new("--exclude-pattern")
+ {
+ Description = LocalizableStrings.command_verify_help_customExcludes_description,
+ Arity = new ArgumentArity(0, 999)
+ };
+
+ private readonly Option _verifyCommandOutputOption = new("--verify-std")
+ {
+ Description = LocalizableStrings.command_verify_help_verifyOutputs_description,
+ };
+
+ private readonly Option _isCommandExpectedToFailOption = new("--fail-expected")
+ {
+ Description = LocalizableStrings.command_verify_help_expectFailure_description,
+ };
+
+ private readonly Option> _uniqueForOption = new("--unique-for")
+ {
+ Description = LocalizableStrings.command_verify_help_uniqueFor_description,
+ Arity = new ArgumentArity(0, 999),
+ AllowMultipleArgumentsPerToken = true,
+ };
+
+ public VerifyCommand(ILoggerFactory loggerFactory)
+ : base(CommandName, LocalizableStrings.command_verify_help_description, loggerFactory)
+ {
+ AddArgument(_templateNameArgument);
+ AddOption(_remainingArguments);
+ AddOption(_templatePathOption);
+ AddOption(_newCommandPathOption);
+ AddOption(_templateOutputPathOption);
+ AddOption(_expectationsDirectoryOption);
+ AddOption(_disableDiffToolOption);
+ AddOption(_disableDefaultExcludePatternsOption);
+ AddOption(_excludePatternOption);
+ AddOption(_verifyCommandOutputOption);
+ AddOption(_isCommandExpectedToFailOption);
+ FromAmongCaseInsensitive(
+ _uniqueForOption,
+ System.Enum.GetNames(typeof(UniqueForOption))
+ .Where(v => !v.Equals(UniqueForOption.None.ToString(), StringComparison.OrdinalIgnoreCase))
+ .ToArray());
+ AddOption(_uniqueForOption);
+ }
+
+ internal static VerifyCommandArgs ExtractArguments(VerifyCommand verifyCommand, ParseResult parseResult)
+ {
+ return new VerifyCommandArgs(
+ templateName: parseResult.GetValueForArgument(verifyCommand._templateNameArgument),
+ templateSpecificArgs: parseResult.GetValueForOption(verifyCommand._remainingArguments),
+ templatePath: parseResult.GetValueForOption(verifyCommand._templatePathOption),
+ dotnetNewCommandAssemblyPath: parseResult.GetValueForOption(verifyCommand._newCommandPathOption),
+ expectationsDirectory: parseResult.GetValueForOption(verifyCommand._expectationsDirectoryOption),
+ outputDirectory: parseResult.GetValueForOption(verifyCommand._templateOutputPathOption),
+ disableDiffTool: parseResult.GetValueForOption(verifyCommand._disableDiffToolOption),
+ disableDefaultVerificationExcludePatterns: parseResult.GetValueForOption(verifyCommand._disableDefaultExcludePatternsOption),
+ verificationExcludePatterns: parseResult.GetValueForOption(verifyCommand._excludePatternOption),
+ verifyCommandOutput: parseResult.GetValueForOption(verifyCommand._verifyCommandOutputOption),
+ isCommandExpectedToFail: parseResult.GetValueForOption(verifyCommand._isCommandExpectedToFailOption),
+ uniqueForOptions: parseResult.GetValueForOption(verifyCommand._uniqueForOption));
+ }
+
+ protected override async Task ExecuteAsync(VerifyCommandArgs args, CancellationToken cancellationToken = default)
+ {
+ Logger.LogInformation("Running the verification of {templateName}.", args.TemplateName);
+
+ try
+ {
+ VerificationEngine engine = new VerificationEngine(LoggerFactory ?? NullLoggerFactory.Instance);
+ TemplateVerifierOptions options = new(templateName: args.TemplateName)
+ {
+ TemplatePath = args.TemplatePath,
+ TemplateSpecificArgs = args.TemplateSpecificArgs,
+ DisableDiffTool = args.DisableDiffTool,
+ DisableDefaultVerificationExcludePatterns = args.DisableDefaultVerificationExcludePatterns,
+ VerificationExcludePatterns = args.VerificationExcludePatterns,
+ DotnetNewCommandAssemblyPath = args.DotnetNewCommandAssemblyPath,
+ ExpectationsDirectory = args.ExpectationsDirectory,
+ OutputDirectory = args.OutputDirectory,
+ VerifyCommandOutput = args.VerifyCommandOutput,
+ IsCommandExpectedToFail = args.IsCommandExpectedToFail,
+ UniqueFor = args.UniqueFor,
+ };
+ await engine.Execute(
+ options,
+ cancellationToken,
+ // We explicitly pass a path - so that the engine then process it and gets the current executing dir
+ // and treats it as a code base of caller of API (as in case of CLI usage we do not want to store
+ // expectation files in CLI sources dir)
+ Path.Combine(Environment.CurrentDirectory, "_"))
+ .ConfigureAwait(false);
+ return 0;
+ }
+ catch (Exception e)
+ {
+ Logger.LogError(LocalizableStrings.command_verify_error_failed);
+ Logger.LogError(e.Message);
+ TemplateVerificationException? ex = e as TemplateVerificationException;
+ return (int)(ex?.TemplateVerificationErrorCode ?? TemplateVerificationErrorCode.InternalError);
+ }
+ }
+
+ protected override BinderBase GetModelBinder() => new VerifyModelBinder(this);
+
+ ///
+ /// Case insensitive version for .
+ ///
+ private static void FromAmongCaseInsensitive(Option option, string[]? allowedValues = null, string? allowedHiddenValue = null)
+ {
+ allowedValues ??= Array.Empty();
+ option.AddValidator(optionResult => ValidateAllowedValues(optionResult, allowedValues, allowedHiddenValue));
+ option.AddCompletions(allowedValues);
+ }
+
+ private static void ValidateAllowedValues(OptionResult optionResult, string[] allowedValues, string? allowedHiddenValue = null)
+ {
+ var invalidArguments = optionResult.Tokens.Where(token => !allowedValues.Append(allowedHiddenValue).Contains(token.Value, StringComparer.OrdinalIgnoreCase)).ToList();
+ if (invalidArguments.Any())
+ {
+ optionResult.ErrorMessage = string.Format(
+ LocalizableStrings.command_verify_error_unrecognizedArguments,
+ string.Join(", ", invalidArguments.Select(arg => $"'{arg.Value}'")),
+ string.Join(", ", allowedValues.Select(allowedValue => $"'{allowedValue}'")));
+ }
+ }
+
+ private class VerifyModelBinder : BinderBase
+ {
+ private readonly VerifyCommand _verifyCommand;
+
+ internal VerifyModelBinder(VerifyCommand verifyCommand)
+ {
+ _verifyCommand = verifyCommand;
+ }
+
+ protected override VerifyCommandArgs GetBoundValue(BindingContext bindingContext)
+ {
+ return ExtractArguments(_verifyCommand, bindingContext.ParseResult);
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs
new file mode 100644
index 0000000000..b66212dbdc
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs
@@ -0,0 +1,149 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Text.RegularExpressions;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+
+namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify
+{
+ ///
+ /// Model class representing the arguments of .
+ ///
+ internal sealed class VerifyCommandArgs
+ {
+ public VerifyCommandArgs(string templateName, string? templateSpecificArgs)
+ {
+ TemplateName = templateName;
+ TemplateSpecificArgs = TokenizeJoinedArgs(templateSpecificArgs);
+ }
+
+ public VerifyCommandArgs(
+ string templateName,
+ string? templatePath,
+ string? templateSpecificArgs,
+ string? dotnetNewCommandAssemblyPath,
+ string? expectationsDirectory,
+ string? outputDirectory,
+ bool? disableDiffTool,
+ bool? disableDefaultVerificationExcludePatterns,
+ IEnumerable? verificationExcludePatterns,
+ bool? verifyCommandOutput,
+ bool isCommandExpectedToFail,
+ IEnumerable? uniqueForOptions)
+ : this(templateName, templateSpecificArgs)
+ {
+ TemplatePath = templatePath;
+ DotnetNewCommandAssemblyPath = dotnetNewCommandAssemblyPath;
+ ExpectationsDirectory = expectationsDirectory;
+ OutputDirectory = outputDirectory;
+ DisableDiffTool = disableDiffTool;
+ DisableDefaultVerificationExcludePatterns = disableDefaultVerificationExcludePatterns;
+ VerificationExcludePatterns = verificationExcludePatterns;
+ VerifyCommandOutput = verifyCommandOutput;
+ IsCommandExpectedToFail = isCommandExpectedToFail;
+ UniqueFor = ToUniqueForOptionFlags(uniqueForOptions);
+ }
+
+ ///
+ /// Gets the name of locally installed template.
+ ///
+ public string TemplateName { get; init; }
+
+ ///
+ /// Gets the path to template.json file or containing directory.
+ ///
+ public string? TemplatePath { get; init; }
+
+ ///
+ /// Gets the path to custom assembly implementing the new command.
+ ///
+ public string? DotnetNewCommandAssemblyPath { get; init; }
+
+ ///
+ /// Gets the template specific arguments.
+ ///
+ public IEnumerable TemplateSpecificArgs { get; init; }
+
+ ///
+ /// Gets the directory with expectation files.
+ ///
+ public string? ExpectationsDirectory { get; init; }
+
+ ///
+ /// Gets the target directory to output the generated template.
+ ///
+ public string? OutputDirectory { get; init; }
+
+ ///
+ /// If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ ///
+ public bool? DisableDiffTool { get; init; }
+
+ ///
+ /// If set to true - all template output files will be verified, unless are specified.
+ /// Otherwise a default exclusions (to be documented - mostly binaries etc.).
+ ///
+ public bool? DisableDefaultVerificationExcludePatterns { get; init; }
+
+ ///
+ /// Set of patterns defining files to be excluded from verification.
+ ///
+ public IEnumerable? VerificationExcludePatterns { get; init; }
+
+ ///
+ /// If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ ///
+ public bool? VerifyCommandOutput { get; init; }
+
+ ///
+ /// If set to true - 'dotnet new' command is expected to return nonzero return code.
+ /// Otherwise a zero error code and no error output is expected.
+ ///
+ public bool IsCommandExpectedToFail { get; init; }
+
+ ///
+ /// Gets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated.
+ ///
+ public UniqueForOption? UniqueFor { get; init; }
+
+ public static IEnumerable TokenizeJoinedArgs(string? joinedArgs)
+ {
+ if (string.IsNullOrEmpty(joinedArgs))
+ {
+ return Enumerable.Empty();
+ }
+
+ if (!joinedArgs.Contains('"') && !joinedArgs.Contains('\''))
+ {
+ return joinedArgs.Split().Where(s => !string.IsNullOrWhiteSpace(s));
+ }
+
+ return Regex.Matches(joinedArgs, @"[\""'].+?[\""']|[^ ]+")
+ .Cast()
+ .Select(m => m.Value)
+ .Select(RemoveEnclosingQuotation)
+ .Where(s => !string.IsNullOrWhiteSpace(s));
+ }
+
+ public static UniqueForOption? ToUniqueForOptionFlags(IEnumerable? uniqueForOptions)
+ {
+ return uniqueForOptions?.Aggregate(UniqueForOption.None, (a, b) => a | b);
+ }
+
+ private static string RemoveEnclosingQuotation(string input)
+ {
+ int indexOfLast = input.Length - 1;
+
+ if (
+ indexOfLast >= 1 &&
+ ((input[0] == '"' && input[indexOfLast] == '"') || (input[0] == '\'' && input[indexOfLast] == '\'')))
+ {
+ return input.Substring(1, indexOfLast - 1);
+ }
+ else
+ {
+ return input;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/LocalizeCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/LocalizeCommand.cs
new file mode 100644
index 0000000000..ffc8b97664
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/LocalizeCommand.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.TemplateEngine.Authoring.CLI.Commands
+{
+ internal class LocalizeCommand : Command
+ {
+ internal LocalizeCommand(ILoggerFactory loggerFactory)
+ : base("localize")
+ {
+ this.AddCommand(new ExportCommand(loggerFactory));
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/Export/ExportCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/export/ExportCommand.cs
similarity index 94%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/Export/ExportCommand.cs
rename to src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/export/ExportCommand.cs
index 62cabb640a..e977725d92 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/Export/ExportCommand.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/export/ExportCommand.cs
@@ -6,19 +6,19 @@
using Microsoft.Extensions.Logging;
using Microsoft.TemplateEngine.TemplateLocalizer.Core;
-namespace Microsoft.TemplateEngine.TemplateLocalizer.Commands.Export
+namespace Microsoft.TemplateEngine.Authoring.CLI.Commands
{
internal sealed class ExportCommand : ExecutableCommand
{
private const string CommandName = "export";
- private readonly Argument> _templatePathArgument = new Argument>("template-path")
+ private readonly Argument> _templatePathArgument = new("template-path")
{
Arity = ArgumentArity.OneOrMore,
Description = LocalizableStrings.command_export_help_templatePath_description,
};
- private readonly Option> _languageOption = new Option>("-l")
+ private readonly Option> _languageOption = new("-l")
{
Name = "--language",
Description = LocalizableStrings.command_export_help_language_description,
@@ -26,13 +26,13 @@ internal sealed class ExportCommand : ExecutableCommand
AllowMultipleArgumentsPerToken = true,
};
- private readonly Option _recursiveOption = new Option("-r")
+ private readonly Option _recursiveOption = new("-r")
{
Name = "--recursive",
Description = LocalizableStrings.command_export_help_recursive_description,
};
- private readonly Option _dryRunOption = new Option("-d")
+ private readonly Option _dryRunOption = new("-d")
{
Name = "--dry-run",
Description = LocalizableStrings.command_export_help_dryrun_description,
@@ -86,7 +86,7 @@ protected override async Task ExecuteAsync(ExportCommandArgs args, Cancella
ExportOptions exportOptions = new(args.DryRun, targetDirectory: null, args.Languages);
runningExportTasks.Add(
(templateJsonPath,
- new Core.TemplateLocalizer(LoggerFactory).ExportLocalizationFilesAsync(templateJsonPath, exportOptions, cancellationToken)));
+ new TemplateLocalizer.Core.TemplateLocalizer(LoggerFactory).ExportLocalizationFilesAsync(templateJsonPath, exportOptions, cancellationToken)));
}
try
@@ -139,7 +139,7 @@ protected override async Task ExecuteAsync(ExportCommandArgs args, Cancella
/// in the case that points to a directory. This parameter has no effect
/// if points to a file.
/// A path for each of the found "template.json" files.
- private IEnumerable GetTemplateJsonFiles(string path, bool searchSubdirectories)
+ private static IEnumerable GetTemplateJsonFiles(string path, bool searchSubdirectories)
{
if (string.IsNullOrEmpty(path))
{
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/Export/ExportCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/export/ExportCommandArgs.cs
similarity index 95%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/Export/ExportCommandArgs.cs
rename to src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/export/ExportCommandArgs.cs
index bb9bb8bfed..2ecbb4c369 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/Commands/Export/ExportCommandArgs.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/localize/export/ExportCommandArgs.cs
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-namespace Microsoft.TemplateEngine.TemplateLocalizer.Commands.Export
+namespace Microsoft.TemplateEngine.Authoring.CLI.Commands
{
///
/// Model class representing the arguments of .
diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs
new file mode 100644
index 0000000000..08fae9e6e6
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs
@@ -0,0 +1,7 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/LocalizableStrings.Designer.cs
rename to src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs
index 66bb954bfa..815cb30209 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/LocalizableStrings.Designer.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace Microsoft.TemplateEngine.TemplateLocalizer {
+namespace Microsoft.TemplateEngine.Authoring.CLI {
using System;
@@ -19,7 +19,7 @@ namespace Microsoft.TemplateEngine.TemplateLocalizer {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class LocalizableStrings {
@@ -39,7 +39,7 @@ internal LocalizableStrings() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TemplateEngine.TemplateLocalizer.LocalizableStrings", typeof(LocalizableStrings).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TemplateEngine.Authoring.CLI.LocalizableStrings", typeof(LocalizableStrings).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -106,7 +106,7 @@ internal static string command_export_help_templatePath_description {
}
///
- /// Looks up a localized string similar to "--export" command for the following file was cancelled: "{0}"..
+ /// Looks up a localized string similar to "export" command for the following file was cancelled: "{0}"..
///
internal static string command_export_log_cancelled {
get {
@@ -115,7 +115,7 @@ internal static string command_export_log_cancelled {
}
///
- /// Looks up a localized string similar to Execution of "--export" command has completed. {0} files were processed..
+ /// Looks up a localized string similar to Execution of "export" command has completed. {0} files were processed..
///
internal static string command_export_log_executionEnded {
get {
@@ -162,7 +162,133 @@ internal static string command_export_log_templateJsonNotFound {
}
///
- /// Looks up a localized string similar to "--{0}" command has encountered an error. See the logs for more details..
+ /// Looks up a localized string similar to Verification Failed..
+ ///
+ internal static string command_verify_error_failed {
+ get {
+ return ResourceManager.GetString("command_verify_error_failed", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Argument(s) {0} are not recognized. Must be one of: {1}..
+ ///
+ internal static string command_verify_error_unrecognizedArguments {
+ get {
+ return ResourceManager.GetString("command_verify_error_unrecognizedArguments", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Specifies pattern(s) defining files to be excluded from verification..
+ ///
+ internal static string command_verify_help_customExcludes_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_customExcludes_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Runs the template with specified arguments and compares the result with expectations files..
+ ///
+ internal static string command_verify_help_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to If set to true - all template output files will be verified, unless --exclude-pattern option is used..
+ ///
+ internal static string command_verify_help_disableDefaultExcludes_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_disableDefaultExcludes_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to If set to true - the diff tool won't be automatically started by the Verifier on verification failures..
+ ///
+ internal static string command_verify_help_disableDiffTool_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_disableDiffTool_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Specifies path to the directory with expectation files..
+ ///
+ internal static string command_verify_help_expectationsDirPath_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_expectationsDirPath_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to If set to true - 'dotnet new' command is expected to return non-zero return code..
+ ///
+ internal static string command_verify_help_expectFailure_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_expectFailure_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Specifies the path to custom assembly implementing 'dotnet new' command..
+ ///
+ internal static string command_verify_help_newCommandPath_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_newCommandPath_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Specifies the path to target directory to output the generated template to..
+ ///
+ internal static string command_verify_help_outputPath_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_outputPath_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option..
+ ///
+ internal static string command_verify_help_templateName_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_templateName_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Specifies the path to the directory with template to be verified..
+ ///
+ internal static string command_verify_help_templatePath_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_templatePath_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated..
+ ///
+ internal static string command_verify_help_uniqueFor_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_uniqueFor_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files..
+ ///
+ internal static string command_verify_help_verifyOutputs_description {
+ get {
+ return ResourceManager.GetString("command_verify_help_verifyOutputs_description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to "{0}" command has encountered an error. See the logs for more details..
///
internal static string generic_log_commandExecutionFailed {
get {
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx
similarity index 74%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/LocalizableStrings.resx
rename to src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx
index e4212abebc..3f760fd527 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/LocalizableStrings.resx
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx
@@ -161,6 +161,55 @@ Do not localize: "template.json"
Failed to find "template.json" file under the path "{0}".Do not localize: "template.json"
+
+ Verification Failed.
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+ Specifies path to the directory with expectation files.
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
"{0}" command has encountered an error. See the logs for more details.{0} will be replaced by the command name. Such as: "export" command has encountered an error.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/Microsoft.TemplateEngine.TemplateLocalizer.csproj b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj
similarity index 69%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/Microsoft.TemplateEngine.TemplateLocalizer.csproj
rename to src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj
index eb244dac5f..8250fe767c 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/Microsoft.TemplateEngine.TemplateLocalizer.csproj
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj
@@ -3,23 +3,27 @@
Exe$(NETCoreTargetFramework)
- A tool that can be used to localize template.json files.
+ A dotnet CLI tool with commands for template authoring.trueenableenabletrue
- dotnet-template-localizer
+ dotnet-template-authoring
+
+
+
+
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/Program.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs
similarity index 58%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/Program.cs
rename to src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs
index 4bb29c20cf..f9867cfe16 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/Program.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs
@@ -3,19 +3,20 @@
using System.CommandLine;
using Microsoft.Extensions.Logging;
-using Microsoft.TemplateEngine.TemplateLocalizer.Commands.Export;
+using Microsoft.TemplateEngine.Authoring.CLI.Commands;
+using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify;
-namespace Microsoft.TemplateEngine.TemplateLocalizer
+namespace Microsoft.TemplateEngine.Authoring.CLI
{
internal sealed class Program
{
internal static async Task Main(string[] args)
{
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
- ILogger logger = loggerFactory.CreateLogger();
- RootCommand rootCommand = new("dotnet-template-localizer");
- rootCommand.AddCommand(new ExportCommand(loggerFactory));
+ RootCommand rootCommand = new("dotnet-template-authoring");
+ rootCommand.AddCommand(new LocalizeCommand(loggerFactory));
+ rootCommand.AddCommand(new VerifyCommand(loggerFactory));
return await rootCommand.InvokeAsync(args).ConfigureAwait(false);
}
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf
similarity index 55%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.cs.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf
index d5883f51b8..d451e2ea19 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.cs.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Soubor „template.json“ se v cestě „{0}“ nepodařilo najít.Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ V příkazu {0} došlo k chybě. Další podrobnosti najdete v protokolech.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.de.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf
index f33dfac5c3..7f733b9dce 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.de.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Die Datei "template.json" konnte unter dem Pfad "{0}" nicht gefunden werden.Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ Fehler beim Ausführen des Befehls "{0}". Weitere Informationen finden Sie in den Protokollen.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.es.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf
index d44b1edd42..a2b0f32928 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.es.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
No se pudo encontrar el archivo "template.json" bajo la ruta "{0}".Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ El comando "{0}" ha encontrado un error. Vea los registros para obtener más información.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.fr.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf
index cd188c2870..0c44da946e 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.fr.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Échec de la recherche du fichier « template.jssur » sous le chemin d’accès «0{0} ».Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ La commande « {0} » a rencontré une erreur. Pour plus d’informations, consultez les journaux.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.it.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf
index 5ebaf4a8f5..492eac7bb9 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.it.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Non è stato possibile trovare il file "template.json" nel percorso "{0}".Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ Si è verificato un errore durante il comando "{0}". Per altri dettagli, vedere i log.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf
similarity index 57%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ja.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf
index bd5aff2f55..512acdd8c4 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ja.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
パス "{0}" の下に "template.json" ファイルが見つかりません。Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ "{0}" コマンドでエラーが発生しました。詳細については、ログを参照してください。
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ko.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf
index 86c86d09ef..c1dc26907d 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ko.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
"{0}” 경로에서 "template.json" 파일을 찾지 못했습니다.Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ "{0}" 명령에 오류가 발생했습니다. 자세한 내용은 로그를 참조하세요.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf
similarity index 56%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.pl.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf
index e9896887dd..e9d66c68c6 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.pl.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Nie można odnaleźć pliku „template.json” pod ścieżką „{0}”.Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ Wystąpił błąd przy poleceniu „{0}”. Zobacz dzienniki, aby uzyskać więcej szczegółów.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf
similarity index 55%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.pt-BR.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf
index b21e7dd7f7..3663145525 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.pt-BR.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Falhou em localizar o arquivo "template.json" no o caminho "{0}".Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ O comando "{0}" encontrou um erro. Veja os logs para mais detalhes.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf
similarity index 59%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ru.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf
index f8eb22b87e..d5d79055ff 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.ru.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
Не удалось найти файл template.json в пути "{0}".Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ Команда "{0}" обнаружила ошибку. Дополнительные сведения см. в журналах.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf
similarity index 55%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.tr.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf
index 463d3f5789..796bc4137d 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.tr.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
"{0}" yolunda "template.json" dosyası bulunamadı.Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ "{0}" komutu bir hatayla karşılaştı. Daha fazla ayrıntı için günlüklere bakın.
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf
similarity index 54%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.zh-Hans.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf
index b14e82f316..d1890f2be7 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.zh-Hans.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
在路径“{0}”下未找到“template.json”文件。Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ “{0}”命令遇到错误。如需了解详细信息,请参阅日志。
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf
similarity index 54%
rename from src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.zh-Hant.xlf
rename to src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf
index 4126aed756..1c6beb21fb 100644
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/xlf/LocalizableStrings.zh-Hant.xlf
+++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf
@@ -63,6 +63,76 @@ Do not localize: "template.json"
在路徑 "{0}" 下找不到 "template.json" 檔案。Do not localize: "template.json"
+
+
+ Verification Failed.
+
+
+
+
+ Argument(s) {0} are not recognized. Must be one of: {1}.
+ {0} and {1} is both a list of arguments
+
+
+
+ Specifies pattern(s) defining files to be excluded from verification.
+
+
+
+
+ Runs the template with specified arguments and compares the result with expectations files.
+
+
+
+
+ If set to true - all template output files will be verified, unless --exclude-pattern option is used.
+ Do not translate 'true'. Do not translate '--exclude-pattern'
+
+
+
+ If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ Do not translate 'true'.
+
+
+
+ If set to true - 'dotnet new' command is expected to return non-zero return code.
+ Do not translate 'true'. Do not translate 'dotnet new'
+
+
+
+ Specifies path to the directory with expectation files.
+
+
+
+
+ Specifies the path to custom assembly implementing 'dotnet new' command.
+ Do not translate 'dotnet new'
+
+
+
+ Specifies the path to target directory to output the generated template to.
+
+
+
+
+ Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.
+ Do not translate the '-p/--template-path'
+
+
+
+ Specifies the path to the directory with template to be verified.
+
+
+
+
+ Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.
+
+
+
+
+ If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ Do not translate 'true'. Do not translate 'dotnet new'
+ "{0}" 命令發生錯誤。如需詳細資料,請參閱記錄檔。
diff --git a/src/Microsoft.TemplateEngine.Tasks/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.Tasks/LocalizableStrings.Designer.cs
similarity index 96%
rename from src/Microsoft.TemplateEngine.Tasks/LocalizableStrings.Designer.cs
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/LocalizableStrings.Designer.cs
index 6b1bc8c794..17021014a9 100644
--- a/src/Microsoft.TemplateEngine.Tasks/LocalizableStrings.Designer.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/LocalizableStrings.Designer.cs
@@ -8,7 +8,7 @@
//
//------------------------------------------------------------------------------
-namespace Microsoft.TemplateEngine.Tasks {
+namespace Microsoft.TemplateEngine.Authoring.Tasks {
using System;
@@ -39,7 +39,7 @@ internal LocalizableStrings() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TemplateEngine.Tasks.LocalizableStrings", typeof(LocalizableStrings).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TemplateEngine.Authoring.Tasks.LocalizableStrings", typeof(LocalizableStrings).Assembly);
resourceMan = temp;
}
return resourceMan;
diff --git a/src/Microsoft.TemplateEngine.Tasks/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.Tasks/LocalizableStrings.resx
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/LocalizableStrings.resx
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/LocalizableStrings.resx
diff --git a/src/Microsoft.TemplateEngine.Tasks/Microsoft.TemplateEngine.Tasks.csproj b/src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj
similarity index 98%
rename from src/Microsoft.TemplateEngine.Tasks/Microsoft.TemplateEngine.Tasks.csproj
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj
index 50dfede5cf..907d1c4824 100644
--- a/src/Microsoft.TemplateEngine.Tasks/Microsoft.TemplateEngine.Tasks.csproj
+++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj
@@ -1,4 +1,4 @@
-
+$(NETStandardTargetFramework)
@@ -14,7 +14,6 @@
-
diff --git a/src/Microsoft.TemplateEngine.Tasks/Tasks/LocalizeTemplates.cs b/src/Microsoft.TemplateEngine.Authoring.Tasks/Tasks/LocalizeTemplates.cs
similarity index 96%
rename from src/Microsoft.TemplateEngine.Tasks/Tasks/LocalizeTemplates.cs
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/Tasks/LocalizeTemplates.cs
index 60ef275f3b..52954db8f4 100644
--- a/src/Microsoft.TemplateEngine.Tasks/Tasks/LocalizeTemplates.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/Tasks/LocalizeTemplates.cs
@@ -9,10 +9,10 @@
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Extensions.Logging;
-using Microsoft.TemplateEngine.Tasks.Utilities;
+using Microsoft.TemplateEngine.Authoring.Tasks.Utilities;
using Microsoft.TemplateEngine.TemplateLocalizer.Core;
-namespace Microsoft.TemplateEngine.Tasks
+namespace Microsoft.TemplateEngine.Authoring.Tasks
{
///
/// A task that exposes template localization functionality of
@@ -132,7 +132,7 @@ public override bool Execute()
/// in the case that points to a directory. This parameter has no effect
/// if points to a file.
/// A path for each of the found "template.json" files.
- private IEnumerable GetTemplateJsonFiles(string path, bool searchSubdirectories)
+ private static IEnumerable GetTemplateJsonFiles(string path, bool searchSubdirectories)
{
if (string.IsNullOrEmpty(path))
{
@@ -187,7 +187,7 @@ private CancellationTokenSource GetOrCreateCancellationTokenSource()
return _cancellationTokenSource;
}
- CancellationTokenSource cts = new CancellationTokenSource();
+ CancellationTokenSource cts = new();
if (Interlocked.CompareExchange(ref _cancellationTokenSource, cts, null) != null)
{
// Reference was already set. This instance is not needed.
diff --git a/src/Microsoft.TemplateEngine.Tasks/Utilities/MSBuildLogger.cs b/src/Microsoft.TemplateEngine.Authoring.Tasks/Utilities/MSBuildLogger.cs
similarity index 97%
rename from src/Microsoft.TemplateEngine.Tasks/Utilities/MSBuildLogger.cs
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/Utilities/MSBuildLogger.cs
index 3cfb71796e..80c9ddf99b 100644
--- a/src/Microsoft.TemplateEngine.Tasks/Utilities/MSBuildLogger.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/Utilities/MSBuildLogger.cs
@@ -5,7 +5,7 @@
using Microsoft.Build.Utilities;
using Microsoft.Extensions.Logging;
-namespace Microsoft.TemplateEngine.Tasks.Utilities
+namespace Microsoft.TemplateEngine.Authoring.Tasks.Utilities
{
///
/// Implements an ILogger that passes the logs to the wrapped TaskLoggingHelper.
diff --git a/src/Microsoft.TemplateEngine.Tasks/Utilities/MSBuildLoggerProvider.cs b/src/Microsoft.TemplateEngine.Authoring.Tasks/Utilities/MSBuildLoggerProvider.cs
similarity index 93%
rename from src/Microsoft.TemplateEngine.Tasks/Utilities/MSBuildLoggerProvider.cs
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/Utilities/MSBuildLoggerProvider.cs
index 4010f7d86e..a0dda0b7e5 100644
--- a/src/Microsoft.TemplateEngine.Tasks/Utilities/MSBuildLoggerProvider.cs
+++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/Utilities/MSBuildLoggerProvider.cs
@@ -4,7 +4,7 @@
using Microsoft.Build.Utilities;
using Microsoft.Extensions.Logging;
-namespace Microsoft.TemplateEngine.Tasks.Utilities
+namespace Microsoft.TemplateEngine.Authoring.Tasks.Utilities
{
///
/// An that creates s which passes
diff --git a/src/Microsoft.TemplateEngine.Tasks/build/Microsoft.TemplateEngine.Tasks.props b/src/Microsoft.TemplateEngine.Authoring.Tasks/build/Microsoft.TemplateEngine.Authoring.Tasks.props
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/build/Microsoft.TemplateEngine.Tasks.props
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/build/Microsoft.TemplateEngine.Authoring.Tasks.props
diff --git a/src/Microsoft.TemplateEngine.Tasks/build/Microsoft.TemplateEngine.Tasks.targets b/src/Microsoft.TemplateEngine.Authoring.Tasks/build/Microsoft.TemplateEngine.Authoring.Tasks.targets
similarity index 88%
rename from src/Microsoft.TemplateEngine.Tasks/build/Microsoft.TemplateEngine.Tasks.targets
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/build/Microsoft.TemplateEngine.Authoring.Tasks.targets
index affbb93b2f..e1624761a5 100644
--- a/src/Microsoft.TemplateEngine.Tasks/build/Microsoft.TemplateEngine.Tasks.targets
+++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/build/Microsoft.TemplateEngine.Authoring.Tasks.targets
@@ -1,6 +1,6 @@
- $(MSBuildThisFileDirectory)..\tasks\netstandard2.0\Microsoft.TemplateEngine.Tasks.dll
+ $(MSBuildThisFileDirectory)..\tasks\netstandard2.0\Microsoft.TemplateEngine.Authoring.Tasks.dll
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.cs.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.cs.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.cs.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.de.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.de.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.de.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.es.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.es.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.es.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.fr.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.fr.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.fr.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.it.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.it.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.it.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.ja.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.ja.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.ja.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.ko.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.ko.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.ko.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.pl.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.pl.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.pl.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.pt-BR.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.pt-BR.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.pt-BR.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.ru.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.ru.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.ru.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.tr.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.tr.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.tr.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.zh-Hans.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.zh-Hans.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.zh-Hans.xlf
diff --git a/src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.zh-Hant.xlf
similarity index 100%
rename from src/Microsoft.TemplateEngine.Tasks/xlf/LocalizableStrings.zh-Hant.xlf
rename to src/Microsoft.TemplateEngine.Authoring.Tasks/xlf/LocalizableStrings.zh-Hant.xlf
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs
new file mode 100644
index 0000000000..7e37d7e992
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal class BasicCommand : TestCommand
+ {
+ private readonly string _processName;
+
+ public BasicCommand(ILogger log, string processName, params string[] args) : base(log)
+ {
+ _processName = processName;
+ Arguments.AddRange(args.Where(a => !string.IsNullOrWhiteSpace(a)));
+ }
+
+ protected override SdkCommandSpec CreateCommand(IEnumerable args)
+ {
+ var sdkCommandSpec = new SdkCommandSpec()
+ {
+ FileName = _processName,
+ Arguments = args.ToList(),
+ WorkingDirectory = WorkingDirectory
+ };
+ return sdkCommandSpec;
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs
new file mode 100644
index 0000000000..e8edebb75b
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.DotNet.Cli.Utils;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal class CommandResultData
+ {
+ public CommandResultData(int exitCode, string stdOut, string stdErr, string workingDirectory)
+ {
+ ExitCode = exitCode;
+ StdOut = stdOut;
+ StdErr = stdErr;
+ WorkingDirectory = workingDirectory;
+ }
+
+ public CommandResultData(CommandResult commandResult)
+ : this(commandResult.ExitCode, commandResult.StdOut, commandResult.StdErr, commandResult.StartInfo.WorkingDirectory)
+ { }
+
+ public int ExitCode { get; }
+
+ public string StdOut { get; }
+
+ public string StdErr { get; }
+
+ public string WorkingDirectory { get; }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs
new file mode 100644
index 0000000000..8b3ef8d524
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal class CommandRunner : ICommandRunner
+ {
+ public CommandResultData RunCommand(TestCommand testCommand)
+ {
+ return new CommandResultData(testCommand.Execute());
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs
new file mode 100644
index 0000000000..4eb9f25ba7
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal class DotnetCommand : TestCommand
+ {
+ private readonly string _commandName;
+
+ public DotnetCommand(ILogger log, string commandName, params string[] args) : base(log)
+ {
+ Arguments.Add(commandName);
+ Arguments.AddRange(args);
+ _commandName = commandName;
+ }
+
+ public DotnetCommand WithCustomHive(string? path = null)
+ {
+ path ??= CreateTemporaryFolder();
+ Arguments.Add("--debug:custom-hive");
+ Arguments.Add(path);
+ return this;
+ }
+
+ protected override SdkCommandSpec CreateCommand(IEnumerable args)
+ {
+ var sdkCommandSpec = new SdkCommandSpec()
+ {
+ FileName = "dotnet",
+ Arguments = args.ToList(),
+ WorkingDirectory = WorkingDirectory
+ };
+ return sdkCommandSpec;
+ }
+
+ private static string CreateTemporaryFolder(string name = "")
+ {
+ string workingDir = Path.Combine(Path.GetTempPath(), "TemplateEngine.Tests", Guid.NewGuid().ToString(), name);
+ Directory.CreateDirectory(workingDir);
+ return workingDir;
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs
new file mode 100644
index 0000000000..a5344249db
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal interface ICommandRunner
+ {
+ CommandResultData RunCommand(TestCommand testCommand);
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs
new file mode 100644
index 0000000000..18c8d3fe9b
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using Microsoft.DotNet.Cli.Utils;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal class SdkCommandSpec
+ {
+ public string? FileName { get; set; }
+
+ public List Arguments { get; set; } = new List();
+
+ public Dictionary Environment { get; set; } = new Dictionary();
+
+ public List EnvironmentToRemove { get; } = new List();
+
+ public string? WorkingDirectory { get; set; }
+
+ public Command ToCommand()
+ {
+ var process = new Process()
+ {
+ StartInfo = ToProcessStartInfo()
+ };
+ var ret = new Command(process, trimtrailingNewlines: true);
+ return ret;
+ }
+
+ public ProcessStartInfo ToProcessStartInfo()
+ {
+ var ret = new ProcessStartInfo
+ {
+ FileName = FileName,
+ Arguments = EscapeArgs(),
+ UseShellExecute = false
+ };
+ foreach (var kvp in Environment)
+ {
+ ret.Environment[kvp.Key] = kvp.Value;
+ }
+ foreach (var envToRemove in EnvironmentToRemove)
+ {
+ ret.Environment.Remove(envToRemove);
+ }
+
+ if (WorkingDirectory != null)
+ {
+ ret.WorkingDirectory = WorkingDirectory;
+ }
+
+ return ret;
+ }
+
+ private string EscapeArgs()
+ {
+ // Note: this doesn't handle invoking .cmd files via "cmd /c" on Windows, which probably won't be necessary here
+ // If it is, refer to the code in WindowsExePreferredCommandSpecFactory in Microsoft.DotNet.Cli.Utils
+ return ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(Arguments);
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs
new file mode 100644
index 0000000000..c04e586b4d
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands
+{
+ internal abstract class TestCommand
+ {
+ protected TestCommand(ILogger log)
+ {
+ Log = log;
+ }
+
+ public ILogger Log { get; }
+
+ public string? WorkingDirectory { get; set; }
+
+ public List Arguments { get; set; } = new List();
+
+ public List EnvironmentToRemove { get; } = new List();
+
+ // These only work via Execute(), not when using GetProcessStartInfo()
+ public Action? CommandOutputHandler { get; set; }
+
+ public Action? ProcessStartedHandler { get; set; }
+
+ protected Dictionary Environment { get; set; } = new Dictionary();
+
+ public TestCommand WithEnvironmentVariable(string name, string value)
+ {
+ Environment[name] = value;
+ return this;
+ }
+
+ public TestCommand WithWorkingDirectory(string workingDirectory)
+ {
+ WorkingDirectory = workingDirectory;
+ return this;
+ }
+
+ public ProcessStartInfo GetProcessStartInfo(params string[] args)
+ {
+ var commandSpec = CreateCommandSpec(args);
+
+ var psi = commandSpec.ToProcessStartInfo();
+
+ return psi;
+ }
+
+ public CommandResult Execute(params string[] args)
+ {
+ IEnumerable enumerableArgs = args;
+ return Execute(enumerableArgs);
+ }
+
+ public virtual CommandResult Execute(IEnumerable args)
+ {
+ var command = CreateCommandSpec(args)
+ .ToCommand()
+ .CaptureStdOut()
+ .CaptureStdErr();
+
+ if (CommandOutputHandler != null)
+ {
+ command.OnOutputLine(CommandOutputHandler);
+ }
+
+ var result = ((Command)command).Execute(ProcessStartedHandler);
+
+ Log.LogInformation($"> {result.StartInfo.FileName} {result.StartInfo.Arguments}");
+ Log.LogInformation(result.StdOut);
+
+ if (!string.IsNullOrEmpty(result.StdErr))
+ {
+ Log.LogWarning("StdErr:");
+ Log.LogWarning(result.StdErr);
+ }
+
+ if (result.ExitCode != 0)
+ {
+ Log.LogInformation($"Exit Code: {result.ExitCode}");
+ }
+
+ return result;
+ }
+
+ protected abstract SdkCommandSpec CreateCommand(IEnumerable args);
+
+ private SdkCommandSpec CreateCommandSpec(IEnumerable args)
+ {
+ var commandSpec = CreateCommand(args);
+ foreach (var kvp in Environment)
+ {
+ commandSpec.Environment[kvp.Key] = kvp.Value;
+ }
+
+ foreach (var envToRemove in EnvironmentToRemove)
+ {
+ commandSpec.EnvironmentToRemove.Add(envToRemove);
+ }
+
+ if (WorkingDirectory != null)
+ {
+ commandSpec.WorkingDirectory = WorkingDirectory;
+ }
+
+ if (Arguments.Any())
+ {
+ commandSpec.Arguments = Arguments.Concat(commandSpec.Arguments).ToList();
+ }
+
+ return commandSpec;
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs
new file mode 100644
index 0000000000..974d69b2b9
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs
@@ -0,0 +1,8 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs
new file mode 100644
index 0000000000..abb48993ce
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.TemplateEngine.Abstractions.PhysicalFileSystem;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ internal interface IPhysicalFileSystemEx : IPhysicalFileSystem
+ {
+ ///
+ /// Same behavior as .
+ ///
+ Task ReadAllTextAsync(string path, CancellationToken cancellationToken = default);
+
+ ///
+ /// Same behavior as .
+ ///
+ Task WriteAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default);
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs
new file mode 100644
index 0000000000..06fe6f9322
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs
@@ -0,0 +1,144 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class LocalizableStrings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal LocalizableStrings() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TemplateEngine.Authoring.TemplateVerifier.LocalizableStrings", typeof(LocalizableStrings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Template installation expected to pass but it had exit code '{0}'..
+ ///
+ internal static string VerificationEngine_Error_InstallUnexpectedFail {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_InstallUnexpectedFail", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to File extension passed to scrubber should not start with dot..
+ ///
+ internal static string VerificationEngine_Error_ScrubberExtension {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_ScrubberExtension", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case..
+ ///
+ internal static string VerificationEngine_Error_StdOutFolderExists {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_StdOutFolderExists", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Template name is mandatory, but was not supplied..
+ ///
+ internal static string VerificationEngine_Error_TemplateNameMandatory {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_TemplateNameMandatory", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Unexpected error encountered..
+ ///
+ internal static string VerificationEngine_Error_Unexpected {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_Unexpected", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Template instantiation expected to pass but it had exit code '{0}'..
+ ///
+ internal static string VerificationEngine_Error_UnexpectedFail {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_UnexpectedFail", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Template instantiation expected to fail but it passed..
+ ///
+ internal static string VerificationEngine_Error_UnexpectedPass {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_UnexpectedPass", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}.
+ ///
+ internal static string VerificationEngine_Error_UnexpectedStdErr {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_UnexpectedStdErr", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The working directory already exists and is not empty..
+ ///
+ internal static string VerificationEngine_Error_WorkDirExists {
+ get {
+ return ResourceManager.GetString("VerificationEngine_Error_WorkDirExists", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx
new file mode 100644
index 0000000000..2f13e36175
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+ Template name is mandatory, but was not supplied.
+
+
+ Unexpected error encountered.
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+ Template instantiation expected to fail but it passed.
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+ The working directory already exists and is not empty.
+
+
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj
new file mode 100644
index 0000000000..8a30a6cf50
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj
@@ -0,0 +1,46 @@
+
+
+
+ Library
+ $(NETCoreTargetFramework)
+ The verification engine for the templates for .NET template engine.
+ true
+ enable
+ enable
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ LocalizableStrings.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ LocalizableStrings.Designer.cs
+
+
+
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs
new file mode 100644
index 0000000000..fb9e245e88
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.TemplateEngine.Utils;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ internal class PhysicalFileSystemEx : PhysicalFileSystem, IPhysicalFileSystemEx
+ {
+ public Task ReadAllTextAsync(string path, CancellationToken cancellationToken = default)
+ => File.ReadAllTextAsync(path, cancellationToken);
+
+ public Task WriteAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default)
+ => File.WriteAllTextAsync(path, contents, cancellationToken);
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt
new file mode 100644
index 0000000000..ab058de62d
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt
@@ -0,0 +1 @@
+#nullable enable
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt
new file mode 100644
index 0000000000..294d43a6a6
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt
@@ -0,0 +1,66 @@
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.AddScrubber(System.Action! scrubber, string? extension = null) -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition!
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.GeneralScrubber.get -> System.Action?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubbersDefinition() -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubbersDefinition(System.Action! scrubber, string? extension = null) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubersByExtension.get -> System.Collections.Generic.Dictionary!>!
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstallFailed = 106 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstantiationFailed = 100 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InternalError = 70 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InvalidOption = 127 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.TemplateDoesNotExist = 103 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.VerificationFailed = 65 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.WorkingDirectoryExists = 73 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationErrorCode.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationErrorCode.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationException(string! message, Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode templateVerificationErrorCode) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationException(string! message, Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode templateVerificationErrorCode, System.Exception! inner) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationException(System.Runtime.Serialization.SerializationInfo! info, System.Runtime.Serialization.StreamingContext context) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.CustomDirectoryVerifier.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.CustomScrubbers.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDefaultVerificationExcludePatterns.get -> bool?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDefaultVerificationExcludePatterns.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDiffTool.get -> bool?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDiffTool.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DotnetNewCommandAssemblyPath.get -> string?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DotnetNewCommandAssemblyPath.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.ExpectationsDirectory.get -> string?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.ExpectationsDirectory.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.IsCommandExpectedToFail.get -> bool?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.IsCommandExpectedToFail.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.OutputDirectory.get -> string?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.OutputDirectory.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.StandardOutputFileExtension.get -> string?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.StandardOutputFileExtension.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateName.get -> string!
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateName.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplatePath.get -> string?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplatePath.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateSpecificArgs.get -> System.Collections.Generic.IEnumerable?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateSpecificArgs.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateVerifierOptions(string! templateName) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.UniqueFor.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.UniqueFor.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerificationExcludePatterns.get -> System.Collections.Generic.IEnumerable?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerificationExcludePatterns.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerifyCommandOutput.get -> bool?
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerifyCommandOutput.init -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.WithCustomDirectoryVerifier(Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory! verifier) -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions!
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.WithCustomScrubbers(Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition! scrubbers) -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions!
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.Architecture = 1 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.None = 0 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.OsPlatform = 2 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.Runtime = 4 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.RuntimeAndVersion = 8 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.TargetFramework = 16 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.TargetFrameworkAndVersion = 32 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.Execute(Microsoft.Extensions.Options.IOptions! optionsAccessor, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken), string! sourceFile = "") -> System.Threading.Tasks.Task!
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.Extensions.Logging.ILogger! logger) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void
+Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory
+static readonly Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.Empty -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition!
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs
new file mode 100644
index 0000000000..cb975f6ca7
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Text;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+
+public class ScrubbersDefinition
+{
+ public static readonly ScrubbersDefinition Empty = new();
+
+ public ScrubbersDefinition() { }
+
+ public ScrubbersDefinition(Action scrubber, string? extension = null)
+ {
+ AddScrubber(scrubber, extension);
+ }
+
+ public Dictionary> ScrubersByExtension { get; private set; } = new Dictionary>();
+
+ public Action? GeneralScrubber { get; private set; }
+
+ public ScrubbersDefinition AddScrubber(Action scrubber, string? extension = null)
+ {
+ if (object.ReferenceEquals(this, Empty))
+ {
+ return new ScrubbersDefinition().AddScrubber(scrubber, extension);
+ }
+
+ if (string.IsNullOrWhiteSpace(extension))
+ {
+ GeneralScrubber += scrubber;
+ }
+ // This is to get the same behavior as Verify.NET
+ else
+ {
+ ScrubersByExtension[extension.Trim()] = extension.Trim().StartsWith('.')
+ ? throw new TemplateVerificationException(LocalizableStrings.VerificationEngine_Error_ScrubberExtension, TemplateVerificationErrorCode.InvalidOption)
+ : scrubber;
+ }
+
+ return this;
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs
new file mode 100644
index 0000000000..6a5a675435
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ ///
+ /// VerificationEngine error codes in thrown . Correspond to VerificationCommand exit codes.
+ ///
+ /// Exit codes based on
+ /// * https://tldp.org/LDP/abs/html/exitcodes.html
+ /// * https://github.com/openbsd/src/blob/master/include/sysexits.h.
+ /// related reference: dotnet new exit codes: https://aka.ms/templating-exit-codes.
+ /// Future exit codes should be allocated in a range of 107 - 113. If not sufficient, a range of 79 - 99 may be used as well.
+ ///
+ public enum TemplateVerificationErrorCode
+ {
+ ///
+ /// Indicates failed verification - assertions defined for the scenarios were not met.
+ /// E.g. unexpected exit code, stdout/stderr output or created templates content.
+ ///
+ VerificationFailed = 65,
+
+ ///
+ /// Unexpected internal error in . This might indicate a bug.
+ ///
+ InternalError = 70,
+
+ ///
+ /// Configured working directory already exists and is not empty - so instantiation cannot proceed without destructive changes.
+ ///
+ WorkingDirectoryExists = 73,
+
+ ///
+ /// Selected template (via name or path) was not found.
+ ///
+ TemplateDoesNotExist = 103,
+
+ ///
+ /// The template instantiation failed and results were not created.
+ ///
+ InstantiationFailed = 100,
+
+ ///
+ /// Installation/Uninstallation Failed - Processing issues.
+ ///
+ InstallFailed = 106,
+
+ ///
+ /// Unrecognized option(s) and/or argument(s) for a command.
+ ///
+ InvalidOption = 127,
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs
new file mode 100644
index 0000000000..77bc6a33f1
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.Serialization;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ [Serializable]
+ public class TemplateVerificationException : Exception
+ {
+ public TemplateVerificationException(string message, TemplateVerificationErrorCode templateVerificationErrorCode) : base(message)
+ {
+ TemplateVerificationErrorCode = templateVerificationErrorCode;
+ }
+
+ public TemplateVerificationException(string message, TemplateVerificationErrorCode templateVerificationErrorCode, Exception inner) : base(message, inner)
+ {
+ TemplateVerificationErrorCode = templateVerificationErrorCode;
+ }
+
+ protected TemplateVerificationException(
+ SerializationInfo info,
+ StreamingContext context) : base(info, context)
+ {
+ }
+
+ public TemplateVerificationErrorCode TemplateVerificationErrorCode { get; init; }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs
new file mode 100644
index 0000000000..a222406edf
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ ///
+ /// Configuration bag for the class.
+ ///
+ public class TemplateVerifierOptions : IOptions
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ public TemplateVerifierOptions(string templateName) => TemplateName = templateName;
+
+ ///
+ /// Gets the name of locally installed template.
+ ///
+ public string TemplateName { get; init; }
+
+ ///
+ /// Gets the path to template.json file or containing directory.
+ ///
+ public string? TemplatePath { get; init; }
+
+ ///
+ /// Gets the path to custom assembly implementing the new command.
+ ///
+ public string? DotnetNewCommandAssemblyPath { get; init; }
+
+ ///
+ /// Gets the template specific arguments.
+ ///
+ public IEnumerable? TemplateSpecificArgs { get; init; }
+
+ ///
+ /// Gets the directory with expectation files.
+ ///
+ public string? ExpectationsDirectory { get; init; }
+
+ ///
+ /// If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.
+ ///
+ public bool? VerifyCommandOutput { get; init; }
+
+ ///
+ /// If set to true - 'dotnet new' command is expected to return nonzero return code.
+ /// Otherwise a zero error code and no error output is expected.
+ ///
+ public bool? IsCommandExpectedToFail { get; init; }
+
+ ///
+ /// If set to true - the diff tool won't be automatically started by the Verifier on verification failures.
+ ///
+ public bool? DisableDiffTool { get; init; }
+
+ ///
+ /// If set to true - all template output files will be verified, unless are specified.
+ /// Otherwise a default exclusions (to be documented - mostly binaries etc.).
+ ///
+ public bool? DisableDefaultVerificationExcludePatterns { get; init; }
+
+ ///
+ /// Set of patterns defining files to be excluded from verification.
+ ///
+ public IEnumerable? VerificationExcludePatterns { get; init; }
+
+ ///
+ /// Gets the target directory to output the generated template.
+ ///
+ public string? OutputDirectory { get; init; }
+
+ ///
+ /// Gets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated.
+ ///
+ public UniqueForOption? UniqueFor { get; init; }
+
+ ///
+ /// Gets the delegates that perform custom scrubbing of template output contents before verifications.
+ ///
+ public ScrubbersDefinition? CustomScrubbers { get; private set; }
+
+ ///
+ /// Gets the delegate that performs custom verification of template output contents.
+ ///
+ public VerifyDirectory? CustomDirectoryVerifier { get; private set; }
+
+ ///
+ /// Gets the extension of autogeneratedfiles with stdout and stderr content.
+ ///
+ public string? StandardOutputFileExtension { get; init; }
+
+ TemplateVerifierOptions IOptions.Value => this;
+
+ ///
+ /// Adds a custom scrubber definition.
+ /// The scrubber definition can alter the template content (globally or based on the file extension), before the verifications occur.
+ ///
+ ///
+ ///
+ public TemplateVerifierOptions WithCustomScrubbers(ScrubbersDefinition scrubbers)
+ {
+ CustomScrubbers = scrubbers;
+ return this;
+ }
+
+ ///
+ /// Adds on optional custom verifier implementation.
+ /// If custom verifier is provided, no default verifications of content will be performed - the caller is responsible for performing the verifications.
+ ///
+ ///
+ ///
+ public TemplateVerifierOptions WithCustomDirectoryVerifier(VerifyDirectory verifier)
+ {
+ CustomDirectoryVerifier = verifier;
+ return this;
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs
new file mode 100644
index 0000000000..d6788bb4ac
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ [Flags]
+ public enum UniqueForOption
+ {
+ None = 0,
+ Architecture = 1,
+ OsPlatform = 2,
+ Runtime = 4,
+ RuntimeAndVersion = 8,
+ TargetFramework = 16,
+ TargetFrameworkAndVersion = 32
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs
new file mode 100644
index 0000000000..3bcbd4b19c
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs
@@ -0,0 +1,405 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.RegularExpressions;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands;
+using Microsoft.TemplateEngine.Utils;
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier
+{
+ public class VerificationEngine
+ {
+ private static readonly IReadOnlyList DefaultVerificationExcludePatterns = new List()
+ {
+ @"obj/*",
+ @"obj\*",
+ @"bin/*",
+ @"bin\*",
+ "*.exe",
+ "*.dll",
+ "*.",
+ "*.exe",
+ };
+
+ private readonly ILogger _logger;
+ private readonly ILoggerFactory? _loggerFactory;
+ private readonly ICommandRunner _commandRunner = new CommandRunner();
+ private readonly IPhysicalFileSystemEx _fileSystem = new PhysicalFileSystemEx();
+
+ static VerificationEngine()
+ {
+ // Customize diff output of verifier
+ VerifyDiffPlex.Initialize(OutputType.Compact);
+ VerifierSettings.UseSplitModeForUniqueDirectory();
+ }
+
+ public VerificationEngine(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public VerificationEngine(ILoggerFactory loggerFactory)
+ : this(loggerFactory.CreateLogger(typeof(VerificationEngine)))
+ {
+ _loggerFactory = loggerFactory;
+ }
+
+ internal VerificationEngine(ICommandRunner commandRunner, ILogger logger)
+ : this(logger)
+ {
+ _commandRunner = commandRunner;
+ }
+
+ public async Task Execute(
+ IOptions optionsAccessor,
+ CancellationToken cancellationToken = default,
+ [CallerFilePath] string sourceFile = "")
+ {
+ if (optionsAccessor == null)
+ {
+ throw new ArgumentNullException(nameof(optionsAccessor));
+ }
+
+ TemplateVerifierOptions options = optionsAccessor.Value;
+
+ CommandResultData commandResult = RunDotnetNewCommand(options, _commandRunner, _loggerFactory, _logger);
+
+ if (options.IsCommandExpectedToFail ?? false)
+ {
+ if (commandResult.ExitCode == 0)
+ {
+ throw new TemplateVerificationException(
+ LocalizableStrings.VerificationEngine_Error_UnexpectedPass,
+ TemplateVerificationErrorCode.VerificationFailed);
+ }
+ }
+ else
+ {
+ if (commandResult.ExitCode != 0)
+ {
+ throw new TemplateVerificationException(
+ string.Format(LocalizableStrings.VerificationEngine_Error_UnexpectedFail, commandResult.ExitCode),
+ TemplateVerificationErrorCode.InstantiationFailed);
+ }
+
+ // We do not expect stderr in passing command.
+ // However if verification of stdout and stderr is opted-in - we will let that verification validate the stderr content
+ if (!(options.VerifyCommandOutput ?? false) && !string.IsNullOrEmpty(commandResult.StdErr))
+ {
+ throw new TemplateVerificationException(
+ string.Format(
+ LocalizableStrings.VerificationEngine_Error_UnexpectedStdErr,
+ Environment.NewLine,
+ commandResult.StdErr),
+ TemplateVerificationErrorCode.InstantiationFailed);
+ }
+ }
+
+ await VerifyResult(options, commandResult, string.IsNullOrEmpty(sourceFile) ? string.Empty : Path.GetDirectoryName(sourceFile)!)
+ .ConfigureAwait(false);
+ }
+
+ internal static Task CreateVerificationTask(
+ string contentDir,
+ string callerDir,
+ TemplateVerifierOptions options,
+ IPhysicalFileSystemEx fileSystem)
+ {
+ List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false)
+ ? new()
+ : new(DefaultVerificationExcludePatterns);
+
+ if (options.VerificationExcludePatterns != null)
+ {
+ exclusionsList.AddRange(options.VerificationExcludePatterns);
+ }
+
+ List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList();
+
+ if (options.CustomDirectoryVerifier != null)
+ {
+ return options.CustomDirectoryVerifier(
+ contentDir,
+ new Lazy>(
+ GetVerificationContent(contentDir, globs, options.CustomScrubbers, fileSystem)));
+ }
+
+ VerifySettings verifySettings = new();
+
+ if (options.CustomScrubbers != null)
+ {
+ if (options.CustomScrubbers.GeneralScrubber != null)
+ {
+ verifySettings.AddScrubber(options.CustomScrubbers.GeneralScrubber);
+ }
+
+ foreach (var pair in options.CustomScrubbers.ScrubersByExtension)
+ {
+ verifySettings.AddScrubber(pair.Key, pair.Value);
+ }
+ }
+
+ verifySettings.UseTypeName(options.TemplateName);
+ string expectationsDir = options.ExpectationsDirectory ?? "VerifyExpectations";
+ if (!string.IsNullOrEmpty(callerDir) && !Path.IsPathRooted(expectationsDir))
+ {
+ expectationsDir = Path.Combine(callerDir, expectationsDir);
+ }
+ verifySettings.UseDirectory(expectationsDir);
+ verifySettings.UseMethodName(EncodeArgsAsPath(options.TemplateSpecificArgs));
+
+ if ((options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None)
+ {
+ foreach (UniqueForOption value in Enum.GetValues(typeof(UniqueForOption)))
+ {
+ if ((options.UniqueFor & value) == value)
+ {
+ switch (value)
+ {
+ case UniqueForOption.None:
+ break;
+ case UniqueForOption.Architecture:
+ verifySettings.UniqueForArchitecture();
+ break;
+ case UniqueForOption.OsPlatform:
+ verifySettings.UniqueForOSPlatform();
+ break;
+ case UniqueForOption.Runtime:
+ verifySettings.UniqueForRuntime();
+ break;
+ case UniqueForOption.RuntimeAndVersion:
+ verifySettings.UniqueForRuntimeAndVersion();
+ break;
+ case UniqueForOption.TargetFramework:
+ verifySettings.UniqueForTargetFramework();
+ break;
+ case UniqueForOption.TargetFrameworkAndVersion:
+ verifySettings.UniqueForTargetFrameworkAndVersion();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ if (options.DisableDiffTool ?? false)
+ {
+ verifySettings.DisableDiff();
+ }
+
+ return Verifier.VerifyDirectory(
+ contentDir,
+ (filePath) => !globs.Any(g => g.IsMatch(filePath)),
+ settings: verifySettings);
+ }
+
+ private static string EncodeArgsAsPath(IEnumerable? args)
+ {
+ if (args == null || !args.Any())
+ {
+ return string.Empty;
+ }
+
+ Regex r = new Regex(string.Format("[{0}]", Regex.Escape(new string(Path.GetInvalidFileNameChars()))));
+ return r.Replace(string.Join('#', args), string.Empty);
+ }
+
+ private static CommandResultData RunDotnetNewCommand(TemplateVerifierOptions options, ICommandRunner commandRunner, ILoggerFactory? loggerFactory, ILogger logger)
+ {
+ // Create temp folder and instantiate there
+ string workingDir = options.OutputDirectory ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+ if (Directory.Exists(workingDir) && Directory.EnumerateFileSystemEntries(workingDir).Any())
+ {
+ throw new TemplateVerificationException(LocalizableStrings.VerificationEngine_Error_WorkDirExists, TemplateVerificationErrorCode.WorkingDirectoryExists);
+ }
+
+ Directory.CreateDirectory(workingDir);
+ ILogger commandLogger = loggerFactory?.CreateLogger(typeof(DotnetCommand)) ?? logger;
+ string? customHiveLocation = null;
+
+ if (!string.IsNullOrEmpty(options.TemplatePath))
+ {
+ customHiveLocation = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName(), "home");
+ var installCommand =
+ new DotnetCommand(commandLogger, "new", "install", options.TemplatePath)
+ .WithCustomHive(customHiveLocation)
+ .WithWorkingDirectory(workingDir);
+
+ CommandResultData installCommandResult = commandRunner.RunCommand(installCommand);
+
+ if (installCommandResult.ExitCode != 0)
+ {
+ throw new TemplateVerificationException(
+ string.Format(LocalizableStrings.VerificationEngine_Error_InstallUnexpectedFail, installCommandResult.ExitCode),
+ TemplateVerificationErrorCode.InstantiationFailed);
+ }
+ }
+
+ List cmdArgs = new();
+ if (!string.IsNullOrEmpty(options.DotnetNewCommandAssemblyPath))
+ {
+ cmdArgs.Add(options.DotnetNewCommandAssemblyPath);
+ }
+ cmdArgs.Add(options.TemplateName);
+ if (options.TemplateSpecificArgs != null)
+ {
+ cmdArgs.AddRange(options.TemplateSpecificArgs);
+ }
+
+ if (!string.IsNullOrEmpty(customHiveLocation))
+ {
+ cmdArgs.Add("--debug:custom-hive");
+ cmdArgs.Add(customHiveLocation);
+ }
+ else
+ {
+ cmdArgs.Add("--debug:ephemeral-hive");
+ }
+
+ // let's make sure the template outputs are named and placed deterministically
+ if (!cmdArgs.Select(arg => arg.Trim())
+ .Any(arg => new[] { "-n", "--name" }.Contains(arg, StringComparer.OrdinalIgnoreCase)))
+ {
+ cmdArgs.Add("-n");
+ cmdArgs.Add(options.TemplateName);
+ }
+ if (!cmdArgs.Select(arg => arg.Trim())
+ .Any(arg => new[] { "-o", "--output" }.Contains(arg, StringComparer.OrdinalIgnoreCase)))
+ {
+ cmdArgs.Add("-o");
+ cmdArgs.Add(options.TemplateName);
+ }
+
+ var command = new DotnetCommand(loggerFactory?.CreateLogger(typeof(DotnetCommand)) ?? logger, "new", cmdArgs.ToArray())
+ .WithWorkingDirectory(workingDir);
+ var result = commandRunner.RunCommand(command);
+ if (!string.IsNullOrEmpty(customHiveLocation))
+ {
+ Directory.Delete(customHiveLocation, true);
+ }
+ return result;
+ }
+
+ private static void DummyMethod()
+ { }
+
+ private static async IAsyncEnumerable<(string FilePath, string ScrubbedContent)> GetVerificationContent(
+ string contentDir,
+ List globs,
+ ScrubbersDefinition? scrubbers,
+ IPhysicalFileSystemEx fileSystem)
+ {
+ foreach (string filePath in fileSystem.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories))
+ {
+ if (globs.Any(g => g.IsMatch(filePath)))
+ {
+ continue;
+ }
+
+ string content = await fileSystem.ReadAllTextAsync(filePath).ConfigureAwait(false);
+
+ if (scrubbers != null)
+ {
+ string extension = Path.GetExtension(filePath);
+ // This is to get the same behavior as Verify.NET
+ if (extension.Length > 0)
+ {
+ extension = extension[1..];
+ }
+ StringBuilder? sb = null;
+
+ if (!string.IsNullOrEmpty(extension) && scrubbers.ScrubersByExtension.TryGetValue(extension, out Action? scrubber))
+ {
+ sb = new StringBuilder(content);
+ scrubber(sb);
+ }
+
+ if (scrubbers.GeneralScrubber != null)
+ {
+ sb ??= new StringBuilder(content);
+ scrubbers.GeneralScrubber(sb);
+ }
+
+ if (sb != null)
+ {
+ content = sb.ToString();
+ }
+ }
+
+ yield return new(filePath, content);
+ }
+ }
+
+ private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData commandResultData, string callerDir)
+ {
+ UsesVerifyAttribute a = new UsesVerifyAttribute();
+ // https://github.com/VerifyTests/Verify/blob/d8cbe38f527d6788ecadd6205c82803bec3cdfa6/src/Verify.Xunit/Verifier.cs#L10
+ // need to simulate execution from tests
+ var v = DummyMethod;
+ MethodInfo mi = v.Method;
+ a.Before(mi);
+
+ if (args.VerifyCommandOutput ?? false)
+ {
+ if (_fileSystem.DirectoryExists(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir)))
+ {
+ throw new TemplateVerificationException(
+ string.Format(
+ LocalizableStrings.VerificationEngine_Error_StdOutFolderExists,
+ SpecialFiles.StandardStreamsDir),
+ TemplateVerificationErrorCode.InternalError);
+ }
+
+ _fileSystem.CreateDirectory(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir));
+
+ await _fileSystem.WriteAllTextAsync(
+ Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (args.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)),
+ commandResultData.StdOut)
+ .ConfigureAwait(false);
+
+ await _fileSystem.WriteAllTextAsync(
+ Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (args.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)),
+ commandResultData.StdErr)
+ .ConfigureAwait(false);
+ }
+
+ Task verifyTask = CreateVerificationTask(commandResultData.WorkingDirectory, callerDir, args, _fileSystem);
+
+ try
+ {
+ await verifyTask.ConfigureAwait(false);
+ }
+ catch (Exception e)
+ {
+ if (e is TemplateVerificationException)
+ {
+ throw;
+ }
+ if (e.GetType().Name == "VerifyException")
+ {
+ throw new TemplateVerificationException(e.Message, TemplateVerificationErrorCode.VerificationFailed);
+ }
+ else
+ {
+ _logger.LogError(e, LocalizableStrings.VerificationEngine_Error_Unexpected);
+ throw;
+ }
+ }
+ }
+
+ private static class SpecialFiles
+ {
+ public const string StandardStreamsDir = "std-streams";
+ public const string StdOut = "stdout";
+ public const string StdErr = "stderr";
+ public const string DefaultExtension = ".txt";
+ public static readonly string[] FileNames = { StdOut, StdErr };
+ }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs
new file mode 100644
index 0000000000..9612b2054c
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+
+///
+/// Delegate signature for performing custom directory content verifications.
+/// Expectable verification failures should be signaled with .
+/// API provider can either perform content enumeration, skipping and scrubbing by themselves (then the second argument can be ignored)
+/// or the contentFetcher can be awaited to get the content of files - filtered by exclusion patterns and scrubbed by scrubbers.
+///
+///
+///
+///
+public delegate Task VerifyDirectory(string contentDirectory, Lazy> contentFetcher);
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf
new file mode 100644
index 0000000000..bf14b01923
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf
new file mode 100644
index 0000000000..1313fa12b5
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf
new file mode 100644
index 0000000000..5b705cebdc
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf
new file mode 100644
index 0000000000..0094d0c9c7
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf
new file mode 100644
index 0000000000..6078316e39
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf
new file mode 100644
index 0000000000..b2de952bf6
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf
new file mode 100644
index 0000000000..8afaac8f26
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf
new file mode 100644
index 0000000000..ab145ca527
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf
new file mode 100644
index 0000000000..5f67ef0a9a
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf
new file mode 100644
index 0000000000..4914bd0a68
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf
new file mode 100644
index 0000000000..f52ec73632
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf
new file mode 100644
index 0000000000..b2445f8d93
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf
new file mode 100644
index 0000000000..42f012f204
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Template installation expected to pass but it had exit code '{0}'.
+
+
+
+
+ File extension passed to scrubber should not start with dot.
+
+
+
+
+ The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.
+ {0} is a folder path
+
+
+
+ Template name is mandatory, but was not supplied.
+
+
+
+
+ Unexpected error encountered.
+
+
+
+
+ Template instantiation expected to pass but it had exit code '{0}'.
+ {0} is an exit code number
+
+
+
+ Template instantiation expected to fail but it passed.
+
+
+
+
+ Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}
+ {0} is newline, {1} is the standard error content
+
+
+
+ The working directory already exists and is not empty.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.TemplateEngine.TemplateLocalizer/Globals.cs b/src/Microsoft.TemplateEngine.TemplateLocalizer/Globals.cs
deleted file mode 100644
index 8919a19b38..0000000000
--- a/src/Microsoft.TemplateEngine.TemplateLocalizer/Globals.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Runtime.CompilerServices;
-
-[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs b/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs
new file mode 100644
index 0000000000..e7e5faef33
--- /dev/null
+++ b/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs
@@ -0,0 +1,43 @@
+// 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.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.TemplateEngine.Utils
+{
+ ///
+ /// Provides support for asynchronous lazy initialization.
+ ///
+ /// The type to be lazily initialized.
+ public class AsyncLazy : Lazy>
+ {
+ // inspired by https://devblogs.microsoft.com/pfxteam/asynclazyt/
+
+ ///
+ /// Creates a lazy type that performs the value construction asynchronously on a first access.
+ ///
+ /// Synchronous value factory that will be executed asynchronously on first access in separate task.
+ public AsyncLazy(Func valueFactory)
+ : base(() => Task.Factory.StartNew(valueFactory, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default))
+ { }
+
+ ///
+ /// Creates a lazy type that performs the value construction asynchronously on a first access.
+ ///
+ /// Asynchronous value factory that will be executed on a first access.
+ public AsyncLazy(Func> taskFactory)
+ : base(() => Task.Factory.StartNew(
+ () => taskFactory(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
+ .Unwrap())
+ { }
+
+ ///
+ /// The awaiter to be awaited in order to trigger asynchronous value creation.
+ ///
+ ///
+ public TaskAwaiter GetAwaiter() { return Value.GetAwaiter(); }
+ }
+}
diff --git a/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt
index 5f282702bb..14d64ba4ce 100644
--- a/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt
@@ -1 +1,4 @@
-
\ No newline at end of file
+Microsoft.TemplateEngine.Utils.AsyncLazy
+Microsoft.TemplateEngine.Utils.AsyncLazy.AsyncLazy(System.Func!>! taskFactory) -> void
+Microsoft.TemplateEngine.Utils.AsyncLazy.AsyncLazy(System.Func! valueFactory) -> void
+Microsoft.TemplateEngine.Utils.AsyncLazy.GetAwaiter() -> System.Runtime.CompilerServices.TaskAwaiter
\ No newline at end of file
diff --git a/test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/ExportCommandFailureTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs
similarity index 96%
rename from test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/ExportCommandFailureTests.cs
rename to test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs
index 52dfb04e29..f1174eaa43 100644
--- a/test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/ExportCommandFailureTests.cs
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs
@@ -3,10 +3,9 @@
using System.Globalization;
using Microsoft.TemplateEngine.TestHelper.Commands;
-using Xunit;
using Xunit.Abstractions;
-namespace Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests
+namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests
{
public class ExportCommandFailureTests : IDisposable
{
@@ -146,7 +145,7 @@ private async Task CreateTemplateAndExport(string templateJsonCont
{
string filePath = Path.Combine(_workingDirectory, Path.GetRandomFileName() + ".json");
await File.WriteAllTextAsync(filePath, templateJsonContent);
- return new BasicCommand(_log, "dotnet", Path.GetFullPath("Microsoft.TemplateEngine.TemplateLocalizer.dll"), "export", filePath);
+ return new BasicCommand(_log, "dotnet", Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), "localize", "export", filePath);
}
}
}
diff --git a/test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/ExportCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandTests.cs
similarity index 88%
rename from test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/ExportCommandTests.cs
rename to test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandTests.cs
index 090dc9bab7..ad61f3a2ab 100644
--- a/test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/ExportCommandTests.cs
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandTests.cs
@@ -6,7 +6,7 @@
using Newtonsoft.Json.Linq;
using Xunit;
-namespace Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests
+namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests
{
public class ExportCommandTests : TestBase, IDisposable
{
@@ -14,7 +14,7 @@ public class ExportCommandTests : TestBase, IDisposable
public ExportCommandTests()
{
- _workingDirectory = Path.Combine(Path.GetTempPath(), "Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests", Path.GetRandomFileName());
+ _workingDirectory = Path.Combine(Path.GetTempPath(), "Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests", Path.GetRandomFileName());
Directory.CreateDirectory(_workingDirectory);
}
@@ -29,7 +29,7 @@ public async Task LocFilesAreExported()
string[] exportedFiles = await RunTemplateLocalizer(
GetTestTemplateJsonContent(),
_workingDirectory,
- args: new string[] { "export", _workingDirectory })
+ args: new string[] { "localize", "export", _workingDirectory })
.ConfigureAwait(false);
Assert.True(exportedFiles.Length > 0);
@@ -44,7 +44,7 @@ public async Task LocFilesAreExported()
public async Task LocFilesAreExportedFirstTime()
{
string testTemplate = GetTestTemplateInTempDir("TemplateWithSourceName");
- int runResult = await Program.Main(new[] { "export", testTemplate }).ConfigureAwait(false);
+ int runResult = await Program.Main(new[] { "localize", "export", testTemplate }).ConfigureAwait(false);
Assert.Equal(0, runResult);
string[] exportedFiles;
string expectedExportDirectory = Path.Combine(testTemplate, ".template.config", "localize");
@@ -69,7 +69,7 @@ public async Task LocFilesAreExportedFirstTime()
public async Task EnglishLocFilesAreOverwritten()
{
string testTemplate = GetTestTemplateInTempDir("TemplateWithSourceName");
- int runResult = await Program.Main(new[] { "export", testTemplate }).ConfigureAwait(false);
+ int runResult = await Program.Main(new[] { "localize", "export", testTemplate }).ConfigureAwait(false);
Assert.Equal(0, runResult);
string expectedExportDirectory = Path.Combine(testTemplate, ".template.config", "localize");
string enLocFile = Path.Combine(expectedExportDirectory, "templatestrings.en.json");
@@ -88,7 +88,7 @@ public async Task EnglishLocFilesAreOverwritten()
templateJsonContent.Property("author")!.Value = "New Author";
File.WriteAllText(baseConfig, templateJsonContent.ToString());
- runResult = await Program.Main(new[] { "export", testTemplate }).ConfigureAwait(false);
+ runResult = await Program.Main(new[] { "localize", "export", testTemplate }).ConfigureAwait(false);
Assert.Equal(0, runResult);
Assert.True(File.Exists(enLocFile));
Assert.True(File.Exists(deLocFile));
@@ -107,7 +107,7 @@ public async Task TemplateLanguageLocFilesAreOverwritten()
templateJsonContent.AddFirst(new JProperty("authoringLanguage", "de"));
File.WriteAllText(baseConfig, templateJsonContent.ToString());
- int runResult = await Program.Main(new[] { "export", testTemplate }).ConfigureAwait(false);
+ int runResult = await Program.Main(new[] { "localize", "export", testTemplate }).ConfigureAwait(false);
Assert.Equal(0, runResult);
string expectedExportDirectory = Path.Combine(testTemplate, ".template.config", "localize");
string enLocFile = Path.Combine(expectedExportDirectory, "templatestrings.en.json");
@@ -125,7 +125,7 @@ public async Task TemplateLanguageLocFilesAreOverwritten()
templateJsonContent.Property("author")!.Value = "New Author";
File.WriteAllText(baseConfig, templateJsonContent.ToString());
- runResult = await Program.Main(new[] { "export", testTemplate }).ConfigureAwait(false);
+ runResult = await Program.Main(new[] { "localize", "export", testTemplate }).ConfigureAwait(false);
Assert.Equal(0, runResult);
Assert.True(File.Exists(enLocFile));
Assert.True(File.Exists(deLocFile));
@@ -141,7 +141,7 @@ public async Task LocFilesAreNotExportedWithDryRun()
string[] exportedFiles = await RunTemplateLocalizer(
GetTestTemplateJsonContent(),
_workingDirectory,
- args: new string[] { "export", _workingDirectory, "--dry-run" })
+ args: new string[] { "localize", "export", _workingDirectory, "--dry-run" })
.ConfigureAwait(false);
Assert.Empty(exportedFiles);
@@ -153,7 +153,7 @@ public async Task LanguagesCanBeOverriden()
string[] exportedFiles = await RunTemplateLocalizer(
GetTestTemplateJsonContent(),
_workingDirectory,
- args: new string[] { "export", _workingDirectory, "--language", "tr", "de" })
+ args: new string[] { "localize", "export", _workingDirectory, "--language", "tr", "de" })
.ConfigureAwait(false);
Assert.Equal(2, exportedFiles.Length);
@@ -172,7 +172,7 @@ public async Task SubdirectoriesAreNotSearchedByDefault()
await File.WriteAllTextAsync(Path.Combine(_workingDirectory, "subdir", "template.json"), templateJson).ConfigureAwait(false);
await File.WriteAllTextAsync(Path.Combine(_workingDirectory, "subdir2", "template.json"), templateJson).ConfigureAwait(false);
- int runResult = await Program.Main(new string[] { "export", _workingDirectory, "--language", "es" }).ConfigureAwait(false);
+ int runResult = await Program.Main(new string[] { "localize", "export", _workingDirectory, "--language", "es" }).ConfigureAwait(false);
// Error: no templates found under the given folder.
Assert.NotEqual(0, runResult);
@@ -190,7 +190,7 @@ public async Task SubdirectoriesCanBeSearched()
await File.WriteAllTextAsync(Path.Combine(_workingDirectory, "subdir", ".template.config", "template.json"), templateJson).ConfigureAwait(false);
await File.WriteAllTextAsync(Path.Combine(_workingDirectory, ".template.config", "template.json"), templateJson).ConfigureAwait(false);
- int runResult = await Program.Main(new string[] { "export", _workingDirectory, "--language", "es", "--recursive" }).ConfigureAwait(false);
+ int runResult = await Program.Main(new string[] { "localize", "export", _workingDirectory, "--language", "es", "--recursive" }).ConfigureAwait(false);
Assert.Equal(0, runResult);
Assert.True(File.Exists(Path.Combine(_workingDirectory, "subdir", ".template.config", "localize", "templatestrings.es.json")));
@@ -204,7 +204,7 @@ public async Task SubdirectoriesWithoutTemplateConfigFileAreNotSearched()
await File.WriteAllTextAsync(Path.Combine(_workingDirectory, "subdir", "template.json"), GetTestTemplateJsonContent()).ConfigureAwait(false);
- int runResult = await Program.Main(new string[] { "export", _workingDirectory, "--language", "es", "--recursive" }).ConfigureAwait(false);
+ int runResult = await Program.Main(new string[] { "localize", "export", _workingDirectory, "--language", "es", "--recursive" }).ConfigureAwait(false);
// Error: no templates found under the given folder.
Assert.NotEqual(0, runResult);
diff --git a/test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj
similarity index 90%
rename from test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests.csproj
rename to test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj
index 49f8884b81..cde80c6391 100644
--- a/test/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests/Microsoft.TemplateEngine.TemplateLocalizer.IntegrationTests.csproj
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs
new file mode 100644
index 0000000000..cca64ae001
--- /dev/null
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs
@@ -0,0 +1,214 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using FluentAssertions;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+using Microsoft.TemplateEngine.TestHelper;
+using Microsoft.TemplateEngine.TestHelper.Commands;
+using Microsoft.TemplateEngine.Tests;
+using Xunit.Abstractions;
+
+namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests
+{
+ [UsesVerify]
+ public class VerifyCommandTests : TestBase
+ {
+ private readonly ITestOutputHelper _log;
+
+ public VerifyCommandTests(ITestOutputHelper log)
+ {
+ _log = log;
+ }
+
+ [Fact]
+ public void VerifyCommandFullDevLoop()
+ {
+ // dots issue https://github.com/VerifyTests/Verify/issues/658
+ string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty));
+ string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty));
+ string templateOutputDir = "path with spaces";
+
+ var cmd = new BasicCommand(
+ _log,
+ "dotnet",
+ Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"),
+ "verify",
+ "console",
+ "--template-args",
+ "--use-program-main -o \"" + templateOutputDir + "\" --no-restore",
+ "--verify-std",
+ "-o",
+ workingDir,
+ "--expectations-directory",
+ expectationsDir,
+ "--disable-diff-tool",
+ "--unique-for",
+ "architecture",
+ "--unique-for",
+ "RuntimeAndVersion");
+
+ cmd.Execute()
+ .Should()
+ .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed)
+ .And.HaveStdOutContaining("Verification Failed.");
+
+ // Assert template created
+ Directory.Exists(Path.Combine(workingDir, templateOutputDir)).Should().BeTrue();
+ File.Exists(Path.Combine(workingDir, templateOutputDir, "console.csproj")).Should().BeTrue();
+ File.Exists(Path.Combine(workingDir, templateOutputDir, "Program.cs")).Should().BeTrue();
+
+ // Assert verification files created
+ Directory.Exists(expectationsDir).Should().BeTrue();
+ Directory.GetDirectories(expectationsDir).Length.Should().Be(2);
+ //for simplicity move to the created dir
+ expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal));
+ File.Exists(Path.Combine(expectationsDir, templateOutputDir, "console.csproj")).Should().BeTrue();
+ File.Exists(Path.Combine(expectationsDir, templateOutputDir, "Program.cs")).Should().BeTrue();
+ File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue();
+ File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue();
+ Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4);
+ // .verified files are only created when diff tool is used - that is however turned off in CI
+ //File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue();
+ //File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue();
+ //File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue();
+ //File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue();
+
+ // .verified files are only created when diff tool is used - that is however turned off in CI
+ //File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty();
+ //File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty();
+ //File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty();
+ //File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty();
+ File.ReadAllText(Path.Combine(expectationsDir, templateOutputDir, "console.csproj").UnixifyLineBreaks()).Should()
+ .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateOutputDir, "console.csproj")).UnixifyLineBreaks());
+ File.ReadAllText(Path.Combine(expectationsDir, templateOutputDir, "Program.cs").UnixifyLineBreaks()).Should()
+ .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateOutputDir, "Program.cs")).UnixifyLineBreaks());
+
+ // Accept changes
+ string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal);
+ Directory.Delete(verifiedDir, false);
+ Directory.Move(expectationsDir, verifiedDir);
+
+ //reset the expectations dir to where it was before previous run
+ expectationsDir = Path.GetDirectoryName(expectationsDir)!;
+
+ // And run again same scenario - verification should succeed now
+ string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+ var cmd2 = new BasicCommand(
+ _log,
+ "dotnet",
+ Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"),
+ "verify",
+ "console",
+ "--template-args",
+ "--use-program-main -o \"" + templateOutputDir + "\" --no-restore",
+ "--verify-std",
+ "-o",
+ workingDir2,
+ "--expectations-directory",
+ expectationsDir,
+ "--unique-for",
+ "architecture",
+ "--unique-for",
+ "RuntimeAndVersion");
+
+ cmd2.Execute()
+ .Should()
+ .Pass()
+ .And.HaveStdOutContaining("Running the verification of console.")
+ .And.NotHaveStdErr();
+
+ Directory.Delete(workingDir, true);
+ Directory.Delete(workingDir2, true);
+ Directory.Delete(expectationsDir, true);
+ }
+
+ [Fact]
+ public void VerifyCommandFullDevLoopWithNotInstalledTemplate()
+ {
+ // dots issue https://github.com/VerifyTests/Verify/issues/658
+ string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty));
+ string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty));
+ string templateShortName = "TestAssets.SampleTestTemplate";
+ string templateOutputDir = templateShortName;
+
+ //get the template location
+ string executingAssemblyPath = this.GetType().Assembly.Location;
+ string templateLocation = Path.Combine(TestTemplatesLocation, "TestTemplate");
+
+ var cmd = new BasicCommand(
+ _log,
+ "dotnet",
+ Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"),
+ "verify",
+ templateShortName,
+ "--template-path",
+ templateLocation,
+ "--template-args",
+ "--paramB true",
+ "--verify-std",
+ "-o",
+ workingDir,
+ "--expectations-directory",
+ expectationsDir,
+ "--disable-diff-tool");
+
+ cmd.Execute()
+ .Should()
+ .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed)
+ .And.HaveStdOutContaining("Verification Failed.");
+
+ // Assert template created
+ Directory.Exists(Path.Combine(workingDir, templateOutputDir)).Should().BeTrue();
+ File.Exists(Path.Combine(workingDir, templateOutputDir, "Test.cs")).Should().BeTrue();
+
+ // Assert verification files created
+ Directory.Exists(expectationsDir).Should().BeTrue();
+ Directory.GetDirectories(expectationsDir).Length.Should().Be(2);
+ //for simplicity move to the created dir
+ expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal));
+ File.Exists(Path.Combine(expectationsDir, templateOutputDir, "Test.cs")).Should().BeTrue();
+ File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue();
+ File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue();
+ Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(3);
+
+ File.ReadAllText(Path.Combine(expectationsDir, templateOutputDir, "Test.cs").UnixifyLineBreaks()).Should()
+ .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateOutputDir, "Test.cs")).UnixifyLineBreaks());
+
+ // Accept changes
+ string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal);
+ Directory.Delete(verifiedDir, false);
+ Directory.Move(expectationsDir, verifiedDir);
+
+ //reset the expectations dir to where it was before previous run
+ expectationsDir = Path.GetDirectoryName(expectationsDir)!;
+
+ // And run again same scenario - verification should succeed now
+ string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+ var cmd2 = new BasicCommand(
+ _log,
+ "dotnet",
+ Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"),
+ "verify",
+ templateShortName,
+ "--template-path",
+ templateLocation,
+ "--template-args",
+ "--paramB true",
+ "--verify-std",
+ "-o",
+ workingDir2,
+ "--expectations-directory",
+ expectationsDir);
+
+ cmd2.Execute()
+ .Should()
+ .Pass()
+ .And.HaveStdOutContaining(string.Format("Running the verification of {0}.", templateShortName))
+ .And.NotHaveStdErr();
+
+ Directory.Delete(workingDir, true);
+ Directory.Delete(workingDir2, true);
+ Directory.Delete(expectationsDir, true);
+ }
+ }
+}
diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj
new file mode 100644
index 0000000000..92aab69eda
--- /dev/null
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj
@@ -0,0 +1,14 @@
+
+
+ $(NETCoreTargetFramework)
+ false
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandArgsTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandArgsTests.cs
new file mode 100644
index 0000000000..8017674a03
--- /dev/null
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandArgsTests.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using FluentAssertions;
+using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify;
+
+namespace Microsoft.TemplateEngine.Authoring.CLI.UnitTests
+{
+ public class VerifyCommandArgsTests
+ {
+ [Theory]
+ [InlineData(null, new string[] { })]
+ [InlineData(" ", new string[] { })]
+ [InlineData(" a b c", new string[] { "a", "b", "c" })]
+ [InlineData(" abc ", new string[] { "abc" })]
+ [InlineData("a \"b c \" d ", new string[] { "a", "b c ", "d" })]
+ [InlineData("aa \" bb cc \"dd", new string[] { "aa", " bb cc ", "dd" })]
+ [InlineData("aa q= 'bb cc'dd", new string[] { "aa", "q=", "bb cc", "dd" })]
+ public void OnTokenizeJoinedArgsResultIsExpected(string? input, IEnumerable expectedOutput)
+ {
+ var result = VerifyCommandArgs.TokenizeJoinedArgs(input);
+ result.Should().BeEquivalentTo(expectedOutput, options => options.WithStrictOrdering());
+ }
+ }
+}
diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs
new file mode 100644
index 0000000000..cd8577e5b9
--- /dev/null
+++ b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Concurrent;
+using System.CommandLine;
+using FluentAssertions;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+
+namespace Microsoft.TemplateEngine.Authoring.CLI.UnitTests
+{
+ public class VerifyCommandTests
+ {
+ public static IEnumerable