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..97dfe23944 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs @@ -0,0 +1,169 @@ +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); + + var gitHubLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubLocalRepositoryPath.Long); + if (gitHubLocalRepositoryPath != null) + { + Logger.LogInformation("GitHub Local Repository Path: " + gitHubLocalRepositoryPath); + } + + 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, + gitHubLocalRepositoryPath, + 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 GitHubLocalRepositoryPath + { + public const string Long = "abp-path"; + } + + 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 e1e8c53abf..e30ed7a77f 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; } @@ -89,7 +89,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/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs index aa1c1501b5..742d327c1c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -7,13 +6,11 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; -using Newtonsoft.Json; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.ProjectBuilding.Analyticses; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.DependencyInjection; using Volo.Abp.Json; -using Volo.Abp.Threading; namespace Volo.Abp.Cli.Commands { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs index 22cd692ec3..c8f221b73c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.DependencyInjection; using Volo.Abp.Json; @@ -8,13 +9,16 @@ namespace Volo.Abp.Cli.Licensing { public class AbpIoApiKeyService : IApiKeyService, ITransientDependency { - public AbpIoApiKeyService(IJsonSerializer jsonSerializer) + protected IJsonSerializer JsonSerializer { get; } + + protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + + public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler) { JsonSerializer = jsonSerializer; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; } - protected IJsonSerializer JsonSerializer { get; } - public async Task GetApiKeyOrNullAsync() { using (var client = new CliHttpClient()) @@ -28,6 +32,8 @@ namespace Volo.Abp.Cli.Licensing throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); } + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + var responseContent = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(responseContent); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs index 0fb8058c61..23ff81555a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs @@ -1,5 +1,4 @@ -using System.Net; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Volo.Abp.Cli.Licensing { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs index b0dd6328db..700303006b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.DependencyInjection; using Volo.Abp.Json; using Volo.Abp.Threading; @@ -17,11 +18,15 @@ namespace Volo.Abp.Cli.NuGet protected ICancellationTokenProvider CancellationTokenProvider { get; } + protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + public NuGetService( IJsonSerializer jsonSerializer, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler, ICancellationTokenProvider cancellationTokenProvider) { JsonSerializer = jsonSerializer; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; CancellationTokenProvider = cancellationTokenProvider; } @@ -35,10 +40,7 @@ namespace Volo.Abp.Cli.NuGet var responseMessage = await client.GetAsync(url, CancellationTokenProvider.Token); - if (!responseMessage.IsSuccessStatusCode) - { - throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); - } + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); var result = await responseMessage.Content.ReadAsStringAsync(); @@ -49,7 +51,8 @@ namespace Volo.Abp.Cli.NuGet versions = versions.Where(x => !x.IsPrerelease); } - return versions.Any() ? versions.Max() : null; + var semanticVersions = versions.ToList(); + return semanticVersions.Any() ? semanticVersions.Max() : null; } } 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 55% 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..ac51be6fac 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 @@ -2,7 +2,9 @@ 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; @@ -15,33 +17,39 @@ 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; } protected IJsonSerializer JsonSerializer { get; } + protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } - public AbpIoTemplateStore( + public AbpIoSourceCodeStore( IOptions options, IJsonSerializer jsonSerializer, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler, ICancellationTokenProvider cancellationTokenProvider) { JsonSerializer = jsonSerializer; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; 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 +60,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 } ); @@ -72,64 +81,66 @@ 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 }); - using (var client = new CliHttpClient()) { - var responseMessage = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/template/get-version/", - new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), + var response = await client.PostAsync( + $"{CliUrls.WwwAbpIo}api/download/{type}/get-version/", + new StringContent( + JsonSerializer.Serialize( + new GetLatestSourceCodeVersionDto { Name = name } + ), + Encoding.UTF8, + MimeTypes.Application.Json + ), CancellationTokenProvider.Token ); - if (!responseMessage.IsSuccessStatusCode) - { - throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); - } + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + + var result = await response.Content.ReadAsStringAsync(); - 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 ); - if (!responseMessage.IsSuccessStatusCode) - { - throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); - } + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); return await responseMessage.Content.ReadAsByteArrayAsync(); } } - 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/Analyticses/CliAnalyticsCollect.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Analyticses/CliAnalyticsCollect.cs index 6598c9fb31..fdfbb8b5d3 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Analyticses/CliAnalyticsCollect.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Analyticses/CliAnalyticsCollect.cs @@ -16,12 +16,16 @@ namespace Volo.Abp.Cli.ProjectBuilding.Analyticses private readonly ICancellationTokenProvider _cancellationTokenProvider; private readonly IJsonSerializer _jsonSerializer; private readonly ILogger _logger; + private readonly IRemoteServiceExceptionHandler _remoteServiceExceptionHandler; - public CliAnalyticsCollect(ICancellationTokenProvider cancellationTokenProvider, - IJsonSerializer jsonSerializer) + public CliAnalyticsCollect( + ICancellationTokenProvider cancellationTokenProvider, + IJsonSerializer jsonSerializer, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler) { _cancellationTokenProvider = cancellationTokenProvider; _jsonSerializer = jsonSerializer; + _remoteServiceExceptionHandler = remoteServiceExceptionHandler; _logger = NullLogger.Instance; } @@ -38,8 +42,15 @@ namespace Volo.Abp.Cli.ProjectBuilding.Analyticses if (!responseMessage.IsSuccessStatusCode) { - _logger.LogInformation("Remote server returns error! HTTP status code: " + - responseMessage.StatusCode); + var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. "; + var remoteServiceErrorMessage = await _remoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage); + + if (remoteServiceErrorMessage != null) + { + exceptionMessage += remoteServiceErrorMessage; + } + + _logger.LogInformation(exceptionMessage); } } } 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..5eba01b388 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ModuleProjectBuildPipelineBuilder.cs @@ -0,0 +1,19 @@ +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 ProjectReferenceReplaceStep()); + pipeline.Steps.Add(new ReplaceCommonPropsStep()); + 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/ProjectReferenceReplaceStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs index b040c5320d..29f5afb19c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs @@ -22,7 +22,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps new ProjectReferenceReplacer.LocalProjectPathReferenceReplacer( context.Files, - "MyCompanyName.MyProjectName", + context.Module?.Namespace ?? "MyCompanyName.MyProjectName", localAbpRepoPath ).Run(); } @@ -37,7 +37,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps new ProjectReferenceReplacer.NugetReferenceReplacer( context.Files, - "MyCompanyName.MyProjectName", + context.Module?.Namespace ?? "MyCompanyName.MyProjectName", nugetPackageVersion ).Run(); } @@ -65,14 +65,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps private abstract class ProjectReferenceReplacer { private readonly List _entries; - private readonly string _companyAndProjectNamePlaceHolder; + private readonly string _projectName; protected ProjectReferenceReplacer( List entries, - string companyAndProjectNamePlaceHolder) + string projectName) { _entries = entries; - _companyAndProjectNamePlaceHolder = companyAndProjectNamePlaceHolder; + _projectName = projectName; } public void Run() @@ -108,7 +108,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps var oldNodeIncludeValue = oldNode.Attributes["Include"].Value; // ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method - if (oldNodeIncludeValue.Contains($"{_companyAndProjectNamePlaceHolder}")) + if (oldNodeIncludeValue.Contains(_projectName)) { continue; } @@ -140,8 +140,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps { private readonly string _nugetPackageVersion; - public NugetReferenceReplacer(List entries, string companyAndProjectNamePlaceHolder, string nugetPackageVersion) - : base(entries, companyAndProjectNamePlaceHolder) + public NugetReferenceReplacer(List entries, string projectName, string nugetPackageVersion) + : base(entries, projectName) { _nugetPackageVersion = nugetPackageVersion; } @@ -177,8 +177,8 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps { private readonly string _gitHubLocalRepositoryPath; - public LocalProjectPathReferenceReplacer(List entries, string companyAndProjectNamePlaceHolder, string gitHubLocalRepositoryPath) - : base(entries, companyAndProjectNamePlaceHolder) + public LocalProjectPathReferenceReplacer(List entries, string projectName, string gitHubLocalRepositoryPath) + : base(entries, projectName) { _gitHubLocalRepositoryPath = gitHubLocalRepositoryPath; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs new file mode 100644 index 0000000000..07b2081738 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Xml; +using Volo.Abp.Cli.ProjectBuilding.Files; + +namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps +{ + public class ReplaceCommonPropsStep : ProjectBuildPipelineStep + { + public override void Execute(ProjectBuildContext context) + { + new CommonPropsReplacer(context.Files).Run(); + } + + private class CommonPropsReplacer + { + private readonly List _entries; + + public CommonPropsReplacer( + List entries) + { + _entries = entries; + } + + public void Run() + { + foreach (var fileEntry in _entries) + { + if (fileEntry.Name.EndsWith(".csproj")) + { + fileEntry.SetContent(ProcessFileContent(fileEntry.Content)); + } + } + } + + private string ProcessFileContent(string content) + { + Check.NotNull(content, nameof(content)); + + var doc = new XmlDocument() { PreserveWhitespace = true }; + + doc.Load(GenerateStreamFromString(content)); + + return ProcessReferenceNodes(doc, content); + } + + private string ProcessReferenceNodes(XmlDocument doc, string content) + { + Check.NotNull(content, nameof(content)); + + var importNodes = doc.SelectNodes("/Project/Import[@Project]"); + + if (importNodes == null) + { + return doc.OuterXml; + } + + foreach (XmlNode node in importNodes) + { + if (!(node.Attributes?["Project"]?.Value?.EndsWith("\\common.props") ?? false)) + { + continue; + } + + node.ParentNode?.RemoveChild(node); + } + + var propertyGroupNodes = doc.SelectNodes("/Project/PropertyGroup"); + + if (propertyGroupNodes == null || propertyGroupNodes.Count < 1) + { + return doc.OuterXml; + } + + var firstPropertyGroupNode = propertyGroupNodes.Item(0); + var langNode = doc.CreateElement("LangVersion"); + langNode.InnerText = "latest"; + firstPropertyGroupNode?.PrependChild(langNode); + + return doc.OuterXml; + } + + private static Stream GenerateStreamFromString(string s) + { + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(s); + writer.Flush(); + stream.Position = 0; + return stream; + } + } + } +} 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 93% 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 55a7984dce..e5916f3cbc 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 @@ -4,7 +4,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..bb8d0d72cb --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IModuleInfoProvider.cs @@ -0,0 +1,10 @@ +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/IRemoteServiceExceptionHandler.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IRemoteServiceExceptionHandler.cs new file mode 100644 index 0000000000..b3459f53ed --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/IRemoteServiceExceptionHandler.cs @@ -0,0 +1,12 @@ +using System.Net.Http; +using System.Threading.Tasks; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public interface IRemoteServiceExceptionHandler + { + Task EnsureSuccessfulHttpResponseAsync(HttpResponseMessage responseMessage); + + Task GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage); + } +} \ No newline at end of file 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..10b3a07172 --- /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.Threading; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public class ModuleInfoProvider : IModuleInfoProvider, ITransientDependency + { + public IJsonSerializer JsonSerializer { get; } + public ICancellationTokenProvider CancellationTokenProvider { get; } + public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + + public ModuleInfoProvider( + IJsonSerializer jsonSerializer, + ICancellationTokenProvider cancellationTokenProvider, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler) + { + JsonSerializer = jsonSerializer; + CancellationTokenProvider = cancellationTokenProvider; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; + } + + 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 + ); + + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); + 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..57332bd5e2 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs @@ -0,0 +1,109 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using System; +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 = null, + 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/RemoteServiceExceptionHandler.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs new file mode 100644 index 0000000000..fe41577583 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/RemoteServiceExceptionHandler.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http; +using Volo.Abp.Json; + +namespace Volo.Abp.Cli.ProjectBuilding +{ + public class RemoteServiceExceptionHandler : IRemoteServiceExceptionHandler, ITransientDependency + { + private readonly IJsonSerializer _jsonSerializer; + + public RemoteServiceExceptionHandler(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + } + + public async Task EnsureSuccessfulHttpResponseAsync(HttpResponseMessage responseMessage) + { + if (responseMessage == null) + { + return; + } + + if (responseMessage.IsSuccessStatusCode) + { + return; + } + + var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. "; + + var remoteServiceErrorMessage = await GetAbpRemoteServiceErrorAsync(responseMessage); + if (remoteServiceErrorMessage != null) + { + exceptionMessage += remoteServiceErrorMessage; + } + + throw new Exception(exceptionMessage); + } + + public async Task GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage) + { + var errorResult = _jsonSerializer.Deserialize + ( + await responseMessage.Content.ReadAsStringAsync() + ); + + if (errorResult?.Error == null) + { + return null; + } + + var sbError = new StringBuilder(); + if (!string.IsNullOrWhiteSpace(errorResult.Error.Code)) + { + sbError.Append("Code: " + errorResult.Error.Code); + } + + if (!string.IsNullOrWhiteSpace(errorResult.Error.Message)) + { + if (sbError.Length > 0) + { + sbError.Append(" - "); + } + + sbError.Append("Message: " + errorResult.Error.Message); + } + + if (errorResult.Error.ValidationErrors != null && errorResult.Error.ValidationErrors.Any()) + { + if (sbError.Length > 0) + { + sbError.Append(" - "); + } + + sbError.AppendLine("Validation Errors: "); + for (var i = 0; i < errorResult.Error.ValidationErrors.Length; i++) + { + var validationError = errorResult.Error.ValidationErrors[i]; + sbError.AppendLine("Validation error #" + i + ": " + validationError.Message + " - Members: " + validationError.Members.JoinAsString(", ") + "."); + } + } + + return sbError.ToString(); + } + } +} \ No newline at end of file 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..5f7ad58ef7 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs @@ -0,0 +1,9 @@ +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..e1248b32f0 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 @@ -2,7 +2,6 @@ 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; @@ -14,32 +13,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 +47,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 +66,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()) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 2d308d9219..09b75ac0e2 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; using JetBrains.Annotations; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -27,22 +25,24 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Module private void DeleteUnrelatedProjects(ProjectBuildContext context, List steps) { - if (context.BuildArgs.ExtraProperties.ContainsKey("no-ui")) + if (!context.BuildArgs.ExtraProperties.ContainsKey("no-ui")) { - steps.Add(new RemoveProjectFromSolutionStep( - "MyCompanyName.MyProjectName.Web" - )); + return; + } - steps.Add(new RemoveProjectFromSolutionStep( - "MyCompanyName.MyProjectName.Web.Host", - projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host" - )); + steps.Add(new RemoveProjectFromSolutionStep( + "MyCompanyName.MyProjectName.Web" + )); - steps.Add(new RemoveProjectFromSolutionStep( - "MyCompanyName.MyProjectName.Web.Unified", - projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified" - )); - } + steps.Add(new RemoveProjectFromSolutionStep( + "MyCompanyName.MyProjectName.Web.Host", + projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host" + )); + + steps.Add(new RemoveProjectFromSolutionStep( + "MyCompanyName.MyProjectName.Web.Unified", + projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified" + )); } private void RandomizeSslPorts(ProjectBuildContext context, List steps) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs index cc4d3f74a9..1c8727852b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationAdder.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.IO; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs index fd6f5be5d1..419b52f7fe 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Threading; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackageJsonFileFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackageJsonFileFinder.cs index b3138e1f87..65aaf44a59 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackageJsonFileFinder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackageJsonFileFinder.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.ProjectModification diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs index 2b2941a30d..1bacd7cd61 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; using Volo.Abp.IO; @@ -22,17 +23,20 @@ namespace Volo.Abp.Cli.ProjectModification protected ProjectNpmPackageAdder NpmPackageAdder { get; } protected DerivedClassFinder ModuleClassFinder { get; } protected ModuleClassDependcyAdder ModuleClassDependcyAdder { get; } + protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } public ProjectNugetPackageAdder( IJsonSerializer jsonSerializer, ProjectNpmPackageAdder npmPackageAdder, DerivedClassFinder moduleClassFinder, - ModuleClassDependcyAdder moduleClassDependcyAdder) + ModuleClassDependcyAdder moduleClassDependcyAdder, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler) { JsonSerializer = jsonSerializer; NpmPackageAdder = npmPackageAdder; ModuleClassFinder = moduleClassFinder; ModuleClassDependcyAdder = moduleClassDependcyAdder; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; Logger = NullLogger.Instance; } @@ -84,7 +88,7 @@ namespace Volo.Abp.Cli.ProjectModification throw new CliUsageException($"'{moduleName}' nuget package could not be found!"); } - throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); } var responseContent = await response.Content.ReadAsStringAsync(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 22e063a8ae..5950872419 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.DependencyInjection; using Volo.Abp.Json; @@ -24,6 +25,7 @@ namespace Volo.Abp.Cli.ProjectModification protected DerivedClassFinder DerivedClassFinder { get; } protected ProjectNpmPackageAdder ProjectNpmPackageAdder { get; } protected NpmGlobalPackagesChecker NpmGlobalPackagesChecker { get; } + protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } public SolutionModuleAdder( IJsonSerializer jsonSerializer, @@ -32,7 +34,8 @@ namespace Volo.Abp.Cli.ProjectModification EfCoreMigrationAdder efCoreMigrationAdder, DerivedClassFinder derivedClassFinder, ProjectNpmPackageAdder projectNpmPackageAdder, - NpmGlobalPackagesChecker npmGlobalPackagesChecker) + NpmGlobalPackagesChecker npmGlobalPackagesChecker, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler) { JsonSerializer = jsonSerializer; ProjectNugetPackageAdder = projectNugetPackageAdder; @@ -41,6 +44,7 @@ namespace Volo.Abp.Cli.ProjectModification DerivedClassFinder = derivedClassFinder; ProjectNpmPackageAdder = projectNpmPackageAdder; NpmGlobalPackagesChecker = npmGlobalPackagesChecker; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; Logger = NullLogger.Instance; } @@ -142,7 +146,7 @@ namespace Volo.Abp.Cli.ProjectModification throw new CliUsageException($"ERROR: '{moduleName}' module could not be found!"); } - throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'"); + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); } var responseContent = await response.Content.ReadAsStringAsync(); diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs index 4564a6d7ae..094f946777 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs @@ -110,8 +110,8 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore .IncludeDetails(includeDetails) .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) - .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null) - .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null) + .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "") + .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "") .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod) .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url)) .WhereIf(userName != null, auditLog => auditLog.UserName == userName) diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs index 1f090f81f2..a0e3c31961 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs @@ -109,8 +109,8 @@ namespace Volo.Abp.AuditLogging.MongoDB return GetMongoQueryable() .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) - .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null) - .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null) + .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "") + .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "") .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod) .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url)) .WhereIf(userName != null, auditLog => auditLog.UserName == userName)