Skip to content

Commit

Permalink
fixes dotnet/templating #3807 update subcommand (#4045)
Browse files Browse the repository at this point in the history
* fixes dotnet/templating #3807 update subcommand
  • Loading branch information
vlada-shubina committed Jan 27, 2022
1 parent 56531f0 commit c285a2e
Show file tree
Hide file tree
Showing 25 changed files with 611 additions and 218 deletions.
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);
}

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

0 comments on commit c285a2e

Please sign in to comment.