CLI add-package with source code

resolves https://github.com/abpframework/abp/issues/8172
pull/8187/head
Yunus Emre Kalkan 5 years ago
parent 03867730d3
commit baa6acc9a2

@ -196,6 +196,7 @@
"MultipleDBOptionsExplanation": "The framework can work with any data source, while the following providers are officially developed and supported;",
"SelectLanguage": "Select language",
"LatestArticleOnCommunity": "Latest Article on ABP Community",
"Register": "Register"
"Register": "Register",
"IsDownloadable": "Is downloadable"
}
}

@ -35,11 +35,16 @@ namespace Volo.Abp.Cli.Commands
}
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
var withSourceCode =commandLineArgs.Options.ContainsKey(Options.SourceCode.Long);
var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file");
await ProjectNugetPackageAdder.AddAsync(
GetProjectFile(commandLineArgs),
commandLineArgs.Target,
version
version,
true,
withSourceCode,
addSourceCodeToSolutionFile
);
}
@ -128,6 +133,11 @@ namespace Volo.Abp.Cli.Commands
public const string Short = "v";
public const string Long = "version";
}
public static class SourceCode
{
public const string Long = "with-source-code";
}
}
}
}

@ -59,7 +59,7 @@ namespace Volo.Abp.Cli.Commands
commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
await _sourceCodeDownloadService.DownloadAsync(
await _sourceCodeDownloadService.DownloadModuleAsync(
commandLineArgs.Target, outputFolder, version, gitHubAbpLocalRepositoryPath, gitHubVoloLocalRepositoryPath, commandLineArgs.Options);
}

@ -17,15 +17,17 @@ namespace Volo.Abp.Cli.Commands.Services
public class SourceCodeDownloadService : ITransientDependency
{
public ModuleProjectBuilder ModuleProjectBuilder { get; }
public PackageProjectBuilder PackageProjectBuilder { get; }
public ILogger<SourceCodeDownloadService> Logger { get; set; }
public SourceCodeDownloadService(ModuleProjectBuilder moduleProjectBuilder)
public SourceCodeDownloadService(ModuleProjectBuilder moduleProjectBuilder, PackageProjectBuilder packageProjectBuilder)
{
ModuleProjectBuilder = moduleProjectBuilder;
PackageProjectBuilder = packageProjectBuilder;
Logger = NullLogger<SourceCodeDownloadService>.Instance;
}
public async Task DownloadAsync(string moduleName, string outputFolder, string version, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath, AbpCommandLineOptions options)
public async Task DownloadModuleAsync(string moduleName, string outputFolder, string version, string gitHubAbpLocalRepositoryPath, string gitHubVoloLocalRepositoryPath, AbpCommandLineOptions options)
{
Logger.LogInformation("Downloading source code of " + moduleName);
Logger.LogInformation("Version: " + version);
@ -90,6 +92,62 @@ namespace Volo.Abp.Cli.Commands.Services
Logger.LogInformation($"'{moduleName}' has been successfully downloaded to '{outputFolder}'");
}
public async Task DownloadPackageAsync(string packageName, string outputFolder, string version)
{
Logger.LogInformation("Downloading source code of " + packageName);
Logger.LogInformation("Version: " + version);
Logger.LogInformation("Output folder: " + outputFolder);
var result = await PackageProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(packageName),
packageName,
version
)
);
using (var templateFileStream = new MemoryStream(result.ZipContent))
{
using (var zipInputStream = new ZipInputStream(templateFileStream))
{
var zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
if (IsAngularTestFile(zipEntry.Name))
{
zipEntry = zipInputStream.GetNextEntry();
continue;
}
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($"'{packageName}' has been successfully downloaded to '{outputFolder}'");
}
private bool IsAngularTestFile(string zipEntryName)
{
if (string.IsNullOrEmpty(zipEntryName))

@ -159,6 +159,11 @@ namespace Volo.Abp.Cli.ProjectBuilding
private async Task<string> GetTemplateNugetVersionAsync(string name, string type, string version)
{
if (type != SourceCodeTypes.Template)
{
return null;
}
try
{
var url = $"{CliUrls.WwwAbpIo}api/download/{type}/get-nuget-version/";

@ -0,0 +1,21 @@
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
using Volo.Abp.Cli.ProjectBuilding.Templates;
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public static class PackageProjectBuildPipelineBuilder
{
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 ReplaceConfigureAwaitPropsStep());
pipeline.Steps.Add(new CreateProjectResultZipStep());
return pipeline;
}
}
}

@ -1,5 +1,6 @@
using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Files;
using Volo.Abp.Cli.ProjectModification;
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
@ -15,22 +16,26 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
public ModuleInfo Module { get; }
public NugetPackageInfo Package { get; }
public FileEntryList Files { get; set; }
public ProjectResult Result { get; set; }
public ProjectBuildContext(
TemplateInfo template,
ModuleInfo module,
NugetPackageInfo package,
[NotNull] TemplateFile templateFile,
[NotNull] ProjectBuildArgs buildArgs)
{
Template = template;
Module = module;
Package = package;
TemplateFile = Check.NotNull(templateFile, nameof(templateFile));
BuildArgs = Check.NotNull(buildArgs, nameof(buildArgs));
Result = new ProjectResult();
}
}
}
}

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectModification;
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface INugetPackageInfoProvider
{
Task<NugetPackageInfo> GetAsync(string name);
}
}

