Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes dotnet/templating #3807 update subcommand #4045

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ private static Option[] NewCommandVisibleArgs
Create.Option("-o|--output", LocalizableStrings.OutputPath, Accept.ExactlyOneArgument()),
Create.Option("-i|--install", LocalizableStrings.InstallHelp, Accept.OneOrMoreArguments()),
Create.Option("-u|--uninstall", LocalizableStrings.UninstallHelp, Accept.ZeroOrMoreArguments()),
Create.Option("--interactive", LocalizableStrings.InteractiveHelp, Accept.NoArguments()),
Create.Option("--nuget-source|--add-source", LocalizableStrings.NuGetSourceHelp, Accept.OneOrMoreArguments()),
Create.Option("--interactive", LocalizableStrings.OptionDescriptionInteractive, Accept.NoArguments()),
Create.Option("--nuget-source|--add-source", LocalizableStrings.OptionDescriptionNuGetSource, Accept.OneOrMoreArguments()),
Create.Option("--type", LocalizableStrings.ShowsFilteredTemplates, Accept.ExactlyOneArgument()),
Create.Option("--dry-run", LocalizableStrings.DryRunDescription, Accept.NoArguments()),
Create.Option("--force", LocalizableStrings.ForcesTemplateCreation, Accept.NoArguments()),
Expand Down
40 changes: 14 additions & 26 deletions src/Microsoft.TemplateEngine.Cli/Commands/InstallCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,38 @@ namespace Microsoft.TemplateEngine.Cli.Commands
{
internal class InstallCommand : BaseInstallCommand
{
private readonly LegacyInstallCommand _legacyInstallCommand;

public InstallCommand(
LegacyInstallCommand legacyInstallCommand,
NewCommand parentCommand,
ITemplateEngineHost host,
ITelemetryLogger logger,
NewCommandCallbacks callbacks)
: base(host, logger, callbacks, "install")
: base(parentCommand, host, logger, callbacks, "install")
{
_legacyInstallCommand = legacyInstallCommand;
AddValidator(symbolResult => ValidateOptionUsageInParent(symbolResult, _legacyInstallCommand.InteractiveOption));
AddValidator(symbolResult => ValidateOptionUsageInParent(symbolResult, _legacyInstallCommand.AddSourceOption));
AddValidator(symbolResult => ValidateOptionUsageInParent(symbolResult, parentCommand.InteractiveOption));
AddValidator(symbolResult => ValidateOptionUsageInParent(symbolResult, parentCommand.AddSourceOption));
}
}

internal class LegacyInstallCommand : BaseInstallCommand
{
public LegacyInstallCommand(NewCommand newCommand, ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks)
: base(host, logger, callbacks, "--install")
: base(newCommand, host, logger, callbacks, "--install")
{
this.IsHidden = true;
this.AddAlias("-i");
AddSourceOption.AddAlias("--nuget-source");
}

//the user should use --nuget-source A --nuget-source B to specify multiple options
AddSourceOption.AllowMultipleArgumentsPerToken = false;
AddSourceOption.IsHidden = true;
InteractiveOption.IsHidden = true;
internal override Option<bool> InteractiveOption => ParentCommand.InteractiveOption;

newCommand.AddOption(AddSourceOption);
newCommand.AddOption(InteractiveOption);
}
internal override Option<IReadOnlyList<string>> AddSourceOption => ParentCommand.AddSourceOption;
}

