committed by
GitHub
12 changed files with 830 additions and 1 deletions
@ -1,4 +1,6 @@ |
|||||
.vs |
.vs |
||||
LocalNuget |
LocalNuget |
||||
*.DotSettings.user |
*.DotSettings.user |
||||
**/*.csproj.user |
**/*.csproj.user |
||||
|
templates |
||||
|
nupkg |
||||
@ -0,0 +1,17 @@ |
|||||
|
<Project> |
||||
|
<PropertyGroup> |
||||
|
<VoloAbpPackageVersion>4.4.0</VoloAbpPackageVersion> |
||||
|
<LINGYUNAbpPackageVersion>4.4.0</LINGYUNAbpPackageVersion> |
||||
|
<SerilogAspNetCorePackageVersion>4.1.0</SerilogAspNetCorePackageVersion> |
||||
|
<SerilogEnrichersEnvironmentPackageVersion>2.2.0</SerilogEnrichersEnvironmentPackageVersion> |
||||
|
<SerilogEnrichersAssemblyPackageVersion>2.0.0</SerilogEnrichersAssemblyPackageVersion> |
||||
|
<SerilogEnrichersProcessPackageVersion>2.0.1</SerilogEnrichersProcessPackageVersion> |
||||
|
<SerilogEnrichersThreadPackageVersion>3.1.0</SerilogEnrichersThreadPackageVersion> |
||||
|
<SerilogExtensionsLoggingPackageVersion>3.0.1</SerilogExtensionsLoggingPackageVersion> |
||||
|
<SerilogSettingsConfigurationPackageVersion>3.1.0</SerilogSettingsConfigurationPackageVersion> |
||||
|
<SerilogSinksConsolePackageVersion>4.0.0</SerilogSinksConsolePackageVersion> |
||||
|
<SerilogSinksElasticsearchPackageVersion>8.4.1</SerilogSinksElasticsearchPackageVersion> |
||||
|
<SerilogSinksFilePackageVersion>5.0.0</SerilogSinksFilePackageVersion> |
||||
|
<MicrosoftPackageVersion>5.0.*</MicrosoftPackageVersion> |
||||
|
</PropertyGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,31 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<OutputType>Exe</OutputType> |
||||
|
<TargetFramework>net5.0</TargetFramework> |
||||
|
<Version>4.4.0</Version> |
||||
|
<PackAsTool>true</PackAsTool> |
||||
|
<ToolCommandName>labp</ToolCommandName> |
||||
|
<PackageOutputPath>./nupkg</PackageOutputPath> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> |
||||
|
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> |
||||
|
<PackageReference Include="Serilog.Extensions.Logging" Version="$(SerilogExtensionsLoggingPackageVersion)" /> |
||||
|
<PackageReference Include="Serilog.Sinks.File" Version="$(SerilogSinksFilePackageVersion)" /> |
||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="$(SerilogSinksConsolePackageVersion)" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftPackageVersion)" /> |
||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="$(MicrosoftPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Autofac" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Cli.Core" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Folder Include="LINGYUN\Abp\Cli\ProjectBuilding\" /> |
||||
|
<Folder Include="LINGYUN\Abp\Cli\Utils\" /> |
||||
|
<Folder Include="nupkg\" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,22 @@ |
|||||
|
using LINGYUN.Abp.Cli.Commands; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpCliCoreModule), |
||||
|
typeof(AbpAutofacModule) |
||||
|
)] |
||||
|
public class AbpCliModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpCliOptions>(options => |
||||
|
{ |
||||
|
options.Commands["create"] = typeof(CreateCommand); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,276 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Cli.Args; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
using Volo.Abp.Cli.Commands.Services; |
||||
|
using Volo.Abp.Cli.ProjectBuilding; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
using Volo.Abp.Cli.Utils; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.IO; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
public class CreateCommand : IConsoleCommand, ITransientDependency |
||||
|
{ |
||||
|
public class FindFile |
||||
|
{ |
||||
|
public string Path { get; } |
||||
|
public string Name { get; } |
||||
|
public int Depth { get; } |
||||
|
public bool IsFolder { get; } |
||||
|
public FindFile() { } |
||||
|
public FindFile( |
||||
|
string path, |
||||
|
string name, |
||||
|
int depth, |
||||
|
bool isFolder) |
||||
|
{ |
||||
|
Path = path; |
||||
|
Name = name; |
||||
|
Depth = depth; |
||||
|
IsFolder = isFolder; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ILogger<CreateCommand> Logger { get; set; } |
||||
|
|
||||
|
public ConnectionStringProvider ConnectionStringProvider { get; } |
||||
|
|
||||
|
public ICreateProjectService CreateProjectService { get; } |
||||
|
|
||||
|
public CreateCommand( |
||||
|
ICreateProjectService createProjectService, |
||||
|
ConnectionStringProvider connectionStringProvider) |
||||
|
{ |
||||
|
CreateProjectService = createProjectService; |
||||
|
ConnectionStringProvider = connectionStringProvider; |
||||
|
|
||||
|
Logger = NullLogger<CreateCommand>.Instance; |
||||
|
} |
||||
|
|
||||
|
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var projectName = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target); |
||||
|
if (string.IsNullOrWhiteSpace(projectName)) |
||||
|
{ |
||||
|
throw new CliUsageException("Project name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); |
||||
|
} |
||||
|
|
||||
|
var packageName = commandLineArgs.Options.GetOrNull(CreateOptions.Package.Short, CreateOptions.Package.Long); |
||||
|
packageName ??= "app"; |
||||
|
|
||||
|
Logger.LogInformation("Package Name: " + packageName); |
||||
|
|
||||
|
var version = commandLineArgs.Options.GetOrNull(NewCommand.Options.Version.Short, NewCommand.Options.Version.Long); |
||||
|
|
||||
|
if (version != null) |
||||
|
{ |
||||
|
Logger.LogInformation("Version: " + version); |
||||
|
} |
||||
|
|
||||
|
var templateName = commandLineArgs.Options.GetOrNull(NewCommand.Options.Template.Short, NewCommand.Options.Template.Long); |
||||
|
templateName ??= "lam"; |
||||
|
|
||||
|
Logger.LogInformation("Template: " + templateName); |
||||
|
|
||||
|
var gitHubAbpLocalRepositoryPath = commandLineArgs.Options.GetOrNull(NewCommand.Options.GitHubAbpLocalRepositoryPath.Long); |
||||
|
if (gitHubAbpLocalRepositoryPath != null) |
||||
|
{ |
||||
|
Logger.LogInformation("GitHub Abp Local Repository Path: " + gitHubAbpLocalRepositoryPath); |
||||
|
} |
||||
|
|
||||
|
var gitHubVoloLocalRepositoryPath = commandLineArgs.Options.GetOrNull(NewCommand.Options.GitHubVoloLocalRepositoryPath.Long); |
||||
|
if (gitHubVoloLocalRepositoryPath != null) |
||||
|
{ |
||||
|
Logger.LogInformation("GitHub Volo Local Repository Path: " + gitHubVoloLocalRepositoryPath); |
||||
|
} |
||||
|
|
||||
|
var databaseProvider = GetDatabaseProvider(commandLineArgs); |
||||
|
if (databaseProvider != DatabaseProvider.NotSpecified) |
||||
|
{ |
||||
|
Logger.LogInformation("Database provider: " + databaseProvider); |
||||
|
} |
||||
|
|
||||
|
var connectionString = GetConnectionString(commandLineArgs); |
||||
|
if (connectionString != null) |
||||
|
{ |
||||
|
Logger.LogInformation("Connection string: " + connectionString); |
||||
|
} |
||||
|
|
||||
|
var databaseManagementSystem = GetDatabaseManagementSystem(commandLineArgs); |
||||
|
if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified) |
||||
|
{ |
||||
|
Logger.LogInformation("DBMS: " + databaseManagementSystem); |
||||
|
} |
||||
|
|
||||
|
var randomPort = string.IsNullOrWhiteSpace( |
||||
|
commandLineArgs.Options.GetOrNull(CreateOptions.NoRandomPort.Short, CreateOptions.NoRandomPort.Long)); |
||||
|
var applicationPort = randomPort ? RandomHelper.GetRandom(5001, 65535).ToString() : "5000"; |
||||
|
|
||||
|
Logger.LogInformation("Application Launch Port: " + applicationPort); |
||||
|
|
||||
|
var daprPort = randomPort ? RandomHelper.GetRandom(3501, 65535).ToString() : "3500"; |
||||
|
|
||||
|
Logger.LogInformation("Dapr Listening Http Port: " + daprPort); |
||||
|
|
||||
|
var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs); |
||||
|
var outputFolder = commandLineArgs.Options.GetOrNull(NewCommand.Options.OutputFolder.Short, NewCommand.Options.OutputFolder.Long); |
||||
|
|
||||
|
var outputFolderRoot = |
||||
|
outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory(); |
||||
|
|
||||
|
outputFolder = createSolutionFolder ? |
||||
|
Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) : |
||||
|
outputFolderRoot; |
||||
|
|
||||
|
var solutionName = SolutionName.Parse(projectName); |
||||
|
|
||||
|
DirectoryHelper.CreateIfNotExists(outputFolder); |
||||
|
|
||||
|
Logger.LogInformation("Output folder: " + outputFolder); |
||||
|
|
||||
|
if (connectionString == null && |
||||
|
databaseManagementSystem != DatabaseManagementSystem.NotSpecified && |
||||
|
databaseManagementSystem != DatabaseManagementSystem.SQLServer) |
||||
|
{ |
||||
|
connectionString = ConnectionStringProvider.GetByDbms(databaseManagementSystem, outputFolder); |
||||
|
} |
||||
|
|
||||
|
commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command); |
||||
|
|
||||
|
var projectArgs = new ProjectCreateArgs( |
||||
|
packageName, |
||||
|
solutionName, |
||||
|
templateName, |
||||
|
version, |
||||
|
outputFolder, |
||||
|
databaseProvider, |
||||
|
databaseManagementSystem, |
||||
|
UiFramework.None, |
||||
|
null, |
||||
|
false, |
||||
|
gitHubAbpLocalRepositoryPath, |
||||
|
gitHubVoloLocalRepositoryPath, |
||||
|
"", |
||||
|
commandLineArgs.Options, |
||||
|
connectionString, |
||||
|
applicationPort, |
||||
|
daprPort |
||||
|
); |
||||
|
|
||||
|
await CreateProjectService.CreateAsync(projectArgs); |
||||
|
} |
||||
|
|
||||
|
public string GetShortDescription() |
||||
|
{ |
||||
|
return "Generate a new solution based on the customed ABP startup templates."; |
||||
|
} |
||||
|
|
||||
|
public string GetUsageInfo() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Usage:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine(" labp create <project-name> [options]"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Options:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("-pk|--package <package-name> (default: app)"); |
||||
|
sb.AppendLine("-t|--template <template-name> (default: lam)"); |
||||
|
sb.AppendLine("-d|--database-provider <database-provider> (if supported by the template)"); |
||||
|
sb.AppendLine("-o|--output-folder <output-folder> (default: current folder)"); |
||||
|
sb.AppendLine("-v|--version <version> (default: latest version)"); |
||||
|
//sb.AppendLine("-ts|--template-source <template-source> (your local or network abp template source)");
|
||||
|
sb.AppendLine("-csf|--create-solution-folder (default: true)"); |
||||
|
sb.AppendLine("-cs|--connection-string <connection-string> (your database connection string)"); |
||||
|
sb.AppendLine("--dbms <database-management-system> (your database management system)"); |
||||
|
sb.AppendLine("--no-random-port (Use template's default ports)"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Examples:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine(" labp create Acme.BookStore"); |
||||
|
sb.AppendLine(" labp create Acme.BookStore -p Com"); |
||||
|
sb.AppendLine(" labp create Acme.BookStore -d mongodb"); |
||||
|
sb.AppendLine(" labp create Acme.BookStore -d mongodb -o d:\\my-project"); |
||||
|
sb.AppendLine(" labp create Acme.BookStore -ts \"D:\\localTemplate\\abp\""); |
||||
|
sb.AppendLine(" labp create Acme.BookStore -csf false"); |
||||
|
sb.AppendLine(" labp create Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); |
||||
|
sb.AppendLine(" labp create Acme.BookStore --dbms mysql"); |
||||
|
sb.AppendLine(" labp create Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\""); |
||||
|
sb.AppendLine(""); |
||||
|
// TODO: 文档
|
||||
|
// sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
|
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
protected bool GetCreateSolutionFolderPreference(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
return commandLineArgs.Options.ContainsKey(NewCommand.Options.CreateSolutionFolder.Long) |
||||
|
|| commandLineArgs.Options.ContainsKey(NewCommand.Options.CreateSolutionFolder.Short); |
||||
|
} |
||||
|
|
||||
|
protected virtual DatabaseProvider GetDatabaseProvider(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var optionValue = commandLineArgs.Options.GetOrNull( |
||||
|
NewCommand.Options.DatabaseProvider.Short, |
||||
|
NewCommand.Options.DatabaseProvider.Long); |
||||
|
switch (optionValue) |
||||
|
{ |
||||
|
case "ef": |
||||
|
return DatabaseProvider.EntityFrameworkCore; |
||||
|
case "mongodb": |
||||
|
return DatabaseProvider.MongoDb; |
||||
|
default: |
||||
|
return DatabaseProvider.NotSpecified; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual DatabaseManagementSystem GetDatabaseManagementSystem(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var optionValue = commandLineArgs.Options.GetOrNull( |
||||
|
NewCommand.Options.DatabaseManagementSystem.Short, |
||||
|
NewCommand.Options.DatabaseManagementSystem.Long); |
||||
|
|
||||
|
if (optionValue == null) |
||||
|
{ |
||||
|
return DatabaseManagementSystem.NotSpecified; |
||||
|
} |
||||
|
|
||||
|
switch (optionValue.ToLowerInvariant()) |
||||
|
{ |
||||
|
case "sqlserver": |
||||
|
return DatabaseManagementSystem.SQLServer; |
||||
|
case "mysql": |
||||
|
return DatabaseManagementSystem.MySQL; |
||||
|
case "postgresql": |
||||
|
return DatabaseManagementSystem.PostgreSQL; |
||||
|
case "oracle-devart": |
||||
|
return DatabaseManagementSystem.OracleDevart; |
||||
|
case "sqlite": |
||||
|
return DatabaseManagementSystem.SQLite; |
||||
|
case "oracle": |
||||
|
return DatabaseManagementSystem.Oracle; |
||||
|
default: |
||||
|
return DatabaseManagementSystem.NotSpecified; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected static string GetConnectionString(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var connectionString = commandLineArgs.Options.GetOrNull( |
||||
|
NewCommand.Options.ConnectionString.Short, |
||||
|
NewCommand.Options.ConnectionString.Long); |
||||
|
return string.IsNullOrWhiteSpace(connectionString) ? null : connectionString; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
public static class CreateOptions |
||||
|
{ |
||||
|
public static string[] ExclusionFolder = new string[3] { ".github", ".vs", ".svn" }; |
||||
|
|
||||
|
public static class Package |
||||
|
{ |
||||
|
public const string Short = "pk"; |
||||
|
public const string Long = "package"; |
||||
|
} |
||||
|
|
||||
|
public static class Company |
||||
|
{ |
||||
|
public const string Short = "cp"; |
||||
|
public const string Long = "company"; |
||||
|
} |
||||
|
|
||||
|
public static class NoRandomPort |
||||
|
{ |
||||
|
public const string Short = "nrp"; |
||||
|
public const string Long = "no-random-port"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
public interface ICreateProjectService |
||||
|
{ |
||||
|
Task CreateAsync(ProjectCreateArgs createArgs); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,322 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
using Volo.Abp.Cli.Utils; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.IO; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
public class LocalFileCreateProjectService : ICreateProjectService, ISingletonDependency |
||||
|
{ |
||||
|
public class FindFile |
||||
|
{ |
||||
|
public string Path { get; } |
||||
|
public string Name { get; } |
||||
|
public int Depth { get; } |
||||
|
public bool IsFolder { get; } |
||||
|
public FindFile() { } |
||||
|
public FindFile( |
||||
|
string path, |
||||
|
string name, |
||||
|
int depth, |
||||
|
bool isFolder) |
||||
|
{ |
||||
|
Path = path; |
||||
|
Name = name; |
||||
|
Depth = depth; |
||||
|
IsFolder = isFolder; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ILogger<CreateCommand> Logger { get; set; } |
||||
|
|
||||
|
public LocalFileCreateProjectService() |
||||
|
{ |
||||
|
Logger = NullLogger<CreateCommand>.Instance; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task CreateAsync(ProjectCreateArgs createArgs) |
||||
|
{ |
||||
|
Logger.LogInformation("Execute dotnet command..."); |
||||
|
|
||||
|
var commandBuilder = new StringBuilder("dotnet new"); |
||||
|
commandBuilder.AppendFormat(" {0}", createArgs.TemplateName); |
||||
|
commandBuilder.AppendFormat(" -n {0}", createArgs.SolutionName.ProjectName); |
||||
|
commandBuilder.AppendFormat(" -o {0}", createArgs.OutputFolder); |
||||
|
|
||||
|
var cmdError = CmdHelper.RunCmdAndGetOutput(commandBuilder.ToString(), out bool isSuccessful); |
||||
|
if (!isSuccessful) |
||||
|
{ |
||||
|
Logger.LogError("Execute command error: " + cmdError); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Logger.LogInformation("Execute command: " + cmdError); |
||||
|
|
||||
|
var projectFiles = new List<FindFile>(); |
||||
|
|
||||
|
Logger.LogInformation("Search Solution files."); |
||||
|
SearchSolutionPath(projectFiles, createArgs.OutputFolder, 0); |
||||
|
|
||||
|
Logger.LogInformation("Rewrite Package and company name."); |
||||
|
|
||||
|
await TryReplacePackageAndCompanyNameWithProjectFile( |
||||
|
projectFiles, |
||||
|
createArgs.PackageName, |
||||
|
createArgs.SolutionName.CompanyName, |
||||
|
createArgs.DatabaseManagementSystem); |
||||
|
|
||||
|
Logger.LogInformation("Rewrite appsettings.json."); |
||||
|
await TryReplaceAppSettingsWithProjectFile( |
||||
|
projectFiles, |
||||
|
createArgs.PackageName, |
||||
|
createArgs.SolutionName.CompanyName, |
||||
|
createArgs.SolutionName.ProjectName, |
||||
|
createArgs.ConnectionString, |
||||
|
createArgs.DatabaseManagementSystem); |
||||
|
|
||||
|
Logger.LogInformation("Rewrite application url."); |
||||
|
await TryReplaceApplicationUrlWithProjectFile( |
||||
|
projectFiles, |
||||
|
createArgs.ApplicationPort, |
||||
|
createArgs.DaprPort); |
||||
|
|
||||
|
Logger.LogInformation("Rewrite package version."); |
||||
|
await TryReplaceVersionWithProjectFile( |
||||
|
projectFiles, |
||||
|
createArgs.Version); |
||||
|
|
||||
|
Logger.LogInformation("Rewrite project folder."); |
||||
|
await TryReplacePackageAndCompanyNameWithProjectFolder( |
||||
|
projectFiles, |
||||
|
createArgs.PackageName, |
||||
|
createArgs.SolutionName.CompanyName, |
||||
|
createArgs.DatabaseManagementSystem); |
||||
|
|
||||
|
Logger.LogInformation($"'{createArgs.SolutionName.ProjectName}' has been successfully created to '{createArgs.OutputFolder}'"); |
||||
|
} |
||||
|
|
||||
|
protected virtual void SearchSolutionPath(List<FindFile> projectFiles, string solutionPath, int depth) |
||||
|
{ |
||||
|
var searchFiles = Directory.GetFileSystemEntries(solutionPath, "*.*", SearchOption.TopDirectoryOnly); |
||||
|
searchFiles = searchFiles.Where(f => !CreateOptions.ExclusionFolder.Any(ef => f.EndsWith(ef))).ToArray(); |
||||
|
foreach (var searchFile in searchFiles) |
||||
|
{ |
||||
|
projectFiles.Add(new FindFile(solutionPath, searchFile, depth, Directory.Exists(searchFile))); |
||||
|
if (Directory.Exists(searchFile)) |
||||
|
{ |
||||
|
SearchSolutionPath(projectFiles, searchFile, depth++); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task TryReplaceVersionWithProjectFile( |
||||
|
List<FindFile> projectFiles, |
||||
|
string version) |
||||
|
{ |
||||
|
if (version.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
var assemblyVersion = GetType().Assembly.GetName().Version; |
||||
|
var currentVersion = $"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}"; |
||||
|
|
||||
|
var buildPropsFile = projectFiles.FirstOrDefault(f => f.Name.EndsWith("Directory.Build.props")); |
||||
|
if (buildPropsFile != null) |
||||
|
{ |
||||
|
await ReplaceFileTextAsync( |
||||
|
buildPropsFile, |
||||
|
$"<VoloAbpPackageVersion>{currentVersion}</VoloAbpPackageVersion>", |
||||
|
$"<VoloAbpPackageVersion>{version}</VoloAbpPackageVersion>"); |
||||
|
|
||||
|
await ReplaceFileTextAsync( |
||||
|
buildPropsFile, |
||||
|
$"<LINGYUNAbpPackageVersion>{currentVersion}</LINGYUNAbpPackageVersion>", |
||||
|
$"<LINGYUNAbpPackageVersion>{version}</LINGYUNAbpPackageVersion>"); |
||||
|
} |
||||
|
|
||||
|
var commonPropsFile = projectFiles.FirstOrDefault(f => f.Name.EndsWith("common.props")); |
||||
|
if (commonPropsFile != null) |
||||
|
{ |
||||
|
await ReplaceFileTextAsync( |
||||
|
commonPropsFile, |
||||
|
$"<Version>{currentVersion}</Version>", |
||||
|
$"<Version>{version}</Version>"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task TryReplaceApplicationUrlWithProjectFile( |
||||
|
List<FindFile> projectFiles, |
||||
|
string port = "5000", |
||||
|
string daprPort = "3500") |
||||
|
{ |
||||
|
var launchFile = projectFiles.FirstOrDefault(f => f.Name.EndsWith("launchSettings.json")); |
||||
|
if (launchFile != null) |
||||
|
{ |
||||
|
string applicationUrl = $"http://localhost:{port}"; |
||||
|
await ReplaceFileTextAsync(launchFile, "http://localhost:5000", applicationUrl); |
||||
|
} |
||||
|
|
||||
|
var daprScriptFile = projectFiles.FirstOrDefault(f => f.Name.EndsWith("dapr.sh")); |
||||
|
if (daprScriptFile != null) |
||||
|
{ |
||||
|
await ReplaceFileTextAsync(daprScriptFile, "--app-port 5000 -H 3500", $"--app-port {port} -H {daprPort}"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task TryReplaceAppSettingsWithProjectFile( |
||||
|
List<FindFile> projectFiles, |
||||
|
string packageName, |
||||
|
string companyName, |
||||
|
string projectName, |
||||
|
string connectionString = null, |
||||
|
DatabaseManagementSystem database = DatabaseManagementSystem.NotSpecified) |
||||
|
{ |
||||
|
var canReplaceFiles = projectFiles.Where(f => !f.IsFolder && f.Name.Contains("appsettings")); |
||||
|
foreach (var projectFile in canReplaceFiles) |
||||
|
{ |
||||
|
await ReplaceFileTextAsync(projectFile, "PackageName", packageName); |
||||
|
await ReplaceFileTextAsync(projectFile, "CompanyName", companyName); |
||||
|
|
||||
|
var defaultConnectionString = $"Server=127.0.0.1;Database={projectName};User Id=root;Password=123456"; |
||||
|
connectionString ??= defaultConnectionString; |
||||
|
await ReplaceFileTextAsync(projectFile, defaultConnectionString, connectionString); |
||||
|
|
||||
|
switch (database) |
||||
|
{ |
||||
|
case DatabaseManagementSystem.SQLServer: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "SqlServer"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.SQLite: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "Sqlite"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.Oracle: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "Oracle"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.OracleDevart: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "Oracle.Devart"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.PostgreSQL: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "PostgreSql"); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task TryReplacePackageAndCompanyNameWithProjectFile( |
||||
|
List<FindFile> projectFiles, |
||||
|
string packageName, |
||||
|
string companyName, |
||||
|
DatabaseManagementSystem database = DatabaseManagementSystem.NotSpecified) |
||||
|
{ |
||||
|
var canReplaceFiles = projectFiles.Where(f => !f.IsFolder && !f.Name.Contains("appsettings")); |
||||
|
foreach (var projectFile in canReplaceFiles) |
||||
|
{ |
||||
|
await ReplaceFileTextAsync(projectFile, "PackageName", packageName); |
||||
|
await ReplaceFileTextAsync(projectFile, "CompanyName", companyName); |
||||
|
|
||||
|
if (database != DatabaseManagementSystem.NotSpecified && |
||||
|
database != DatabaseManagementSystem.MySQL && |
||||
|
projectFile.Name.EndsWith("MigrationsDbContextFactory.cs")) |
||||
|
{ |
||||
|
await ReplaceFileTextAsync( |
||||
|
projectFile, |
||||
|
// 非 MySql 替换一下这一句
|
||||
|
"connectionString, ServerVersion.AutoDetect(connectionString)", |
||||
|
"connectionString"); |
||||
|
} |
||||
|
// DB 驱动
|
||||
|
switch (database) |
||||
|
{ |
||||
|
case DatabaseManagementSystem.SQLServer: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "SqlServer"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.SQLite: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "Sqlite"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.Oracle: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "Oracle"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.OracleDevart: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "Oracle.Devart"); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.PostgreSQL: |
||||
|
await ReplaceFileTextAsync(projectFile, "MySQL", "PostgreSql"); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual Task TryReplacePackageAndCompanyNameWithProjectFolder( |
||||
|
List<FindFile> projectFiles, |
||||
|
string packageName, |
||||
|
string companyName, |
||||
|
DatabaseManagementSystem database = DatabaseManagementSystem.NotSpecified) |
||||
|
{ |
||||
|
var canReplaceFiles = projectFiles |
||||
|
.OrderByDescending(f => f.Depth) |
||||
|
.OrderByDescending(f => !f.IsFolder); |
||||
|
foreach (var projectFile in canReplaceFiles) |
||||
|
{ |
||||
|
var replaceFileName = projectFile.Name.Replace("PackageName", packageName).Replace("CompanyName", companyName); |
||||
|
switch (database) |
||||
|
{ |
||||
|
case DatabaseManagementSystem.SQLServer: |
||||
|
replaceFileName = replaceFileName.Replace("MySQL", "SqlServer", StringComparison.InvariantCultureIgnoreCase); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.SQLite: |
||||
|
replaceFileName = replaceFileName.Replace("MySQL", "Sqlite", StringComparison.InvariantCultureIgnoreCase); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.Oracle: |
||||
|
replaceFileName = replaceFileName.Replace("MySQL", "Oracle", StringComparison.InvariantCultureIgnoreCase); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.OracleDevart: |
||||
|
replaceFileName = replaceFileName.Replace("MySQL", "Oracle.Devart", StringComparison.InvariantCultureIgnoreCase); |
||||
|
break; |
||||
|
case DatabaseManagementSystem.PostgreSQL: |
||||
|
replaceFileName = replaceFileName.Replace("MySQL", "PostgreSQL", StringComparison.InvariantCultureIgnoreCase); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (File.Exists(projectFile.Name)) |
||||
|
{ |
||||
|
DirectoryHelper.CreateIfNotExists(Path.GetDirectoryName(replaceFileName)); |
||||
|
File.Move(projectFile.Name, replaceFileName); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var canReplacePaths = projectFiles |
||||
|
.Where(projectFile => projectFile.Name.Contains("PackageName") || projectFile.Name.Contains("CompanyName")) |
||||
|
.OrderByDescending(f => f.Depth) |
||||
|
.OrderByDescending(f => f.IsFolder); |
||||
|
foreach (var projectFile in canReplacePaths) |
||||
|
{ |
||||
|
DirectoryHelper.DeleteIfExists(projectFile.Name, true); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
protected static async Task ReplaceFileTextAsync(FindFile projectFile, string sourceText, string replaceText) |
||||
|
{ |
||||
|
string fileText; |
||||
|
using (var stream = new StreamReader(projectFile.Name, Encoding.UTF8)) |
||||
|
{ |
||||
|
fileText = await stream.ReadToEndAsync(); |
||||
|
} |
||||
|
fileText = fileText.Replace(sourceText, replaceText, StringComparison.InvariantCultureIgnoreCase); |
||||
|
|
||||
|
using (StreamWriter writer = new StreamWriter(projectFile.Name, false, Encoding.UTF8)) |
||||
|
{ |
||||
|
await writer.WriteAsync(fileText); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Cli.ProjectBuilding; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
public class ProjectCreateArgs : ProjectBuildArgs |
||||
|
{ |
||||
|
public string PackageName { get; } |
||||
|
public string OutputFolder { get; } |
||||
|
public string ApplicationPort { get; } |
||||
|
public string DaprPort { get; } |
||||
|
public ProjectCreateArgs( |
||||
|
string packageName, |
||||
|
SolutionName solutionName, |
||||
|
string templateName = null, |
||||
|
string version = null, |
||||
|
string outputFolder = null, |
||||
|
DatabaseProvider databaseProvider = DatabaseProvider.NotSpecified, |
||||
|
DatabaseManagementSystem databaseManagementSystem = DatabaseManagementSystem.NotSpecified, |
||||
|
UiFramework uiFramework = UiFramework.NotSpecified, |
||||
|
MobileApp? mobileApp = null, |
||||
|
bool publicWebSite = false, |
||||
|
string abpGitHubLocalRepositoryPath = null, |
||||
|
string voloGitHubLocalRepositoryPath = null, |
||||
|
string templateSource = null, |
||||
|
Dictionary<string, string> extraProperties = null, |
||||
|
string connectionString = null, |
||||
|
string applicationPort = "5000", |
||||
|
string daprPort = "3500") |
||||
|
: base( |
||||
|
solutionName, |
||||
|
templateName, |
||||
|
version, |
||||
|
databaseProvider, |
||||
|
databaseManagementSystem, |
||||
|
uiFramework, |
||||
|
mobileApp, |
||||
|
publicWebSite, |
||||
|
abpGitHubLocalRepositoryPath, |
||||
|
voloGitHubLocalRepositoryPath, |
||||
|
templateSource, |
||||
|
extraProperties, |
||||
|
connectionString) |
||||
|
{ |
||||
|
PackageName = packageName; |
||||
|
OutputFolder = outputFolder; |
||||
|
ApplicationPort = applicationPort; |
||||
|
DaprPort = daprPort; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Serilog; |
||||
|
using Serilog.Events; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Cli; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
private static async Task Main(string[] args) |
||||
|
{ |
||||
|
Console.OutputEncoding = System.Text.Encoding.UTF8; |
||||
|
|
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
.MinimumLevel.Information() |
||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) |
||||
|
.MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) |
||||
|
.MinimumLevel.Override("LINGYUN.Abp", LogEventLevel.Warning) |
||||
|
.MinimumLevel.Override("System.Net.Http.HttpClient", LogEventLevel.Warning) |
||||
|
#if DEBUG
|
||||
|
.MinimumLevel.Override("Volo.Abp.Cli", LogEventLevel.Debug) |
||||
|
.MinimumLevel.Override("LINGYUN.Abp.Cli", LogEventLevel.Debug) |
||||
|
#else
|
||||
|
.MinimumLevel.Override("Volo.Abp.Cli", LogEventLevel.Information) |
||||
|
.MinimumLevel.Override("LINGYUN.Abp.Cli", LogEventLevel.Information) |
||||
|
#endif
|
||||
|
.Enrich.FromLogContext() |
||||
|
.WriteTo.File(Path.Combine(CliPaths.Log, "lingyun-abp-cli-logs.txt")) |
||||
|
.WriteTo.Console() |
||||
|
.CreateLogger(); |
||||
|
|
||||
|
using (var application = AbpApplicationFactory.Create<AbpCliModule>( |
||||
|
options => |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
options.Services.AddLogging(c => c.AddSerilog()); |
||||
|
})) |
||||
|
{ |
||||
|
application.Initialize(); |
||||
|
|
||||
|
await application.ServiceProvider |
||||
|
.GetRequiredService<CliService>() |
||||
|
.RunAsync(args); |
||||
|
|
||||
|
application.Shutdown(); |
||||
|
|
||||
|
Log.CloseAndFlush(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"profiles": { |
||||
|
"LINGYUN.Abp.Cli": { |
||||
|
"commandName": "Project", |
||||
|
"commandLineArgs": "create MyCompany.MyProject -pk MyPackage -t lam -dbms sqlserver -cs \"Server=127.0.0.1;Database=master;User Id=sa;Password=662871\" -o \"D:\\Projects\\MicroService\\CRM\\Vue\\vue-abp\\aspnet-core\\modules\\cli\\LINGYUN.Abp.Cli\\bin\\Debug\\net5.0\\TTT\"" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue