From 92486177a8ac70a951f45252e06ccadb6f7e3181 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Fri, 20 Sep 2019 15:55:18 +0300 Subject: [PATCH] source code download --- .../Volo/Abp/Cli/AbpCliCoreModule.cs | 1 + .../Volo/Abp/Cli/Commands/GetSourceCommand.cs | 157 ++++++++++++++++++ .../Volo/Abp/Cli/Commands/NewCommand.cs | 8 +- ...mplateStore.cs => AbpIoSourceCodeStore.cs} | 40 +++-- .../ProjectBuilding/Building/ModuleInfo.cs | 11 ++ .../ModuleProjectBuildPipelineBuilder.cs | 18 ++ .../Building/ProjectBuildContext.cs | 9 +- .../Steps/NugetReferenceReplaceStep.cs | 2 +- ...=> TemplateProjectBuildPipelineBuilder.cs} | 2 +- .../ProjectBuilding/IModuleInfoProvider.cs | 13 ++ ...{ITemplateStore.cs => ISourceCodeStore.cs} | 3 +- .../Cli/ProjectBuilding/ModuleInfoProvider.cs | 58 +++++++ .../ProjectBuilding/ModuleProjectBuilder.cs | 110 ++++++++++++ .../Cli/ProjectBuilding/SourceCodeTypes.cs | 13 ++ ...ctBuilder.cs => TemplateProjectBuilder.cs} | 20 ++- 15 files changed, 428 insertions(+), 37 deletions(-) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs rename framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/{AbpIoTemplateStore.cs => AbpIoSourceCodeStore.cs} (71%) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleInfo.cs create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs rename framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/{ProjectBuildPipelineBuilder.cs => TemplateProjectBuildPipelineBuilder.cs} (94%) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs rename framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/{ITemplateStore.cs => ISourceCodeStore.cs} (78%) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleInfoProvider.cs create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs rename framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/{ProjectBuilder.cs => TemplateProjectBuilder.cs} (90%) 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 11e2e23a98..b51ef5fb2d 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 @@ -27,6 +27,7 @@ namespace Volo.Abp.Cli { options.Commands["help"] = typeof(HelpCommand); options.Commands["new"] = typeof(NewCommand); + options.Commands["get-source"] = typeof(GetSourceCommand); options.Commands["update"] = typeof(UpdateCommand); options.Commands["add-package"] = typeof(AddPackageCommand); options.Commands["add-module"] = typeof(AddModuleCommand); 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 new file mode 100644 index 0000000000..54711fbc31 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs @@ -0,0 +1,157 @@ +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.ProjectBuilding; +using Volo.Abp.Cli.ProjectBuilding.Building; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands +{ + public class GetSourceCommand : IConsoleCommand, ITransientDependency + { + public ModuleProjectBuilder ModuleProjectBuilder { get; } + + public ILogger Logger { get; set; } + + public GetSourceCommand(ModuleProjectBuilder moduleProjectBuilder) + { + ModuleProjectBuilder = moduleProjectBuilder; + Logger = NullLogger.Instance; + } + + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + if (commandLineArgs.Target == null) + { + throw new CliUsageException( + "Module name is missing!" + + Environment.NewLine + Environment.NewLine + + GetUsageInfo() + ); + } + + Logger.LogInformation("Downloading source code of " + commandLineArgs.Target); + + var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); + if (version != null) + { + Logger.LogInformation("Version: " + version); + } + + var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long); + if (outputFolder != null) + { + if (!Directory.Exists(outputFolder)) + { + Directory.CreateDirectory(outputFolder); + } + + outputFolder = Path.GetFullPath(outputFolder); + } + else + { + outputFolder = Directory.GetCurrentDirectory(); + } + + Logger.LogInformation("Output folder: " + outputFolder); + + commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command); + + var result = await ModuleProjectBuilder.BuildAsync( + new ProjectBuildArgs( + SolutionName.Parse(commandLineArgs.Target), + commandLineArgs.Target, + version, + DatabaseProvider.NotSpecified, + UiFramework.NotSpecified, + commandLineArgs.Options + ) + ); + + using (var templateFileStream = new MemoryStream(result.ZipContent)) + { + using (var zipInputStream = new ZipInputStream(templateFileStream)) + { + var zipEntry = zipInputStream.GetNextEntry(); + while (zipEntry != null) + { + var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name); + var directoryName = Path.GetDirectoryName(fullZipToPath); + + if (!string.IsNullOrEmpty(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + + var fileName = Path.GetFileName(fullZipToPath); + if (fileName.Length == 0) + { + zipEntry = zipInputStream.GetNextEntry(); + continue; + } + + var buffer = new byte[4096]; // 4K is optimum + using (var streamWriter = File.Create(fullZipToPath)) + { + StreamUtils.Copy(zipInputStream, streamWriter, buffer); + } + + zipEntry = zipInputStream.GetNextEntry(); + } + } + } + + Logger.LogInformation($"'{commandLineArgs.Target}' has been successfully downloaded to '{outputFolder}'"); + } + + public string GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(""); + sb.AppendLine(" abp get-source [options]"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine(""); + sb.AppendLine("-o|--output-folder (default: current folder)"); + sb.AppendLine("-v|--version (default: latest version)"); + sb.AppendLine(""); + sb.AppendLine("Examples:"); + sb.AppendLine(""); + sb.AppendLine(" abp get-source Volo.Blogging"); + sb.AppendLine(" abp get-source Volo.Blogging -o d:\\my-project"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); + + return sb.ToString(); + } + + public string GetShortDescription() + { + return "Downloads the source code of the specified module."; + } + + public static class Options + { + public static class OutputFolder + { + public const string Short = "o"; + public const string Long = "output-folder"; + } + + public static class Version + { + public const string Short = "v"; + public const string Long = "version"; + } + } + } +} 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 6921f8e4d8..d8d9395554 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 @@ -17,11 +17,11 @@ namespace Volo.Abp.Cli.Commands { public ILogger Logger { get; set; } - protected ProjectBuilder ProjectBuilder { get; } + protected TemplateProjectBuilder TemplateProjectBuilder { get; } - public NewCommand(ProjectBuilder projectBuilder) + public NewCommand(TemplateProjectBuilder templateProjectBuilder) { - ProjectBuilder = projectBuilder; + TemplateProjectBuilder = templateProjectBuilder; Logger = NullLogger.Instance; } @@ -83,7 +83,7 @@ namespace Volo.Abp.Cli.Commands commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command); - var result = await ProjectBuilder.BuildAsync( + var result = await TemplateProjectBuilder.BuildAsync( new ProjectBuildArgs( SolutionName.Parse(commandLineArgs.Target), template, diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoTemplateStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs similarity index 71% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoTemplateStore.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs index 21f868e73f..6fde8db9e3 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoTemplateStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs @@ -15,9 +15,9 @@ using Volo.Abp.Threading; namespace Volo.Abp.Cli.ProjectBuilding { - public class AbpIoTemplateStore : ITemplateStore, ITransientDependency + public class AbpIoSourceCodeStore : ISourceCodeStore, ITransientDependency { - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } protected CliOptions Options { get; } @@ -25,7 +25,7 @@ namespace Volo.Abp.Cli.ProjectBuilding protected ICancellationTokenProvider CancellationTokenProvider { get; } - public AbpIoTemplateStore( + public AbpIoSourceCodeStore( IOptions options, IJsonSerializer jsonSerializer, ICancellationTokenProvider cancellationTokenProvider) @@ -34,14 +34,15 @@ namespace Volo.Abp.Cli.ProjectBuilding CancellationTokenProvider = cancellationTokenProvider; Options = options.Value; - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } public async Task GetAsync( string name, + string type, string version = null) { - var latestVersion = await GetLatestTemplateVersionAsync(name); + var latestVersion = await GetLatestSourceCodeVersionAsync(name, type); if (version == null) { version = latestVersion; @@ -52,16 +53,17 @@ namespace Volo.Abp.Cli.ProjectBuilding var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip"); if (Options.CacheTemplates && File.Exists(localCacheFile)) { - Logger.LogInformation("Using cached template: " + name + ", version: " + version); + Logger.LogInformation("Using cached " + type + ": " + name + ", version: " + version); return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion); } - Logger.LogInformation("Downloading template: " + name + ", version: " + version); + Logger.LogInformation("Downloading " + type + ": " + name + ", version: " + version); - var fileContent = await DownloadTemplateFileContentAsync( - new TemplateDownloadInputDto + var fileContent = await DownloadSourceCodeContentAsync( + new SourceCodeDownloadInputDto { Name = name, + Type = type, Version = version } ); @@ -74,14 +76,14 @@ namespace Volo.Abp.Cli.ProjectBuilding return new TemplateFile(fileContent, version, latestVersion); } - private async Task GetLatestTemplateVersionAsync(string name) + private async Task GetLatestSourceCodeVersionAsync(string name, string type) { - var postData = JsonSerializer.Serialize(new GetLatestTemplateVersionDto { Name = name }); + var postData = JsonSerializer.Serialize(new GetLatestSourceCodeVersionDto { Name = name }); using (var client = new CliHttpClient()) { var responseMessage = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/template/get-version/", + $"{CliUrls.WwwAbpIo}api/download/{type}/get-version/", new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), CancellationTokenProvider.Token ); @@ -92,18 +94,18 @@ namespace Volo.Abp.Cli.ProjectBuilding } var result = await responseMessage.Content.ReadAsStringAsync(); - return JsonSerializer.Deserialize(result).Version; + return JsonSerializer.Deserialize(result).Version; } } - private async Task DownloadTemplateFileContentAsync(TemplateDownloadInputDto input) + private async Task DownloadSourceCodeContentAsync(SourceCodeDownloadInputDto input) { var postData = JsonSerializer.Serialize(input); using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) { var responseMessage = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/template/", + $"{CliUrls.WwwAbpIo}api/download/{input.Type}/", new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), CancellationTokenProvider.Token ); @@ -117,19 +119,21 @@ namespace Volo.Abp.Cli.ProjectBuilding } } - public class TemplateDownloadInputDto + public class SourceCodeDownloadInputDto { public string Name { get; set; } public string Version { get; set; } + + public string Type { get; set; } } - public class GetLatestTemplateVersionDto + public class GetLatestSourceCodeVersionDto { public string Name { get; set; } } - public class GetLatestTemplateVersionResultDto + public class GetLatestSourceCodeVersionResultDto { public string Version { get; set; } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleInfo.cs new file mode 100644 index 0000000000..dfeabf6aed --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleInfo.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.Cli.ProjectBuilding.Building +{ + public class ModuleInfo + { + public string Name { get; set; } + + public string Namespace { get; set; } + + public string DocumentUrl { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs new file mode 100644 index 0000000000..3a5fcee77b --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs @@ -0,0 +1,18 @@ +using Volo.Abp.Cli.ProjectBuilding.Building.Steps; + +namespace Volo.Abp.Cli.ProjectBuilding.Building +{ + public static class ModuleProjectBuildPipelineBuilder + { + public static ProjectBuildPipeline Build(ProjectBuildContext context) + { + var pipeline = new ProjectBuildPipeline(context); + + pipeline.Steps.Add(new FileEntryListReadStep()); + pipeline.Steps.Add(new NugetReferenceReplaceStep()); + pipeline.Steps.Add(new CreateProjectResultZipStep()); + + return pipeline; + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs index 1ea040022f..8b5522165f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs @@ -11,19 +11,22 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building [NotNull] public ProjectBuildArgs BuildArgs { get; } - [NotNull] public TemplateInfo Template { get; } + public ModuleInfo Module { get; } + public FileEntryList Files { get; set; } public ProjectResult Result { get; set; } public ProjectBuildContext( - [NotNull] TemplateInfo template, + TemplateInfo template, + ModuleInfo module, [NotNull] TemplateFile templateFile, [NotNull] ProjectBuildArgs buildArgs) { - Template = Check.NotNull(template, nameof(template)); + Template = template; + Module = module; TemplateFile = Check.NotNull(templateFile, nameof(templateFile)); BuildArgs = Check.NotNull(buildArgs, nameof(buildArgs)); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs index cb790ba91f..7d08ed7ff6 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps new NugetReferenceReplacer( context.Files, - "MyCompanyName.MyProjectName", + context.Module?.Namespace ?? "MyCompanyName.MyProjectName", nugetPackageVersion ).Run(); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs similarity index 94% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index 49cb44d13a..7ff1f5a38a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -3,7 +3,7 @@ using Volo.Abp.Cli.ProjectBuilding.Templates.App; namespace Volo.Abp.Cli.ProjectBuilding.Building { - public static class ProjectBuildPipelineBuilder + public static class TemplateProjectBuildPipelineBuilder { public static ProjectBuildPipeline Build(ProjectBuildContext context) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs new file mode 100644 index 0000000000..7e490a78d2 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Cli.ProjectBuilding.Building; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public interface IModuleInfoProvider + { + Task GetAsync(string name); + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs similarity index 78% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateStore.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs index 728d4d4a51..4d1ed7aa0c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ITemplateStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs @@ -3,10 +3,11 @@ using JetBrains.Annotations; namespace Volo.Abp.Cli.ProjectBuilding { - public interface ITemplateStore + public interface ISourceCodeStore { Task GetAsync( string name, + string type, [CanBeNull] string version = null ); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleInfoProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleInfoProvider.cs new file mode 100644 index 0000000000..b13cf262c9 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleInfoProvider.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Json; +using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding.Building; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http; +using Volo.Abp.Threading; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public class ModuleInfoProvider: IModuleInfoProvider, ITransientDependency + { + public IJsonSerializer JsonSerializer { get; } + public ICancellationTokenProvider CancellationTokenProvider { get; } + + public ModuleInfoProvider(IJsonSerializer jsonSerializer, ICancellationTokenProvider cancellationTokenProvider) + { + JsonSerializer = jsonSerializer; + CancellationTokenProvider = cancellationTokenProvider; + } + + public async Task GetAsync(string name) + { + var moduleList = await GetModuleListAsync(); + + var module = moduleList.FirstOrDefault(m => m.Name == name); + + if (module == null) + { + throw new Exception("Module not found!"); + } + + return module; + } + + private async Task> GetModuleListAsync() + { + using (var client = new CliHttpClient()) + { + var responseMessage = await client.GetAsync( + $"{CliUrls.WwwAbpIo}api/download/modules/", + CancellationTokenProvider.Token + ); + + if (!responseMessage.IsSuccessStatusCode) + { + throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); + } + + var result = await responseMessage.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize>(result); + } + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs new file mode 100644 index 0000000000..c527375a70 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs @@ -0,0 +1,110 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Cli.Commands; +using Volo.Abp.Cli.Licensing; +using Volo.Abp.Cli.ProjectBuilding.Analyticses; +using Volo.Abp.Cli.ProjectBuilding.Building; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public class ModuleProjectBuilder : IProjectBuilder, ITransientDependency + { + public ILogger Logger { get; set; } + + protected ISourceCodeStore SourceCodeStore { get; } + protected IModuleInfoProvider ModuleInfoProvider { get; } + protected ICliAnalyticsCollect CliAnalyticsCollect { get; } + protected CliOptions Options { get; } + protected IJsonSerializer JsonSerializer { get; } + protected IApiKeyService ApiKeyService { get; } + + public ModuleProjectBuilder(ISourceCodeStore sourceCodeStore, + IModuleInfoProvider moduleInfoProvider, + ICliAnalyticsCollect cliAnalyticsCollect, + IOptions options, + IJsonSerializer jsonSerializer, + IApiKeyService apiKeyService) + { + SourceCodeStore = sourceCodeStore; + ModuleInfoProvider = moduleInfoProvider; + CliAnalyticsCollect = cliAnalyticsCollect; + Options = options.Value; + JsonSerializer = jsonSerializer; + ApiKeyService = apiKeyService; + + Logger = NullLogger.Instance; + } + + public async Task BuildAsync(ProjectBuildArgs args) + { + var moduleInfo = await GetModuleInfoAsync(args); + + var templateFile = await SourceCodeStore.GetAsync( + args.TemplateName, + SourceCodeTypes.Module, + args.Version + ); + + var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync(); + if (apiKeyResult?.ApiKey != null) + { + args.ExtraProperties["api-key"] = apiKeyResult.ApiKey; + } + + if (apiKeyResult?.LicenseCode != null) + { + args.ExtraProperties["license-code"] = apiKeyResult.LicenseCode; + } + + var context = new ProjectBuildContext( + null, + moduleInfo, + templateFile, + args + ); + + ModuleProjectBuildPipelineBuilder.Build(context).Execute(); + + if (!moduleInfo.DocumentUrl.IsNullOrEmpty()) + { + Logger.LogInformation("Check out the documents at " + moduleInfo.DocumentUrl); + } + + // Exclude unwanted or known options. + var options = args.ExtraProperties + .Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) && + !x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) && + !x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase)) + .Select(x => x.Key).ToList(); + + await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto + { + Tool = Options.ToolName, + Command = args.ExtraProperties.ContainsKey(CliConsts.Command) ? args.ExtraProperties[CliConsts.Command] : "", + DatabaseProvider = null, + IsTiered = false, + UiFramework = null, + Options = JsonSerializer.Serialize(options), + ProjectName = null, + TemplateName = args.TemplateName, + TemplateVersion = templateFile.Version + }); + + return new ProjectBuildResult(context.Result.ZipContent, args.TemplateName); + } + + private async Task GetModuleInfoAsync(ProjectBuildArgs args) + { + return await ModuleInfoProvider.GetAsync(args.TemplateName); + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs new file mode 100644 index 0000000000..9b2d21cc8d --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public static class SourceCodeTypes + { + public const string Template = "template"; + + public const string Module = "module"; + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs similarity index 90% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs rename to framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs index 6c9b6fa145..1031b965e0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -14,32 +14,32 @@ using Volo.Abp.Json; namespace Volo.Abp.Cli.ProjectBuilding { - public class ProjectBuilder : IProjectBuilder, ITransientDependency + public class TemplateProjectBuilder : IProjectBuilder, ITransientDependency { - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } - protected ITemplateStore TemplateStore { get; } + protected ISourceCodeStore SourceCodeStore { get; } protected ITemplateInfoProvider TemplateInfoProvider { get; } protected ICliAnalyticsCollect CliAnalyticsCollect { get; } protected CliOptions Options { get; } protected IJsonSerializer JsonSerializer { get; } protected IApiKeyService ApiKeyService { get; } - public ProjectBuilder(ITemplateStore templateStore, + public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore, ITemplateInfoProvider templateInfoProvider, ICliAnalyticsCollect cliAnalyticsCollect, IOptions options, IJsonSerializer jsonSerializer, IApiKeyService apiKeyService) { - TemplateStore = templateStore; + SourceCodeStore = sourceCodeStore; TemplateInfoProvider = templateInfoProvider; CliAnalyticsCollect = cliAnalyticsCollect; Options = options.Value; JsonSerializer = jsonSerializer; ApiKeyService = apiKeyService; - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } public async Task BuildAsync(ProjectBuildArgs args) @@ -48,11 +48,12 @@ namespace Volo.Abp.Cli.ProjectBuilding NormalizeArgs(args, templateInfo); - var templateFile = await TemplateStore.GetAsync( + var templateFile = await SourceCodeStore.GetAsync( args.TemplateName, + SourceCodeTypes.Template, args.Version ); - + var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync(); if (apiKeyResult?.ApiKey != null) { @@ -66,11 +67,12 @@ namespace Volo.Abp.Cli.ProjectBuilding var context = new ProjectBuildContext( templateInfo, + null, templateFile, args ); - ProjectBuildPipelineBuilder.Build(context).Execute(); + TemplateProjectBuildPipelineBuilder.Build(context).Execute(); if (!templateInfo.DocumentUrl.IsNullOrEmpty()) {