internal abstract class BaseInstallCommand : BaseCommand<InstallCommandArgs>
{
internal BaseInstallCommand(ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks, string commandName)
internal BaseInstallCommand(NewCommand parentCommand, ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks, string commandName)
: base(host, logger, callbacks, commandName)
{
ParentCommand = parentCommand;
this.AddArgument(NameArgument);
this.AddOption(InteractiveOption);
this.AddOption(AddSourceOption);
Expand All @@ -66,16 +59,11 @@ internal BaseInstallCommand(ITemplateEngineHost host, ITelemetryLogger logger, N
Arity = new ArgumentArity(1, 99)
};

internal Option<bool> InteractiveOption { get; } = new("--interactive")
{
Description = "When downloading enable NuGet interactive."
};
internal virtual Option<bool> InteractiveOption { get; } = SharedOptionsFactory.GetInteractiveOption();

internal Option<IReadOnlyList<string>> AddSourceOption { get; } = new(new[] { "--add-source", "--nuget-source" })
{
Description = "Add NuGet source when looking for package.",
AllowMultipleArgumentsPerToken = true,
};
internal virtual Option<IReadOnlyList<string>> AddSourceOption { get; } = SharedOptionsFactory.GetAddSourceOption();

protected NewCommand ParentCommand { get; }

protected override async Task<NewCommandStatus> ExecuteAsync(InstallCommandArgs args, IEngineEnvironmentSettings environmentSettings, InvocationContext context)
{
Expand Down
21 changes: 18 additions & 3 deletions src/Microsoft.TemplateEngine.Cli/Commands/NewCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,23 @@ internal NewCommand(string commandName, ITemplateEngineHost host, ITelemetryLogg
this.TreatUnmatchedTokensAsErrors = true;

this.Add(new InstantiateCommand(host, telemetryLogger, callbacks));
LegacyInstallCommand legacyInstall = new LegacyInstallCommand(this, host, telemetryLogger, callbacks);
this.Add(legacyInstall);
this.Add(new InstallCommand(legacyInstall, host, telemetryLogger, callbacks));
this.Add(new LegacyInstallCommand(this, host, telemetryLogger, callbacks));
this.Add(new InstallCommand(this, host, telemetryLogger, callbacks));
this.Add(new LegacyUninstallCommand(host, telemetryLogger, callbacks));
this.Add(new UninstallCommand(host, telemetryLogger, callbacks));

this.Add(new LegacyUpdateCheckCommand(this, host, telemetryLogger, callbacks));
this.Add(new LegacyUpdateApplyCommand(this, host, telemetryLogger, callbacks));
this.Add(new UpdateCommand(this, host, telemetryLogger, callbacks));

//yield return (host, telemetryLogger, callbacks) => new ListCommand(host, telemetryLogger, callbacks);
//yield return (host, telemetryLogger, callbacks) => new SearchCommand(host, telemetryLogger, callbacks);
//yield return (host, telemetryLogger, callbacks) => new UpdateCommand(host, telemetryLogger, callbacks);
//yield return (host, telemetryLogger, callbacks) => new AliasCommand(host, telemetryLogger, callbacks);

//legacy options
this.AddOption(InteractiveOption);
this.AddOption(AddSourceOption);
}

internal Argument<string> ShortNameArgument { get; } = new Argument<string>("template-short-name")
Expand All @@ -51,6 +58,14 @@ internal NewCommand(string commandName, ITemplateEngineHost host, ITelemetryLogg

internal Option<bool> HelpOption { get; } = new Option<bool>(new string[] { "-h", "--help", "-?" });

#region Legacy Options

internal virtual Option<bool> InteractiveOption { get; } = SharedOptionsFactory.GetInteractiveOption().AsHidden();

internal virtual Option<IReadOnlyList<string>> AddSourceOption { get; } = SharedOptionsFactory.GetAddSourceOption().AsHidden().DisableAllowMultipleArgumentsPerToken();

#endregion

protected override IEnumerable<string> GetSuggestions(NewCommandArgs args, IEngineEnvironmentSettings environmentSettings, string? textToMatch)
{
using TemplatePackageManager templatePackageManager = new TemplatePackageManager(environmentSettings);
Expand Down
39 changes: 39 additions & 0 deletions src/Microsoft.TemplateEngine.Cli/Commands/SharedOptionsFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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;

namespace Microsoft.TemplateEngine.Cli.Commands
{
internal static class SharedOptionsFactory
{
internal static Option<bool> GetInteractiveOption()
{
return new Option<bool>("--interactive")
{
Description = LocalizableStrings.OptionDescriptionInteractive
};
}

internal static Option<IReadOnlyList<string>> GetAddSourceOption()
{
return new(new[] { "--add-source", "--nuget-source" })
{
Description = LocalizableStrings.OptionDescriptionNuGetSource,
AllowMultipleArgumentsPerToken = true,
};
}

internal static Option<T> AsHidden<T>(this Option<T> o)
{
o.IsHidden = true;
return o;
}

internal static Option<T> DisableAllowMultipleArgumentsPerToken<T>(this Option<T> o)
{
o.AllowMultipleArgumentsPerToken = false;
return o;
}
}
}
117 changes: 112 additions & 5 deletions src/Microsoft.TemplateEngine.Cli/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,132 @@

#nullable enable

using System.CommandLine;
using System.CommandLine.Invocation;
using System.CommandLine.Parsing;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Cli.Extensions;
using Microsoft.TemplateEngine.Cli.HelpAndUsage;
using Microsoft.TemplateEngine.Edge.Settings;
using Microsoft.TemplateEngine.Edge.Template;

namespace Microsoft.TemplateEngine.Cli.Commands
{
internal class UpdateCommand : BaseCommand<UpdateCommandArgs>
internal class UpdateCommand : BaseUpdateCommand
{
internal UpdateCommand(ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks) : base(host, logger, callbacks, "update") { }
public UpdateCommand(
NewCommand newCommand,
ITemplateEngineHost host,
ITelemetryLogger logger,
NewCommandCallbacks callbacks)
: base(newCommand, host, logger, callbacks, "update")
{
AddValidator(symbolResult => ValidateOptionUsageInParent(symbolResult, newCommand.InteractiveOption));
AddValidator(symbolResult => ValidateOptionUsageInParent(symbolResult, newCommand.AddSourceOption));

this.AddOption(CheckOnlyOption);
}

internal Option<bool> CheckOnlyOption { get; } = new(new[] { "--check-only", "--dry-run" })
{
Description = LocalizableStrings.OptionDescriptionCheckOnly
};
}

internal class LegacyUpdateApplyCommand : BaseUpdateCommand
{
public LegacyUpdateApplyCommand(NewCommand newCommand, ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks)
: base(newCommand, host, logger, callbacks, "--update-apply")
{
this.IsHidden = true;
}

protected override Task<NewCommandStatus> ExecuteAsync(UpdateCommandArgs args, IEngineEnvironmentSettings environmentSettings, InvocationContext context) => throw new NotImplementedException();
internal override Option<bool> InteractiveOption => ParentCommand.InteractiveOption;

protected override UpdateCommandArgs ParseContext(ParseResult parseResult) => throw new NotImplementedException();
internal override Option<IReadOnlyList<string>> AddSourceOption => ParentCommand.AddSourceOption;
}

internal class LegacyUpdateCheckCommand : BaseUpdateCommand
{
public LegacyUpdateCheckCommand(NewCommand newCommand, ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks)
: base(newCommand, host, logger, callbacks, "--update-check")
{
this.IsHidden = true;
}

internal override Option<bool> InteractiveOption => ParentCommand.InteractiveOption;

internal override Option<IReadOnlyList<string>> AddSourceOption => ParentCommand.AddSourceOption;
}

internal class BaseUpdateCommand : BaseCommand<UpdateCommandArgs>
{
internal BaseUpdateCommand(NewCommand parentCommand, ITemplateEngineHost host, ITelemetryLogger logger, NewCommandCallbacks callbacks, string commandName) : base(host, logger, callbacks, commandName)
{
ParentCommand = parentCommand;
this.AddOption(InteractiveOption);
this.AddOption(AddSourceOption);
}

internal virtual Option<bool> InteractiveOption { get; } = SharedOptionsFactory.GetInteractiveOption();

internal virtual Option<IReadOnlyList<string>> AddSourceOption { get; } = SharedOptionsFactory.GetAddSourceOption();

protected NewCommand ParentCommand { get; }

protected override async Task<NewCommandStatus> ExecuteAsync(UpdateCommandArgs args, IEngineEnvironmentSettings environmentSettings, InvocationContext context)
{
using TemplatePackageManager templatePackageManager = new TemplatePackageManager(environmentSettings);
TemplateInformationCoordinator templateInformationCoordinator = new TemplateInformationCoordinator(
environmentSettings,
templatePackageManager,
new TemplateCreator(environmentSettings),
new HostSpecificDataLoader(environmentSettings),
TelemetryLogger,
environmentSettings.GetDefaultLanguage());

TemplatePackageCoordinator templatePackageCoordinator = new TemplatePackageCoordinator(
TelemetryLogger,
environmentSettings,
templatePackageManager,
templateInformationCoordinator);

//TODO: we need to await, otherwise templatePackageManager will be disposed.
return await templatePackageCoordinator.EnterUpdateFlowAsync(args, context.GetCancellationToken()).ConfigureAwait(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for async/await

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing with templatePackageManager: we should await due to using. Forgot comment :)

}

protected override UpdateCommandArgs ParseContext(ParseResult parseResult) => new(this, parseResult);
}

internal class UpdateCommandArgs : GlobalArgs
{
public UpdateCommandArgs(UpdateCommand command, ParseResult parseResult) : base(command, parseResult)
public UpdateCommandArgs(BaseUpdateCommand command, ParseResult parseResult) : base(command, parseResult)
{
if (command is UpdateCommand updateCommand)
{
CheckOnly = parseResult.GetValueForOption(updateCommand.CheckOnlyOption);
}
else if (command is LegacyUpdateCheckCommand)
{
CheckOnly = true;
}
else if (command is LegacyUpdateApplyCommand)
{
CheckOnly = false;
}
else
{
throw new ArgumentException($"Unsupported type {command.GetType().FullName}", nameof(command));
}

Interactive = parseResult.GetValueForOption(command.InteractiveOption);
AdditionalSources = parseResult.GetValueForOption(command.AddSourceOption);
}

public bool CheckOnly { get; }

public bool Interactive { get; }

public IReadOnlyList<string>? AdditionalSources { get; }
}
}
45 changes: 27 additions & 18 deletions src/Microsoft.TemplateEngine.Cli/LocalizableStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading