diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs new file mode 100644 index 0000000000..61b5f5975a --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.ProjectModification +{ + public class NugetPackageToLocalReferenceConverter : ITransientDependency + { + public async Task Convert(ModuleWithMastersInfo module, string solutionFile) + { + var nugetPackageList = GetNugetPackages(module); + + var projectFilesUnderModules = GetProjectFilesUnder(Path.Combine(Path.GetDirectoryName(solutionFile), "modules")); ; + var projectFilesUnderSrc = GetProjectFilesUnder(Path.Combine(Path.GetDirectoryName(solutionFile), "src")); ; + var projectFilesUnderTest = GetProjectFilesUnder(Path.Combine(Path.GetDirectoryName(solutionFile), "test")); ; + + foreach (var projectFile in projectFilesUnderModules) + { + ConvertToLocalReference(projectFile, nugetPackageList, "..\\..\\..\\"); + } + foreach (var projectFile in projectFilesUnderSrc) + { + ConvertToLocalReference(projectFile, nugetPackageList, "..\\..\\modules\\"); + } + foreach (var projectFile in projectFilesUnderTest) + { + ConvertToLocalReference(projectFile, nugetPackageList, "..\\..\\modules\\", "test"); + } + } + + private void ConvertToLocalReference(string projectFile, List nugetPackageList, string localPathPrefix, string sourceFile = "src") + { + var content = File.ReadAllText(projectFile); + var doc = new XmlDocument() { PreserveWhitespace = true }; + + doc.Load(GenerateStreamFromString(content)); + + var convertedProject = ProcessReferenceNodes(doc, nugetPackageList, localPathPrefix, sourceFile); + + File.WriteAllText(projectFile, convertedProject); + } + + + private string ProcessReferenceNodes(XmlDocument doc, List nugetPackageList, string localPathPrefix, string sourceFile = "src") + { + var nodes = doc.SelectNodes("/Project/ItemGroup/PackageReference[@Include]"); + + if (nodes == null) + { + return doc.OuterXml; + } + + foreach (XmlNode oldNode in nodes) + { + var oldNodeIncludeValue = oldNode?.Attributes?["Include"]?.Value; + + var nugetPackage = nugetPackageList.FirstOrDefault(n => n.NugetPackage.Name == oldNodeIncludeValue); + + if (nugetPackage == null) + { + continue; + } + + var referenceProjectPath = + $"{localPathPrefix}{nugetPackage.ModuleName}\\{sourceFile}\\{nugetPackage.NugetPackage.Name}\\{nugetPackage.NugetPackage.Name}.csproj"; + + XmlNode newNode = GetNewReferenceNode(doc, referenceProjectPath); + + oldNode?.ParentNode?.ReplaceChild(newNode, oldNode); + } + + return doc.OuterXml; + } + + protected XmlElement GetNewReferenceNode(XmlDocument doc, string newValue) + { + var newNode = doc.CreateElement("ProjectReference"); + + var includeAttr = doc.CreateAttribute("Include"); + includeAttr.Value = newValue; + newNode.Attributes.Append(includeAttr); + + return newNode; + } + + public List GetNugetPackages(ModuleWithMastersInfo module) + { + var list = new List(); + + list.AddRange(module.NugetPackages.Select(n => new NugetPackageInfoWithModuleName + { + ModuleName = module.Name, + NugetPackage = n + })); + + if (module.MasterModuleInfos != null) + { + foreach (var masterModule in module.MasterModuleInfos) + { + list.AddRange(GetNugetPackages(masterModule)); + } + } + + return list; + } + + private static string[] GetProjectFilesUnder(string path) + { + return Directory.GetFiles(path, + "*.csproj", + SearchOption.AllDirectories); + } + + 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; + } + + public class NugetPackageInfoWithModuleName + { + public NugetPackageInfo NugetPackage { get; set; } + + public string ModuleName { get; set; } + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 1f74f0df66..5dd6aa4337 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -29,6 +29,7 @@ namespace Volo.Abp.Cli.ProjectModification protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } public SourceCodeDownloadService SourceCodeDownloadService { get; } public SolutionFileModifier SolutionFileModifier { get; } + public NugetPackageToLocalReferenceConverter NugetPackageToLocalReferenceConverter { get; } public SolutionModuleAdder( IJsonSerializer jsonSerializer, @@ -40,7 +41,8 @@ namespace Volo.Abp.Cli.ProjectModification NpmGlobalPackagesChecker npmGlobalPackagesChecker, IRemoteServiceExceptionHandler remoteServiceExceptionHandler, SourceCodeDownloadService sourceCodeDownloadService, - SolutionFileModifier solutionFileModifier) + SolutionFileModifier solutionFileModifier, + NugetPackageToLocalReferenceConverter nugetPackageToLocalReferenceConverter) { JsonSerializer = jsonSerializer; ProjectNugetPackageAdder = projectNugetPackageAdder; @@ -52,6 +54,7 @@ namespace Volo.Abp.Cli.ProjectModification RemoteServiceExceptionHandler = remoteServiceExceptionHandler; SourceCodeDownloadService = sourceCodeDownloadService; SolutionFileModifier = solutionFileModifier; + NugetPackageToLocalReferenceConverter = nugetPackageToLocalReferenceConverter; Logger = NullLogger.Instance; } @@ -72,16 +75,17 @@ namespace Volo.Abp.Cli.ProjectModification var projectFiles = ProjectFinder.GetProjectFiles(solutionFile); - await AddNugetAndNpmReferences(module, projectFiles); + //await AddNugetAndNpmReferences(module, projectFiles); if (withSourceCode) { var modulesFolderInSolution = Path.Combine(Path.GetDirectoryName(solutionFile), "modules"); await DownloadSourceCodesToSolutionFolder(module, modulesFolderInSolution, version); await SolutionFileModifier.AddModuleToSolutionFileAsync(module, solutionFile); + await NugetPackageToLocalReferenceConverter.Convert(module, solutionFile); } - ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations); + //ModifyDbContext(projectFiles, module, startupProject, skipDbMigrations); } private async Task DownloadSourceCodesToSolutionFolder(ModuleWithMastersInfo module, string modulesFolderInSolution, string version = null)