diff --git a/src/Microsoft.TemplateEngine.Cli/AnsiConsole.cs b/src/Microsoft.TemplateEngine.Cli/AnsiConsole.cs index f9184234751..62a3c3ce5a4 100644 --- a/src/Microsoft.TemplateEngine.Cli/AnsiConsole.cs +++ b/src/Microsoft.TemplateEngine.Cli/AnsiConsole.cs @@ -1,13 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + namespace Microsoft.TemplateEngine.Cli { internal class AnsiConsole { private int _boldRecursion; - private AnsiConsole(TextWriter writer) + internal AnsiConsole(TextWriter writer) { Writer = writer; diff --git a/src/Microsoft.TemplateEngine.Cli/CliTemplateInfo.cs b/src/Microsoft.TemplateEngine.Cli/CliTemplateInfo.cs index 9db70465027..544dcd5bdda 100644 --- a/src/Microsoft.TemplateEngine.Cli/CliTemplateInfo.cs +++ b/src/Microsoft.TemplateEngine.Cli/CliTemplateInfo.cs @@ -4,6 +4,8 @@ #nullable enable using Microsoft.TemplateEngine.Abstractions; +using Microsoft.TemplateEngine.Abstractions.TemplatePackage; +using Microsoft.TemplateEngine.Edge.Settings; using Microsoft.TemplateEngine.Utils; namespace Microsoft.TemplateEngine.Cli @@ -120,5 +122,32 @@ internal static IEnumerable FromTemplateInfo(IEnumerable new CliTemplateInfo(templateInfo, hostSpecificDataLoader.ReadHostSpecificTemplateData(templateInfo))); } + + /// + /// Gets the managed template package which contain the template, otherwise. + /// + /// + /// The method might throw exceptions if call throws. + /// + internal async Task GetManagedTemplatePackageAsync( + TemplatePackageManager templatePackageManager, + CancellationToken cancellationToken) + { + ITemplatePackage templatePackage = await GetTemplatePackageAsync(templatePackageManager, cancellationToken).ConfigureAwait(false); + return templatePackage as IManagedTemplatePackage; + } + + /// + /// Gets the template package which contains the template. + /// + /// + /// The method might throw exceptions if call throws. + /// + internal Task GetTemplatePackageAsync( + TemplatePackageManager templatePackageManager, + CancellationToken cancellationToken) + { + return templatePackageManager.GetTemplatePackageAsync(this, cancellationToken); + } } } diff --git a/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.Help.cs b/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.Help.cs index 01143da484d..7ff8013afab 100644 --- a/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.Help.cs +++ b/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.Help.cs @@ -56,7 +56,7 @@ public void WriteHelp(HelpContext context, ParseResult parseResult) } if (selectedTemplateGroups.Take(2).Count() > 1) { - HandleAmbiguousTemplateGroup(instantiateCommandArgs); + HandleAmbiguousTemplateGroup(environmentSettings, templatePackageManager, selectedTemplateGroups, Reporter.Output); return; } @@ -78,8 +78,8 @@ public void WriteHelp(HelpContext context, ParseResult parseResult) if (!VerifyMatchingTemplates( environmentSettings, - context.Output, matchingTemplates, + Reporter.Output, out IEnumerable? templatesToShow)) { //error @@ -129,8 +129,8 @@ internal static IEnumerable GetMatchingTemplates( internal static bool VerifyMatchingTemplates( IEngineEnvironmentSettings environmentSettings, - TextWriter writer, IEnumerable matchingTemplates, + Reporter reporter, [NotNullWhen(true)] out IEnumerable? filteredTemplates) { @@ -153,7 +153,7 @@ internal static bool VerifyMatchingTemplates( HandleAmbiguousLanguage( environmentSettings, matchingTemplates.Select(c => c.Template), - writer); + reporter); filteredTemplates = null; return false; @@ -164,7 +164,7 @@ internal static bool VerifyMatchingTemplates( HandleAmbiguousLanguage( environmentSettings, matchingTemplates.Select(c => c.Template), - writer); + reporter); filteredTemplates = null; return false; @@ -178,7 +178,7 @@ internal static bool VerifyMatchingTemplates( HandleAmbiguousType( environmentSettings, matchingTemplates.Select(c => c.Template), - writer); + reporter); filteredTemplates = null; return false; } @@ -371,38 +371,6 @@ internal void ShowUsage(IReadOnlyList shortNames, HelpContext context) context.Output.WriteLine(); } - private static NewCommandStatus HandleAmbiguousLanguage( - IEngineEnvironmentSettings environmentSettings, - IEnumerable templates, - TextWriter writer) - { - writer.WriteLine(HelpStrings.TableHeader_AmbiguousTemplatesList); - TemplateGroupDisplay.DisplayTemplateList( - environmentSettings, - templates, - new TabularOutputSettings(environmentSettings.Environment), - writer: writer); - writer.WriteLine(HelpStrings.Hint_AmbiguousLanguage); - return NewCommandStatus.NotFound; - } - - private static NewCommandStatus HandleAmbiguousType( - IEngineEnvironmentSettings environmentSettings, - IEnumerable templates, - TextWriter writer) - { - writer.WriteLine(HelpStrings.TableHeader_AmbiguousTemplatesList); - TemplateGroupDisplay.DisplayTemplateList( - environmentSettings, - templates, - new TabularOutputSettings( - environmentSettings.Environment, - columnsToDisplay: new[] { TabularOutputSettings.ColumnNames.Type }), - writer: writer); - writer.WriteLine(HelpStrings.Hint_AmbiguousType); - return NewCommandStatus.NotFound; - } - /// /// Ensure are sorted in priority order /// The highest priority should come first. diff --git a/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.cs b/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.cs index f1d4a8135a8..708e3e6b8f3 100644 --- a/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.cs +++ b/src/Microsoft.TemplateEngine.Cli/Commands/InstantiateCommand.cs @@ -7,9 +7,13 @@ using System.CommandLine.Help; using System.CommandLine.Invocation; using System.CommandLine.Parsing; +using Microsoft.Extensions.Logging; using Microsoft.TemplateEngine.Abstractions; +using Microsoft.TemplateEngine.Abstractions.TemplatePackage; using Microsoft.TemplateEngine.Cli.Extensions; +using Microsoft.TemplateEngine.Cli.TabularOutput; using Microsoft.TemplateEngine.Edge.Settings; +using Microsoft.TemplateEngine.Utils; namespace Microsoft.TemplateEngine.Cli.Commands { @@ -136,7 +140,48 @@ internal void HandleNoMatchingTemplateGroup(InstantiateCommandArgs instantiateAr reporter.WriteLine(); } - internal NewCommandStatus HandleAmbiguousTemplateGroup(InstantiateCommandArgs instantiateArgs) => throw new NotImplementedException(); + internal NewCommandStatus HandleAmbiguousTemplateGroup( + IEngineEnvironmentSettings environmentSettings, + TemplatePackageManager templatePackageManager, + IEnumerable templateGroups, + Reporter reporter, + CancellationToken cancellationToken = default) + { + IEnvironment environment = environmentSettings.Environment; + reporter.WriteLine(LocalizableStrings.AmbiguousTemplatesHeader.Bold().Red()); + TabularOutput formatter = + TabularOutput.TabularOutput + .For( + new TabularOutputSettings(environment), + templateGroups) + .DefineColumn(t => t.GroupIdentity ?? t.Templates[0].Identity, out object identityColumn, LocalizableStrings.ColumnNameIdentity, showAlways: true) + .DefineColumn(t => t.Name, LocalizableStrings.ColumnNameTemplateName, shrinkIfNeeded: true, minWidth: 15, showAlways: true) + .DefineColumn(t => string.Join(",", t.ShortNames), LocalizableStrings.ColumnNameShortName, showAlways: true) + .DefineColumn(t => string.Join(",", t.Languages), LocalizableStrings.ColumnNameLanguage, showAlways: true) + .DefineColumn(t => string.Join(",", t.Authors), LocalizableStrings.ColumnNameAuthor, showAlways: true, shrinkIfNeeded: true, minWidth: 10) + .DefineColumn(t => Task.Run(() => GetTemplatePackagesList(t)).GetAwaiter().GetResult(), LocalizableStrings.ColumnNamePackage, showAlways: true) + .OrderBy(identityColumn, StringComparer.CurrentCultureIgnoreCase); + + reporter.WriteLine(formatter.Layout().Bold().Red()); + reporter.WriteLine(LocalizableStrings.AmbiguousTemplatesMultiplePackagesHint.Bold().Red()); + return NewCommandStatus.NotFound; + + async Task GetTemplatePackagesList(TemplateGroup templateGroup) + { + try + { + IReadOnlyList templatePackages = + await templateGroup.GetManagedTemplatePackagesAsync(templatePackageManager, cancellationToken).ConfigureAwait(false); + return string.Join(environment.NewLine, templatePackages.Select(templatePackage => templatePackage.Identifier)); + } + catch (Exception ex) + { + environmentSettings.Host.Logger.LogWarning($"Failed to get information about template packages for template group {templateGroup.GroupIdentity}."); + environmentSettings.Host.Logger.LogDebug($"Details: {ex}."); + return string.Empty; + } + } + } protected async override Task ExecuteAsync(InstantiateCommandArgs instantiateArgs, IEngineEnvironmentSettings environmentSettings, InvocationContext context) { @@ -167,7 +212,7 @@ protected async override Task ExecuteAsync(InstantiateCommandA } if (selectedTemplateGroups.Count() > 1) { - return HandleAmbiguousTemplateGroup(instantiateArgs); + return HandleAmbiguousTemplateGroup(environmentSettings, templatePackageManager, selectedTemplateGroups, Reporter.Error, cancellationToken); } return await HandleTemplateInstantationAsync( instantiateArgs, @@ -179,6 +224,38 @@ protected async override Task ExecuteAsync(InstantiateCommandA protected override InstantiateCommandArgs ParseContext(ParseResult parseResult) => new(this, parseResult); + private static NewCommandStatus HandleAmbiguousLanguage( + IEngineEnvironmentSettings environmentSettings, + IEnumerable templates, + Reporter reporter) + { + reporter.WriteLine(HelpStrings.TableHeader_AmbiguousTemplatesList); + TemplateGroupDisplay.DisplayTemplateList( + environmentSettings, + templates, + new TabularOutputSettings(environmentSettings.Environment), + reporter); + reporter.WriteLine(HelpStrings.Hint_AmbiguousLanguage); + return NewCommandStatus.NotFound; + } + + private static NewCommandStatus HandleAmbiguousType( + IEngineEnvironmentSettings environmentSettings, + IEnumerable templates, + Reporter reporter) + { + reporter.WriteLine(HelpStrings.TableHeader_AmbiguousTemplatesList); + TemplateGroupDisplay.DisplayTemplateList( + environmentSettings, + templates, + new TabularOutputSettings( + environmentSettings.Environment, + columnsToDisplay: new[] { TabularOutputSettings.ColumnNames.Type }), + reporter); + reporter.WriteLine(HelpStrings.Hint_AmbiguousType); + return NewCommandStatus.NotFound; + } + private async Task HandleTemplateInstantationAsync( InstantiateCommandArgs args, IEngineEnvironmentSettings environmentSettings, @@ -195,13 +272,87 @@ private async Task HandleTemplateInstantationAsync( } else if (candidates.Any()) { - return HandleAmbuguousResult(); + return HandleAmbiguousResult( + environmentSettings, + templatePackageManager, + candidates.Select(c => c.Template), + Reporter.Error, + cancellationToken); } return HandleNoTemplateFoundResult(args, environmentSettings, templatePackageManager, templateGroup, Reporter.Error); } - private NewCommandStatus HandleAmbuguousResult() => throw new NotImplementedException(); + private NewCommandStatus HandleAmbiguousResult( + IEngineEnvironmentSettings environmentSettings, + TemplatePackageManager templatePackageManager, + IEnumerable templates, + Reporter reporter, + CancellationToken cancellationToken = default) + { + if (!templates.Any(t => string.IsNullOrWhiteSpace(t.GetLanguage())) + && !templates.AllAreTheSame(t => t.GetLanguage())) + { + return HandleAmbiguousLanguage( + environmentSettings, + templates, + Reporter.Error); + } + + if (!templates.Any(t => string.IsNullOrWhiteSpace(t.GetTemplateType())) + && !templates.AllAreTheSame(t => t.GetTemplateType())) + { + return HandleAmbiguousType( + environmentSettings, + templates, + Reporter.Error); + } + + reporter.WriteLine(LocalizableStrings.AmbiguousTemplatesHeader.Bold().Red()); + IEnvironment environment = environmentSettings.Environment; + TabularOutput formatter = + TabularOutput.TabularOutput + .For( + new TabularOutputSettings(environment), + templates) + .DefineColumn(t => t.Identity, out object identityColumn, LocalizableStrings.ColumnNameIdentity, showAlways: true) + .DefineColumn(t => t.Name, LocalizableStrings.ColumnNameTemplateName, shrinkIfNeeded: true, minWidth: 15, showAlways: true) + .DefineColumn(t => string.Join(",", t.ShortNameList), LocalizableStrings.ColumnNameShortName, showAlways: true) + .DefineColumn(t => t.GetLanguage(), LocalizableStrings.ColumnNameLanguage, showAlways: true) + .DefineColumn(t => t.Precedence.ToString(), out object prcedenceColumn, LocalizableStrings.ColumnNamePrecedence, showAlways: true) + .DefineColumn(t => t.Author, LocalizableStrings.ColumnNameAuthor, showAlways: true, shrinkIfNeeded: true, minWidth: 10) + .DefineColumn(t => Task.Run(() => GetTemplatePackage(t)).GetAwaiter().GetResult(), LocalizableStrings.ColumnNamePackage, showAlways: true) + .OrderBy(identityColumn, StringComparer.CurrentCultureIgnoreCase) + .OrderByDescending(prcedenceColumn, new NullOrEmptyIsLastStringComparer()); + reporter.WriteLine(formatter.Layout().Bold().Red()); + + reporter.WriteLine(LocalizableStrings.AmbiguousTemplatesMultiplePackagesHint.Bold().Red()); + if (templates.AllAreTheSame(t => t.MountPointUri)) + { + string templatePackage = Task.Run(() => GetTemplatePackage(templates.First())).GetAwaiter().GetResult(); + if (!string.IsNullOrWhiteSpace(templatePackage)) + { + reporter.WriteLine(string.Format(LocalizableStrings.AmbiguousTemplatesSamePackageHint, templatePackage).Bold().Red()); + } + } + return NewCommandStatus.NotFound; + + async Task GetTemplatePackage(CliTemplateInfo template) + { + try + { + IManagedTemplatePackage? templatePackage = + await template.GetManagedTemplatePackageAsync(templatePackageManager, cancellationToken).ConfigureAwait(false); + return templatePackage?.Identifier ?? string.Empty; + } + catch (Exception ex) + { + environmentSettings.Host.Logger.LogWarning($"Failed to get information about template packages for template group {template.Identity}."); + environmentSettings.Host.Logger.LogDebug($"Details: {ex}."); + return string.Empty; + } + } + } private HashSet ReparseForTemplate( InstantiateCommandArgs args, diff --git a/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs index 5afd445c8ad..2b43c4d667b 100644 --- a/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs @@ -410,7 +410,7 @@ internal static string AmbiguousTemplatesHeader { } /// - /// Looks up a localized string similar to Uninstall the templates or the packages to keep only one template from the list.. + /// Looks up a localized string similar to Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run.. /// internal static string AmbiguousTemplatesMultiplePackagesHint { get { diff --git a/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx index 0385afcdebc..3068b78a005 100644 --- a/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Cli/LocalizableStrings.resx @@ -493,7 +493,7 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases. Unable to resolve the template, the following installed templates are conflicting: - Uninstall the templates or the packages to keep only one template from the list. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. The package {0} is not correct, uninstall it and report the issue to the package author. diff --git a/src/Microsoft.TemplateEngine.Cli/Reporter.cs b/src/Microsoft.TemplateEngine.Cli/Reporter.cs index a433a7442c2..33ddb951414 100644 --- a/src/Microsoft.TemplateEngine.Cli/Reporter.cs +++ b/src/Microsoft.TemplateEngine.Cli/Reporter.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + namespace Microsoft.TemplateEngine.Cli { internal class Reporter @@ -8,14 +10,21 @@ internal class Reporter private static readonly Reporter NullReporter = new Reporter(console: null); private static object _lock = new object(); - private readonly AnsiConsole _console; + private readonly AnsiConsole? _console; static Reporter() { - Reset(); + lock (_lock) + { + Output = new Reporter(AnsiConsole.GetOutput()); + Error = new Reporter(AnsiConsole.GetError()); + Verbose = IsVerbose ? + new Reporter(AnsiConsole.GetOutput()) : + NullReporter; + } } - private Reporter(AnsiConsole console) + internal Reporter(AnsiConsole? console) { _console = console; } @@ -36,21 +45,6 @@ private bool ShouldPassAnsiCodesThrough get { return bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_ANSI_PASS_THRU") ?? "false", out bool value) && value; } } - /// - /// Resets the Reporters to write to the current Console Out/Error. - /// - internal static void Reset() - { - lock (_lock) - { - Output = new Reporter(AnsiConsole.GetOutput()); - Error = new Reporter(AnsiConsole.GetError()); - Verbose = IsVerbose ? - new Reporter(AnsiConsole.GetOutput()) : - NullReporter; - } - } - internal void WriteLine(string message) { lock (_lock) diff --git a/src/Microsoft.TemplateEngine.Cli/TabularOutput/TemplateGroupDisplay.cs b/src/Microsoft.TemplateEngine.Cli/TabularOutput/TemplateGroupDisplay.cs index ebe9516fad4..088c5c93927 100644 --- a/src/Microsoft.TemplateEngine.Cli/TabularOutput/TemplateGroupDisplay.cs +++ b/src/Microsoft.TemplateEngine.Cli/TabularOutput/TemplateGroupDisplay.cs @@ -29,16 +29,15 @@ internal static void DisplayTemplateList( IEngineEnvironmentSettings engineEnvironmentSettings, IEnumerable templateGroups, TabularOutputSettings helpFormatterSettings, - string? selectedLanguage = null, - bool useErrorOutput = false, - TextWriter? writer = null) + Reporter reporter, + string? selectedLanguage = null) { IReadOnlyCollection groupsForDisplay = GetTemplateGroupsForListDisplay( templateGroups, selectedLanguage, engineEnvironmentSettings.GetDefaultLanguage(), engineEnvironmentSettings.Environment); - DisplayTemplateList(groupsForDisplay, helpFormatterSettings, useErrorOutput, writer: writer); + DisplayTemplateList(groupsForDisplay, helpFormatterSettings, reporter); } /// @@ -57,16 +56,15 @@ internal static void DisplayTemplateList( IEngineEnvironmentSettings engineEnvironmentSettings, IEnumerable templates, TabularOutputSettings helpFormatterSettings, - string? selectedLanguage = null, - bool useErrorOutput = false, - TextWriter? writer = null) + Reporter reporter, + string? selectedLanguage = null) { IReadOnlyCollection groupsForDisplay = GetTemplateGroupsForListDisplay( templates, selectedLanguage, engineEnvironmentSettings.GetDefaultLanguage(), engineEnvironmentSettings.Environment); - DisplayTemplateList(groupsForDisplay, helpFormatterSettings, useErrorOutput, writer: writer); + DisplayTemplateList(groupsForDisplay, helpFormatterSettings, reporter); } /// @@ -154,8 +152,7 @@ private static IReadOnlyList GetTemplateGroupsForListDisp private static void DisplayTemplateList( IReadOnlyCollection groupsForDisplay, TabularOutputSettings tabularOutputSettings, - bool useErrorOutput = false, - TextWriter? writer = null) + Reporter reporter) { TabularOutput formatter = TabularOutput @@ -169,13 +166,6 @@ private static void DisplayTemplateList( .DefineColumn(t => t.Author, LocalizableStrings.ColumnNameAuthor, TabularOutputSettings.ColumnNames.Tags, defaultColumn: false, shrinkIfNeeded: true, minWidth: 10) .DefineColumn(t => t.Classifications, out object tagsColumn, LocalizableStrings.ColumnNameTags, TabularOutputSettings.ColumnNames.Author, defaultColumn: true) .OrderBy(nameColumn, StringComparer.OrdinalIgnoreCase); - - if (writer != null) - { - writer.WriteLine(formatter.Layout()); - return; - } - Reporter reporter = useErrorOutput ? Reporter.Error : Reporter.Output; reporter.WriteLine(formatter.Layout()); } diff --git a/src/Microsoft.TemplateEngine.Cli/TemplateGroup.cs b/src/Microsoft.TemplateEngine.Cli/TemplateGroup.cs index 49850142bbe..bf1b0b4ad3e 100644 --- a/src/Microsoft.TemplateEngine.Cli/TemplateGroup.cs +++ b/src/Microsoft.TemplateEngine.Cli/TemplateGroup.cs @@ -4,6 +4,8 @@ #nullable enable using Microsoft.TemplateEngine.Abstractions; +using Microsoft.TemplateEngine.Abstractions.TemplatePackage; +using Microsoft.TemplateEngine.Edge.Settings; using Microsoft.TemplateEngine.Utils; namespace Microsoft.TemplateEngine.Cli @@ -132,9 +134,9 @@ internal string Name } /// - /// Returns the description of template group - /// Template group name is the name of highest precedence template in the group. - /// If multiple templates have the maximum precedence, the name of first one is returned. + /// Returns the description of template group. + /// Template group description is the description of the template in the group with the highest precedence. + /// If multiple templates have the maximum precedence, the description of the first one is returned. /// internal string Description { @@ -144,6 +146,26 @@ internal string Description } } + /// + /// Returns the authors of template group. + /// If different templates have different authors, lists all of them. + /// + internal IReadOnlyList Authors + { + get + { + HashSet authors = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (ITemplateInfo template in Templates) + { + if (!string.IsNullOrWhiteSpace(template.Author)) + { + authors.Add(template.Author); + } + } + return authors.ToList(); + } + } + /// /// Returns true when is not null or empty. /// @@ -166,6 +188,35 @@ internal static IEnumerable FromTemplateList (IEnumerable new TemplateGroup(group.ToList())); } + /// + /// Gets the list of managed template packages which contain templates of template group. + /// + /// + /// The method might throw exceptions if call throws. + /// + internal async Task> GetManagedTemplatePackagesAsync( + TemplatePackageManager templatePackageManager, + CancellationToken cancellationToken) + { + var templatePackages = await GetTemplatePackagesAsync(templatePackageManager, cancellationToken).ConfigureAwait(false); + + return templatePackages.OfType().ToArray(); + } + + /// + /// Gets the list of template packages which contain templates of template group. + /// + /// + /// The method might throw exceptions if call throws. + /// + internal async Task> GetTemplatePackagesAsync( + TemplatePackageManager templatePackageManager, + CancellationToken cancellationToken) + { + var templatePackages = await Task.WhenAll(Templates.Select(t => templatePackageManager.GetTemplatePackageAsync(t, cancellationToken))).ConfigureAwait(false); + return templatePackages.Distinct().ToArray(); + } + private IEnumerable GetHighestPrecedenceTemplates() { if (!Templates.Any()) diff --git a/src/Microsoft.TemplateEngine.Cli/TemplateListCoordinator.cs b/src/Microsoft.TemplateEngine.Cli/TemplateListCoordinator.cs index 34311642826..c7907d1f3a5 100644 --- a/src/Microsoft.TemplateEngine.Cli/TemplateListCoordinator.cs +++ b/src/Microsoft.TemplateEngine.Cli/TemplateListCoordinator.cs @@ -65,6 +65,7 @@ internal async Task DisplayTemplateGroupListAsync( _engineEnvironmentSettings, resolutionResult.TemplateGroupsWithMatchingTemplateInfoAndParameters, settings, + reporter: Reporter.Output, selectedLanguage: args.Language); return NewCommandStatus.Success; } @@ -127,7 +128,8 @@ internal async Task DisplayCommandDescriptionAsync( TemplateGroupDisplay.DisplayTemplateList( _engineEnvironmentSettings, curatedTemplates, - new TabularOutputSettings(_engineEnvironmentSettings.Environment)); + new TabularOutputSettings(_engineEnvironmentSettings.Environment), + reporter: Reporter.Output); Reporter.Output.WriteLine(LocalizableStrings.TemplateInformationCoordinator_DotnetNew_ExampleHeader); Reporter.Output.WriteCommand(CommandExamples.InstantiateTemplateExample(args.CommandName, "console")); diff --git a/src/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs b/src/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs index f8ccf21498f..06218d6d764 100644 --- a/src/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs +++ b/src/Microsoft.TemplateEngine.Cli/TemplatePackageCoordinator.cs @@ -539,7 +539,11 @@ private async Task DisplayInstallResultAsync(string packageToInstall, InstallerO string.Format( LocalizableStrings.TemplatePackageCoordinator_lnstall_Info_Success, result.TemplatePackage.DisplayName)); - TemplateGroupDisplay.DisplayTemplateList(_engineEnvironmentSettings, templates, new TabularOutputSettings(_engineEnvironmentSettings.Environment)); + TemplateGroupDisplay.DisplayTemplateList( + _engineEnvironmentSettings, + templates, + new TabularOutputSettings(_engineEnvironmentSettings.Environment), + reporter: Reporter.Output); } else { diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf index bd323bb2cff..9660774ef04 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.cs.xlf @@ -207,8 +207,8 @@ Pokud si chcete zobrazit všechny aliasy, spusťte bez argumentů příkaz dotne - Uninstall the templates or the packages to keep only one template from the list. - Odinstalujte šablony nebo balíčky, aby z daného seznamu zůstala pouze jedna šablona. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Odinstalujte šablony nebo balíčky, aby z daného seznamu zůstala pouze jedna šablona. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf index 79f137406ff..d04bb433454 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.de.xlf @@ -207,8 +207,8 @@ Führen Sie "dotnet {1}--show-aliases" ohne Argumente aus, um alle Aliase anzuze - Uninstall the templates or the packages to keep only one template from the list. - Deinstallieren Sie die Vorlagen oder Pakete, um nur eine Vorlage aus der Liste zu behalten. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Deinstallieren Sie die Vorlagen oder Pakete, um nur eine Vorlage aus der Liste zu behalten. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf index 6fc9ec890a0..e06ae369141 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.es.xlf @@ -207,8 +207,8 @@ Ejecute "dotnet {1} --show-aliases" sin argumentos para mostrar todos los alias. - Uninstall the templates or the packages to keep only one template from the list. - Desinstale las plantillas o los paquetes para conservar solo una plantilla de la lista. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Desinstale las plantillas o los paquetes para conservar solo una plantilla de la lista. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf index 57ec9e0983e..85198334b3d 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.fr.xlf @@ -207,8 +207,8 @@ Exécutez « dotnet {1} --show-aliases » sans arguments pour afficher tous le - Uninstall the templates or the packages to keep only one template from the list. - Désinstallez les modèles ou les packages pour ne conserver qu’un seul modèle dans la liste. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Désinstallez les modèles ou les packages pour ne conserver qu’un seul modèle dans la liste. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf index 8426ca6ab9a..e495dd3f86c 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.it.xlf @@ -207,8 +207,8 @@ Eseguire 'dotnet {1}--show-alias ' senza argomenti per mostrare tutti gli alias. - Uninstall the templates or the packages to keep only one template from the list. - Disinstallare i modelli o i pacchetti per mantenere un solo modello dall'elenco. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Disinstallare i modelli o i pacchetti per mantenere un solo modello dall'elenco. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf index 4a42ac003a8..11f9901358d 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ja.xlf @@ -207,8 +207,8 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases. - Uninstall the templates or the packages to keep only one template from the list. - テンプレートまたはパッケージをアンインストールして、一覧から1つのテンプレートのみを保持します。 + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + テンプレートまたはパッケージをアンインストールして、一覧から1つのテンプレートのみを保持します。 diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf index 7eff866b1b2..4b57ebe110e 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ko.xlf @@ -207,8 +207,8 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases. - Uninstall the templates or the packages to keep only one template from the list. - 목록에서 하나의 템플릿만 유지하려면 템플릿 또는 패키지를 제거합니다. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + 목록에서 하나의 템플릿만 유지하려면 템플릿 또는 패키지를 제거합니다. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf index 6edc6e6064a..aa05f470c03 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pl.xlf @@ -207,8 +207,8 @@ Uruchom polecenie "dotnet {1}--show-aliases" bez argumentów, aby wyświetlić w - Uninstall the templates or the packages to keep only one template from the list. - Odinstaluj szablony lub pakiety, aby zachować tylko jeden szablon z listy. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Odinstaluj szablony lub pakiety, aby zachować tylko jeden szablon z listy. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf index e814822688c..653a1fd0b36 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.pt-BR.xlf @@ -207,8 +207,8 @@ Execute 'dotnet {1} --mostrar- aliases' sem nenhum args para mostrar todos os al - Uninstall the templates or the packages to keep only one template from the list. - Desinstale os modelos ou os pacotes para manter somente um modelo da lista. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Desinstale os modelos ou os pacotes para manter somente um modelo da lista. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf index 52a03f316d8..0ce0961c893 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.ru.xlf @@ -207,8 +207,8 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases. - Uninstall the templates or the packages to keep only one template from the list. - Удалите шаблоны или пакеты, чтобы оставить только один шаблон из списка. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Удалите шаблоны или пакеты, чтобы оставить только один шаблон из списка. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf index f66f402667b..0f03bc1ead6 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.tr.xlf @@ -207,8 +207,8 @@ Tüm diğer adları göstermek için 'dotnet {1} --show-aliases' komutunu bağı - Uninstall the templates or the packages to keep only one template from the list. - Şablonları veya paketleri kaldırarak listede yalnızca bir şablon tutun. + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + Şablonları veya paketleri kaldırarak listede yalnızca bir şablon tutun. diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf index 50580b592d5..c1eb78a034e 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hans.xlf @@ -207,8 +207,8 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases. - Uninstall the templates or the packages to keep only one template from the list. - 卸载模板或程序包以仅保留列表中的一个模板。 + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + 卸载模板或程序包以仅保留列表中的一个模板。 diff --git a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf index 74adf78fe15..0939a36834b 100644 --- a/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Cli/xlf/LocalizableStrings.zh-Hant.xlf @@ -207,8 +207,8 @@ Run 'dotnet {1} --show-aliases' with no args to show all aliases. - Uninstall the templates or the packages to keep only one template from the list. - 解除安裝範本或套件,只保留清單中的一個範本。 + Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. + 解除安裝範本或套件,只保留清單中的一個範本。 diff --git a/test/Microsoft.TemplateEngine.Cli.UnitTests/ParserTests/HelpTests.Resolution.cs b/test/Microsoft.TemplateEngine.Cli.UnitTests/ParserTests/HelpTests.Resolution.cs index c72960a9921..371af4c3f80 100644 --- a/test/Microsoft.TemplateEngine.Cli.UnitTests/ParserTests/HelpTests.Resolution.cs +++ b/test/Microsoft.TemplateEngine.Cli.UnitTests/ParserTests/HelpTests.Resolution.cs @@ -46,7 +46,8 @@ public void UniqueNameMatchesCorrectly() var matchingTemplates = InstantiateCommand.GetMatchingTemplates(instantiateCommand, args, settings, A.Fake(), templateGroup); Assert.Equal(1, matchingTemplates.Count()); StringWriter output = new StringWriter(); - Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, output, matchingTemplates, out _)); + Reporter reporter = new Reporter(new AnsiConsole(output)); + Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, matchingTemplates, reporter, out _)); Assert.Empty(output.ToString()); } @@ -72,7 +73,8 @@ public Task FailedToResolveTemplate_WhenMultipleLanguagesAreFound() var matchingTemplates = InstantiateCommand.GetMatchingTemplates(instantiateCommand, args, settings, A.Fake(), templateGroup); Assert.Equal(3, matchingTemplates.Count()); StringWriter output = new StringWriter(); - Assert.False(InstantiateCommand.VerifyMatchingTemplates(settings, output, matchingTemplates, out _)); + Reporter reporter = new Reporter(new AnsiConsole(output)); + Assert.False(InstantiateCommand.VerifyMatchingTemplates(settings, matchingTemplates, reporter, out _)); return Verifier.Verify(output.ToString(), _verifySettings.Settings); } @@ -98,7 +100,8 @@ public void DefaultLanguageDisambiguates() var matchingTemplates = InstantiateCommand.GetMatchingTemplates(instantiateCommand, args, settings, A.Fake(), templateGroup); Assert.Equal(2, matchingTemplates.Count()); StringWriter output = new StringWriter(); - Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, output, matchingTemplates, out IEnumerable? filtered)); + Reporter reporter = new Reporter(new AnsiConsole(output)); + Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, matchingTemplates, reporter, out IEnumerable? filtered)); Assert.Equal(1, filtered?.Count()); Assert.Equal("Console.App.L1", filtered?.Single().Template.Identity); Assert.Empty(output.ToString()); @@ -125,7 +128,8 @@ public void InputLanguageIsPreferredOverDefault() var matchingTemplates = InstantiateCommand.GetMatchingTemplates(instantiateCommand, args, settings, A.Fake(), templateGroup); Assert.Equal(1, matchingTemplates.Count()); StringWriter output = new StringWriter(); - Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, output, matchingTemplates, out IEnumerable? filtered)); + Reporter reporter = new Reporter(new AnsiConsole(output)); + Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, matchingTemplates, reporter, out IEnumerable? filtered)); Assert.Equal(1, filtered?.Count()); Assert.Equal("Console.App.L2", filtered?.Single().Template.Identity); Assert.Empty(output.ToString()); @@ -150,7 +154,8 @@ public void TemplatesAreSameLanguage() var matchingTemplates = InstantiateCommand.GetMatchingTemplates(instantiateCommand, args, settings, A.Fake(), templateGroup); Assert.Equal(3, matchingTemplates.Count()); StringWriter output = new StringWriter(); - Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, output, matchingTemplates, out IEnumerable? filtered)); + Reporter reporter = new Reporter(new AnsiConsole(output)); + Assert.True(InstantiateCommand.VerifyMatchingTemplates(settings, matchingTemplates, reporter, out IEnumerable? filtered)); Assert.Equal(3, filtered?.Count()); Assert.Empty(output.ToString()); } diff --git a/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicFSharp/.template.config/template.json b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicFSharp/.template.config/template.json new file mode 100644 index 00000000000..1c4a89a4cc8 --- /dev/null +++ b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicFSharp/.template.config/template.json @@ -0,0 +1,15 @@ +{ + "author": "Test Asset", + "classifications": [ "Test Asset" ], + "name": "Basic FSharp", + "generatorVersions": "[1.0.0.0-*)", + "groupIdentity": "TestAssets.Group1", + "precedence": "100", + "identity": "TestAssets.DifferentLanguagesGroup.BasicFSharp", + "shortName": "basic", + "sourceName": "bar", + "tags": { + "language": "F#", + "type": "item" + } +} diff --git a/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicFSharp/bar.fs b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicFSharp/bar.fs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicVB/.template.config/template.json b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicVB/.template.config/template.json new file mode 100644 index 00000000000..f7700980eab --- /dev/null +++ b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicVB/.template.config/template.json @@ -0,0 +1,15 @@ +{ + "author": "Test Asset", + "classifications": [ "Test Asset" ], + "name": "Basic VB", + "generatorVersions": "[1.0.0.0-*)", + "groupIdentity": "TestAssets.Group2", + "precedence": "100", + "identity": "TestAssets.DifferentLanguagesGroup.BasicVB", + "shortName": "basic", + "sourceName": "bar", + "tags": { + "language": "VB", + "type": "item" + } +} diff --git a/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicVB/bar.vb b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TemplateResolution/SameShortName/BasicVB/bar.vb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenAmbiguousShortNameChoice.approved.txt b/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenAmbiguousShortNameChoice.approved.txt new file mode 100644 index 00000000000..76ad9740fc0 --- /dev/null +++ b/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenAmbiguousShortNameChoice.approved.txt @@ -0,0 +1,7 @@ +Unable to resolve the template, the following installed templates are conflicting: +Identity Template Name Short Name Language Author Package +%delimiter% +TestAssets.Group1 Basic FSharp basic F# Test Asset BasicFSharp +TestAssets.Group2 Basic VB basic VB Test Asset BasicVB + +Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. \ No newline at end of file diff --git a/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenPrecedenceIsSame.approved.txt b/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenPrecedenceIsSame.approved.txt index 849c644eb00..65241335752 100644 --- a/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenPrecedenceIsSame.approved.txt +++ b/test/dotnet-new3.UnitTests/Approvals/DotnetNewInstantiate.CannotInstantiateTemplate_WhenPrecedenceIsSame.approved.txt @@ -4,4 +4,4 @@ Identity Template Name Short Name Langu TestAssets.SamePrecedenceGroup.BasicTemplate1 Basic Template basic C# 100 Test Asset TestAssets.SamePrecedenceGroup.BasicTemplate2 Basic Template basic C# 100 Test Asset -Uninstall the templates or the packages to keep only one template from the list. \ No newline at end of file +Uninstall the template packages containing the templates to keep only one template from the list or add the template options which differentiate the template to run. \ No newline at end of file diff --git a/test/dotnet-new3.UnitTests/DotnetNewHelp.Approval.cs b/test/dotnet-new3.UnitTests/DotnetNewHelp.Approval.cs index dfbaf72b29c..6b2d0ae8fe5 100644 --- a/test/dotnet-new3.UnitTests/DotnetNewHelp.Approval.cs +++ b/test/dotnet-new3.UnitTests/DotnetNewHelp.Approval.cs @@ -209,13 +209,12 @@ public void CannotShowHelpForTemplate_FullNameMatch() .WithWorkingDirectory(workingDirectory) .Execute(); + //help command cannot fail, therefore the output is written to stdout commandResult.Should().Pass().And.NotHaveStdErr(); Approvals.Verify(commandResult.StdOut); } -#pragma warning disable xUnit1004 // Test methods should not be skipped - [Fact(Skip = "TODO: does not fail now, check if can fail")] -#pragma warning restore xUnit1004 // Test methods should not be skipped + [Fact] public void CannotShowHelpForTemplate_WhenAmbiguousLanguageChoice() { string workingDirectory = TestUtils.CreateTemporaryFolder(); @@ -227,9 +226,9 @@ public void CannotShowHelpForTemplate_WhenAmbiguousLanguageChoice() .WithWorkingDirectory(workingDirectory) .Execute(); - commandResult.Should().Fail().And.NotHaveStdOut(); - - Approvals.Verify(commandResult.StdErr); + //help command cannot fail, therefore the output is written to stdout + commandResult.Should().Pass().And.NotHaveStdErr(); + Approvals.Verify(commandResult.StdOut); } [Fact] diff --git a/test/dotnet-new3.UnitTests/DotnetNewInstantiate.Approval.cs b/test/dotnet-new3.UnitTests/DotnetNewInstantiate.Approval.cs index 462b25811a8..499d69808f3 100644 --- a/test/dotnet-new3.UnitTests/DotnetNewInstantiate.Approval.cs +++ b/test/dotnet-new3.UnitTests/DotnetNewInstantiate.Approval.cs @@ -46,9 +46,7 @@ public void CannotInstantiateTemplateWithUnknownLanguage() Approvals.Verify(commandResult.StdErr); } -#pragma warning disable xUnit1004 // Test methods should not be skipped - [Fact(Skip = "instantiation error handling is not complete yet")] -#pragma warning restore xUnit1004 // Test methods should not be skipped + [Fact] public void CannotInstantiateTemplate_WhenAmbiguousLanguageChoice() { string home = TestUtils.CreateTemporaryFolder("Home"); @@ -69,6 +67,37 @@ public void CannotInstantiateTemplate_WhenAmbiguousLanguageChoice() Approvals.Verify(commandResult.StdErr); } + [Fact] + public void CannotInstantiateTemplate_WhenAmbiguousShortNameChoice() + { + string home = TestUtils.CreateTemporaryFolder("Home"); + string workingDirectory = TestUtils.CreateTemporaryFolder(); + string templateOneLocation = Helpers.InstallTestTemplate("TemplateResolution/SameShortName/BasicFSharp", _log, workingDirectory, home); + string templateTwoLocation = Helpers.InstallTestTemplate("TemplateResolution/SameShortName/BasicVB", _log, workingDirectory, home); + + var commandResult = new DotnetNewCommand(_log, "basic") + .WithCustomHive(home) + .WithWorkingDirectory(workingDirectory) + .Execute(); + + commandResult + .Should() + .Fail() + .And.NotHaveStdOut(); + + Approvals.Verify(commandResult.StdErr, (output) => + { + //package locaions are machine specific so we cannot use them in approval tests + //replace them with directory name + var finalOutput = output.Replace(templateOneLocation, Path.GetFileName(templateOneLocation)).Replace(templateTwoLocation, Path.GetFileName(templateTwoLocation)); + //removes the delimiter line as we don't know the length of last columns containing paths above + finalOutput = Regex.Replace(finalOutput, "-+[ -]*", "%delimiter%"); + //replace the "Package" column header as we don't know the amount of spaces after it (depends on the paths above) + finalOutput = Regex.Replace(finalOutput, "Package *", "Package"); + return finalOutput; + }); + } + [Fact] public void CannotInstantiateTemplate_WhenFullNameIsUsed() { @@ -158,9 +187,7 @@ public void CannotInstantiateTemplate_OnMultipleParameterErrors() Approvals.Verify(commandResult.StdErr); } -#pragma warning disable xUnit1004 // Test methods should not be skipped - [Fact(Skip = "instantiation error handling is not complete yet")] -#pragma warning restore xUnit1004 // Test methods should not be skipped + [Fact] public void CannotInstantiateTemplate_WhenPrecedenceIsSame() { string home = TestUtils.CreateTemporaryFolder("Home");