From 484f0bc08ce2f795bbb873efacd67baa846ce9dd Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 2 Mar 2020 15:45:06 +0800 Subject: [PATCH] Allow CLI to generate templates with custom sources --- .../Volo/Abp/Cli/Commands/GetSourceCommand.cs | 1 + .../Volo/Abp/Cli/Commands/NewCommand.cs | 18 +++++++- .../ProjectBuilding/AbpIoSourceCodeStore.cs | 42 ++++++++++++++----- .../Cli/ProjectBuilding/ISourceCodeStore.cs | 3 +- .../Cli/ProjectBuilding/ProjectBuildArgs.cs | 7 +++- .../ProjectBuilding/TemplateProjectBuilder.cs | 15 +++---- 6 files changed, 65 insertions(+), 21 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs index 9ad7eb5b49..175ce84fb3 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs @@ -78,6 +78,7 @@ namespace Volo.Abp.Cli.Commands UiFramework.NotSpecified, MobileApp.None, gitHubLocalRepositoryPath, + null, commandLineArgs.Options ) ); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index d39a333860..050ee4b51f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.Cli.Commands public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { var projectName = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target); - + if (projectName == null) { throw new CliUsageException( @@ -39,7 +39,7 @@ namespace Volo.Abp.Cli.Commands GetUsageInfo() ); } - + Logger.LogInformation("Creating your project..."); Logger.LogInformation("Project name: " + projectName); @@ -79,6 +79,12 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("GitHub Local Repository Path: " + gitHubLocalRepositoryPath); } + var templateSource = commandLineArgs.Options.GetOrNull(Options.TemplateSource.Long); + if (templateSource != null) + { + Logger.LogInformation("Template Source: " + templateSource); + } + var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long); outputFolder = Path.Combine(outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory(), @@ -102,6 +108,7 @@ namespace Volo.Abp.Cli.Commands uiFramework, mobileApp, gitHubLocalRepositoryPath, + templateSource, commandLineArgs.Options ) ); @@ -162,6 +169,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("--no-ui (if supported by the template)"); sb.AppendLine("--separate-identity-server (if supported by the template)"); sb.AppendLine("--local-framework-ref --abp-path (keeps local references to projects instead of replacing with NuGet package references)"); + sb.AppendLine("--template-source (your local or network abp template source)"); sb.AppendLine(""); sb.AppendLine("Examples:"); sb.AppendLine(""); @@ -174,6 +182,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -t module"); sb.AppendLine(" abp new Acme.BookStore -t module --no-ui"); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); + sb.AppendLine(" abp new Acme.BookStore --template-url \"D:\\localTemplate\\abp\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); @@ -271,6 +280,11 @@ namespace Volo.Abp.Cli.Commands public const string Short = "m"; public const string Long = "mobile"; } + + public static class TemplateSource + { + public const string Long = "template-source"; + } } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs index fd0a0e5246..03504251f5 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs @@ -2,9 +2,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -46,7 +44,8 @@ namespace Volo.Abp.Cli.ProjectBuilding public async Task GetAsync( string name, string type, - string version = null) + string version = null, + string templateSource = null) { var latestVersion = await GetLatestSourceCodeVersionAsync(name, type); @@ -57,8 +56,14 @@ namespace Volo.Abp.Cli.ProjectBuilding DirectoryHelper.CreateIfNotExists(CliPaths.TemplateCache); + if (!string.IsNullOrWhiteSpace(templateSource) && !IsNetworkSource(templateSource)) + { + Logger.LogInformation("Using local " + type + ": " + name + ", version: " + version); + return new TemplateFile(File.ReadAllBytes(Path.Combine(templateSource, name + "-" + version + ".zip")), version, latestVersion); + } + var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip"); - if (Options.CacheTemplates && File.Exists(localCacheFile)) + if (Options.CacheTemplates && File.Exists(localCacheFile) && templateSource.IsNullOrWhiteSpace()) { Logger.LogInformation("Using cached " + type + ": " + name + ", version: " + version); return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion); @@ -71,11 +76,12 @@ namespace Volo.Abp.Cli.ProjectBuilding { Name = name, Type = type, + TemplateSource = templateSource, Version = version } ); - if (Options.CacheTemplates) + if (Options.CacheTemplates && templateSource.IsNullOrWhiteSpace()) { File.WriteAllBytes(localCacheFile, fileContent); } @@ -114,11 +120,20 @@ namespace Volo.Abp.Cli.ProjectBuilding using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) { - var responseMessage = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/{input.Type}/", - new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), - CancellationTokenProvider.Token - ); + HttpResponseMessage responseMessage; + + if (input.TemplateSource.IsNullOrWhiteSpace()) + { + responseMessage = await client.PostAsync( + $"{CliUrls.WwwAbpIo}api/download/{input.Type}/", + new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), + CancellationTokenProvider.Token + ); + } + else + { + responseMessage = await client.GetAsync(input.TemplateSource, CancellationTokenProvider.Token); + } await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); @@ -126,6 +141,11 @@ namespace Volo.Abp.Cli.ProjectBuilding } } + private bool IsNetworkSource(string source) + { + return source.ToLower().StartsWith("http"); + } + public class SourceCodeDownloadInputDto { public string Name { get; set; } @@ -133,6 +153,8 @@ namespace Volo.Abp.Cli.ProjectBuilding public string Version { get; set; } public string Type { get; set; } + + public string TemplateSource { get; set; } } public class GetLatestSourceCodeVersionDto diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs index 4d1ed7aa0c..de082d4bcf 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs @@ -8,7 +8,8 @@ namespace Volo.Abp.Cli.ProjectBuilding Task GetAsync( string name, string type, - [CanBeNull] string version = null + [CanBeNull] string version = null, + [CanBeNull] string templateSource = null ); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs index bb20c19e80..2f79f330e5 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs @@ -24,17 +24,21 @@ namespace Volo.Abp.Cli.ProjectBuilding [CanBeNull] public string AbpGitHubLocalRepositoryPath { get; set; } + [CanBeNull] + public string TemplateSource { get; set; } + [NotNull] public Dictionary ExtraProperties { get; set; } public ProjectBuildArgs( - [NotNull] SolutionName solutionName, + [NotNull] SolutionName solutionName, [CanBeNull] string templateName = null, [CanBeNull] string version = null, DatabaseProvider databaseProvider = DatabaseProvider.NotSpecified, UiFramework uiFramework = UiFramework.NotSpecified, MobileApp mobileApp = MobileApp.ReactNative, [CanBeNull] string abpGitHubLocalRepositoryPath = null, + [CanBeNull] string templateSource = null, Dictionary extraProperties = null) { SolutionName = Check.NotNull(solutionName, nameof(solutionName)); @@ -44,6 +48,7 @@ namespace Volo.Abp.Cli.ProjectBuilding UiFramework = uiFramework; MobileApp = mobileApp; AbpGitHubLocalRepositoryPath = abpGitHubLocalRepositoryPath; + TemplateSource = templateSource; ExtraProperties = extraProperties ?? new Dictionary(); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs index 80a25660fc..a0f156de7b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -24,11 +24,11 @@ namespace Volo.Abp.Cli.ProjectBuilding protected IJsonSerializer JsonSerializer { get; } protected IApiKeyService ApiKeyService { get; } - public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore, + public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore, ITemplateInfoProvider templateInfoProvider, - ICliAnalyticsCollect cliAnalyticsCollect, + ICliAnalyticsCollect cliAnalyticsCollect, IOptions options, - IJsonSerializer jsonSerializer, + IJsonSerializer jsonSerializer, IApiKeyService apiKeyService) { SourceCodeStore = sourceCodeStore; @@ -40,7 +40,7 @@ namespace Volo.Abp.Cli.ProjectBuilding Logger = NullLogger.Instance; } - + public async Task BuildAsync(ProjectBuildArgs args) { var templateInfo = GetTemplateInfo(args); @@ -50,9 +50,10 @@ namespace Volo.Abp.Cli.ProjectBuilding var templateFile = await SourceCodeStore.GetAsync( args.TemplateName, SourceCodeTypes.Template, - args.Version + args.Version, + args.TemplateSource ); - + var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync(); if (apiKeyResult?.ApiKey != null) { @@ -82,7 +83,7 @@ namespace Volo.Abp.Cli.ProjectBuilding var options = args.ExtraProperties .Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals("tiered", StringComparison.InvariantCultureIgnoreCase)) - .Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) && + .Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.DatabaseProvider.Short, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase))