diff --git a/src/GitVersion.App/ArgumentParserExtensions.cs b/src/GitVersion.App/ArgumentParserExtensions.cs index 7a5bbfb006..852773f941 100644 --- a/src/GitVersion.App/ArgumentParserExtensions.cs +++ b/src/GitVersion.App/ArgumentParserExtensions.cs @@ -40,7 +40,7 @@ public static bool IsValidPath(this string? path) public static bool IsSwitchArgument(this string? value) { - var patternRegex = RegexPatterns.Common.SwitchArgumentRegex; + var patternRegex = RegexPatterns.Common.SwitchArgumentRegex(); return value != null && (value.StartsWith('-') || value.StartsWith('/')) && !patternRegex.Match(value).Success; diff --git a/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.cs b/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.cs index 390aca6cbb..9ce9311f5b 100644 --- a/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.cs +++ b/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.cs @@ -258,7 +258,7 @@ public void CanReadDefaultDocument() configuration.AssemblyInformationalFormat.ShouldBe(null); configuration.Branches["develop"].Label.ShouldBe("alpha"); configuration.Branches["release"].Label.ShouldBe("beta"); - configuration.TagPrefixPattern.ShouldBe(RegexPatterns.Configuration.DefaultTagPrefixPattern); + configuration.TagPrefixPattern.ShouldBe(RegexPatterns.Configuration.DefaultTagPrefixRegexPattern); configuration.NextVersion.ShouldBe(null); } @@ -418,7 +418,7 @@ public void ShouldUseDefaultTagPrefixWhenNotSetInConfigFile() using var _ = this.fileSystem.SetupConfigFile(path: this.repoPath, text: text); var configuration = this.configurationProvider.ProvideForDirectory(this.repoPath); - configuration.TagPrefixPattern.ShouldBe(RegexPatterns.Configuration.DefaultTagPrefixPattern); + configuration.TagPrefixPattern.ShouldBe(RegexPatterns.Configuration.DefaultTagPrefixRegexPattern); } [Test] @@ -457,7 +457,7 @@ public void ShouldNotOverrideDefaultTagPrefixWhenNotSetInOverrideConfig() var configuration = this.configurationProvider.ProvideForDirectory(this.repoPath, overrideConfiguration); - configuration.TagPrefixPattern.ShouldBe(RegexPatterns.Configuration.DefaultTagPrefixPattern); + configuration.TagPrefixPattern.ShouldBe(RegexPatterns.Configuration.DefaultTagPrefixRegexPattern); } [Test] diff --git a/src/GitVersion.Configuration/Builders/BranchConfigurationBuilder.cs b/src/GitVersion.Configuration/Builders/BranchConfigurationBuilder.cs index d158110b9f..c45a5625bd 100644 --- a/src/GitVersion.Configuration/Builders/BranchConfigurationBuilder.cs +++ b/src/GitVersion.Configuration/Builders/BranchConfigurationBuilder.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; @@ -81,7 +82,7 @@ public virtual BranchConfigurationBuilder WithCommitMessageIncrementing(CommitMe return this; } - public virtual BranchConfigurationBuilder WithRegularExpression(string? value) + public virtual BranchConfigurationBuilder WithRegularExpression([StringSyntax(StringSyntaxAttribute.Regex)] string? value) { this.regularExpression = value; return this; diff --git a/src/GitVersion.Configuration/Builders/GitFlowConfigurationBuilder.cs b/src/GitVersion.Configuration/Builders/GitFlowConfigurationBuilder.cs index 08398c0c58..b45967ac4c 100644 --- a/src/GitVersion.Configuration/Builders/GitFlowConfigurationBuilder.cs +++ b/src/GitVersion.Configuration/Builders/GitFlowConfigurationBuilder.cs @@ -14,14 +14,14 @@ private GitFlowConfigurationBuilder() AssemblyFileVersioningScheme = ConfigurationConstants.DefaultAssemblyFileVersioningScheme, AssemblyVersioningScheme = ConfigurationConstants.DefaultAssemblyVersioningScheme, CommitDateFormat = ConfigurationConstants.DefaultCommitDateFormat, - MajorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMajorPattern, - MinorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMinorPattern, - NoBumpMessage = RegexPatterns.VersionCalculation.DefaultNoBumpPattern, - PatchVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultPatchPattern, + MajorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMajorRegexPattern, + MinorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMinorRegexPattern, + NoBumpMessage = RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern, + PatchVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultPatchRegexPattern, SemanticVersionFormat = ConfigurationConstants.DefaultSemanticVersionFormat, VersionStrategies = ConfigurationConstants.DefaultVersionStrategies, - TagPrefixPattern = RegexPatterns.Configuration.DefaultTagPrefixPattern, - VersionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchPattern, + TagPrefixPattern = RegexPatterns.Configuration.DefaultTagPrefixRegexPattern, + VersionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern, TagPreReleaseWeight = ConfigurationConstants.DefaultTagPreReleaseWeight, UpdateBuildNumber = ConfigurationConstants.DefaultUpdateBuildNumber, DeploymentMode = DeploymentMode.ContinuousDelivery, diff --git a/src/GitVersion.Configuration/Builders/GitHubFlowConfigurationBuilder.cs b/src/GitVersion.Configuration/Builders/GitHubFlowConfigurationBuilder.cs index b470db4174..3a95c130d4 100644 --- a/src/GitVersion.Configuration/Builders/GitHubFlowConfigurationBuilder.cs +++ b/src/GitVersion.Configuration/Builders/GitHubFlowConfigurationBuilder.cs @@ -14,14 +14,14 @@ private GitHubFlowConfigurationBuilder() AssemblyFileVersioningScheme = ConfigurationConstants.DefaultAssemblyFileVersioningScheme, AssemblyVersioningScheme = ConfigurationConstants.DefaultAssemblyVersioningScheme, CommitDateFormat = ConfigurationConstants.DefaultCommitDateFormat, - MajorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMajorPattern, - MinorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMinorPattern, - NoBumpMessage = RegexPatterns.VersionCalculation.DefaultNoBumpPattern, - PatchVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultPatchPattern, + MajorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMajorRegexPattern, + MinorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMinorRegexPattern, + NoBumpMessage = RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern, + PatchVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultPatchRegexPattern, SemanticVersionFormat = ConfigurationConstants.DefaultSemanticVersionFormat, VersionStrategies = ConfigurationConstants.DefaultVersionStrategies, - TagPrefixPattern = RegexPatterns.Configuration.DefaultTagPrefixPattern, - VersionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchPattern, + TagPrefixPattern = RegexPatterns.Configuration.DefaultTagPrefixRegexPattern, + VersionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern, TagPreReleaseWeight = ConfigurationConstants.DefaultTagPreReleaseWeight, UpdateBuildNumber = ConfigurationConstants.DefaultUpdateBuildNumber, DeploymentMode = DeploymentMode.ContinuousDelivery, diff --git a/src/GitVersion.Configuration/Builders/TrunkBasedConfigurationBuilder.cs b/src/GitVersion.Configuration/Builders/TrunkBasedConfigurationBuilder.cs index 43fb64df46..608bcc1533 100644 --- a/src/GitVersion.Configuration/Builders/TrunkBasedConfigurationBuilder.cs +++ b/src/GitVersion.Configuration/Builders/TrunkBasedConfigurationBuilder.cs @@ -14,17 +14,17 @@ private TrunkBasedConfigurationBuilder() AssemblyFileVersioningScheme = ConfigurationConstants.DefaultAssemblyFileVersioningScheme, AssemblyVersioningScheme = ConfigurationConstants.DefaultAssemblyVersioningScheme, CommitDateFormat = ConfigurationConstants.DefaultCommitDateFormat, - MajorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMajorPattern, - MinorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMinorPattern, - NoBumpMessage = RegexPatterns.VersionCalculation.DefaultNoBumpPattern, - PatchVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultPatchPattern, + MajorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMajorRegexPattern, + MinorVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultMinorRegexPattern, + NoBumpMessage = RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern, + PatchVersionBumpMessage = RegexPatterns.VersionCalculation.DefaultPatchRegexPattern, SemanticVersionFormat = ConfigurationConstants.DefaultSemanticVersionFormat, VersionStrategies = [ VersionStrategies.ConfiguredNextVersion, VersionStrategies.Mainline ], - TagPrefixPattern = RegexPatterns.Configuration.DefaultTagPrefixPattern, - VersionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchPattern, + TagPrefixPattern = RegexPatterns.Configuration.DefaultTagPrefixRegexPattern, + VersionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern, TagPreReleaseWeight = ConfigurationConstants.DefaultTagPreReleaseWeight, UpdateBuildNumber = ConfigurationConstants.DefaultUpdateBuildNumber, DeploymentMode = DeploymentMode.ContinuousDelivery, diff --git a/src/GitVersion.Configuration/GitVersionConfiguration.cs b/src/GitVersion.Configuration/GitVersionConfiguration.cs index da01a143a3..6e3a49bf9c 100644 --- a/src/GitVersion.Configuration/GitVersionConfiguration.cs +++ b/src/GitVersion.Configuration/GitVersionConfiguration.cs @@ -36,14 +36,14 @@ internal sealed record GitVersionConfiguration : BranchConfiguration, IGitVersio public string? AssemblyFileVersioningFormat { get; internal init; } [JsonPropertyName("tag-prefix")] - [JsonPropertyDescription($"A regular expression which is used to trim Git tags before processing. Defaults to '{RegexPatterns.Configuration.DefaultTagPrefixPattern}'")] - [JsonPropertyDefault(RegexPatterns.Configuration.DefaultTagPrefixPattern)] + [JsonPropertyDescription($"A regular expression which is used to trim Git tags before processing. Defaults to '{RegexPatterns.Configuration.DefaultTagPrefixRegexPattern}'")] + [JsonPropertyDefault(RegexPatterns.Configuration.DefaultTagPrefixRegexPattern)] [JsonPropertyFormat(Format.Regex)] public string? TagPrefixPattern { get; internal init; } [JsonPropertyName("version-in-branch-pattern")] - [JsonPropertyDescription($"A regular expression which is used to determine the version number in the branch name or commit message (e.g., v1.0.0-LTS). Defaults to '{RegexPatterns.Configuration.DefaultVersionInBranchPattern}'.")] - [JsonPropertyDefault(RegexPatterns.Configuration.DefaultVersionInBranchPattern)] + [JsonPropertyDescription($"A regular expression which is used to determine the version number in the branch name or commit message (e.g., v1.0.0-LTS). Defaults to '{RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern}'.")] + [JsonPropertyDefault(RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern)] [JsonPropertyFormat(Format.Regex)] public string? VersionInBranchPattern { get; internal init; } @@ -60,26 +60,26 @@ public string? NextVersion private string? nextVersion; [JsonPropertyName("major-version-bump-message")] - [JsonPropertyDescription($"The regular expression to match commit messages with to perform a major version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultMajorPattern}'")] - [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultMajorPattern)] + [JsonPropertyDescription($"The regular expression to match commit messages with to perform a major version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultMajorRegexPattern}'")] + [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultMajorRegexPattern)] [JsonPropertyFormat(Format.Regex)] public string? MajorVersionBumpMessage { get; internal init; } [JsonPropertyName("minor-version-bump-message")] - [JsonPropertyDescription($"The regular expression to match commit messages with to perform a minor version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultMinorPattern}'")] - [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultMinorPattern)] + [JsonPropertyDescription($"The regular expression to match commit messages with to perform a minor version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultMinorRegexPattern}'")] + [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultMinorRegexPattern)] [JsonPropertyFormat(Format.Regex)] public string? MinorVersionBumpMessage { get; internal init; } [JsonPropertyName("patch-version-bump-message")] - [JsonPropertyDescription($"The regular expression to match commit messages with to perform a patch version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultPatchPattern}'")] - [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultPatchPattern)] + [JsonPropertyDescription($"The regular expression to match commit messages with to perform a patch version increment. Defaults to '{RegexPatterns.VersionCalculation.DefaultPatchRegexPattern}'")] + [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultPatchRegexPattern)] [JsonPropertyFormat(Format.Regex)] public string? PatchVersionBumpMessage { get; internal init; } [JsonPropertyName("no-bump-message")] - [JsonPropertyDescription($"Used to tell GitVersion not to increment when in Mainline development mode. Defaults to '{RegexPatterns.VersionCalculation.DefaultNoBumpPattern}'")] - [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultNoBumpPattern)] + [JsonPropertyDescription($"Used to tell GitVersion not to increment when in Mainline development mode. Defaults to '{RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern}'")] + [JsonPropertyDefault(RegexPatterns.VersionCalculation.DefaultNoBumpRegexPattern)] [JsonPropertyFormat(Format.Regex)] public string? NoBumpMessage { get; internal init; } diff --git a/src/GitVersion.Core.Tests/Core/RegexPatternTests.cs b/src/GitVersion.Core.Tests/Core/RegexPatternTests.cs new file mode 100644 index 0000000000..d56739de7f --- /dev/null +++ b/src/GitVersion.Core.Tests/Core/RegexPatternTests.cs @@ -0,0 +1,439 @@ +using System.Text.RegularExpressions; +using static GitVersion.Core.RegexPatterns.AssemblyVersion; + +namespace GitVersion.Core.Continuous.Tests +{ + public class RegexPatternsTests + { + [TestCase("/foo:", true, "/foo:")] + [TestCase("/bar:", true, "/bar:")] + [TestCase("foo:", false, null)] + public void SwitchArgumentRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Common.SwitchArgumentRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("https://user:pass@host", true, "https://user:pass@")] + [TestCase("http://user:pass@host", true, "http://user:pass@")] + [TestCase("ftp://user:pass@host", false, null)] + public void ObscurePasswordRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Common.ObscurePasswordRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("{env:FOO}", true, "{env:FOO}")] + [TestCase("{bar}", true, "{bar}")] + [TestCase("{env:FOO ?? \"fallback\"}", true, "{env:FOO ?? \"fallback\"}")] + [TestCase("{bar ?? fallback}", true, "{bar ?? fallback}")] + [TestCase("env:FOO", false, null)] + public void ExpandTokensRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Common.ExpandTokensRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("v", true, "v")] + [TestCase("V", true, "V")] + [TestCase("v1", true, "v")] + [TestCase("V2.0", true, "V")] + [TestCase("1", true, "")] + [TestCase("x", true, "")] + [TestCase("", true, "")] + public void DefaultTagPrefixRegex_MatchesExpected(string input, bool expected, string expectedCapture) + { + var match = RegexPatterns.Configuration.DefaultTagPrefixRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("v1.2.3", true, "v1.2.3")] + [TestCase("1.2", true, "1.2")] + [TestCase("main", false, null)] + public void DefaultVersionInBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.DefaultVersionInBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("main", true, "main")] + [TestCase("master", true, "master")] + [TestCase("develop", false, null)] + public void MainBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.MainBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("develop", true, "develop")] + [TestCase("development", true, "development")] + [TestCase("dev", true, "dev")] + [TestCase("main", false, null)] + public void DevelopBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.DevelopBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("release/1.0", true, "release/1.0")] + [TestCase("releases-2.0", true, "releases-2.0")] + [TestCase("feature/foo", false, null)] + public void ReleaseBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.ReleaseBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("feature/foo", true, "feature/foo")] + [TestCase("features-bar", true, "features-bar")] + [TestCase("hotfix/1.0", false, null)] + public void FeatureBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.FeatureBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("pull-requests/123", true, "pull-requests/123")] + [TestCase("pull-123", true, "pull-123")] + [TestCase("pr-456", true, "pr-456")] + [TestCase("main", false, null)] + public void PullRequestBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.PullRequestBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("hotfix/1.0", true, "hotfix/1.0")] + [TestCase("hotfixes-2.0", true, "hotfixes-2.0")] + [TestCase("support/1.0", false, null)] + public void HotfixBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.HotfixBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("support/1.0", true, "support/1.0")] + [TestCase("support-2.0", true, "support-2.0")] + [TestCase("main", false, null)] + public void SupportBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.SupportBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("any-branch", true, "any-branch")] + [TestCase("main", true, "main")] + public void UnknownBranchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Configuration.UnknownBranchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("Merge branch 'feature/foo' into develop", true, "Merge branch 'feature/foo' into develop")] + [TestCase("Merge tag 'v1.0.0'", true, "Merge tag 'v1.0.0'")] + [TestCase("Finish feature/foo", false, null)] + public void DefaultMergeMessageRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.MergeMessage.DefaultMergeMessageRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("Finish feature/foo into develop", true, "Finish feature/foo into develop")] + [TestCase("Finish bugfix/bar", true, "Finish bugfix/bar")] + [TestCase("Merge branch 'feature/foo'", false, null)] + public void SmartGitMergeMessageRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.MergeMessage.SmartGitMergeMessageRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("Merge pull request #123 from repo from feature/foo to develop", true, "Merge pull request #123 from repo from feature/foo to develop")] + [TestCase("Merge pull request #1 in repo from bugfix/bar to main", true, "Merge pull request #1 in repo from bugfix/bar to main")] + [TestCase("Finish feature/foo", false, null)] + public void BitBucketPullMergeMessageRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.MergeMessage.BitBucketPullMergeMessageRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("Pull request #123\n\nMerge in repo from feature/foo to develop", true, "Pull request #123\n\nMerge in repo from feature/foo to develop")] + [TestCase("Pull request #1\n\nMerge in repo from bugfix/bar to main", true, "Pull request #1\n\nMerge in repo from bugfix/bar to main")] + [TestCase("Merge pull request #123 from repo from feature/foo to develop", false, null)] + public void BitBucketPullv7MergeMessageRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.MergeMessage.BitBucketPullv7MergeMessageRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("Merged in feature/foo (pull request #123)", true, "Merged in feature/foo (pull request #123)")] + [TestCase("Merged in bugfix/bar (pull request #1)", true, "Merged in bugfix/bar (pull request #1)")] + [TestCase("Merge pull request #123 from repo from feature/foo to develop", false, null)] + public void BitBucketCloudPullMergeMessageRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.MergeMessage.BitBucketCloudPullMergeMessageRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("Merge pull request #123 from repo/feature/foo", false, null)] + [TestCase("Merge pull request #123 from feature/foo into develop", false, null)] + public void AzureDevOpsPullMergeMessageRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.MergeMessage.AzureDevOpsPullMergeMessageRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("[assembly: AssemblyVersion(\"1.0.0.0\")]", true, "[assembly: AssemblyVersion(\"1.0.0.0\")]")] + [TestCase("[assembly: AssemblyFileVersion(\"1.0.0.0\")]", true, "[assembly: AssemblyFileVersion(\"1.0.0.0\")]")] + [TestCase("[assembly: AssemblyInformationalVersion(\"1.0.0.0\")]", true, "[assembly: AssemblyInformationalVersion(\"1.0.0.0\")]")] + [TestCase("random text", false, null)] + public void CsharpAssemblyAttributeRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Output.CsharpAssemblyAttributeRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("[]", true, "[]")] + [TestCase("[]", true, "[]")] + [TestCase("[]", true, "[]")] + [TestCase("random text", false, null)] + public void FsharpAssemblyAttributeRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Output.FsharpAssemblyAttributeRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("", true, "")] + [TestCase("", true, "")] + [TestCase("", true, "")] + [TestCase("random text", false, null)] + public void VisualBasicAssemblyAttributeRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.Output.VisualBasicAssemblyAttributeRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("+semver: major", true, "+semver: major")] + [TestCase("+semver: breaking", true, "+semver: breaking")] + [TestCase("+semver: minor", false, null)] + public void DefaultMajorRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.VersionCalculation.DefaultMajorRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("+semver: minor", true, "+semver: minor")] + [TestCase("+semver: feature", true, "+semver: feature")] + [TestCase("+semver: patch", false, null)] + public void DefaultMinorRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.VersionCalculation.DefaultMinorRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("+semver: patch", true, "+semver: patch")] + [TestCase("+semver: fix", true, "+semver: fix")] + [TestCase("+semver: none", false, null)] + public void DefaultPatchRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.VersionCalculation.DefaultPatchRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("+semver: none", true, "+semver: none")] + [TestCase("+semver: skip", true, "+semver: skip")] + [TestCase("+semver: patch", false, null)] + public void DefaultNoBumpRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.VersionCalculation.DefaultNoBumpRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("1.2.3", true, "1.2.3")] + [TestCase("1.2.3-alpha", true, "1.2.3-alpha")] + [TestCase("1.2", false, null)] + public void ParseStrictRegex_MatchesExpected(string input, bool expected, string? expectedCapture) + { + var match = RegexPatterns.SemanticVersion.ParseStrictRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("1.2.3", true, "1.2.3")] + [TestCase("1.2", true, "1.2")] + [TestCase("1", true, "1")] + [TestCase("1.2.3.4", true, "1.2.3.4")] + public void ParseLooseRegex_MatchesExpected(string input, bool expected, string expectedCapture) + { + var match = RegexPatterns.SemanticVersion.ParseLooseRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("123.BranchName.foo.Sha.abc", true, "123.BranchName.foo.Sha.abc")] + [TestCase("Branch.Name.develop", true, "Branch.Name.develop")] + [TestCase("random", true, "random")] + public void ParseBuildMetaDataRegex_MatchesExpected(string input, bool expected, string expectedCapture) + { + var match = RegexPatterns.SemanticVersion.ParseBuildMetaDataRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("meta-data", false, new string[0])] + [TestCase("meta_data", true, new[] { "_" })] + [TestCase("meta.data", false, new string[0])] + [TestCase("meta+data$", true, new[] { "+", "$" })] + [TestCase("m@e#t!a", true, new[] { "@", "#", "!" })] + public void FormatBuildMetaDataRegex_CapturesInvalidCharacters(string input, bool shouldMatch, string[] expectedCaptures) + { + var matches = RegexPatterns.SemanticVersion.FormatBuildMetaDataRegex().Matches(input); + + var matched = matches.Count > 0; + matched.ShouldBe(shouldMatch, $"Expected match: {shouldMatch}, but found {matches.Count} matches."); + + var captured = new List(); + foreach (Match m in matches) + captured.Add(m.Value); + + captured.ShouldBe(expectedCaptures); + } + + [TestCase("alpha.1", true, "alpha.1")] + [TestCase("beta", true, "beta")] + [TestCase("rc.2", true, "rc.2")] + public void ParsePreReleaseTagRegex_MatchesExpected(string input, bool expected, string expectedCapture) + { + var match = RegexPatterns.SemanticVersion.ParsePreReleaseTagRegex().Match(input); + match.Success.ShouldBe(expected); + if (expected) + match.Value.ShouldBe(expectedCapture); + } + + [TestCase("/* block comment */", true, "block", " block comment ")] + [TestCase("// line comment\r\n", true, "line", " line comment")] + [TestCase("\"string \\\"text\\\" inside\"", true, "str", "string \\\"text\\\" inside")] + [TestCase("int x = 5;", false, "", "")] + public void CSharpTriviaRegex_CapturesExpected(string input, bool expectedMatch, string expectedGroup, string expectedGroupValue) + { + var regex = CSharp.TriviaRegex(); + var match = regex.Match(input); + match.Success.ShouldBe(expectedMatch); + + if (expectedMatch && !string.IsNullOrEmpty(expectedGroup)) + { + // Match group 1: block, group 2: line, group 3: string + var groups = match.Groups; + var actualGroupValue = expectedGroup switch + { + "block" => groups[1].Success ? groups[1].Value : "", + "line" => groups[2].Success ? groups[2].Value : "", + "str" => groups[3].Success ? groups[3].Value : "", + _ => "" + }; + actualGroupValue.ShouldBe(expectedGroupValue); + } + } + + [TestCase("[assembly: AssemblyVersion()]", true)] + [TestCase("[assembly:AssemblyFileVersion()]", true)] + [TestCase("[assembly:System.Reflection.AssemblyInformationalVersion()]", true)] + [TestCase("[assembly: AssemblyTitle(\"App\")]", false)] + public void CSharpAttributeRegex_MatchesExpected(string input, bool expectedMatch) + { + var regex = CSharp.AttributeRegex(); + var match = regex.Match(input); + match.Success.ShouldBe(expectedMatch); + } + + [TestCase("/* block comment */", true, "block", " block comment ")] + [TestCase("// line comment\r\n", true, "line", " line comment")] + [TestCase("\"string \\\"text\\\" inside\"", true, "str", "string \\\"text\\\" inside")] + [TestCase("let x = 1", false, "", "")] + public void FSharpTriviaRegex_CapturesExpected(string input, bool expectedMatch, string expectedGroup, string expectedGroupValue) + { + var regex = FSharp.TriviaRegex(); + var match = regex.Match(input); + match.Success.ShouldBe(expectedMatch); + + if (expectedMatch && !string.IsNullOrEmpty(expectedGroup)) + { + var groups = match.Groups; + var actualGroupValue = expectedGroup switch + { + "block" => groups[1].Success ? groups[1].Value : "", + "line" => groups[2].Success ? groups[2].Value : "", + "str" => groups[3].Success ? groups[3].Value : "", + _ => "" + }; + actualGroupValue.ShouldBe(expectedGroupValue); + } + } + + [TestCase("[]", true)] + [TestCase("[]", true)] + [TestCase("[]", true)] + [TestCase("[]", false)] + [TestCase("[assembly: AssemblyVersion()]", false)] + public void FSharpAttributeRegex_MatchesExpected(string input, bool expectedMatch) + { + var regex = FSharp.AttributeRegex(); + var match = regex.Match(input); + match.Success.ShouldBe(expectedMatch); + } + } +} diff --git a/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs index 9609853812..86f6280cd8 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs @@ -215,7 +215,7 @@ public void CanSpecifyTagPrefixes() [Test] public void CanSpecifyTagPrefixesAsRegex() { - var configuration = GitFlowConfigurationBuilder.New.WithTagPrefixPattern($"version-|{RegexPatterns.Configuration.DefaultTagPrefixPattern}").Build(); + var configuration = GitFlowConfigurationBuilder.New.WithTagPrefixPattern($"version-|{RegexPatterns.Configuration.DefaultTagPrefixRegexPattern}").Build(); using var fixture = new EmptyRepositoryFixture(); var taggedVersion = "v1.0.3"; fixture.Repository.MakeATaggedCommit(taggedVersion); diff --git a/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs index ae8fdb55db..2d0279a15c 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs @@ -22,9 +22,9 @@ public class SemanticVersionTests : TestBase [TestCase("1.2.3+4.Branch.Foo", 1, 2, 3, "", null, 4, "Foo", null, null, null, null, SemanticVersionFormat.Strict)] [TestCase("1.2.3+randomMetaData", 1, 2, 3, "", null, null, null, null, "randomMetaData", null, null, SemanticVersionFormat.Strict)] [TestCase("1.2.3-beta.1+4.Sha.12234.Othershiz", 1, 2, 3, "beta", 1, 4, null, "12234", "Othershiz", null, null, SemanticVersionFormat.Strict)] - [TestCase("1.2.3", 1, 2, 3, "", null, null, null, null, null, null, RegexPatterns.Configuration.DefaultTagPrefixPattern, SemanticVersionFormat.Strict)] - [TestCase("v1.2.3", 1, 2, 3, "", null, null, null, null, null, "1.2.3", RegexPatterns.Configuration.DefaultTagPrefixPattern, SemanticVersionFormat.Strict)] - [TestCase("V1.2.3", 1, 2, 3, "", null, null, null, null, null, "1.2.3", RegexPatterns.Configuration.DefaultTagPrefixPattern, SemanticVersionFormat.Strict)] + [TestCase("1.2.3", 1, 2, 3, "", null, null, null, null, null, null, RegexPatterns.Configuration.DefaultTagPrefixRegexPattern, SemanticVersionFormat.Strict)] + [TestCase("v1.2.3", 1, 2, 3, "", null, null, null, null, null, "1.2.3", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern, SemanticVersionFormat.Strict)] + [TestCase("V1.2.3", 1, 2, 3, "", null, null, null, null, null, "1.2.3", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern, SemanticVersionFormat.Strict)] [TestCase("version-1.2.3", 1, 2, 3, "", null, null, null, null, null, "1.2.3", "version-", SemanticVersionFormat.Strict)] [TestCase("1.0.0-develop-20201007113711", 1, 0, 0, "develop-20201007113711", null, null, null, null, null, "1.0.0-develop-20201007113711", null, SemanticVersionFormat.Strict)] [TestCase("20201007113711.658165168461351.64136516984163213-develop-20201007113711.98848747823+65416321321", 20201007113711, 658165168461351, 64136516984163213, "develop-20201007113711", 98848747823, 65416321321, null, null, null, "20201007113711.658165168461351.64136516984163213-develop-20201007113711.98848747823+65416321321", null, SemanticVersionFormat.Strict)] @@ -62,7 +62,7 @@ public void ValidateVersionParsing( [TestCase("someText")] [TestCase("some-T-ext")] - [TestCase("v.1.2.3", RegexPatterns.Configuration.DefaultTagPrefixPattern)] + [TestCase("v.1.2.3", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern)] public void ValidateInvalidVersionParsing(string versionString, string? tagPrefixRegex = null) => Assert.That(SemanticVersion.TryParse(versionString, tagPrefixRegex, out _), Is.False, "TryParse Result"); diff --git a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs index bd16f1f2ba..4d72d3109a 100644 --- a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs +++ b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using GitVersion.Extensions; using GitVersion.VersionCalculation; @@ -100,6 +101,7 @@ public EffectiveConfiguration( public IncrementStrategy Increment { get; } + [StringSyntax(StringSyntaxAttribute.Regex)] public string? RegularExpression { get; } public bool PreventIncrementOfMergedBranch { get; } diff --git a/src/GitVersion.Core/Configuration/IBranchConfiguration.cs b/src/GitVersion.Core/Configuration/IBranchConfiguration.cs index 8a72789533..f3e6730ac2 100644 --- a/src/GitVersion.Core/Configuration/IBranchConfiguration.cs +++ b/src/GitVersion.Core/Configuration/IBranchConfiguration.cs @@ -1,5 +1,5 @@ +using System.Diagnostics.CodeAnalysis; using GitVersion.Core; -using GitVersion.Extensions; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; @@ -20,6 +20,7 @@ public interface IBranchConfiguration CommitMessageIncrementMode? CommitMessageIncrementing { get; } + [StringSyntax(StringSyntaxAttribute.Regex)] string? RegularExpression { get; } bool IsMatch(string branchName) diff --git a/src/GitVersion.Core/Configuration/ReferenceNameExtensions.cs b/src/GitVersion.Core/Configuration/ReferenceNameExtensions.cs index 214b42d7f1..9dda4c2521 100644 --- a/src/GitVersion.Core/Configuration/ReferenceNameExtensions.cs +++ b/src/GitVersion.Core/Configuration/ReferenceNameExtensions.cs @@ -47,7 +47,7 @@ private static bool TryGetSemanticVersion(this ReferenceName referenceName, out static string GetVersionInBranchPattern(string? versionInBranchPattern) { - if (versionInBranchPattern.IsNullOrEmpty()) versionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchPattern; + if (versionInBranchPattern.IsNullOrEmpty()) versionInBranchPattern = RegexPatterns.Configuration.DefaultVersionInBranchRegexPattern; return $"^{versionInBranchPattern.TrimStart('^')}"; } } diff --git a/src/GitVersion.Core/Core/RegexPatterns.cs b/src/GitVersion.Core/Core/RegexPatterns.cs index 2a41378836..a9ad425397 100644 --- a/src/GitVersion.Core/Core/RegexPatterns.cs +++ b/src/GitVersion.Core/Core/RegexPatterns.cs @@ -1,251 +1,318 @@ using System.Collections.Concurrent; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; namespace GitVersion.Core; -[SuppressMessage("Performance", "SYSLIB1045:Convert to \'GeneratedRegexAttribute\'.")] -internal static class RegexPatterns +internal static partial class RegexPatterns { private const RegexOptions Options = RegexOptions.IgnoreCase | RegexOptions.Compiled; - internal static readonly ConcurrentDictionary Cache = new(); - - static RegexPatterns() + public static class Cache { - Cache.TryAdd(Common.SwitchArgumentRegex.ToString(), Common.SwitchArgumentRegex); - Cache.TryAdd(Common.ObscurePasswordRegex.ToString(), Common.ObscurePasswordRegex); - Cache.TryAdd(Common.ExpandTokensRegex.ToString(), Common.ExpandTokensRegex); - - Cache.TryAdd(Configuration.DefaultTagPrefixRegex.ToString(), Configuration.DefaultTagPrefixRegex); - Cache.TryAdd(Configuration.DefaultVersionInBranchRegex.ToString(), Configuration.DefaultVersionInBranchRegex); - Cache.TryAdd(Configuration.MainBranchRegex.ToString(), Configuration.MainBranchRegex); - Cache.TryAdd(Configuration.DevelopBranchRegex.ToString(), Configuration.DevelopBranchRegex); - Cache.TryAdd(Configuration.ReleaseBranchRegex.ToString(), Configuration.ReleaseBranchRegex); - Cache.TryAdd(Configuration.FeatureBranchRegex.ToString(), Configuration.FeatureBranchRegex); - Cache.TryAdd(Configuration.PullRequestBranchRegex.ToString(), Configuration.PullRequestBranchRegex); - Cache.TryAdd(Configuration.HotfixBranchRegex.ToString(), Configuration.HotfixBranchRegex); - Cache.TryAdd(Configuration.SupportBranchRegex.ToString(), Configuration.SupportBranchRegex); - Cache.TryAdd(Configuration.UnknownBranchRegex.ToString(), Configuration.UnknownBranchRegex); - - Cache.TryAdd(MergeMessage.DefaultMergeMessageRegex.ToString(), MergeMessage.DefaultMergeMessageRegex); - Cache.TryAdd(MergeMessage.SmartGitMergeMessageRegex.ToString(), MergeMessage.SmartGitMergeMessageRegex); - Cache.TryAdd(MergeMessage.BitBucketPullMergeMessageRegex.ToString(), MergeMessage.BitBucketPullMergeMessageRegex); - Cache.TryAdd(MergeMessage.BitBucketPullv7MergeMessageRegex.ToString(), MergeMessage.BitBucketPullv7MergeMessageRegex); - Cache.TryAdd(MergeMessage.BitBucketCloudPullMergeMessageRegex.ToString(), MergeMessage.BitBucketCloudPullMergeMessageRegex); - Cache.TryAdd(MergeMessage.GitHubPullMergeMessageRegex.ToString(), MergeMessage.GitHubPullMergeMessageRegex); - Cache.TryAdd(MergeMessage.RemoteTrackingMergeMessageRegex.ToString(), MergeMessage.RemoteTrackingMergeMessageRegex); - Cache.TryAdd(MergeMessage.AzureDevOpsPullMergeMessageRegex.ToString(), MergeMessage.AzureDevOpsPullMergeMessageRegex); - - Cache.TryAdd(Output.AssemblyVersionRegex.ToString(), Output.AssemblyVersionRegex); - Cache.TryAdd(Output.AssemblyInfoVersionRegex.ToString(), Output.AssemblyInfoVersionRegex); - Cache.TryAdd(Output.AssemblyFileVersionRegex.ToString(), Output.AssemblyFileVersionRegex); - Cache.TryAdd(Output.CsharpAssemblyAttributeRegex.ToString(), Output.CsharpAssemblyAttributeRegex); - Cache.TryAdd(Output.FsharpAssemblyAttributeRegex.ToString(), Output.FsharpAssemblyAttributeRegex); - Cache.TryAdd(Output.VisualBasicAssemblyAttributeRegex.ToString(), Output.VisualBasicAssemblyAttributeRegex); - - Cache.TryAdd(VersionCalculation.DefaultMajorRegex.ToString(), VersionCalculation.DefaultMajorRegex); - Cache.TryAdd(VersionCalculation.DefaultMinorRegex.ToString(), VersionCalculation.DefaultMinorRegex); - Cache.TryAdd(VersionCalculation.DefaultPatchRegex.ToString(), VersionCalculation.DefaultPatchRegex); - Cache.TryAdd(VersionCalculation.DefaultNoBumpRegex.ToString(), VersionCalculation.DefaultNoBumpRegex); - - Cache.TryAdd(SemanticVersion.ParseStrictRegex.ToString(), SemanticVersion.ParseStrictRegex); - Cache.TryAdd(SemanticVersion.ParseLooseRegex.ToString(), SemanticVersion.ParseLooseRegex); - Cache.TryAdd(SemanticVersion.ParseBuildMetaDataRegex.ToString(), SemanticVersion.ParseBuildMetaDataRegex); - Cache.TryAdd(SemanticVersion.FormatBuildMetaDataRegex.ToString(), SemanticVersion.FormatBuildMetaDataRegex); - Cache.TryAdd(SemanticVersion.ParsePreReleaseTagRegex.ToString(), SemanticVersion.ParsePreReleaseTagRegex); - - Cache.TryAdd(AssemblyVersion.CSharp.TriviaRegex.ToString(), AssemblyVersion.CSharp.TriviaRegex); - Cache.TryAdd(AssemblyVersion.CSharp.AttributeRegex.ToString(), AssemblyVersion.CSharp.AttributeRegex); - Cache.TryAdd(AssemblyVersion.FSharp.TriviaRegex.ToString(), AssemblyVersion.FSharp.TriviaRegex); - Cache.TryAdd(AssemblyVersion.FSharp.AttributeRegex.ToString(), AssemblyVersion.FSharp.AttributeRegex); - Cache.TryAdd(AssemblyVersion.VisualBasic.TriviaRegex.ToString(), AssemblyVersion.VisualBasic.TriviaRegex); - Cache.TryAdd(AssemblyVersion.VisualBasic.AttributeRegex.ToString(), AssemblyVersion.VisualBasic.AttributeRegex); + private static readonly ConcurrentDictionary cache = new(); + + public static Regex GetOrAdd([StringSyntax(StringSyntaxAttribute.Regex)] string pattern) + { + ArgumentNullException.ThrowIfNull(pattern); + + return cache.GetOrAdd(pattern, key => + KnownRegexes.TryGetValue(key, out var factory) + ? factory() + : new Regex(key, Options)); + } + + private static readonly ImmutableDictionary> KnownRegexes = + new Dictionary> + { + [Common.SwitchArgumentRegexPattern] = Common.SwitchArgumentRegex, + [Common.ObscurePasswordRegexPattern] = Common.ObscurePasswordRegex, + [Common.ExpandTokensRegexPattern] = Common.ExpandTokensRegex, + [Configuration.DefaultTagPrefixRegexPattern] = Configuration.DefaultTagPrefixRegex, + [Configuration.DefaultVersionInBranchRegexPattern] = Configuration.DefaultVersionInBranchRegex, + [Configuration.MainBranchRegexPattern] = Configuration.MainBranchRegex, + [Configuration.DevelopBranchRegexPattern] = Configuration.DevelopBranchRegex, + [Configuration.ReleaseBranchRegexPattern] = Configuration.ReleaseBranchRegex, + [Configuration.FeatureBranchRegexPattern] = Configuration.FeatureBranchRegex, + [Configuration.PullRequestBranchRegexPattern] = Configuration.PullRequestBranchRegex, + [Configuration.HotfixBranchRegexPattern] = Configuration.HotfixBranchRegex, + [Configuration.SupportBranchRegexPattern] = Configuration.SupportBranchRegex, + [Configuration.UnknownBranchRegexPattern] = Configuration.UnknownBranchRegex, + [MergeMessage.DefaultMergeMessageRegexPattern] = MergeMessage.DefaultMergeMessageRegex, + [MergeMessage.SmartGitMergeMessageRegexPattern] = MergeMessage.SmartGitMergeMessageRegex, + [MergeMessage.BitBucketPullMergeMessageRegexPattern] = MergeMessage.BitBucketPullMergeMessageRegex, + [MergeMessage.BitBucketPullv7MergeMessageRegexPattern] = MergeMessage.BitBucketPullv7MergeMessageRegex, + [MergeMessage.BitBucketCloudPullMergeMessageRegexPattern] = MergeMessage.BitBucketCloudPullMergeMessageRegex, + [MergeMessage.GitHubPullMergeMessageRegexPattern] = MergeMessage.GitHubPullMergeMessageRegex, + [MergeMessage.RemoteTrackingMergeMessageRegexPattern] = MergeMessage.RemoteTrackingMergeMessageRegex, + [MergeMessage.AzureDevOpsPullMergeMessageRegexPattern] = MergeMessage.AzureDevOpsPullMergeMessageRegex, + [Output.AssemblyVersionRegexPattern] = Output.AssemblyVersionRegex, + [Output.AssemblyInfoVersionRegexPattern] = Output.AssemblyInfoVersionRegex, + [Output.AssemblyFileVersionRegexPattern] = Output.AssemblyFileVersionRegex, + [Output.CsharpAssemblyAttributeRegexPattern] = Output.CsharpAssemblyAttributeRegex, + [Output.FsharpAssemblyAttributeRegexPattern] = Output.FsharpAssemblyAttributeRegex, + [Output.VisualBasicAssemblyAttributeRegexPattern] = Output.VisualBasicAssemblyAttributeRegex, + [VersionCalculation.DefaultMajorRegexPattern] = VersionCalculation.DefaultMajorRegex, + [VersionCalculation.DefaultMinorRegexPattern] = VersionCalculation.DefaultMinorRegex, + [VersionCalculation.DefaultPatchRegexPattern] = VersionCalculation.DefaultPatchRegex, + [VersionCalculation.DefaultNoBumpRegexPattern] = VersionCalculation.DefaultNoBumpRegex, + [SemanticVersion.ParseStrictRegexPattern] = SemanticVersion.ParseStrictRegex, + [SemanticVersion.ParseLooseRegexPattern] = SemanticVersion.ParseLooseRegex, + [SemanticVersion.ParseBuildMetaDataRegexPattern] = SemanticVersion.ParseBuildMetaDataRegex, + [SemanticVersion.FormatBuildMetaDataRegexPattern] = SemanticVersion.FormatBuildMetaDataRegex, + [SemanticVersion.ParsePreReleaseTagRegexPattern] = SemanticVersion.ParsePreReleaseTagRegex, + [AssemblyVersion.CSharp.TriviaRegexPattern] = AssemblyVersion.CSharp.TriviaRegex, + [AssemblyVersion.CSharp.AttributeRegexPattern] = AssemblyVersion.CSharp.AttributeRegex, + [AssemblyVersion.FSharp.TriviaRegexPattern] = AssemblyVersion.FSharp.TriviaRegex, + // AssemblyVersion.FSharp.TriviaRegexPattern is same as C# so can't be added to the cache so C# TriviaRegex is used for F# as well. + [AssemblyVersion.FSharp.AttributeRegexPattern] = AssemblyVersion.FSharp.AttributeRegex, + [AssemblyVersion.VisualBasic.TriviaRegexPattern] = AssemblyVersion.VisualBasic.TriviaRegex, + [AssemblyVersion.VisualBasic.AttributeRegexPattern] = AssemblyVersion.VisualBasic.AttributeRegex + }.ToImmutableDictionary(); } - internal static class Common + internal static partial class Common { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string SwitchArgumentRegexPattern = @"/\w+:"; + internal const string SwitchArgumentRegexPattern = @"/\w+:"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string ObscurePasswordRegexPattern = "(https?://)(.+)(:.+@)"; + internal const string ObscurePasswordRegexPattern = "(https?://)(.+)(:.+@)"; - // this regex matches an expression to replace. - // - env:ENV name OR a member name - // - optional fallback value after " ?? " - // - the fallback value should be a quoted string, but simple unquoted text is allowed for back compat [StringSyntax(StringSyntaxAttribute.Regex)] - private const string ExpandTokensRegexPattern = """{((env:(?\w+))|(?\w+))(\s+(\?\?)??\s+((?\w+)|"(?.*)"))??}"""; + internal const string ExpandTokensRegexPattern = """{((env:(?\w+))|(?\w+))(\s+(\?\?)??\s+((?\w+)|"(?.*)"))??}"""; + + [GeneratedRegex(SwitchArgumentRegexPattern, Options)] + public static partial Regex SwitchArgumentRegex(); - public static Regex SwitchArgumentRegex { get; } = new(SwitchArgumentRegexPattern, Options); - public static Regex ObscurePasswordRegex { get; } = new(ObscurePasswordRegexPattern, Options); - public static Regex ExpandTokensRegex { get; } = new(ExpandTokensRegexPattern, Options); + [GeneratedRegex(ObscurePasswordRegexPattern, Options)] + public static partial Regex ObscurePasswordRegex(); + + [GeneratedRegex(ExpandTokensRegexPattern, Options)] + public static partial Regex ExpandTokensRegex(); } - internal static class Configuration + internal static partial class Configuration { [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DefaultTagPrefixPattern = "[vV]?"; + internal const string DefaultTagPrefixRegexPattern = "[vV]?"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DefaultVersionInBranchPattern = @"(?[vV]?\d+(\.\d+)?(\.\d+)?).*"; + internal const string DefaultVersionInBranchRegexPattern = @"(?[vV]?\d+(\.\d+)?(\.\d+)?).*"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string MainBranchRegexPattern = "^master$|^main$"; + internal const string MainBranchRegexPattern = "^master$|^main$"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DevelopBranchRegexPattern = "^dev(elop)?(ment)?$"; + internal const string DevelopBranchRegexPattern = "^dev(elop)?(ment)?$"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string ReleaseBranchRegexPattern = @"^releases?[\/-](?.+)"; + internal const string ReleaseBranchRegexPattern = @"^releases?[\/-](?.+)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string FeatureBranchRegexPattern = @"^features?[\/-](?.+)"; + internal const string FeatureBranchRegexPattern = @"^features?[\/-](?.+)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string PullRequestBranchRegexPattern = @"^(pull-requests|pull|pr)[\/-](?\d*)"; + internal const string PullRequestBranchRegexPattern = @"^(pull-requests|pull|pr)[\/-](?\d*)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string HotfixBranchRegexPattern = @"^hotfix(es)?[\/-](?.+)"; + internal const string HotfixBranchRegexPattern = @"^hotfix(es)?[\/-](?.+)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string SupportBranchRegexPattern = @"^support[\/-](?.+)"; + internal const string SupportBranchRegexPattern = @"^support[\/-](?.+)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string UnknownBranchRegexPattern = "(?.+)"; + internal const string UnknownBranchRegexPattern = "(?.+)"; + + [GeneratedRegex(DefaultTagPrefixRegexPattern, Options)] + public static partial Regex DefaultTagPrefixRegex(); - public static Regex DefaultTagPrefixRegex { get; } = new(DefaultTagPrefixPattern, Options); - public static Regex DefaultVersionInBranchRegex { get; } = new(DefaultVersionInBranchPattern, Options); - public static Regex MainBranchRegex { get; } = new(MainBranchRegexPattern, Options); - public static Regex DevelopBranchRegex { get; } = new(DevelopBranchRegexPattern, Options); - public static Regex ReleaseBranchRegex { get; } = new(ReleaseBranchRegexPattern, Options); - public static Regex FeatureBranchRegex { get; } = new(FeatureBranchRegexPattern, Options); - public static Regex PullRequestBranchRegex { get; } = new(PullRequestBranchRegexPattern, Options); - public static Regex HotfixBranchRegex { get; } = new(HotfixBranchRegexPattern, Options); - public static Regex SupportBranchRegex { get; } = new(SupportBranchRegexPattern, Options); - public static Regex UnknownBranchRegex { get; } = new(UnknownBranchRegexPattern, Options); + [GeneratedRegex(DefaultVersionInBranchRegexPattern, Options)] + public static partial Regex DefaultVersionInBranchRegex(); + + [GeneratedRegex(MainBranchRegexPattern, Options)] + public static partial Regex MainBranchRegex(); + + [GeneratedRegex(DevelopBranchRegexPattern, Options)] + public static partial Regex DevelopBranchRegex(); + + [GeneratedRegex(ReleaseBranchRegexPattern, Options)] + public static partial Regex ReleaseBranchRegex(); + + [GeneratedRegex(FeatureBranchRegexPattern, Options)] + public static partial Regex FeatureBranchRegex(); + + [GeneratedRegex(PullRequestBranchRegexPattern, Options)] + public static partial Regex PullRequestBranchRegex(); + + [GeneratedRegex(HotfixBranchRegexPattern, Options)] + public static partial Regex HotfixBranchRegex(); + + [GeneratedRegex(SupportBranchRegexPattern, Options)] + public static partial Regex SupportBranchRegex(); + + [GeneratedRegex(UnknownBranchRegexPattern, Options)] + public static partial Regex UnknownBranchRegex(); } - internal static class MergeMessage + internal static partial class MergeMessage { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string DefaultMergeMessageRegexPattern = @"^Merge (branch|tag) '(?[^']*)'(?: into (?[^\s]*))*"; + internal const string DefaultMergeMessageRegexPattern = @"^Merge (branch|tag) '(?[^']*)'(?: into (?[^\s]*))*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string SmartGitMergeMessageRegexPattern = @"^Finish (?[^\s]*)(?: into (?[^\s]*))*"; + internal const string SmartGitMergeMessageRegexPattern = @"^Finish (?[^\s]*)(?: into (?[^\s]*))*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string BitBucketPullMergeMessageRegexPattern = @"^Merge pull request #(?\d+) (from|in) (?.*) from (?[^\s]*) to (?[^\s]*)"; + internal const string BitBucketPullMergeMessageRegexPattern = @"^Merge pull request #(?\d+) (from|in) (?.*) from (?[^\s]*) to (?[^\s]*)"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string BitBucketPullv7MergeMessageRegexPattern = @"^Pull request #(?\d+).*\r?\n\r?\nMerge in (?.*) from (?[^\s]*) to (?[^\s]*)"; + internal const string BitBucketPullv7MergeMessageRegexPattern = @"^Pull request #(?\d+).*\r?\n\r?\nMerge in (?.*) from (?[^\s]*) to (?[^\s]*)"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string BitBucketCloudPullMergeMessageRegexPattern = @"^Merged in (?[^\s]*) \(pull request #(?\d+)\)"; + internal const string BitBucketCloudPullMergeMessageRegexPattern = @"^Merged in (?[^\s]*) \(pull request #(?\d+)\)"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string GitHubPullMergeMessageRegexPattern = @"^Merge pull request #(?\d+) (from|in) (?:[^\s\/]+\/)?(?[^\s]*)(?: into (?[^\s]*))*"; + internal const string GitHubPullMergeMessageRegexPattern = @"^Merge pull request #(?\d+) (from|in) (?:[^\s\/]+\/)?(?[^\s]*)(?: into (?[^\s]*))*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string RemoteTrackingMergeMessageRegexPattern = @"^Merge remote-tracking branch '(?[^\s]*)'(?: into (?[^\s]*))*"; + internal const string RemoteTrackingMergeMessageRegexPattern = @"^Merge remote-tracking branch '(?[^\s]*)'(?: into (?[^\s]*))*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AzureDevOpsPullMergeMessageRegexPattern = @"^Merge pull request (?\d+) from (?[^\s]*) into (?[^\s]*)"; + internal const string AzureDevOpsPullMergeMessageRegexPattern = @"^Merge pull request (?\d+) from (?[^\s]*) into (?[^\s]*)"; + + [GeneratedRegex(DefaultMergeMessageRegexPattern, Options)] + public static partial Regex DefaultMergeMessageRegex(); - public static Regex DefaultMergeMessageRegex { get; } = new(DefaultMergeMessageRegexPattern, Options); - public static Regex SmartGitMergeMessageRegex { get; } = new(SmartGitMergeMessageRegexPattern, Options); - public static Regex BitBucketPullMergeMessageRegex { get; } = new(BitBucketPullMergeMessageRegexPattern, Options); - public static Regex BitBucketPullv7MergeMessageRegex { get; } = new(BitBucketPullv7MergeMessageRegexPattern, Options); - public static Regex BitBucketCloudPullMergeMessageRegex { get; } = new(BitBucketCloudPullMergeMessageRegexPattern, Options); - public static Regex GitHubPullMergeMessageRegex { get; } = new(GitHubPullMergeMessageRegexPattern, Options); - public static Regex RemoteTrackingMergeMessageRegex { get; } = new(RemoteTrackingMergeMessageRegexPattern, Options); - public static Regex AzureDevOpsPullMergeMessageRegex { get; } = new(AzureDevOpsPullMergeMessageRegexPattern, Options); + [GeneratedRegex(SmartGitMergeMessageRegexPattern, Options)] + public static partial Regex SmartGitMergeMessageRegex(); + + [GeneratedRegex(BitBucketPullMergeMessageRegexPattern, Options)] + public static partial Regex BitBucketPullMergeMessageRegex(); + + [GeneratedRegex(BitBucketPullv7MergeMessageRegexPattern, Options)] + public static partial Regex BitBucketPullv7MergeMessageRegex(); + + [GeneratedRegex(BitBucketCloudPullMergeMessageRegexPattern, Options)] + public static partial Regex BitBucketCloudPullMergeMessageRegex(); + + [GeneratedRegex(GitHubPullMergeMessageRegexPattern, Options)] + public static partial Regex GitHubPullMergeMessageRegex(); + + [GeneratedRegex(RemoteTrackingMergeMessageRegexPattern, Options)] + public static partial Regex RemoteTrackingMergeMessageRegex(); + + [GeneratedRegex(AzureDevOpsPullMergeMessageRegexPattern, Options)] + public static partial Regex AzureDevOpsPullMergeMessageRegex(); } - internal static class Output + internal static partial class Output { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AssemblyVersionRegexPattern = @"AssemblyVersion(Attribute)?\s*\(.*\)\s*"; + internal const string AssemblyVersionRegexPattern = @"AssemblyVersion(Attribute)?\s*\(.*\)\s*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AssemblyInfoVersionRegexPattern = @"AssemblyInformationalVersion(Attribute)?\s*\(.*\)\s*"; + internal const string AssemblyInfoVersionRegexPattern = @"AssemblyInformationalVersion(Attribute)?\s*\(.*\)\s*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AssemblyFileVersionRegexPattern = @"AssemblyFileVersion(Attribute)?\s*\(.*\)\s*"; + internal const string AssemblyFileVersionRegexPattern = @"AssemblyFileVersion(Attribute)?\s*\(.*\)\s*"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string CsharpAssemblyAttributeRegexPattern = @"(\s*\[\s*assembly:\s*(?:.*)\s*\]\s*$(\r?\n)?)"; + internal const string CsharpAssemblyAttributeRegexPattern = @"(\s*\[\s*assembly:\s*(?:.*)\s*\]\s*$(\r?\n)?)"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string FsharpAssemblyAttributeRegexPattern = @"(\s*\[\s*\\s*\]\s*$(\r?\n)?)"; + internal const string FsharpAssemblyAttributeRegexPattern = @"(\s*\[\s*\\s*\]\s*$(\r?\n)?)"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string VisualBasicAssemblyAttributeRegexPattern = @"(\s*\\s*$(\r?\n)?)"; + internal const string VisualBasicAssemblyAttributeRegexPattern = @"(\s*\\s*$(\r?\n)?)"; + + [GeneratedRegex(AssemblyVersionRegexPattern, Options)] + public static partial Regex AssemblyVersionRegex(); + + [GeneratedRegex(AssemblyInfoVersionRegexPattern, Options)] + public static partial Regex AssemblyInfoVersionRegex(); + + [GeneratedRegex(AssemblyFileVersionRegexPattern, Options)] + public static partial Regex AssemblyFileVersionRegex(); - public static Regex AssemblyVersionRegex { get; } = new(AssemblyVersionRegexPattern, Options); - public static Regex AssemblyInfoVersionRegex { get; } = new(AssemblyInfoVersionRegexPattern, Options); - public static Regex AssemblyFileVersionRegex { get; } = new(AssemblyFileVersionRegexPattern, Options); - public static Regex CsharpAssemblyAttributeRegex { get; } = new(CsharpAssemblyAttributeRegexPattern, Options | RegexOptions.Multiline); - public static Regex FsharpAssemblyAttributeRegex { get; } = new(FsharpAssemblyAttributeRegexPattern, Options | RegexOptions.Multiline); - public static Regex VisualBasicAssemblyAttributeRegex { get; } = new(VisualBasicAssemblyAttributeRegexPattern, Options | RegexOptions.Multiline); + [GeneratedRegex(CsharpAssemblyAttributeRegexPattern, Options | RegexOptions.Multiline)] + public static partial Regex CsharpAssemblyAttributeRegex(); + + [GeneratedRegex(FsharpAssemblyAttributeRegexPattern, Options | RegexOptions.Multiline)] + public static partial Regex FsharpAssemblyAttributeRegex(); + + [GeneratedRegex(VisualBasicAssemblyAttributeRegexPattern, Options | RegexOptions.Multiline)] + public static partial Regex VisualBasicAssemblyAttributeRegex(); } - internal static class VersionCalculation + internal static partial class VersionCalculation { [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DefaultMajorPattern = @"\+semver:\s?(breaking|major)"; + internal const string DefaultMajorRegexPattern = @"\+semver:\s?(breaking|major)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DefaultMinorPattern = @"\+semver:\s?(feature|minor)"; + internal const string DefaultMinorRegexPattern = @"\+semver:\s?(feature|minor)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DefaultPatchPattern = @"\+semver:\s?(fix|patch)"; + internal const string DefaultPatchRegexPattern = @"\+semver:\s?(fix|patch)"; [StringSyntax(StringSyntaxAttribute.Regex)] - public const string DefaultNoBumpPattern = @"\+semver:\s?(none|skip)"; + internal const string DefaultNoBumpRegexPattern = @"\+semver:\s?(none|skip)"; + + [GeneratedRegex(DefaultMajorRegexPattern, Options)] + public static partial Regex DefaultMajorRegex(); + + [GeneratedRegex(DefaultMinorRegexPattern, Options)] + public static partial Regex DefaultMinorRegex(); - public static Regex DefaultMajorRegex { get; } = new(DefaultMajorPattern, Options); - public static Regex DefaultMinorRegex { get; } = new(DefaultMinorPattern, Options); - public static Regex DefaultPatchRegex { get; } = new(DefaultPatchPattern, Options); - public static Regex DefaultNoBumpRegex { get; } = new(DefaultNoBumpPattern, Options); + [GeneratedRegex(DefaultPatchRegexPattern, Options)] + public static partial Regex DefaultPatchRegex(); + + [GeneratedRegex(DefaultNoBumpRegexPattern, Options)] + public static partial Regex DefaultNoBumpRegex(); } - internal static class SemanticVersion + internal static partial class SemanticVersion { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string ParseStrictRegexPattern = @"^(?0|[1-9]\d*)\.(?0|[1-9]\d*)\.(?0|[1-9]\d*)(?:-(?(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"; + internal const string ParseStrictRegexPattern = @"^(?0|[1-9]\d*)\.(?0|[1-9]\d*)\.(?0|[1-9]\d*)(?:-(?(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string ParseLooseRegexPattern = @"^(?(?\d+)(\.(?\d+))?(\.(?\d+))?)(\.(?\d+))?(-(?[^\+]*))?(\+(?.*))?$"; + internal const string ParseLooseRegexPattern = @"^(?(?\d+)(\.(?\d+))?(\.(?\d+))?)(\.(?\d+))?(-(?[^\+]*))?(\+(?.*))?$"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string ParseBuildMetaDataRegexPattern = @"(?\d+)?(\.?Branch(Name)?\.(?[^\.]+))?(\.?Sha?\.(?[^\.]+))?(?.*)"; + internal const string ParseBuildMetaDataRegexPattern = @"(?\d+)?(\.?Branch(Name)?\.(?[^\.]+))?(\.?Sha?\.(?[^\.]+))?(?.*)"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string FormatBuildMetaDataRegexPattern = "[^0-9A-Za-z-.]"; + internal const string FormatBuildMetaDataRegexPattern = "[^0-9A-Za-z-.]"; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string ParsePreReleaseTagRegexPattern = @"(?.*?)\.?(?\d+)?$"; + internal const string ParsePreReleaseTagRegexPattern = @"(?.*?)\.?(?\d+)?$"; // uses the git-semver spec https://github.com/semver/semver/blob/master/semver.md - public static Regex ParseStrictRegex { get; } = new(ParseStrictRegexPattern, Options); + [GeneratedRegex(ParseStrictRegexPattern, Options)] + public static partial Regex ParseStrictRegex(); - public static Regex ParseLooseRegex { get; } = new(ParseLooseRegexPattern, Options); + [GeneratedRegex(ParseLooseRegexPattern, Options)] + public static partial Regex ParseLooseRegex(); - public static Regex ParseBuildMetaDataRegex { get; } = new(ParseBuildMetaDataRegexPattern, Options); + [GeneratedRegex(ParseBuildMetaDataRegexPattern, Options)] + public static partial Regex ParseBuildMetaDataRegex(); - public static Regex FormatBuildMetaDataRegex { get; } = new(FormatBuildMetaDataRegexPattern, Options); + [GeneratedRegex(FormatBuildMetaDataRegexPattern, Options)] + public static partial Regex FormatBuildMetaDataRegex(); - public static Regex ParsePreReleaseTagRegex { get; } = new(ParsePreReleaseTagRegexPattern, Options); + [GeneratedRegex(ParsePreReleaseTagRegexPattern, Options)] + public static partial Regex ParsePreReleaseTagRegex(); } - internal static class AssemblyVersion + internal static partial class AssemblyVersion { - internal static class CSharp + internal static partial class CSharp { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string TriviaRegexPattern = + internal const string TriviaRegexPattern = """ /\*(.*?)\*/ # Block comments: matches /* ... */ |//(.*?)\r?\n # Line comments: matches // ... followed by a newline @@ -253,7 +320,7 @@ internal static class CSharp """; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AttributeRegexPattern = + internal const string AttributeRegexPattern = """ (?x) # IgnorePatternWhitespace \[\s*assembly\s*:\s* # The [assembly: part @@ -262,14 +329,17 @@ internal static class CSharp \s*\(\s*\)\s*\] # End brackets ()] """; - public static Regex TriviaRegex { get; } = new(TriviaRegexPattern, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | Options); - public static Regex AttributeRegex { get; } = new(AttributeRegexPattern, RegexOptions.IgnorePatternWhitespace | Options); + [GeneratedRegex(TriviaRegexPattern, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | Options)] + public static partial Regex TriviaRegex(); + + [GeneratedRegex(AttributeRegexPattern, RegexOptions.IgnorePatternWhitespace | Options)] + public static partial Regex AttributeRegex(); } - internal static class FSharp + internal static partial class FSharp { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string TriviaRegexPattern = + internal const string TriviaRegexPattern = """ /\*(.*?)\*/ # Block comments: matches /* ... */ |//(.*?)\r?\n # Line comments: matches // ... followed by a newline @@ -277,7 +347,7 @@ internal static class FSharp """; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AttributeRegexPattern = + internal const string AttributeRegexPattern = """ (?x) # IgnorePatternWhitespace \[\s*<\s*assembly\s*:\s* # The [\s*\] # End brackets ()>] """; - public static Regex TriviaRegex { get; } = new(TriviaRegexPattern, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | Options); - public static Regex AttributeRegex { get; } = new(AttributeRegexPattern, RegexOptions.IgnorePatternWhitespace | Options); + /// + /// Note that while available to call direct, as the C# TriviaRegex is the same it will handle any calls through the cache for F# too. + /// + /// + [GeneratedRegex(TriviaRegexPattern, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | Options)] + public static partial Regex TriviaRegex(); + + [GeneratedRegex(AttributeRegexPattern, RegexOptions.IgnorePatternWhitespace | Options)] + public static partial Regex AttributeRegex(); } - internal static class VisualBasic + internal static partial class VisualBasic { [StringSyntax(StringSyntaxAttribute.Regex)] - private const string TriviaRegexPattern = + internal const string TriviaRegexPattern = """ '(.*?)\r?\n # Line comments: matches // ... followed by a newline |"((\\[^\n]|[^"\n])*)" # Strings: matches " ... " including escaped quotes """; [StringSyntax(StringSyntaxAttribute.Regex)] - private const string AttributeRegexPattern = + internal const string AttributeRegexPattern = """ (?x) # IgnorePatternWhitespace \<\s*Assembly\s*:\s* # The # End brackets ()> """; - public static Regex TriviaRegex { get; } = new(TriviaRegexPattern, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | Options); - public static Regex AttributeRegex { get; } = new(AttributeRegexPattern, RegexOptions.IgnorePatternWhitespace | Options); + [GeneratedRegex(TriviaRegexPattern, RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | Options)] + public static partial Regex TriviaRegex(); + + [GeneratedRegex(AttributeRegexPattern, RegexOptions.IgnorePatternWhitespace | Options)] + public static partial Regex AttributeRegex(); } } } diff --git a/src/GitVersion.Core/Extensions/DictionaryExtensions.cs b/src/GitVersion.Core/Extensions/DictionaryExtensions.cs index 4f5c670692..02f0f28a66 100644 --- a/src/GitVersion.Core/Extensions/DictionaryExtensions.cs +++ b/src/GitVersion.Core/Extensions/DictionaryExtensions.cs @@ -1,12 +1,8 @@ -using System.Collections.Concurrent; -using System.Diagnostics.CodeAnalysis; -using System.Text.RegularExpressions; - namespace GitVersion.Extensions; -public static class DictionaryExtensions +internal static class DictionaryExtensions { - public static TValue GetOrAdd(this Dictionary dict, TKey key, Func getValue) where TKey : notnull + internal static TValue GetOrAdd(this Dictionary dict, TKey key, Func getValue) where TKey : notnull { ArgumentNullException.ThrowIfNull(dict); ArgumentNullException.ThrowIfNull(getValue); @@ -16,12 +12,4 @@ public static TValue GetOrAdd(this Dictionary dict, dict.Add(key, value); return value; } - - public static Regex GetOrAdd(this ConcurrentDictionary dict, [StringSyntax(StringSyntaxAttribute.Regex)] string pattern) - { - ArgumentNullException.ThrowIfNull(dict); - ArgumentNullException.ThrowIfNull(pattern); - - return dict.GetOrAdd(pattern, regex => new(regex, RegexOptions.IgnoreCase | RegexOptions.Compiled)); - } } diff --git a/src/GitVersion.Core/Helpers/StringFormatWith.cs b/src/GitVersion.Core/Helpers/StringFormatWith.cs index 03a84ae3c8..d36d5df01d 100644 --- a/src/GitVersion.Core/Helpers/StringFormatWith.cs +++ b/src/GitVersion.Core/Helpers/StringFormatWith.cs @@ -33,7 +33,7 @@ public static string FormatWith(this string template, T? source, IEnvironment ArgumentNullException.ThrowIfNull(template); ArgumentNullException.ThrowIfNull(source); - foreach (var match in RegexPatterns.Common.ExpandTokensRegex.Matches(template).Cast()) + foreach (var match in RegexPatterns.Common.ExpandTokensRegex().Matches(template).Cast()) { string propertyValue; var fallback = match.Groups["fallback"].Success ? match.Groups["fallback"].Value : null; diff --git a/src/GitVersion.Core/Logging/Log.cs b/src/GitVersion.Core/Logging/Log.cs index d5dc15e39b..23459c4b1c 100644 --- a/src/GitVersion.Core/Logging/Log.cs +++ b/src/GitVersion.Core/Logging/Log.cs @@ -58,7 +58,7 @@ public IDisposable IndentLog(string operationDescription) private string FormatMessage(string message, string level) { - var obscuredMessage = RegexPatterns.Common.ObscurePasswordRegex.Replace(message, "$1$2:*******@"); + var obscuredMessage = RegexPatterns.Common.ObscurePasswordRegex().Replace(message, "$1$2:*******@"); var timestamp = $"{DateTime.Now:yy-MM-dd H:mm:ss:ff}"; return string.Format(CultureInfo.InvariantCulture, "{0}{1} [{2}] {3}", this.currentIndentation, level, timestamp, obscuredMessage); } diff --git a/src/GitVersion.Core/MergeMessage.cs b/src/GitVersion.Core/MergeMessage.cs index 8d195f1b22..345a9b1c8b 100644 --- a/src/GitVersion.Core/MergeMessage.cs +++ b/src/GitVersion.Core/MergeMessage.cs @@ -11,14 +11,14 @@ public class MergeMessage { private static readonly IList<(string Name, Regex Pattern)> DefaultFormats = [ - new("Default", RegexPatterns.MergeMessage.DefaultMergeMessageRegex), - new("SmartGit", RegexPatterns.MergeMessage.SmartGitMergeMessageRegex), - new("BitBucketPull", RegexPatterns.MergeMessage.BitBucketPullMergeMessageRegex), - new("BitBucketPullv7", RegexPatterns.MergeMessage.BitBucketPullv7MergeMessageRegex), - new("BitBucketCloudPull", RegexPatterns.MergeMessage.BitBucketCloudPullMergeMessageRegex), - new("GitHubPull", RegexPatterns.MergeMessage.GitHubPullMergeMessageRegex), - new("RemoteTracking", RegexPatterns.MergeMessage.RemoteTrackingMergeMessageRegex), - new("AzureDevOpsPull", RegexPatterns.MergeMessage.AzureDevOpsPullMergeMessageRegex) + new("Default", RegexPatterns.MergeMessage.DefaultMergeMessageRegex()), + new("SmartGit", RegexPatterns.MergeMessage.SmartGitMergeMessageRegex()), + new("BitBucketPull", RegexPatterns.MergeMessage.BitBucketPullMergeMessageRegex()), + new("BitBucketPullv7", RegexPatterns.MergeMessage.BitBucketPullv7MergeMessageRegex()), + new("BitBucketCloudPull", RegexPatterns.MergeMessage.BitBucketCloudPullMergeMessageRegex()), + new("GitHubPull", RegexPatterns.MergeMessage.GitHubPullMergeMessageRegex()), + new("RemoteTracking", RegexPatterns.MergeMessage.RemoteTrackingMergeMessageRegex()), + new("AzureDevOpsPull", RegexPatterns.MergeMessage.AzureDevOpsPullMergeMessageRegex()) ]; public MergeMessage(string mergeMessage, IGitVersionConfiguration configuration) diff --git a/src/GitVersion.Core/PublicAPI.Shipped.txt b/src/GitVersion.Core/PublicAPI.Shipped.txt index 27793f8f08..ef124b7b64 100644 --- a/src/GitVersion.Core/PublicAPI.Shipped.txt +++ b/src/GitVersion.Core/PublicAPI.Shipped.txt @@ -154,7 +154,6 @@ GitVersion.ConfigurationInfo.OverrideConfiguration -> System.Collections.Generic GitVersion.ConfigurationInfo.ShowConfiguration -> bool GitVersion.Extensions.AssemblyVersionsGeneratorExtensions GitVersion.Extensions.CommonExtensions -GitVersion.Extensions.DictionaryExtensions GitVersion.Extensions.EnumerableExtensions GitVersion.Extensions.FileSystemExtensions GitVersion.Extensions.GitExtensions @@ -730,8 +729,6 @@ static GitVersion.Extensions.AssemblyVersionsGeneratorExtensions.GetAssemblyVers static GitVersion.Extensions.CommonExtensions.NotNull(this T? value, string! name = "") -> T! static GitVersion.Extensions.CommonExtensions.NotNullOrEmpty(this string? value, string! name = "") -> string! static GitVersion.Extensions.CommonExtensions.NotNullOrWhitespace(this string? value, string! name = "") -> string! -static GitVersion.Extensions.DictionaryExtensions.GetOrAdd(this System.Collections.Concurrent.ConcurrentDictionary! dict, string! pattern) -> System.Text.RegularExpressions.Regex! -static GitVersion.Extensions.DictionaryExtensions.GetOrAdd(this System.Collections.Generic.Dictionary! dict, TKey key, System.Func! getValue) -> TValue static GitVersion.Extensions.EnumerableExtensions.AddRange(this System.Collections.Generic.ICollection! source, System.Collections.Generic.IEnumerable! items) -> void static GitVersion.Extensions.EnumerableExtensions.OnlyOrDefault(this System.Collections.Generic.IEnumerable! source) -> T? static GitVersion.Extensions.EnumerableExtensions.SingleOfType(this System.Collections.IEnumerable! source) -> T diff --git a/src/GitVersion.Core/SemVer/SemanticVersion.cs b/src/GitVersion.Core/SemVer/SemanticVersion.cs index cab2f2cb3b..eb421e36c7 100644 --- a/src/GitVersion.Core/SemVer/SemanticVersion.cs +++ b/src/GitVersion.Core/SemVer/SemanticVersion.cs @@ -149,7 +149,7 @@ public static bool TryParse(string version, string? tagPrefixRegex, private static bool TryParseStrict(string version, [NotNullWhen(true)] out SemanticVersion? semanticVersion) { - var parsed = RegexPatterns.SemanticVersion.ParseStrictRegex.Match(version); + var parsed = RegexPatterns.SemanticVersion.ParseStrictRegex().Match(version); if (!parsed.Success) { @@ -171,7 +171,7 @@ private static bool TryParseStrict(string version, [NotNullWhen(true)] out Seman private static bool TryParseLoose(string version, [NotNullWhen(true)] out SemanticVersion? semanticVersion) { - var parsed = RegexPatterns.SemanticVersion.ParseLooseRegex.Match(version); + var parsed = RegexPatterns.SemanticVersion.ParseLooseRegex().Match(version); if (!parsed.Success) { diff --git a/src/GitVersion.Core/SemVer/SemanticVersionBuildMetaData.cs b/src/GitVersion.Core/SemVer/SemanticVersionBuildMetaData.cs index 5ae4086543..88f2fc658a 100644 --- a/src/GitVersion.Core/SemVer/SemanticVersionBuildMetaData.cs +++ b/src/GitVersion.Core/SemVer/SemanticVersionBuildMetaData.cs @@ -111,7 +111,7 @@ public static SemanticVersionBuildMetaData Parse(string? buildMetaData) if (buildMetaData.IsNullOrEmpty()) return Empty; - var parsed = RegexPatterns.SemanticVersion.ParseBuildMetaDataRegex.Match(buildMetaData); + var parsed = RegexPatterns.SemanticVersion.ParseBuildMetaDataRegex().Match(buildMetaData); long? buildMetaDataCommitsSinceTag = null; long? buildMetaDataCommitsSinceVersionSource = null; @@ -147,7 +147,7 @@ public static SemanticVersionBuildMetaData Parse(string? buildMetaData) private static string FormatMetaDataPart(string value) { if (!value.IsNullOrEmpty()) - value = RegexPatterns.SemanticVersion.FormatBuildMetaDataRegex.Replace(value, "-"); + value = RegexPatterns.SemanticVersion.FormatBuildMetaDataRegex().Replace(value, "-"); return value; } } diff --git a/src/GitVersion.Core/SemVer/SemanticVersionPreReleaseTag.cs b/src/GitVersion.Core/SemVer/SemanticVersionPreReleaseTag.cs index 5244c32240..30dc819449 100644 --- a/src/GitVersion.Core/SemVer/SemanticVersionPreReleaseTag.cs +++ b/src/GitVersion.Core/SemVer/SemanticVersionPreReleaseTag.cs @@ -70,7 +70,7 @@ public static SemanticVersionPreReleaseTag Parse(string? preReleaseTag) { if (preReleaseTag.IsNullOrEmpty()) return Empty; - var match = RegexPatterns.SemanticVersion.ParsePreReleaseTagRegex.Match(preReleaseTag); + var match = RegexPatterns.SemanticVersion.ParsePreReleaseTagRegex().Match(preReleaseTag); if (!match.Success) { // TODO check how to log this diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index 98c51fe60c..8b08f0869b 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -47,10 +47,10 @@ public VersionField DetermineIncrementedField( { commits.NotNull(); - var majorRegex = TryGetRegexOrDefault(configuration.MajorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMajorRegex); - var minorRegex = TryGetRegexOrDefault(configuration.MinorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMinorRegex); - var patchRegex = TryGetRegexOrDefault(configuration.PatchVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultPatchRegex); - var noBumpRegex = TryGetRegexOrDefault(configuration.NoBumpMessage, RegexPatterns.VersionCalculation.DefaultNoBumpRegex); + var majorRegex = TryGetRegexOrDefault(configuration.MajorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMajorRegex()); + var minorRegex = TryGetRegexOrDefault(configuration.MinorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMinorRegex()); + var patchRegex = TryGetRegexOrDefault(configuration.PatchVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultPatchRegex()); + var noBumpRegex = TryGetRegexOrDefault(configuration.NoBumpMessage, RegexPatterns.VersionCalculation.DefaultNoBumpRegex()); var increments = commits .Select(c => GetIncrementFromCommit(c, majorRegex, minorRegex, patchRegex, noBumpRegex)) @@ -207,10 +207,10 @@ public VersionField GetIncrementForcedByCommit(ICommit commit, IGitVersionConfig commit.NotNull(); configuration.NotNull(); - var majorRegex = TryGetRegexOrDefault(configuration.MajorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMajorRegex); - var minorRegex = TryGetRegexOrDefault(configuration.MinorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMinorRegex); - var patchRegex = TryGetRegexOrDefault(configuration.PatchVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultPatchRegex); - var none = TryGetRegexOrDefault(configuration.NoBumpMessage, RegexPatterns.VersionCalculation.DefaultNoBumpRegex); + var majorRegex = TryGetRegexOrDefault(configuration.MajorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMajorRegex()); + var minorRegex = TryGetRegexOrDefault(configuration.MinorVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultMinorRegex()); + var patchRegex = TryGetRegexOrDefault(configuration.PatchVersionBumpMessage, RegexPatterns.VersionCalculation.DefaultPatchRegex()); + var none = TryGetRegexOrDefault(configuration.NoBumpMessage, RegexPatterns.VersionCalculation.DefaultNoBumpRegex()); return GetIncrementFromCommit(commit, majorRegex, minorRegex, patchRegex, none) ?? VersionField.None; } diff --git a/src/GitVersion.MsBuild/Helpers/AssemblyInfoFileHelper.cs b/src/GitVersion.MsBuild/Helpers/AssemblyInfoFileHelper.cs index a61c6797e6..5f96caead6 100644 --- a/src/GitVersion.MsBuild/Helpers/AssemblyInfoFileHelper.cs +++ b/src/GitVersion.MsBuild/Helpers/AssemblyInfoFileHelper.cs @@ -44,9 +44,9 @@ private static bool FileContainsVersionAttribute(IFileSystem fileSystem, string var (attributeRegex, triviaRegex) = compileFileExtension switch { - ".cs" => (CSharp.AttributeRegex, CSharp.TriviaRegex), - ".fs" => (FSharp.AttributeRegex, FSharp.TriviaRegex), - ".vb" => (VisualBasic.AttributeRegex, VisualBasic.TriviaRegex), + ".cs" => (CSharp.AttributeRegex(), CSharp.TriviaRegex()), + ".fs" => (FSharp.AttributeRegex(), FSharp.TriviaRegex()), + ".vb" => (VisualBasic.AttributeRegex(), VisualBasic.TriviaRegex()), _ => throw new WarningException("File with name containing AssemblyInfo could not be checked for assembly version attributes which conflict with the attributes generated by GitVersion " + compileFile) }; diff --git a/src/GitVersion.Output.Tests/Output/AssemblyInfoFileUpdaterTests.cs b/src/GitVersion.Output.Tests/Output/AssemblyInfoFileUpdaterTests.cs index 69cac98f45..3b05e42d85 100644 --- a/src/GitVersion.Output.Tests/Output/AssemblyInfoFileUpdaterTests.cs +++ b/src/GitVersion.Output.Tests/Output/AssemblyInfoFileUpdaterTests.cs @@ -46,7 +46,7 @@ public void ShouldCreateAssemblyInfoFileWhenNotExistsAndEnsureAssemblyInfo(strin var fullPath = FileSystemHelper.Path.Combine(workingDir, assemblyInfoFile); var variables = this.variableProvider.GetVariablesFor( - SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0); + SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0); using var assemblyInfoFileUpdater = new AssemblyInfoFileUpdater(this.log, this.fileSystem); assemblyInfoFileUpdater.Execute(variables, new(workingDir, true, assemblyInfoFile)); @@ -62,7 +62,7 @@ public void ShouldCreateAssemblyInfoFileAtPathWhenNotExistsAndEnsureAssemblyInfo var assemblyInfoFile = FileSystemHelper.Path.Combine("src", "Project", "Properties", $"VersionAssemblyInfo.{fileExtension}"); var fullPath = FileSystemHelper.Path.Combine(workingDir, assemblyInfoFile); var variables = this.variableProvider.GetVariablesFor( - SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0 + SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0 ); using var assemblyInfoFileUpdater = new AssemblyInfoFileUpdater(this.log, this.fileSystem); @@ -77,7 +77,7 @@ public void ShouldCreateAssemblyInfoFileAtPathWhenNotExistsAndEnsureAssemblyInfo public void ShouldCreateAssemblyInfoFilesAtPathWhenNotExistsAndEnsureAssemblyInfo(string fileExtension) { var assemblyInfoFiles = new HashSet { "AssemblyInfo." + fileExtension, FileSystemHelper.Path.Combine("src", "Project", "Properties", "VersionAssemblyInfo." + fileExtension) }; - var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0); + var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0); using var assemblyInfoFileUpdater = new AssemblyInfoFileUpdater(this.log, this.fileSystem); assemblyInfoFileUpdater.Execute(variables, new(workingDir, true, [.. assemblyInfoFiles])); @@ -97,7 +97,7 @@ public void ShouldNotCreateAssemblyInfoFileWhenNotExistsAndNotEnsureAssemblyInfo var assemblyInfoFile = "NoVersionAssemblyInfo." + fileExtension; var fullPath = FileSystemHelper.Path.Combine(workingDir, assemblyInfoFile); var variables = this.variableProvider.GetVariablesFor( - SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0 + SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0 ); using var assemblyInfoFileUpdater = new AssemblyInfoFileUpdater(this.log, this.fileSystem); @@ -114,7 +114,7 @@ public void ShouldNotCreateAssemblyInfoFileForUnknownSourceCodeAndEnsureAssembly const string assemblyInfoFile = "VersionAssemblyInfo.js"; var fullPath = FileSystemHelper.Path.Combine(workingDir, assemblyInfoFile); var variables = this.variableProvider.GetVariablesFor( - SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0 + SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0 ); using var assemblyInfoFileUpdater = new AssemblyInfoFileUpdater(this.log, this.fileSystem); @@ -130,7 +130,7 @@ public void ShouldStartSearchFromWorkingDirectory() string[] assemblyInfoFiles = []; var variables = this.variableProvider.GetVariablesFor( - SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0 + SemanticVersion.Parse("1.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0 ); using var assemblyInfoFileUpdater = new AssemblyInfoFileUpdater(this.log, this.fileSystem); diff --git a/src/GitVersion.Output.Tests/Output/ProjectFileUpdaterTests.cs b/src/GitVersion.Output.Tests/Output/ProjectFileUpdaterTests.cs index 1b04f35260..93bad568f5 100644 --- a/src/GitVersion.Output.Tests/Output/ProjectFileUpdaterTests.cs +++ b/src/GitVersion.Output.Tests/Output/ProjectFileUpdaterTests.cs @@ -146,7 +146,7 @@ public void CannotUpdateProjectFileWithoutAPropertyGroup(string xml) public void UpdateProjectXmlVersionElementWithStandardXmlInsertsElement(string xml) { var variables = this.variableProvider.GetVariablesFor( - SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0 + SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0 ); var xmlRoot = XElement.Parse(xml); variables.AssemblySemVer.ShouldNotBeNull(); @@ -177,7 +177,7 @@ public void UpdateProjectXmlVersionElementWithStandardXmlInsertsElement(string x )] public void UpdateProjectXmlVersionElementWithStandardXmlModifiesElement(string xml) { - var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0); + var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0); var xmlRoot = XElement.Parse(xml); variables.AssemblySemVer.ShouldNotBeNull(); ProjectFileUpdater.UpdateProjectVersionElement(xmlRoot, ProjectFileUpdater.AssemblyVersionElement, variables.AssemblySemVer); @@ -210,7 +210,7 @@ public void UpdateProjectXmlVersionElementWithStandardXmlModifiesElement(string )] public void UpdateProjectXmlVersionElementWithDuplicatePropertyGroupsModifiesLastElement(string xml) { - var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0); + var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0); var xmlRoot = XElement.Parse(xml); variables.AssemblySemVer.ShouldNotBeNull(); ProjectFileUpdater.UpdateProjectVersionElement(xmlRoot, ProjectFileUpdater.AssemblyVersionElement, variables.AssemblySemVer); @@ -244,7 +244,7 @@ public void UpdateProjectXmlVersionElementWithDuplicatePropertyGroupsModifiesLas )] public void UpdateProjectXmlVersionElementWithMultipleVersionElementsLastOneIsModified(string xml) { - var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixPattern), EmptyConfigurationBuilder.New.Build(), 0); + var variables = this.variableProvider.GetVariablesFor(SemanticVersion.Parse("2.0.0", RegexPatterns.Configuration.DefaultTagPrefixRegexPattern), EmptyConfigurationBuilder.New.Build(), 0); var xmlRoot = XElement.Parse(xml); variables.AssemblySemVer.ShouldNotBeNull(); ProjectFileUpdater.UpdateProjectVersionElement(xmlRoot, ProjectFileUpdater.AssemblyVersionElement, variables.AssemblySemVer); diff --git a/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs b/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs index bfb0166d5d..3b531597ee 100644 --- a/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs +++ b/src/GitVersion.Output/AssemblyInfo/AssemblyInfoFileUpdater.cs @@ -17,9 +17,9 @@ internal sealed class AssemblyInfoFileUpdater(ILog log, IFileSystem fileSystem) private readonly Dictionary assemblyAttributeRegexes = new() { - [".cs"] = RegexPatterns.Output.CsharpAssemblyAttributeRegex, - [".fs"] = RegexPatterns.Output.FsharpAssemblyAttributeRegex, - [".vb"] = RegexPatterns.Output.VisualBasicAssemblyAttributeRegex + [".cs"] = RegexPatterns.Output.CsharpAssemblyAttributeRegex(), + [".fs"] = RegexPatterns.Output.FsharpAssemblyAttributeRegex(), + [".vb"] = RegexPatterns.Output.VisualBasicAssemblyAttributeRegex() }; private const string NewLine = "\r\n"; @@ -65,17 +65,17 @@ public void Execute(GitVersionVariables variables, AssemblyInfoContext context) if (!assemblyVersion.IsNullOrWhiteSpace()) { - fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyVersionRegex, fileContents, assemblyVersionString, assemblyInfoFile.Extension, ref appendedAttributes); + fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyVersionRegex(), fileContents, assemblyVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } if (!assemblyFileVersion.IsNullOrWhiteSpace()) { - fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyFileVersionRegex, fileContents, assemblyFileVersionString, assemblyInfoFile.Extension, ref appendedAttributes); + fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyFileVersionRegex(), fileContents, assemblyFileVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } if (!assemblyInfoVersion.IsNullOrWhiteSpace()) { - fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyInfoVersionRegex, fileContents, assemblyInfoVersionString, assemblyInfoFile.Extension, ref appendedAttributes); + fileContents = ReplaceOrInsertAfterLastAssemblyAttributeOrAppend(RegexPatterns.Output.AssemblyInfoVersionRegex(), fileContents, assemblyInfoVersionString, assemblyInfoFile.Extension, ref appendedAttributes); } if (appendedAttributes)