mirror of https://github.com/abpframework/abp.git
31 changed files with 726 additions and 103 deletions
@ -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<NewCommand> Logger { get; set; } |
||||
|
|
||||
|
public GetSourceCommand(ModuleProjectBuilder moduleProjectBuilder) |
||||
|
{ |
||||
|
ModuleProjectBuilder = moduleProjectBuilder; |
||||
|
Logger = NullLogger<NewCommand>.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 <module-name> [options]"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Options:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("-o|--output-folder <output-folder> (default: current folder)"); |
||||
|
sb.AppendLine("-v|--version <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"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<FileEntry> _entries; |
||||
|
|
||||
|
public CommonPropsReplacer( |
||||
|
List<FileEntry> 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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding |
||||
|
{ |
||||
|
public interface IModuleInfoProvider |
||||
|
{ |
||||
|
Task<ModuleInfo> GetAsync(string name); |
||||
|
} |
||||
|
} |
||||
@ -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<string> GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage); |
||||
|
} |
||||
|
} |
||||
@ -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<ModuleInfo> 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<List<ModuleInfo>> 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<List<ModuleInfo>>(result); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<ModuleProjectBuilder> 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<CliOptions> options, |
||||
|
IJsonSerializer jsonSerializer, |
||||
|
IApiKeyService apiKeyService) |
||||
|
{ |
||||
|
SourceCodeStore = sourceCodeStore; |
||||
|
ModuleInfoProvider = moduleInfoProvider; |
||||
|
CliAnalyticsCollect = cliAnalyticsCollect; |
||||
|
Options = options.Value; |
||||
|
JsonSerializer = jsonSerializer; |
||||
|
ApiKeyService = apiKeyService; |
||||
|
|
||||
|
Logger = NullLogger<ModuleProjectBuilder>.Instance; |
||||
|
} |
||||
|
|
||||
|
public async Task<ProjectBuildResult> 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<ModuleInfo> GetModuleInfoAsync(ProjectBuildArgs args) |
||||
|
{ |
||||
|
return await ModuleInfoProvider.GetAsync(args.TemplateName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<string> GetAbpRemoteServiceErrorAsync(HttpResponseMessage responseMessage) |
||||
|
{ |
||||
|
var errorResult = _jsonSerializer.Deserialize<RemoteServiceErrorResponse> |
||||
|
( |
||||
|
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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace Volo.Abp.Cli.ProjectBuilding |
||||
|
{ |
||||
|
public static class SourceCodeTypes |
||||
|
{ |
||||
|
public const string Template = "template"; |
||||
|
|
||||
|
public const string Module = "module"; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue