diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs index a86d17fee2..93dbeacc22 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs @@ -1,5 +1,7 @@ using System.IO; +using System.Text.RegularExpressions; using System.Xml; +using NuGet.Versioning; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; @@ -9,28 +11,139 @@ namespace Volo.Abp.Cli.ProjectModification { public string Find(string solutionFile) { - var projectFilesUnderSrc = Directory.GetFiles(Path.GetDirectoryName(solutionFile), - "*.csproj", - SearchOption.AllDirectories); - + var projectFilesUnderSrc = GetProjectFilesOfSolution(solutionFile); foreach (var projectFile in projectFilesUnderSrc) { var content = File.ReadAllText(projectFile); - var doc = new XmlDocument() { PreserveWhitespace = true }; + if (TryParseVersionFromCsprojViaXmlDocument(content, out var s)) + { + return s; + } + } - doc.Load(StreamHelper.GenerateStreamFromString(content)); + return null; + } + private static bool TryParseVersionFromCsprojViaXmlDocument(string content, out string version) + { + var doc = new XmlDocument() { PreserveWhitespace = true }; + using (var stream = StreamHelper.GenerateStreamFromString(content)) + { + doc.Load(stream); var nodes = doc.SelectNodes("/Project/ItemGroup/PackageReference[starts-with(@Include, 'Volo.Abp')]"); - var value = nodes?[0]?.Attributes?["Version"]?.Value; + if (value == null) + { + version = null; + return false; + } + + version = value; + return true; + } + } - if (value != null) + public static bool TryParseVersionFromCsprojFile(string csprojContent, out string version) + { + try + { + var matches = Regex.Matches(csprojContent, + @"PackageReference\s*Include\s*=\s*\""Volo.Abp(.*?)\""\s*Version\s*=\s*\""(.*?)\""", + RegexOptions.IgnoreCase | + RegexOptions.IgnorePatternWhitespace | + RegexOptions.Singleline | RegexOptions.Multiline); + + foreach (Match match in matches) { - return value; + if (match.Groups.Count > 2) + { + version = match.Groups[2].Value; + return true; + } } } + catch + { + //ignored + } - return null; + version = null; + return false; + } + + + public static bool TryParseSemanticVersionFromCsprojFile(string csprojContent, out SemanticVersion version) + { + try + { + if (TryParseVersionFromCsprojFile(csprojContent, out var versionText)) + { + return SemanticVersion.TryParse(versionText, out version); + } + } + catch + { + //ignored + } + + version = null; + return false; + } + + public static bool TryFind(string solutionFile, out string version) + { + var projectFiles = GetProjectFilesOfSolution(solutionFile); + foreach (var projectFile in projectFiles) + { + var csprojContent = File.ReadAllText(projectFile); + if (TryParseVersionFromCsprojFile(csprojContent, out var parsedVersion)) + { + version = parsedVersion; + return true; + } + } + + version = null; + return false; + } + + public static bool TryFindSemanticVersion(string solutionFile, out SemanticVersion version) + { + var projectFiles = GetProjectFilesOfSolution(solutionFile); + foreach (var projectFile in projectFiles) + { + var csprojContent = File.ReadAllText(projectFile); + if (TryParseSemanticVersionFromCsprojFile(csprojContent, out var parsedVersion)) + { + version = parsedVersion; + return true; + } + } + + version = null; + return false; + } + + //public static bool TryFindSemanticVersion(string solutionFile, out SemanticVersion version) + //{ + // if (TryFind(solutionFile, out var versionText)) + // { + // return SemanticVersion.TryParse(versionText, out version); + // } + + // version = null; + // return false; + //} + + private static string[] GetProjectFilesOfSolution(string solutionFile) + { + var solutionDirectory = Path.GetDirectoryName(solutionFile); + if (solutionDirectory == null) + { + return new string[] { }; + } + + return Directory.GetFiles(solutionDirectory, "*.csproj", SearchOption.AllDirectories); } } } diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectVersionParse_Tests.cs b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectVersionParse_Tests.cs new file mode 100644 index 0000000000..eb4a9eda24 --- /dev/null +++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectVersionParse_Tests.cs @@ -0,0 +1,70 @@ +using Shouldly; +using Volo.Abp.Cli.ProjectModification; +using Xunit; + +namespace Volo.Abp.Cli +{ + public class ProjectVersionParse_Tests + { + [Fact] + public void Find_Abp_Version() + { + const string csprojContent = "" + + "" + + "" + + "net5.0" + + "Blazoor.EfCore07062034" + + "" + + "" + + "" + + "" + + "" + + "< PackageReference Include = \"Volo.Abp.Emailing\" Version = \"4.4.0-rc.1\" />" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + var success = SolutionAbpVersionFinder.TryParseVersionFromCsprojFile(csprojContent, out var version); + success.ShouldBe(true); + version.ShouldBe("4.4.0-rc.1"); + } + + [Fact] + public void Find_Abp_Semantic_Version() + { + const string csprojContent = "" + + "" + + "" + + "net5.0" + + "Blazoor.EfCore07062034" + + "" + + "" + + "" + + "" + + "" + + "< PackageReference Include = \"Volo.Abp.Emailing\" Version= \"12.8.3-beta.1\" />" + + "" + + ""; + + var success = SolutionAbpVersionFinder.TryParseSemanticVersionFromCsprojFile(csprojContent, out var version); + success.ShouldBe(true); + version.Major.ShouldBe(12); + version.Minor.ShouldBe(8); + version.Patch.ShouldBe(3); + version.Release.ShouldBe("beta.1"); + } + + } +}