diff --git a/docs/en/CLI.md b/docs/en/CLI.md index f2da02d889..9c06cd2a84 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -27,6 +27,7 @@ While each command may have a set of options, there are some global options that Here, is the list of all available commands before explaining their details: * **`help`**: Shows help on the usage of the ABP CLI. +* **`cli`**: Update or remove ABP CLI. * **`new`**: Generates a new solution based on the ABP [startup templates](Startup-Templates/Index.md). * **`update`**: Automatically updates all ABP related NuGet and NPM packages in a solution. * **`clean`**: Deletes all `BIN` and `OBJ` folders in the current folder. @@ -63,6 +64,25 @@ abp help # Shows a general help. abp help new # Shows help about the "new" command. ```` +### cli + +Update or remove ABP CLI. + +Usage: + +````bash +abp cli [command-name] +```` + +Examples: + +````bash +abp cli update +abp cli update --preview +abp cli update --version 5.0.0 +abp cli remove +```` + ### new Generates a new solution based on the ABP [startup templates](Startup-Templates/Index.md). diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index fea3ec781f..96d78538ef 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -27,6 +27,7 @@ dotnet tool update -g Volo.Abp.Cli 这里是所有可用的命令列表: * **`help`**: 展示ABP CLI的用法帮助信息. +* **`cli`**: 更新或删除ABP CLI. * **`new`**:生成基于ABP的[启动模板](Startup-Templates/Index.md). * **`update`**:自动更新的ABP解决方案ABP相关的NuGet和NPM包. * **`clean`**: 删除当前目录下所有的 `BIN` 和 `OBJ` 子目录. @@ -60,6 +61,25 @@ abp help # Shows a general help. abp help new # Shows help about the "new" command. ```` +### cli + +更新或删除ABP CLI + +用法: + +````bash +abp cli [command-name] +```` + +示例: + +````bash +abp cli update +abp cli update --preview +abp cli update --version 5.0.0 +abp cli remove +```` + ### new 生成基于ABP[启动模板](Startup-Templates/Index.md)的新解决方案. diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index 3e4649b6e3..4fda075521 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -64,6 +64,7 @@ public class AbpCliCoreModule : AbpModule options.Commands[CreateMigrationAndRunMigratorCommand.Name] = typeof(CreateMigrationAndRunMigratorCommand); options.Commands[InstallLibsCommand.Name] = typeof(InstallLibsCommand); options.Commands[CleanCommand.Name] = typeof(CleanCommand); + options.Commands[CliCommand.Name] = typeof(CliCommand); }); Configure(options => diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs new file mode 100644 index 0000000000..7a6926ecdd --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CliCommand.cs @@ -0,0 +1,172 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Commands.Services; +using Volo.Abp.Cli.NuGet; +using Volo.Abp.Cli.Utils; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands; + +public class CliCommand : IConsoleCommand, ITransientDependency +{ + public const string Name = "cli"; + + private const string CliPackageName = "Volo.Abp.Cli"; + + private readonly ICmdHelper _cmdHelper; + private readonly NuGetService _nuGetService; + private readonly AbpNuGetIndexUrlService _nuGetIndexUrlService; + public ILogger Logger { get; set; } + + public CliCommand(ICmdHelper cmdHelper, NuGetService nuGetService, AbpNuGetIndexUrlService nuGetIndexUrlService) + { + _cmdHelper = cmdHelper; + _nuGetService = nuGetService; + _nuGetIndexUrlService = nuGetIndexUrlService; + + Logger = NullLogger.Instance; + } + + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + var operationType = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target); + + var preview = commandLineArgs.Options.ContainsKey(Options.Preview.Short) || + commandLineArgs.Options.ContainsKey(Options.Preview.Long); + + var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); + + switch (operationType) + { + case "": + case null: + _cmdHelper.RunCmd("abp"); + break; + + case "update": + await UpdateCliAsync(version, preview); + break; + + case "remove": + RemoveCli(); + break; + } + } + + private async Task UpdateCliAsync(string version = null, bool preview = false) + { + var infoText = "Updating ABP CLI "; + if (version != null) + { + infoText += "to the " + version + "... "; + } + else if (preview) + { + infoText += "to the latest preview version..."; + } + else + { + infoText += "..."; + } + + Logger.LogInformation(infoText); + + try + { + var versionOption = string.Empty; + + if (preview) + { + var latestPreviewVersion = await GetLatestPreviewVersion(); + if (latestPreviewVersion != null) + { + versionOption = $" --version {latestPreviewVersion}"; + Logger.LogInformation("Latest preview version is " + latestPreviewVersion); + } + } + else if (version != null) + { + versionOption = $" --version {version}"; + } + + _cmdHelper.RunCmdAndExit($"dotnet tool update {CliPackageName}{versionOption} -g", delaySeconds: 2); + } + catch (Exception ex) + { + Logger.LogError("Couldn't update ABP CLI." + ex.Message); + ShowCliManualUpdateCommand(); + } + } + + private async Task GetLatestPreviewVersion() + { + var latestPreviewVersion = await _nuGetService + .GetLatestVersionOrNullAsync( + packageId: CliPackageName, + includeReleaseCandidates: true + ); + + return latestPreviewVersion.IsPrerelease ? latestPreviewVersion.ToString() : null; + } + + private void ShowCliManualUpdateCommand() + { + Logger.LogError("You can also run the following command to update ABP CLI."); + Logger.LogError("dotnet tool update -g Volo.Abp.Cli"); + } + + private void RemoveCli() + { + Logger.LogInformation("Removing CLI..."); + _cmdHelper.RunCmdAndExit("dotnet tool uninstall " + CliPackageName + " -g", delaySeconds: 2); + } + + public string GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(""); + sb.AppendLine(" abp cli [options]"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine(""); + sb.AppendLine("update (update ABP CLI to the latest)"); + sb.AppendLine("remove (uninstall ABP CLI)"); + sb.AppendLine(""); + sb.AppendLine("Examples:"); + sb.AppendLine(""); + sb.AppendLine(" abp cli update"); + sb.AppendLine(" abp cli update --preview"); + sb.AppendLine(" abp cli update --version 4.2.2"); + sb.AppendLine(" abp cli remove"); + sb.AppendLine(""); + + return sb.ToString(); + } + + public string GetShortDescription() + { + return "Update or remove ABP CLI. See https://docs.abp.io/en/abp/latest/CLI"; + } + + public static class Options + { + public static class Preview + { + public const string Long = "preview"; + public const string Short = "p"; + } + + public static class Version + { + public const string Long = "version"; + public const string Short = "v"; + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs index 741390dc73..c6325a4681 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using Volo.Abp.DependencyInjection; @@ -125,15 +126,31 @@ public class CmdHelper : ICmdHelper, ITransientDependency return output.Trim(); } - public string GetArguments(string command) + public void RunCmdAndExit(string command, string workingDirectory = null, int? delaySeconds = null) + { + var procStartInfo = new ProcessStartInfo( + GetFileName(), + GetArguments(command, delaySeconds) + ); + + if (!string.IsNullOrEmpty(workingDirectory)) + { + procStartInfo.WorkingDirectory = workingDirectory; + } + + Process.Start(procStartInfo); + Environment.Exit(0); + } + + public string GetArguments(string command, int? delaySeconds = null) { if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - return "-c \"" + command + "\""; + return delaySeconds == null ? "-c \"" + command + "\"" : "-c \"" + $"sleep {delaySeconds}s > /dev/null && " + command + "\""; } //Windows default. - return "/C \"" + command + "\""; + return delaySeconds == null ? "/C \"" + command + "\"" : "/C \"" + $"timeout /nobreak /t {delaySeconds} >null && " + command + "\""; } public string GetFileName() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs index 648215d24f..f96697b1cc 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs @@ -8,20 +8,22 @@ public interface ICmdHelper void Run(string file, string arguments); - string GetArguments(string command); + string GetArguments(string command, int? delaySeconds = null); string GetFileName(); void RunCmd(string command, string workingDirectory = null); Process RunCmdAndGetProcess(string command, string workingDirectory = null); - + void RunCmd(string command, out int exitCode, string workingDirectory = null); string RunCmdAndGetOutput(string command, string workingDirectory = null); - string RunCmdAndGetOutput(string command, out bool isExitCodeSuccessful, string workingDirectory = null); string RunCmdAndGetOutput(string command, out int exitCode, string workingDirectory = null); + + void RunCmdAndExit(string command, string workingDirectory = null, int? delaySeconds = null); + }