Browse Source

Made SolutionFileModifier work with slnx files cont.

pull/23822/head
Yunus Emre Kalkan 10 months ago
parent
commit
d2e25cd5d1
  1. 247
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs

247
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs

@ -13,7 +13,6 @@ namespace Volo.Abp.Cli.ProjectModification;
public class SolutionFileModifier : ITransientDependency
{
private readonly ICmdHelper _cmdHelper;
public static Encoding DefaultEncoding = Encoding.UTF8;
public SolutionFileModifier(ICmdHelper cmdHelper)
{
@ -22,13 +21,15 @@ public class SolutionFileModifier : ITransientDependency
public async Task RemoveProjectFromSolutionFileAsync(string solutionFile, string projectName)
{
if (solutionFile.EndsWith(".sln"))
{
await RemoveProjectFromSlnFileAsync(solutionFile, projectName);
}
else
var list = _cmdHelper.RunCmdAndGetOutput($"dotnet sln {solutionFile} list");
foreach (var line in list.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None))
{
await RemoveProjectFromSlnxFileAsync(solutionFile, projectName);
if (Path.GetFileNameWithoutExtension(line.Trim()).Equals(projectName, StringComparison.InvariantCultureIgnoreCase))
{
_cmdHelper.RunCmd($"dotnet sln {solutionFile} remove {line.Trim()}");
break;
}
}
}
@ -42,168 +43,18 @@ public class SolutionFileModifier : ITransientDependency
await AddPackageAsync(package, solutionFile);
}
private async Task RemoveProjectFromSlnxFileAsync(string solutionFile, string projectName)
{
var document = new XmlDocument { PreserveWhitespace = true };
document.Load(solutionFile);
var projectNodes = document.SelectNodes("/Solution/Folder/Project");
if (projectNodes == null || projectNodes.Count < 1)
{
return;
}
var nodesToBeRemoved = new List<XmlNode>();
foreach (XmlNode projectNode in projectNodes)
{
var pathAttr = projectNode.Attributes?["Path"]?.Value;
if (string.IsNullOrWhiteSpace(pathAttr))
{
continue;
}
var normalized = pathAttr.Replace('\\', '/');
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(normalized);
if (string.Equals(fileNameWithoutExtension, projectName, StringComparison.OrdinalIgnoreCase))
{
nodesToBeRemoved.Add(projectNode);
}
}
foreach (var node in nodesToBeRemoved)
{
node.ParentNode!.RemoveChild(node);
}
await File.WriteAllTextAsync(solutionFile, document.OuterXml);
}
private async Task RemoveProjectFromSlnFileAsync(string solutionFile, string projectName)
{
using (var fileStream = File.Open(solutionFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
using (var sr = new StreamReader(fileStream, Encoding.Default, true))
{
var solutionFileContent = await sr.ReadToEndAsync();
solutionFileContent.NormalizeLineEndings();
var lines = solutionFileContent.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None);
var updatedContent = RemoveProject(lines.ToList(), projectName).JoinAsString(Environment.NewLine);
fileStream.Seek(0, SeekOrigin.Begin);
fileStream.SetLength(0);
using (var sw = new StreamWriter(fileStream, DefaultEncoding))
{
await sw.WriteAsync(updatedContent);
await sw.FlushAsync();
}
}
}
}
private async Task AddPackageAsync(NugetPackageInfo package, string solutionFile)
{
var srcFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "src");
var solutionFileContent = File.ReadAllText(solutionFile);
var lines = solutionFileContent.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None).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), DefaultEncoding);
}
private List<string> RemoveProject(List<string> solutionFileLines, string projectName)
{
var projectKey = FindProjectKey(solutionFileLines, projectName);
if (projectKey == null)
{
return solutionFileLines;
}
var newSolutionFileLines = new List<string>();
var firstOccurence = true;
for (var i = 0; i < solutionFileLines.Count; ++i)
{
if (solutionFileLines[i].Contains(projectKey))
{
if (firstOccurence)
{
firstOccurence = false;
++i; //Skip "EndProject" line too.
}
continue;
}
newSolutionFileLines.Add(solutionFileLines[i]);
}
return newSolutionFileLines;
}
private string FindProjectKey(List<string> solutionFileLines, string projectName)
{
var projectNameWithQuotes = $"\"{projectName}\"";
foreach (var solutionFileLine in solutionFileLines)
{
if (solutionFileLine.Contains(projectNameWithQuotes))
{
var curlyBracketStartIndex = solutionFileLine.LastIndexOf("{", StringComparison.OrdinalIgnoreCase);
var curlyBracketEndIndex = solutionFileLine.LastIndexOf("}", StringComparison.OrdinalIgnoreCase);
return solutionFileLine.Substring(curlyBracketStartIndex + 1,
curlyBracketEndIndex - curlyBracketStartIndex - 1);
}
}
return null;
_cmdHelper.RunCmd($"dotnet sln {solutionFile} add packages\\{package.Name}\\{package.Name}.csproj --solution-folder src");
}
private async Task AddModuleAsync(ModuleWithMastersInfo module, string solutionFile)
{
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(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None).ToList();
var projectsUnderModule = Directory.GetFiles(
Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name),
"*.csproj",
SearchOption.AllDirectories);
var projectsUnderTest = new List<string>();
if (Directory.Exists(Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name, "test")))
{
@ -215,41 +66,14 @@ public class SolutionFileModifier : ITransientDependency
foreach (var projectPath in projectsUnderModule)
{
var parentFolderId = projectsUnderTest.Contains(projectPath) ? testModuleFolderId : srcModuleFolderId;
var projectId = Path.GetFileName(projectPath).Replace(".csproj", "");
var projectParentFolderInModule = projectsUnderTest.Contains(projectPath) ? "test" : "src";
if (lines.Any(l => l.Contains($"\"{projectId}\"")))
{
continue;
}
var projectGuid = Guid.NewGuid().ToString();
var folder = projectsUnderTest.Contains(projectPath) ? "test" : "src";
var newProjectLine = "Project(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"" + projectId + "\"," +
" \"modules\\" + module.Name + "\\" + projectParentFolderInModule + "\\" +
projectId + "\\" + projectId + ".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 + "} = {" + parentFolderId + "}";
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
var projectId = Path.GetFileName(projectPath).Replace(".csproj", "");
var package = @$"modules\{module.Name}\{folder}\{projectId}\{projectId}.csproj";
_cmdHelper.RunCmd($"dotnet sln {solutionFile} add {package} --solution-folder {folder}");
}
File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines), Encoding.UTF8);
if (module.MasterModuleInfos != null)
{
foreach (var masterModule in module.MasterModuleInfos)
@ -258,43 +82,4 @@ public class SolutionFileModifier : ITransientDependency
}
}
}
private async Task<string> AddNewFolderAndGetIdOrGetExistingIdAsync(string solutionFile, string folderName,
string parentFolderId = null)
{
var file = File.ReadAllText(solutionFile);
var lines = file.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None).ToList();
string folderId;
var folderLineIndex = lines.FindIndex(l =>
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 + "}\""
+ Environment.NewLine + "EndProject";
lines.InsertAfter(l => l.Trim().Equals("EndProject"), newFolderLine);
if (parentFolderId != null)
{
var newPreSolutionLine =
" {" + folderId + "} = {" + parentFolderId + "}";
lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"),
newPreSolutionLine);
}
}
else
{
folderId = lines[folderLineIndex].Replace("\"", " ").Replace("{", " ").Replace("}", " ").TrimEnd()
.Split(" ").Last();
}
File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines), Encoding.UTF8);
return folderId;
}
}

Loading…
Cancel
Save