@ -67,6 +67,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
var context = new ProjectBuildContext(
null,
moduleInfo,
null,
templateFile,
args
);

@ -0,0 +1,62 @@
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.ProjectModification;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class NugetPackageInfoProvider : INugetPackageInfoProvider, ITransientDependency
{
public IJsonSerializer JsonSerializer { get; }
public ICancellationTokenProvider CancellationTokenProvider { get; }
public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
private readonly CliHttpClientFactory _cliHttpClientFactory;
public NugetPackageInfoProvider(
IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
CliHttpClientFactory cliHttpClientFactory)
{
JsonSerializer = jsonSerializer;
CancellationTokenProvider = cancellationTokenProvider;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
_cliHttpClientFactory = cliHttpClientFactory;
}
public async Task<NugetPackageInfo> GetAsync(string name)
{
var packageList = await GetPackageListInternalAsync();
var package = packageList.FirstOrDefault(m => m.Name == name);
if (package == null)
{
throw new Exception("Package is not found or downloadable!");
}
return package;
}
private async Task<List<NugetPackageInfo>> GetPackageListInternalAsync()
{
var client = _cliHttpClientFactory.CreateClient();
using (var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/download/packages/",
CancellationTokenProvider.Token
))
{
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var result = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<List<NugetPackageInfo>>(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.Cli.ProjectModification;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class PackageProjectBuilder : IProjectBuilder, ITransientDependency
{
public ILogger<PackageProjectBuilder> Logger { get; set; }
protected ISourceCodeStore SourceCodeStore { get; }
protected INugetPackageInfoProvider NugetPackageInfoProvider { get; }
protected ICliAnalyticsCollect CliAnalyticsCollect { get; }
protected AbpCliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IApiKeyService ApiKeyService { get; }
public PackageProjectBuilder(ISourceCodeStore sourceCodeStore,
INugetPackageInfoProvider nugetPackageInfoProvider,
ICliAnalyticsCollect cliAnalyticsCollect,
IOptions<AbpCliOptions> options,
IJsonSerializer jsonSerializer,
IApiKeyService apiKeyService)
{
SourceCodeStore = sourceCodeStore;
NugetPackageInfoProvider = nugetPackageInfoProvider;
CliAnalyticsCollect = cliAnalyticsCollect;
Options = options.Value;
JsonSerializer = jsonSerializer;
ApiKeyService = apiKeyService;
Logger = NullLogger<PackageProjectBuilder>.Instance;
}
public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args)
{
var packageInfo = await GetPackageInfoAsync(args);
var templateFile = await SourceCodeStore.GetAsync(
args.TemplateName,
SourceCodeTypes.Package,
args.Version,
null,
args.ExtraProperties.ContainsKey(GetSourceCommand.Options.Preview.Long)
);
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,
null,
packageInfo,
templateFile,
args
);
PackageProjectBuildPipelineBuilder.Build(context).Execute();
// 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))
.Where(x => !x.Key.Equals(NewCommand.Options.TemplateSource.Short, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.TemplateSource.Long, 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<NugetPackageInfo> GetPackageInfoAsync(ProjectBuildArgs args)
{
return await NugetPackageInfoProvider.GetAsync(args.TemplateName);
}
}
}

@ -5,5 +5,7 @@
public const string Template = "template";
public const string Module = "module";
public const string Package = "package";
}
}

@ -105,6 +105,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
var context = new ProjectBuildContext(
templateInfo,
null,
null,
templateFile,
args
);

@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Commands.Services;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.Cli.Utils;
@ -22,6 +23,8 @@ namespace Volo.Abp.Cli.ProjectModification
{
public ILogger<ProjectNugetPackageAdder> Logger { get; set; }
public BundleCommand BundleCommand { get; }
public SourceCodeDownloadService SourceCodeDownloadService { get; }
public SolutionFileModifier SolutionFileModifier { get; }
protected IJsonSerializer JsonSerializer { get; }
protected ProjectNpmPackageAdder NpmPackageAdder { get; }
@ -38,7 +41,9 @@ namespace Volo.Abp.Cli.ProjectModification
ModuleClassDependcyAdder moduleClassDependcyAdder,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
BundleCommand bundleCommand,
CliHttpClientFactory cliHttpClientFactory)
CliHttpClientFactory cliHttpClientFactory,
SourceCodeDownloadService sourceCodeDownloadService,
SolutionFileModifier solutionFileModifier)
{
JsonSerializer = jsonSerializer;
NpmPackageAdder = npmPackageAdder;
@ -46,21 +51,151 @@ namespace Volo.Abp.Cli.ProjectModification
ModuleClassDependcyAdder = moduleClassDependcyAdder;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
BundleCommand = bundleCommand;
SourceCodeDownloadService = sourceCodeDownloadService;
SolutionFileModifier = solutionFileModifier;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<ProjectNugetPackageAdder>.Instance;
}
public async Task AddAsync(string projectFile, string packageName, string version = null)
public async Task AddAsync(
string projectFile,
string packageName,
string version = null,
bool useDotnetCliToInstall = true,
bool withSourceCode = false,
bool addSourceCodeToSolutionFile = false)
{
await AddAsync(
projectFile,
await FindNugetPackageInfoAsync(packageName),
version,
useDotnetCliToInstall,
withSourceCode,
addSourceCodeToSolutionFile
);
}
public async Task AddAsync(
string projectFile,
NugetPackageInfo package,
string version = null,
bool useDotnetCliToInstall = true,
bool withSourceCode = false,
bool addSourceCodeToSolutionFile = false)
{
await AddAsPackageReference(projectFile, package, version, useDotnetCliToInstall);
if (withSourceCode)
{
await AddSourceCode(projectFile, package, version);
await ConvertPackageReferenceToProjectReference(projectFile, package);
if (addSourceCodeToSolutionFile)
{
await SolutionFileModifier.AddPackageToSolutionFileAsync(package, FindSolutionFile(projectFile));
}
}
}
private async Task ConvertPackageReferenceToProjectReference(string projectFile, NugetPackageInfo package)
{
var content = File.ReadAllText(projectFile);
var doc = new XmlDocument() {PreserveWhitespace = true};
doc.Load(StreamHelper.GenerateStreamFromString(content));
var nodes = doc.SelectNodes(
$"/Project/ItemGroup/PackageReference[starts-with(@Include, '{package.Name}')]");
if (nodes == null)
{
return;
}
var downloadedProjectPath = FindRelativeFolderToDownloadPackage(projectFile, package);
var oldNodeIncludeValue = nodes[0]?.Attributes?["Include"]?.Value;
if (package.Name == oldNodeIncludeValue)
{
var referenceProjectPath = $"{downloadedProjectPath}\\{package.Name}.csproj";
var newNode = doc.CreateElement("ProjectReference");
var includeAttr = doc.CreateAttribute("Include");
includeAttr.Value = referenceProjectPath;
newNode.Attributes.Append(includeAttr);
nodes[0]?.ParentNode?.ReplaceChild(newNode, nodes[0]);
}
File.WriteAllText(projectFile, doc.OuterXml);
}
private async Task AddSourceCode(string projectFile, NugetPackageInfo package, string version = null)
{
var targetFolder = FindFolderToDownloadPackage(projectFile, package);
if (Directory.Exists(targetFolder))
{
Directory.Delete(targetFolder, true);
}
await DownloadSourceCode(targetFolder, package, version);
}
private string FindFolderToDownloadPackage(string projectFile, NugetPackageInfo package)
{
return Path.Combine(FindSolutionFolder(projectFile), "packages", package.Name);
}
private string FindRelativeFolderToDownloadPackage(string projectFile, NugetPackageInfo package)
{
var folder = Path.Combine(FindSolutionFolder(projectFile), "packages", package.Name);
return new Uri(projectFile).MakeRelativeUri(new Uri(folder)).ToString().Replace("/", "\\");
}
private async Task DownloadSourceCode(string targetFolder, NugetPackageInfo package, string version = null)
{
await SourceCodeDownloadService.DownloadPackageAsync(
package.Name,
targetFolder,
version
);
}
public async Task AddAsync(string projectFile, NugetPackageInfo package, string version = null,
bool useDotnetCliToInstall = true)
private string FindSolutionFile(string projectFile)
{
var folder = FindSolutionFolder(projectFile);
return Directory.GetFiles(folder, "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault();
}
private string FindSolutionFolder(string projectFile)
{
var targetFolder = Path.GetDirectoryName(projectFile);
do
{
if (Directory.GetParent(targetFolder) != null)
{
targetFolder = Directory.GetParent(targetFolder).FullName;
}
else
{
return Path.GetDirectoryName(projectFile);
}
if (Directory.GetFiles(targetFolder, "*.sln", SearchOption.TopDirectoryOnly).Any())
{
break;
}
} while (targetFolder != null);
return targetFolder;
}
private async Task AddAsPackageReference(string projectFile, NugetPackageInfo package, string version,
bool useDotnetCliToInstall)
{
var projectFileContent = File.ReadAllText(projectFile);
@ -105,7 +240,9 @@ namespace Volo.Abp.Cli.ProjectModification
ModuleClassDependcyAdder.Add(moduleFiles.First(), package.ModuleClass);
}
if (useDotnetCliToInstall && (package.Target == NuGetPackageTarget.Blazor || package.Target == NuGetPackageTarget.BlazorServer || package.Target == NuGetPackageTarget.BlazorWebAssembly))
if (useDotnetCliToInstall && (package.Target == NuGetPackageTarget.Blazor ||
package.Target == NuGetPackageTarget.BlazorServer ||
package.Target == NuGetPackageTarget.BlazorWebAssembly))
{
await RunBundleForBlazorAsync(projectFile);
}
@ -125,7 +262,7 @@ namespace Volo.Abp.Cli.ProjectModification
private Task AddToCsprojManuallyAsync(string projectFile, NugetPackageInfo package, string version = null)
{
var projectFileContent = File.ReadAllText(projectFile);
var doc = new XmlDocument() { PreserveWhitespace = true };
var doc = new XmlDocument() {PreserveWhitespace = true};
doc.Load(StreamHelper.GenerateStreamFromString(projectFileContent));
var itemGroupNodes = doc.SelectNodes("/Project/ItemGroup");
@ -166,7 +303,7 @@ namespace Volo.Abp.Cli.ProjectModification
private string GetAbpVersionOrNull(string projectFileContent)
{
var doc = new XmlDocument() { PreserveWhitespace = true };
var doc = new XmlDocument() {PreserveWhitespace = true};
doc.Load(StreamHelper.GenerateStreamFromString(projectFileContent));

@ -15,7 +15,8 @@ namespace Volo.Abp.Cli.ProjectModification
var solutionFileContent = File.ReadAllText(solutionFile);
solutionFileContent.NormalizeLineEndings();
var lines = solutionFileContent.Split(new[] {Environment.NewLine, "\n"}, StringSplitOptions.None);
File.WriteAllText(solutionFile, RemoveProject(lines.ToList(), projectName).JoinAsString(Environment.NewLine));
File.WriteAllText(solutionFile,
RemoveProject(lines.ToList(), projectName).JoinAsString(Environment.NewLine));
}
public async Task AddModuleToSolutionFileAsync(ModuleWithMastersInfo module, string solutionFile)
@ -23,6 +24,49 @@ namespace Volo.Abp.Cli.ProjectModification
await AddModuleAsync(module, solutionFile);
}
public async Task AddPackageToSolutionFileAsync(NugetPackageInfo package, string solutionFile)
{
await AddPackageAsync(package, solutionFile);
}
private async Task AddPackageAsync(NugetPackageInfo package, string solutionFile)
{
var srcFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "src");
var file = File.ReadAllText(solutionFile);
var lines = file.Split(Environment.NewLine).ToList();
if (lines.Any(l => l.Contains($"\"{package.Name}\"")))
{
return;
}
var projectGuid = Guid.NewGuid().ToString();
var newProjectLine = "Project(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"" + package.Name + "\"," +
" \"packages\\" + package.Name + "\\" +
"\\" + package.Name + ".csproj\", \"{" + projectGuid + "}\""
+ Environment.NewLine + "EndProject";
lines.InsertAfter(l => l.Trim().Equals("EndProject"), newProjectLine);
var newPostSolutionLine =
" {" + projectGuid + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Debug|Any CPU.Build.0 = Debug|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Release|Any CPU.ActiveCfg = Release|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Release|Any CPU.Build.0 = Release|Any CPU";
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("ProjectConfigurationPlatforms"),
newPostSolutionLine);
var newPreSolutionLine =
" {" + projectGuid + "} = {" + srcFolderId + "}";
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines));
}
private List<string> RemoveProject(List<string> solutionFileLines, string projectName)
{
var projectKey = FindProjectKey(solutionFileLines, projectName);
@ -63,7 +107,8 @@ namespace Volo.Abp.Cli.ProjectModification
{
var curlyBracketStartIndex = solutionFileLine.LastIndexOf("{", StringComparison.OrdinalIgnoreCase);
var curlyBracketEndIndex = solutionFileLine.LastIndexOf("}", StringComparison.OrdinalIgnoreCase);
return solutionFileLine.Substring(curlyBracketStartIndex + 1, curlyBracketEndIndex - curlyBracketStartIndex - 1);
return solutionFileLine.Substring(curlyBracketStartIndex + 1,
curlyBracketEndIndex - curlyBracketStartIndex - 1);
}
}
@ -72,13 +117,14 @@ namespace Volo.Abp.Cli.ProjectModification
private async Task AddModuleAsync(ModuleWithMastersInfo module, string solutionFile)
{
var srcModuleFolderId = await AddNewFolderAndGetIdOrGetExistingId(solutionFile, module.Name, await AddNewFolderAndGetIdOrGetExistingId(solutionFile, "modules"));
var testModuleFolderId = await AddNewFolderAndGetIdOrGetExistingId(solutionFile, module.Name + ".Tests", await AddNewFolderAndGetIdOrGetExistingId(solutionFile, "test"));
var srcModuleFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, module.Name,
await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "modules"));
var testModuleFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, module.Name + ".Tests",
await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "test"));
var file = File.ReadAllText(solutionFile);
var lines = file.Split(Environment.NewLine).ToList();
var projectsUnderModule = Directory.GetFiles(
Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name),
"*.csproj",
@ -92,7 +138,7 @@ namespace Volo.Abp.Cli.ProjectModification
foreach (var projectPath in projectsUnderModule)
{
var parentFolderId = projectsUnderTest.Contains(projectPath) ? testModuleFolderId : srcModuleFolderId;
var projectId = Path.GetFileName(projectPath).Replace(".csproj","");
var projectId = Path.GetFileName(projectPath).Replace(".csproj", "");
var projectParentFolderInModule = projectsUnderTest.Contains(projectPath) ? "test" : "src";
if (lines.Any(l => l.Contains($"\"{projectId}\"")))
@ -103,8 +149,9 @@ namespace Volo.Abp.Cli.ProjectModification
var projectGuid = Guid.NewGuid().ToString();
var newProjectLine = "Project(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"" + projectId + "\"," +
" \"modules\\" + module.Name + "\\"+ projectParentFolderInModule + "\\" + projectId + "\\" + projectId + ".csproj\", \"{" + projectGuid + "}\""
+ Environment.NewLine + "EndProject";
" \"modules\\" + module.Name + "\\" + projectParentFolderInModule + "\\" +
projectId + "\\" + projectId + ".csproj\", \"{" + projectGuid + "}\""
+ Environment.NewLine + "EndProject";
lines.InsertAfter(l => l.Trim().Equals("EndProject"), newProjectLine);
@ -114,12 +161,13 @@ namespace Volo.Abp.Cli.ProjectModification
" {" + projectGuid + "}.Release|Any CPU.ActiveCfg = Release|Any CPU" + Environment.NewLine +
" {" + projectGuid + "}.Release|Any CPU.Build.0 = Release|Any CPU";
lines.InsertAfter(l=>l.Contains("GlobalSection") && l.Contains("ProjectConfigurationPlatforms"), newPostSolutionLine);
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("ProjectConfigurationPlatforms"),
newPostSolutionLine);
var newPreSolutionLine =
" {"+ projectGuid + "} = {"+ parentFolderId + "}";
" {" + projectGuid + "} = {" + parentFolderId + "}";
lines.InsertAfter(l=>l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
}
File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines));
@ -133,19 +181,21 @@ namespace Volo.Abp.Cli.ProjectModification
}
}
private async Task<string> AddNewFolderAndGetIdOrGetExistingId(string solutionFile, string folderName, string parentFolderId = null)
private async Task<string> AddNewFolderAndGetIdOrGetExistingIdAsync(string solutionFile, string folderName,
string parentFolderId = null)
{
var file = File.ReadAllText(solutionFile);
var lines = file.Split(Environment.NewLine).ToList();
string folderId;
var folderLineIndex = lines.FindIndex(l =>
l.Contains("2150E333-8FDC-42A3-9474-1A3956D46DE8") && l.Contains("\""+ folderName + "\""));
l.Contains("2150E333-8FDC-42A3-9474-1A3956D46DE8") && l.Contains("\"" + folderName + "\""));
if (folderLineIndex < 0)
{
folderId = Guid.NewGuid().ToString();
var newFolderLine = "Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \""+ folderName + "\", \""+ folderName + "\", \"{" + folderId + "}\""
var newFolderLine = "Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"" + folderName + "\", \"" +
folderName + "\", \"{" + folderId + "}\""
+ Environment.NewLine + "EndProject";
lines.InsertAfter(l => l.Trim().Equals("EndProject"), newFolderLine);
@ -155,7 +205,8 @@ namespace Volo.Abp.Cli.ProjectModification
var newPreSolutionLine =
" {" + folderId + "} = {" + parentFolderId + "}";
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"),
newPreSolutionLine);
}
}
else

@ -365,7 +365,7 @@ namespace Volo.Abp.Cli.ProjectModification
}
else
{
await SourceCodeDownloadService.DownloadAsync(
await SourceCodeDownloadService.DownloadModuleAsync(
module.Name,
targetModuleFolder,
version,

Loading…
Cancel
Save