pull/1904/head
Halil İbrahim Kalkan 5 years ago
commit 34d5990c1d

@ -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);

@ -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";
}
}
}
}

@ -17,11 +17,11 @@ namespace Volo.Abp.Cli.Commands
{
public ILogger<NewCommand> 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<NewCommand>.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,

@ -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
{

@ -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<DeveloperApiKeyResult> 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<DeveloperApiKeyResult>(responseContent);
}

@ -1,5 +1,4 @@
using System.Net;
using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Volo.Abp.Cli.Licensing
{

@ -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;
}
}

@ -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<AbpIoTemplateStore> Logger { get; set; }
public ILogger<AbpIoSourceCodeStore> Logger { get; set; }
protected CliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public AbpIoTemplateStore(
public AbpIoSourceCodeStore(
IOptions<CliOptions> options,
IJsonSerializer jsonSerializer,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ICancellationTokenProvider cancellationTokenProvider)
{
JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
CancellationTokenProvider = cancellationTokenProvider;
Options = options.Value;
Logger = NullLogger<AbpIoTemplateStore>.Instance;
Logger = NullLogger<AbpIoSourceCodeStore>.Instance;
}
public async Task<TemplateFile> 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<string> GetLatestTemplateVersionAsync(string name)
private async Task<string> 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<GetLatestTemplateVersionResultDto>(result).Version;
return JsonSerializer.Deserialize<GetLatestSourceCodeVersionResultDto>(result).Version;
}
}
private async Task<byte[]> DownloadTemplateFileContentAsync(TemplateDownloadInputDto input)
private async Task<byte[]> 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; }
}

@ -16,12 +16,16 @@ namespace Volo.Abp.Cli.ProjectBuilding.Analyticses
private readonly ICancellationTokenProvider _cancellationTokenProvider;
private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger<CliAnalyticsCollect> _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<CliAnalyticsCollect>.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);
}
}
}

@ -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;
}
}
}

@ -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));

@ -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<FileEntry> _entries;
private readonly string _companyAndProjectNamePlaceHolder;
private readonly string _projectName;
protected ProjectReferenceReplacer(
List<FileEntry> 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<FileEntry> entries, string companyAndProjectNamePlaceHolder, string nugetPackageVersion)
: base(entries, companyAndProjectNamePlaceHolder)
public NugetReferenceReplacer(List<FileEntry> 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<FileEntry> entries, string companyAndProjectNamePlaceHolder, string gitHubLocalRepositoryPath)
: base(entries, companyAndProjectNamePlaceHolder)
public LocalProjectPathReferenceReplacer(List<FileEntry> entries, string projectName, string gitHubLocalRepositoryPath)
: base(entries, projectName)
{
_gitHubLocalRepositoryPath = gitHubLocalRepositoryPath;
}

@ -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;
}
}
}
}

@ -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)
{

@ -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);
}
}

@ -3,10 +3,11 @@ using JetBrains.Annotations;
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface ITemplateStore
public interface ISourceCodeStore
{
Task<TemplateFile> GetAsync(
string name,
string type,
[CanBeNull] string version = null
);
}

@ -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";
}
}

@ -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<ProjectBuilder> Logger { get; set; }
public ILogger<TemplateProjectBuilder> 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<CliOptions> options,
IJsonSerializer jsonSerializer,
IApiKeyService apiKeyService)
{
TemplateStore = templateStore;
SourceCodeStore = sourceCodeStore;
TemplateInfoProvider = templateInfoProvider;
CliAnalyticsCollect = cliAnalyticsCollect;
Options = options.Value;
JsonSerializer = jsonSerializer;
ApiKeyService = apiKeyService;
Logger = NullLogger<ProjectBuilder>.Instance;
Logger = NullLogger<TemplateProjectBuilder>.Instance;
}
public async Task<ProjectBuildResult> 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())
{

@ -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<ProjectBuildPipelineStep> 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<ProjectBuildPipelineStep> steps)

@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.IO;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;

@ -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;

@ -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

@ -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<ProjectNugetPackageAdder>.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();

@ -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<SolutionModuleAdder>.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();

@ -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)

@ -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)

Loading…
Cancel
Save