From e45f63c13f4527f27e406ecf6a1fd6712a6ed2f5 Mon Sep 17 00:00:00 2001 From: roeil Date: Thu, 13 Feb 2025 17:23:42 +0200 Subject: [PATCH 01/14] feat(paths-filter): first commit that supports paths filtering (ignore inclusive only) --- docs/input/docs/workflows/GitFlow/v1.yml | 1 + docs/input/docs/workflows/GitHubFlow/v1.yml | 1 + .../docs/workflows/TrunkBased/preview1.yml | 1 + schemas/6.1/GitVersion.configuration.json | 7 ++ ...riteOutEffectiveConfiguration.approved.txt | 1 + .../Workflows/approved/GitFlow/v1.yml | 1 + .../Workflows/approved/GitHubFlow/v1.yml | 1 + .../approved/TrunkBased/preview1.yml | 1 + .../IgnoreConfiguration.cs | 8 ++ .../VersionCalculation/PathFilterTests.cs | 20 +++++ .../Configuration/EffectiveConfiguration.cs | 4 +- .../Configuration/IIgnoreConfiguration.cs | 4 +- .../Extensions/ConfigurationExtensions.cs | 3 +- src/GitVersion.Core/Git/IGitRepository.cs | 5 ++ src/GitVersion.Core/PublicAPI.Shipped.txt | 1 - src/GitVersion.Core/PublicAPI.Unshipped.txt | 6 +- .../IncrementStrategyFinder.cs | 8 +- .../VersionCalculation/PathFilter.cs | 76 +++++++++++++++++++ .../NextVersionCalculator.cs | 3 +- .../Git/GitRepository.cs | 3 + 20 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs create mode 100644 src/GitVersion.Core/VersionCalculation/PathFilter.cs diff --git a/docs/input/docs/workflows/GitFlow/v1.yml b/docs/input/docs/workflows/GitFlow/v1.yml index 114ecf8e4f..dd44250ac5 100644 --- a/docs/input/docs/workflows/GitFlow/v1.yml +++ b/docs/input/docs/workflows/GitFlow/v1.yml @@ -148,6 +148,7 @@ branches: is-main-branch: false ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/docs/input/docs/workflows/GitHubFlow/v1.yml b/docs/input/docs/workflows/GitHubFlow/v1.yml index bc0452231a..be7da3a729 100644 --- a/docs/input/docs/workflows/GitHubFlow/v1.yml +++ b/docs/input/docs/workflows/GitHubFlow/v1.yml @@ -97,6 +97,7 @@ branches: is-main-branch: false ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/docs/input/docs/workflows/TrunkBased/preview1.yml b/docs/input/docs/workflows/TrunkBased/preview1.yml index 83d231527f..c261444d9f 100644 --- a/docs/input/docs/workflows/TrunkBased/preview1.yml +++ b/docs/input/docs/workflows/TrunkBased/preview1.yml @@ -82,6 +82,7 @@ branches: pre-release-weight: 30000 ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/schemas/6.1/GitVersion.configuration.json b/schemas/6.1/GitVersion.configuration.json index a186b94b48..8ce044db95 100644 --- a/schemas/6.1/GitVersion.configuration.json +++ b/schemas/6.1/GitVersion.configuration.json @@ -189,6 +189,13 @@ "null" ] }, + "paths": { + "description": "A sequence of file paths to be excluded from the version calculations.", + "type": "array", + "items": { + "type": "string" + } + }, "sha": { "description": "A sequence of SHAs to be excluded from the version calculations.", "$ref": "#/$defs/hashSetOfString" diff --git a/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.CanWriteOutEffectiveConfiguration.approved.txt b/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.CanWriteOutEffectiveConfiguration.approved.txt index 114ecf8e4f..dd44250ac5 100644 --- a/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.CanWriteOutEffectiveConfiguration.approved.txt +++ b/src/GitVersion.Configuration.Tests/Configuration/ConfigurationProviderTests.CanWriteOutEffectiveConfiguration.approved.txt @@ -148,6 +148,7 @@ branches: is-main-branch: false ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/src/GitVersion.Configuration.Tests/Workflows/approved/GitFlow/v1.yml b/src/GitVersion.Configuration.Tests/Workflows/approved/GitFlow/v1.yml index 114ecf8e4f..dd44250ac5 100644 --- a/src/GitVersion.Configuration.Tests/Workflows/approved/GitFlow/v1.yml +++ b/src/GitVersion.Configuration.Tests/Workflows/approved/GitFlow/v1.yml @@ -148,6 +148,7 @@ branches: is-main-branch: false ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/src/GitVersion.Configuration.Tests/Workflows/approved/GitHubFlow/v1.yml b/src/GitVersion.Configuration.Tests/Workflows/approved/GitHubFlow/v1.yml index bc0452231a..be7da3a729 100644 --- a/src/GitVersion.Configuration.Tests/Workflows/approved/GitHubFlow/v1.yml +++ b/src/GitVersion.Configuration.Tests/Workflows/approved/GitHubFlow/v1.yml @@ -97,6 +97,7 @@ branches: is-main-branch: false ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/src/GitVersion.Configuration.Tests/Workflows/approved/TrunkBased/preview1.yml b/src/GitVersion.Configuration.Tests/Workflows/approved/TrunkBased/preview1.yml index 83d231527f..c261444d9f 100644 --- a/src/GitVersion.Configuration.Tests/Workflows/approved/TrunkBased/preview1.yml +++ b/src/GitVersion.Configuration.Tests/Workflows/approved/TrunkBased/preview1.yml @@ -82,6 +82,7 @@ branches: pre-release-weight: 30000 ignore: sha: [] + paths: [] mode: ContinuousDelivery label: '{BranchName}' increment: Inherit diff --git a/src/GitVersion.Configuration/IgnoreConfiguration.cs b/src/GitVersion.Configuration/IgnoreConfiguration.cs index 9ec97e2b0a..489148831a 100644 --- a/src/GitVersion.Configuration/IgnoreConfiguration.cs +++ b/src/GitVersion.Configuration/IgnoreConfiguration.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using GitVersion.Configuration.Attributes; namespace GitVersion.Configuration; @@ -22,4 +23,11 @@ public string? BeforeString [JsonPropertyName("sha")] [JsonPropertyDescription("A sequence of SHAs to be excluded from the version calculations.")] public HashSet Shas { get; init; } = []; + + [JsonIgnore] + IReadOnlyCollection IIgnoreConfiguration.Paths => Paths; + + [JsonPropertyName("paths")] + [JsonPropertyDescription("A sequence of file paths to be excluded from the version calculations.")] + public Collection Paths { get; init; } = []; } diff --git a/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs new file mode 100644 index 0000000000..6e4610912f --- /dev/null +++ b/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs @@ -0,0 +1,20 @@ +using GitVersion.Core.Tests.Helpers; +using GitVersion.Git; +using GitVersion.VersionCalculation; + +namespace GitVersion.Core.Tests; + +[TestFixture] +public class PathFilterTests : TestBase +{ + [Test] + public void VerifyNullGuard() => Should.Throw(() => new PathFilter(null!, null!, null!)); + + [Test] + public void VerifyNullGuard2() + { + var sut = new PathFilter(null!, null!, [""]); + + Should.Throw(() => sut.Exclude((ICommit?)null, out _)); + } +} diff --git a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs index bd16f1f2ba..21e8a7782c 100644 --- a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs +++ b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs @@ -1,4 +1,5 @@ using GitVersion.Extensions; +using GitVersion.Git; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; @@ -67,7 +68,6 @@ public EffectiveConfiguration( PatchVersionBumpMessage = configuration.PatchVersionBumpMessage; NoBumpMessage = configuration.NoBumpMessage; CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing.Value; - VersionFilters = configuration.Ignore.ToFilters(); Ignore = configuration.Ignore; TracksReleaseBranches = branchConfiguration.TracksReleaseBranches ?? false; IsReleaseBranch = branchConfiguration.IsReleaseBranch ?? false; @@ -122,8 +122,6 @@ public EffectiveConfiguration( public CommitMessageIncrementMode CommitMessageIncrementing { get; } - public IEnumerable VersionFilters { get; } - public IIgnoreConfiguration Ignore { get; } public string? CommitDateFormat { get; } diff --git a/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs b/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs index f836d52915..ab3ebb9da3 100644 --- a/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs +++ b/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs @@ -6,5 +6,7 @@ public interface IIgnoreConfiguration IReadOnlySet Shas { get; } - bool IsEmpty => Before == null && Shas.Count == 0; + IReadOnlyCollection Paths { get; } + + public bool IsEmpty => Before == null && Shas.Count == 0 && Paths.Count == 0; } diff --git a/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs b/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs index 65b6d0cb67..49061631ba 100644 --- a/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs +++ b/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs @@ -38,12 +38,13 @@ public static IBranchConfiguration GetBranchConfiguration(this IGitVersionConfig return branchConfiguration; } - public static IEnumerable ToFilters(this IIgnoreConfiguration source) + public static IEnumerable ToFilters(this IIgnoreConfiguration source, IGitRepository repository, GitVersionContext versionContext) { source.NotNull(); if (source.Shas.Count != 0) yield return new ShaVersionFilter(source.Shas); if (source.Before.HasValue) yield return new MinDateVersionFilter(source.Before.Value); + if (source.Paths.Count != 0) yield return new PathFilter(repository, versionContext, source.Paths); } private static IEnumerable GetBranchConfigurations(IGitVersionConfiguration configuration, string branchName) diff --git a/src/GitVersion.Core/Git/IGitRepository.cs b/src/GitVersion.Core/Git/IGitRepository.cs index bfad989068..747570a7df 100644 --- a/src/GitVersion.Core/Git/IGitRepository.cs +++ b/src/GitVersion.Core/Git/IGitRepository.cs @@ -1,3 +1,5 @@ +using LibGit2Sharp; + namespace GitVersion.Git; public interface IGitRepository : IDisposable @@ -14,6 +16,9 @@ public interface IGitRepository : IDisposable IBranchCollection Branches { get; } ICommitCollection Commits { get; } IRemoteCollection Remotes { get; } + IQueryableCommitLog InnerCommits { get; } + IEnumerable InnerTags { get; } + Diff InnerDiff { get; } ICommit? FindMergeBase(ICommit commit, ICommit otherCommit); int UncommittedChangesCount(); diff --git a/src/GitVersion.Core/PublicAPI.Shipped.txt b/src/GitVersion.Core/PublicAPI.Shipped.txt index 8feb99e5cc..2aee15d3dc 100644 --- a/src/GitVersion.Core/PublicAPI.Shipped.txt +++ b/src/GitVersion.Core/PublicAPI.Shipped.txt @@ -88,7 +88,6 @@ GitVersion.Configuration.EffectiveConfiguration.TrackMergeMessage.get -> bool GitVersion.Configuration.EffectiveConfiguration.TrackMergeTarget.get -> bool GitVersion.Configuration.EffectiveConfiguration.TracksReleaseBranches.get -> bool GitVersion.Configuration.EffectiveConfiguration.UpdateBuildNumber.get -> bool -GitVersion.Configuration.EffectiveConfiguration.VersionFilters.get -> System.Collections.Generic.IEnumerable! GitVersion.Configuration.EffectiveConfiguration.VersionInBranchPattern.get -> string? GitVersion.Configuration.EffectiveConfiguration.VersionStrategy.get -> GitVersion.VersionCalculation.VersionStrategies GitVersion.Configuration.IBranchConfiguration diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index 57bf801923..a6f9e0e3a8 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -1,3 +1,5 @@ #nullable enable -GitVersion.Extensions.FileSystemExtensions -static GitVersion.Extensions.FileSystemExtensions.GetLastDirectoryWrite(this System.IO.Abstractions.IFileSystem! fileSystem, string! path) -> long +GitVersion.Configuration.IIgnoreConfiguration.Paths.get -> System.Collections.Generic.IReadOnlyCollection! +GitVersion.Git.IGitRepository.InnerCommits.get -> LibGit2Sharp.IQueryableCommitLog! +GitVersion.Git.IGitRepository.InnerDiff.get -> LibGit2Sharp.Diff! +GitVersion.Git.IGitRepository.InnerTags.get -> System.Collections.Generic.IEnumerable! \ No newline at end of file diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index d0f69f4bbb..59c5aba866 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -7,7 +7,11 @@ namespace GitVersion.VersionCalculation; -internal class IncrementStrategyFinder(IRepositoryStore repositoryStore, ITaggedSemanticVersionRepository taggedSemanticVersionRepository) +internal class IncrementStrategyFinder( + IRepositoryStore repositoryStore, + Lazy versionContext, + IGitRepository repository, + ITaggedSemanticVersionRepository taggedSemanticVersionRepository) : IIncrementStrategyFinder { private readonly Dictionary commitIncrementCache = []; @@ -51,8 +55,10 @@ public VersionField DetermineIncrementedField( 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 pathFilters = configuration.Ignore.ToFilters(repository, versionContext.Value).OfType(); var increments = commits + .Where(c => !pathFilters.Any(f => f.Exclude(c, out _))) .Select(c => GetIncrementFromCommit(c, majorRegex, minorRegex, patchRegex, noBumpRegex)) .Where(v => v != null) .ToList(); diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs new file mode 100644 index 0000000000..f7e857df50 --- /dev/null +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -0,0 +1,76 @@ +using GitVersion.Extensions; +using GitVersion.Git; +using LibGit2Sharp; + +namespace GitVersion.VersionCalculation; + +internal class PathFilter(IGitRepository repository, GitVersionContext context, IEnumerable paths, PathFilter.PathFilterMode mode = PathFilter.PathFilterMode.Inclusive) : IVersionFilter +{ + private readonly static Dictionary patchsCache = []; + + public enum PathFilterMode { Inclusive = 0, Exclusive = 1 } + + private readonly IEnumerable paths = paths.NotNull(); + private readonly PathFilterMode mode = mode; + private readonly GitVersionContext context = context; + + public bool Exclude(IBaseVersion baseVersion, out string? reason) + { + ArgumentNullException.ThrowIfNull(baseVersion); + + reason = null; + if (baseVersion.Source.StartsWith("Fallback") || baseVersion.Source.StartsWith("Git tag") || baseVersion.Source.StartsWith("NextVersion")) return false; + + return Exclude(baseVersion.BaseVersionSource, out reason); + } + + public bool Exclude(ICommit? localCommit, out string? reason) + { + localCommit.NotNull(); + var commit = repository.InnerCommits.First(c => c.Sha == localCommit.Sha); + + reason = null; + + var match = new System.Text.RegularExpressions.Regex($"^({context.Configuration.TagPrefixPattern}).*$", + System.Text.RegularExpressions.RegexOptions.Compiled); + + if (commit != null) + { + Patch? patch = null; + if (!patchsCache.ContainsKey(commit.Sha)) + { + if (!repository.InnerTags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) + { + Tree commitTree = commit.Tree; // Main Tree + Tree? parentCommitTree = commit.Parents.FirstOrDefault()?.Tree; // Secondary Tree + patch = repository.InnerDiff.Compare(parentCommitTree, commitTree); // Difference + } + patchsCache[commit.Sha] = patch; + } + + patch = patchsCache[commit.Sha]; + if (patch != null) + { + switch (mode) + { + case PathFilterMode.Inclusive: + if (!paths.Any(path => patch.Any(p => p.Path.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) + { + reason = "Source was ignored due to commit path is not present"; + return true; + } + break; + case PathFilterMode.Exclusive: + if (paths.Any(path => patch.All(p => p.Path.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) + { + reason = "Source was ignored due to commit path excluded"; + return true; + } + break; + } + } + } + + return false; + } +} diff --git a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs index 8e4ebc4640..39eadbd222 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs @@ -11,6 +11,7 @@ namespace GitVersion.VersionCalculation; internal class NextVersionCalculator( ILog log, Lazy versionContext, + IGitRepository repository, IEnumerable deploymentModeCalculators, IEnumerable versionStrategies, IEffectiveBranchConfigurationFinder effectiveBranchConfigurationFinder, @@ -284,7 +285,7 @@ IEnumerable GetNextVersionsInternal() private bool IncludeVersion(IBaseVersion baseVersion, IIgnoreConfiguration ignoreConfiguration) { - foreach (var versionFilter in ignoreConfiguration.ToFilters()) + foreach (var versionFilter in ignoreConfiguration.ToFilters(repository, Context)) { if (versionFilter.Exclude(baseVersion, out var reason)) { diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index aea0217adc..b8e4145461 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -28,6 +28,9 @@ private IRepository RepositoryInstance public IBranchCollection Branches => new BranchCollection(RepositoryInstance.Branches); public ICommitCollection Commits => new CommitCollection(RepositoryInstance.Commits); public IRemoteCollection Remotes => new RemoteCollection(RepositoryInstance.Network.Remotes); + public IQueryableCommitLog InnerCommits => RepositoryInstance.Commits; + public IEnumerable InnerTags => RepositoryInstance.Tags; + public Diff InnerDiff => RepositoryInstance.Diff; public void DiscoverRepository(string? gitDirectory) { From 9d9c5dd9e3e26d8e8e6b31d7739aa8bc429cbc75 Mon Sep 17 00:00:00 2001 From: roeil Date: Thu, 13 Feb 2025 17:44:42 +0200 Subject: [PATCH 02/14] refactor(paths-filter): implement path find logic in gitrepository class --- src/GitVersion.Core/Git/IGitRepository.cs | 6 +--- src/GitVersion.Core/PublicAPI.Unshipped.txt | 4 +-- .../VersionCalculation/PathFilter.cs | 31 ++++--------------- .../Git/GitRepository.cs | 25 +++++++++++++-- 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/src/GitVersion.Core/Git/IGitRepository.cs b/src/GitVersion.Core/Git/IGitRepository.cs index 747570a7df..e98632a970 100644 --- a/src/GitVersion.Core/Git/IGitRepository.cs +++ b/src/GitVersion.Core/Git/IGitRepository.cs @@ -1,5 +1,3 @@ -using LibGit2Sharp; - namespace GitVersion.Git; public interface IGitRepository : IDisposable @@ -16,11 +14,9 @@ public interface IGitRepository : IDisposable IBranchCollection Branches { get; } ICommitCollection Commits { get; } IRemoteCollection Remotes { get; } - IQueryableCommitLog InnerCommits { get; } - IEnumerable InnerTags { get; } - Diff InnerDiff { get; } ICommit? FindMergeBase(ICommit commit, ICommit otherCommit); + IEnumerable? FindPatchPaths(ICommit commit, string? tagPrefix); int UncommittedChangesCount(); void DiscoverRepository(string? gitDirectory); } diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index a6f9e0e3a8..3488a70072 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -1,5 +1,3 @@ #nullable enable GitVersion.Configuration.IIgnoreConfiguration.Paths.get -> System.Collections.Generic.IReadOnlyCollection! -GitVersion.Git.IGitRepository.InnerCommits.get -> LibGit2Sharp.IQueryableCommitLog! -GitVersion.Git.IGitRepository.InnerDiff.get -> LibGit2Sharp.Diff! -GitVersion.Git.IGitRepository.InnerTags.get -> System.Collections.Generic.IEnumerable! \ No newline at end of file +GitVersion.Git.IGitRepository.FindPatchPaths(GitVersion.Git.ICommit! commit, string? tagPrefix) -> System.Collections.Generic.IEnumerable? diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index f7e857df50..02659b372b 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -1,13 +1,10 @@ using GitVersion.Extensions; using GitVersion.Git; -using LibGit2Sharp; namespace GitVersion.VersionCalculation; internal class PathFilter(IGitRepository repository, GitVersionContext context, IEnumerable paths, PathFilter.PathFilterMode mode = PathFilter.PathFilterMode.Inclusive) : IVersionFilter { - private readonly static Dictionary patchsCache = []; - public enum PathFilterMode { Inclusive = 0, Exclusive = 1 } private readonly IEnumerable paths = paths.NotNull(); @@ -24,44 +21,28 @@ public bool Exclude(IBaseVersion baseVersion, out string? reason) return Exclude(baseVersion.BaseVersionSource, out reason); } - public bool Exclude(ICommit? localCommit, out string? reason) + public bool Exclude(ICommit? commit, out string? reason) { - localCommit.NotNull(); - var commit = repository.InnerCommits.First(c => c.Sha == localCommit.Sha); - + commit.NotNull(); reason = null; - var match = new System.Text.RegularExpressions.Regex($"^({context.Configuration.TagPrefixPattern}).*$", - System.Text.RegularExpressions.RegexOptions.Compiled); - if (commit != null) { - Patch? patch = null; - if (!patchsCache.ContainsKey(commit.Sha)) - { - if (!repository.InnerTags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) - { - Tree commitTree = commit.Tree; // Main Tree - Tree? parentCommitTree = commit.Parents.FirstOrDefault()?.Tree; // Secondary Tree - patch = repository.InnerDiff.Compare(parentCommitTree, commitTree); // Difference - } - patchsCache[commit.Sha] = patch; - } + var patchPaths = repository.FindPatchPaths(commit, context.Configuration.TagPrefixPattern); - patch = patchsCache[commit.Sha]; - if (patch != null) + if (patchPaths != null) { switch (mode) { case PathFilterMode.Inclusive: - if (!paths.Any(path => patch.Any(p => p.Path.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) + if (!paths.Any(path => patchPaths.Any(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) { reason = "Source was ignored due to commit path is not present"; return true; } break; case PathFilterMode.Exclusive: - if (paths.Any(path => patch.All(p => p.Path.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) + if (paths.Any(path => patchPaths.All(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) { reason = "Source was ignored due to commit path excluded"; return true; diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index b8e4145461..5f7d008a56 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -1,3 +1,4 @@ +using System.Text.RegularExpressions; using GitVersion.Extensions; using GitVersion.Helpers; using LibGit2Sharp; @@ -7,6 +8,7 @@ namespace GitVersion.Git; internal sealed partial class GitRepository { private Lazy? repositoryLazy; + private readonly static Dictionary patchsCache = []; private IRepository RepositoryInstance { @@ -28,9 +30,6 @@ private IRepository RepositoryInstance public IBranchCollection Branches => new BranchCollection(RepositoryInstance.Branches); public ICommitCollection Commits => new CommitCollection(RepositoryInstance.Commits); public IRemoteCollection Remotes => new RemoteCollection(RepositoryInstance.Network.Remotes); - public IQueryableCommitLog InnerCommits => RepositoryInstance.Commits; - public IEnumerable InnerTags => RepositoryInstance.Tags; - public Diff InnerDiff => RepositoryInstance.Diff; public void DiscoverRepository(string? gitDirectory) { @@ -56,6 +55,26 @@ public void DiscoverRepository(string? gitDirectory) }); } + public IEnumerable? FindPatchPaths(ICommit commit, string? tagPrefix) + { + Patch? patch = null; + var innerCommit = RepositoryInstance.Commits.First(c => c.Sha == commit.Sha); + var match = new Regex($"^({tagPrefix ?? ""}).*$", RegexOptions.Compiled); + + if (!patchsCache.ContainsKey(commit.Sha)) + { + if (!RepositoryInstance.Tags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) + { + Tree commitTree = innerCommit.Tree; // Main Tree + Tree? parentCommitTree = innerCommit.Parents.FirstOrDefault()?.Tree; // Secondary Tree + patch = RepositoryInstance.Diff.Compare(parentCommitTree, commitTree); // Difference + } + patchsCache[commit.Sha] = patch; + } + + return patch?.Select(p => p.Path); + } + public int UncommittedChangesCount() { var retryAction = new RetryAction(); From ad8bc2ff528d797f8fa093168fd4c58cb559df07 Mon Sep 17 00:00:00 2001 From: Roei Levi <97434370+Roei-Levi@users.noreply.github.com> Date: Sun, 16 Feb 2025 07:40:53 +0200 Subject: [PATCH 03/14] refactor: apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Asbjørn Ulsberg --- src/GitVersion.Core/Configuration/EffectiveConfiguration.cs | 1 - src/GitVersion.LibGit2Sharp/Git/GitRepository.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs index 21e8a7782c..29f7280f74 100644 --- a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs +++ b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs @@ -1,5 +1,4 @@ using GitVersion.Extensions; -using GitVersion.Git; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index 5f7d008a56..5fdcb37dda 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -8,7 +8,7 @@ namespace GitVersion.Git; internal sealed partial class GitRepository { private Lazy? repositoryLazy; - private readonly static Dictionary patchsCache = []; + private readonly static Dictionary patchCache = []; private IRepository RepositoryInstance { @@ -61,7 +61,7 @@ public void DiscoverRepository(string? gitDirectory) var innerCommit = RepositoryInstance.Commits.First(c => c.Sha == commit.Sha); var match = new Regex($"^({tagPrefix ?? ""}).*$", RegexOptions.Compiled); - if (!patchsCache.ContainsKey(commit.Sha)) + if (!this.patchsCache.ContainsKey(commit.Sha)) { if (!RepositoryInstance.Tags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) { From 354790edbee8185a190d2269b7c1bea5a28a4e0d Mon Sep 17 00:00:00 2001 From: roeil Date: Sun, 16 Feb 2025 07:48:14 +0200 Subject: [PATCH 04/14] fix: patchCache --- src/GitVersion.LibGit2Sharp/Git/GitRepository.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index 5fdcb37dda..0df45a7885 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -8,7 +8,7 @@ namespace GitVersion.Git; internal sealed partial class GitRepository { private Lazy? repositoryLazy; - private readonly static Dictionary patchCache = []; + private readonly Dictionary patchCache = []; private IRepository RepositoryInstance { @@ -61,15 +61,15 @@ public void DiscoverRepository(string? gitDirectory) var innerCommit = RepositoryInstance.Commits.First(c => c.Sha == commit.Sha); var match = new Regex($"^({tagPrefix ?? ""}).*$", RegexOptions.Compiled); - if (!this.patchsCache.ContainsKey(commit.Sha)) + if (!this.patchCache.ContainsKey(commit.Sha)) { if (!RepositoryInstance.Tags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) { Tree commitTree = innerCommit.Tree; // Main Tree Tree? parentCommitTree = innerCommit.Parents.FirstOrDefault()?.Tree; // Secondary Tree patch = RepositoryInstance.Diff.Compare(parentCommitTree, commitTree); // Difference + this.patchCache[commit.Sha] = patch; } - patchsCache[commit.Sha] = patch; } return patch?.Select(p => p.Path); From 115295338f1f4a6e32d7ebdc57d886bc959445ec Mon Sep 17 00:00:00 2001 From: roeil Date: Sun, 16 Feb 2025 08:41:31 +0200 Subject: [PATCH 05/14] refactor: restore VersionFilters in EffectiveConfiguration --- src/GitVersion.Core/Configuration/EffectiveConfiguration.cs | 6 ++++++ src/GitVersion.Core/Extensions/ConfigurationExtensions.cs | 2 +- src/GitVersion.Core/PublicAPI.Shipped.txt | 1 - src/GitVersion.Core/PublicAPI.Unshipped.txt | 2 ++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs index 29f7280f74..d7baa0df16 100644 --- a/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs +++ b/src/GitVersion.Core/Configuration/EffectiveConfiguration.cs @@ -1,4 +1,5 @@ using GitVersion.Extensions; +using GitVersion.Git; using GitVersion.VersionCalculation; namespace GitVersion.Configuration; @@ -12,6 +13,8 @@ public record EffectiveConfiguration public EffectiveConfiguration( IGitVersionConfiguration configuration, IBranchConfiguration branchConfiguration, + IGitRepository? repository = null, + Lazy? versionContext = null, EffectiveConfiguration? fallbackConfiguration = null) { configuration.NotNull(); @@ -67,6 +70,7 @@ public EffectiveConfiguration( PatchVersionBumpMessage = configuration.PatchVersionBumpMessage; NoBumpMessage = configuration.NoBumpMessage; CommitMessageIncrementing = branchConfiguration.CommitMessageIncrementing.Value; + VersionFilters = versionContext != null && repository != null ? configuration.Ignore.ToFilters(repository, versionContext.Value) : []; Ignore = configuration.Ignore; TracksReleaseBranches = branchConfiguration.TracksReleaseBranches ?? false; IsReleaseBranch = branchConfiguration.IsReleaseBranch ?? false; @@ -121,6 +125,8 @@ public EffectiveConfiguration( public CommitMessageIncrementMode CommitMessageIncrementing { get; } + public IEnumerable VersionFilters { get; } + public IIgnoreConfiguration Ignore { get; } public string? CommitDateFormat { get; } diff --git a/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs b/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs index 49061631ba..2f3dc18236 100644 --- a/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs +++ b/src/GitVersion.Core/Extensions/ConfigurationExtensions.cs @@ -25,7 +25,7 @@ public static EffectiveConfiguration GetEffectiveConfiguration( { fallbackConfiguration = parentConfiguration; } - return new EffectiveConfiguration(configuration, branchConfiguration, fallbackConfiguration); + return new EffectiveConfiguration(configuration, branchConfiguration, fallbackConfiguration: fallbackConfiguration); } public static IBranchConfiguration GetBranchConfiguration(this IGitVersionConfiguration configuration, IBranch branch) diff --git a/src/GitVersion.Core/PublicAPI.Shipped.txt b/src/GitVersion.Core/PublicAPI.Shipped.txt index 2aee15d3dc..e5718d771e 100644 --- a/src/GitVersion.Core/PublicAPI.Shipped.txt +++ b/src/GitVersion.Core/PublicAPI.Shipped.txt @@ -65,7 +65,6 @@ GitVersion.Configuration.EffectiveConfiguration.AssemblyVersioningScheme.get -> GitVersion.Configuration.EffectiveConfiguration.CommitDateFormat.get -> string? GitVersion.Configuration.EffectiveConfiguration.CommitMessageIncrementing.get -> GitVersion.VersionCalculation.CommitMessageIncrementMode GitVersion.Configuration.EffectiveConfiguration.DeploymentMode.get -> GitVersion.VersionCalculation.DeploymentMode -GitVersion.Configuration.EffectiveConfiguration.EffectiveConfiguration(GitVersion.Configuration.IGitVersionConfiguration! configuration, GitVersion.Configuration.IBranchConfiguration! branchConfiguration, GitVersion.Configuration.EffectiveConfiguration? fallbackConfiguration = null) -> void GitVersion.Configuration.EffectiveConfiguration.Ignore.get -> GitVersion.Configuration.IIgnoreConfiguration! GitVersion.Configuration.EffectiveConfiguration.Increment.get -> GitVersion.IncrementStrategy GitVersion.Configuration.EffectiveConfiguration.IsMainBranch.get -> bool diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index 3488a70072..a2a0c5a720 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -1,3 +1,5 @@ #nullable enable +GitVersion.Configuration.EffectiveConfiguration.EffectiveConfiguration(GitVersion.Configuration.IGitVersionConfiguration! configuration, GitVersion.Configuration.IBranchConfiguration! branchConfiguration, GitVersion.Git.IGitRepository? repository = null, System.Lazy? versionContext = null, GitVersion.Configuration.EffectiveConfiguration? fallbackConfiguration = null) -> void +GitVersion.Configuration.EffectiveConfiguration.VersionFilters.get -> System.Collections.Generic.IEnumerable! GitVersion.Configuration.IIgnoreConfiguration.Paths.get -> System.Collections.Generic.IReadOnlyCollection! GitVersion.Git.IGitRepository.FindPatchPaths(GitVersion.Git.ICommit! commit, string? tagPrefix) -> System.Collections.Generic.IEnumerable? From a3003ef5f66eee3c400d1056b6549e2aeeb532fc Mon Sep 17 00:00:00 2001 From: roeil Date: Sun, 16 Feb 2025 20:27:00 +0200 Subject: [PATCH 06/14] refactor: add VersionIncrementSourceType to distinguish between version increment strategies --- src/GitVersion.Core/PublicAPI.Shipped.txt | 2 -- src/GitVersion.Core/PublicAPI.Unshipped.txt | 13 +++++++++++++ .../VersionCalculation/PathFilter.cs | 2 +- .../VersionSearchStrategies/BaseVersion.cs | 8 ++++---- .../VersionSearchStrategies/BaseVersionOperand.cs | 4 +++- .../VersionSearchStrategies/BaseVersionOperator.cs | 2 ++ .../ConfiguredNextVersionVersionStrategy.cs | 2 +- .../FallbacktVersionStrategy.cs | 3 ++- .../IBaseVersionIncrement.cs | 2 ++ .../TaggedCommitVersionStrategy.cs | 2 +- .../VersionIncrementSourceType.cs | 9 +++++++++ 11 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/VersionIncrementSourceType.cs diff --git a/src/GitVersion.Core/PublicAPI.Shipped.txt b/src/GitVersion.Core/PublicAPI.Shipped.txt index e5718d771e..bde2e4919c 100644 --- a/src/GitVersion.Core/PublicAPI.Shipped.txt +++ b/src/GitVersion.Core/PublicAPI.Shipped.txt @@ -600,7 +600,6 @@ GitVersion.Settings.OnlyTrackedBranches -> bool GitVersion.VersionCalculation.BaseVersion GitVersion.VersionCalculation.BaseVersion.BaseVersion() -> void GitVersion.VersionCalculation.BaseVersion.BaseVersion(GitVersion.VersionCalculation.BaseVersionOperand! Operand) -> void -GitVersion.VersionCalculation.BaseVersion.BaseVersion(string! source, GitVersion.SemanticVersion! semanticVersion, GitVersion.Git.ICommit? baseVersionSource = null) -> void GitVersion.VersionCalculation.BaseVersion.BaseVersionSource.get -> GitVersion.Git.ICommit? GitVersion.VersionCalculation.BaseVersion.GetIncrementedVersion() -> GitVersion.SemanticVersion! GitVersion.VersionCalculation.BaseVersion.Operand.get -> GitVersion.VersionCalculation.BaseVersionOperand! @@ -612,7 +611,6 @@ GitVersion.VersionCalculation.BaseVersion.ShouldIncrement.get -> bool GitVersion.VersionCalculation.BaseVersion.Source.get -> string! GitVersion.VersionCalculation.BaseVersionOperand GitVersion.VersionCalculation.BaseVersionOperand.BaseVersionOperand() -> void -GitVersion.VersionCalculation.BaseVersionOperand.BaseVersionOperand(string! Source, GitVersion.SemanticVersion! SemanticVersion, GitVersion.Git.ICommit? BaseVersionSource = null) -> void GitVersion.VersionCalculation.BaseVersionOperand.BaseVersionSource.get -> GitVersion.Git.ICommit? GitVersion.VersionCalculation.BaseVersionOperand.BaseVersionSource.init -> void GitVersion.VersionCalculation.BaseVersionOperand.SemanticVersion.get -> GitVersion.SemanticVersion! diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index a2a0c5a720..de4c753804 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -3,3 +3,16 @@ GitVersion.Configuration.EffectiveConfiguration.EffectiveConfiguration(GitVersio GitVersion.Configuration.EffectiveConfiguration.VersionFilters.get -> System.Collections.Generic.IEnumerable! GitVersion.Configuration.IIgnoreConfiguration.Paths.get -> System.Collections.Generic.IReadOnlyCollection! GitVersion.Git.IGitRepository.FindPatchPaths(GitVersion.Git.ICommit! commit, string? tagPrefix) -> System.Collections.Generic.IEnumerable? +GitVersion.VersionCalculation.BaseVersion.BaseVersion(string! source, GitVersion.SemanticVersion! semanticVersion, GitVersion.Git.ICommit? baseVersionSource = null, GitVersion.VersionCalculation.VersionIncrementSourceType sourceType = GitVersion.VersionCalculation.VersionIncrementSourceType.Tree) -> void +GitVersion.VersionCalculation.BaseVersion.SourceType.get -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.BaseVersion.SourceType.init -> void +GitVersion.VersionCalculation.BaseVersionOperand.BaseVersionOperand(string! Source, GitVersion.SemanticVersion! SemanticVersion, GitVersion.Git.ICommit? BaseVersionSource = null, GitVersion.VersionCalculation.VersionIncrementSourceType SourceType = GitVersion.VersionCalculation.VersionIncrementSourceType.Tree) -> void +GitVersion.VersionCalculation.BaseVersionOperand.SourceType.get -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.BaseVersionOperand.SourceType.init -> void +GitVersion.VersionCalculation.BaseVersionOperator.SourceType.get -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.IBaseVersionIncrement.SourceType.get -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.VersionIncrementSourceType.Fallback = 2 -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.VersionIncrementSourceType.NextVersionConfig = 3 -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.VersionIncrementSourceType.Tag = 1 -> GitVersion.VersionCalculation.VersionIncrementSourceType +GitVersion.VersionCalculation.VersionIncrementSourceType.Tree = 0 -> GitVersion.VersionCalculation.VersionIncrementSourceType diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index 02659b372b..b340cd25b2 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -16,7 +16,7 @@ public bool Exclude(IBaseVersion baseVersion, out string? reason) ArgumentNullException.ThrowIfNull(baseVersion); reason = null; - if (baseVersion.Source.StartsWith("Fallback") || baseVersion.Source.StartsWith("Git tag") || baseVersion.Source.StartsWith("NextVersion")) return false; + if (baseVersion.SourceType != VersionIncrementSourceType.Tree) return false; return Exclude(baseVersion.BaseVersionSource, out reason); } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersion.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersion.cs index 28a574b6a0..0ccc0d3220 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersion.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersion.cs @@ -10,13 +10,13 @@ public BaseVersion() : this(new BaseVersionOperand()) { } - public BaseVersion(string source, SemanticVersion semanticVersion, ICommit? baseVersionSource = null) - : this(new BaseVersionOperand(source, semanticVersion, baseVersionSource)) - { - } + public BaseVersion(string source, SemanticVersion semanticVersion, ICommit? baseVersionSource = null, VersionIncrementSourceType sourceType = VersionIncrementSourceType.Tree) + : this(new BaseVersionOperand(source, semanticVersion, baseVersionSource, sourceType)) => this.SourceType = sourceType; public string Source => (Operator?.Source).IsNullOrEmpty() ? Operand.Source : Operator.Source; + public VersionIncrementSourceType SourceType { get; init; } = VersionIncrementSourceType.Tree; + public SemanticVersion SemanticVersion => Operand.SemanticVersion; public ICommit? BaseVersionSource => Operator?.BaseVersionSource ?? Operand.BaseVersionSource; diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperand.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperand.cs index 0a46368ba5..4878fee300 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperand.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperand.cs @@ -3,7 +3,7 @@ namespace GitVersion.VersionCalculation; -public sealed record BaseVersionOperand(string Source, SemanticVersion SemanticVersion, ICommit? BaseVersionSource = null) +public sealed record BaseVersionOperand(string Source, SemanticVersion SemanticVersion, ICommit? BaseVersionSource = null, VersionIncrementSourceType SourceType = VersionIncrementSourceType.Tree) : IBaseVersionIncrement { public BaseVersionOperand() : this(string.Empty, SemanticVersion.Empty) @@ -12,6 +12,8 @@ public BaseVersionOperand() : this(string.Empty, SemanticVersion.Empty) public string Source { get; init; } = Source.NotNull(); + public VersionIncrementSourceType SourceType { get; init; } = SourceType; + public SemanticVersion SemanticVersion { get; init; } = SemanticVersion.NotNull(); public override string ToString() diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperator.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperator.cs index 767dd7b83f..4a34bb4c68 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperator.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/BaseVersionOperator.cs @@ -6,6 +6,8 @@ public sealed record BaseVersionOperator : IBaseVersionIncrement { public string Source { get; init; } = string.Empty; + public VersionIncrementSourceType SourceType { get; } = VersionIncrementSourceType.Tree; + public ICommit? BaseVersionSource { get; init; } public VersionField Increment { get; init; } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs index 87645553ca..5f6a8e41c9 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs @@ -42,7 +42,7 @@ public IEnumerable GetBaseVersions(EffectiveBranchConfiguration con }; } - yield return new BaseVersion("NextVersion in GitVersion configuration file", semanticVersion) + yield return new BaseVersion("NextVersion in GitVersion configuration file", semanticVersion, sourceType: VersionIncrementSourceType.NextVersionConfig) { Operator = operation }; diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs index 31858d5a4d..7724a69117 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs @@ -58,7 +58,8 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur Increment = increment, ForceIncrement = false, Label = label - } + }, + SourceType = VersionIncrementSourceType.Fallback }; } } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/IBaseVersionIncrement.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/IBaseVersionIncrement.cs index 02f53b7cd1..9cf7acea9d 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/IBaseVersionIncrement.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/IBaseVersionIncrement.cs @@ -6,5 +6,7 @@ public interface IBaseVersionIncrement { string Source { get; } + VersionIncrementSourceType SourceType { get; } + ICommit? BaseVersionSource { get; } } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs index 4e08eef9c8..9d00de96ea 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs @@ -78,7 +78,7 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur semanticVersionTreshold = semanticVersion.Value.Increment(increment, null, forceIncrement: true); yield return new BaseVersion( - $"Git tag '{semanticVersion.Tag.Name.Friendly}'", semanticVersion.Value, baseVersionSource) + $"Git tag '{semanticVersion.Tag.Name.Friendly}'", semanticVersion.Value, baseVersionSource, VersionIncrementSourceType.Tag) { Operator = new BaseVersionOperator { diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/VersionIncrementSourceType.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/VersionIncrementSourceType.cs new file mode 100644 index 0000000000..25dc551e09 --- /dev/null +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/VersionIncrementSourceType.cs @@ -0,0 +1,9 @@ +namespace GitVersion.VersionCalculation; + +public enum VersionIncrementSourceType +{ + Tree, + Tag, + Fallback, + NextVersionConfig +} From b3a10eb841297215b9e681ea3ff62739776254a2 Mon Sep 17 00:00:00 2001 From: roeil Date: Wed, 19 Feb 2025 09:26:30 +0200 Subject: [PATCH 07/14] refactor: prefix local field access with 'this' --- src/GitVersion.Core/VersionCalculation/PathFilter.cs | 8 ++++---- src/GitVersion.LibGit2Sharp/Git/GitRepository.cs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index b340cd25b2..3a75135d67 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -28,21 +28,21 @@ public bool Exclude(ICommit? commit, out string? reason) if (commit != null) { - var patchPaths = repository.FindPatchPaths(commit, context.Configuration.TagPrefixPattern); + var patchPaths = repository.FindPatchPaths(commit, this.context.Configuration.TagPrefixPattern); if (patchPaths != null) { - switch (mode) + switch (this.mode) { case PathFilterMode.Inclusive: - if (!paths.Any(path => patchPaths.Any(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) + if (!this.paths.Any(path => patchPaths.Any(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) { reason = "Source was ignored due to commit path is not present"; return true; } break; case PathFilterMode.Exclusive: - if (paths.Any(path => patchPaths.All(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) + if (this.paths.Any(path => patchPaths.All(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) { reason = "Source was ignored due to commit path excluded"; return true; diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index 0df45a7885..fac3a1b5bd 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -58,16 +58,16 @@ public void DiscoverRepository(string? gitDirectory) public IEnumerable? FindPatchPaths(ICommit commit, string? tagPrefix) { Patch? patch = null; - var innerCommit = RepositoryInstance.Commits.First(c => c.Sha == commit.Sha); + var innerCommit = this.RepositoryInstance.Commits.First(c => c.Sha == commit.Sha); var match = new Regex($"^({tagPrefix ?? ""}).*$", RegexOptions.Compiled); if (!this.patchCache.ContainsKey(commit.Sha)) { - if (!RepositoryInstance.Tags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) + if (!this.RepositoryInstance.Tags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) { Tree commitTree = innerCommit.Tree; // Main Tree Tree? parentCommitTree = innerCommit.Parents.FirstOrDefault()?.Tree; // Secondary Tree - patch = RepositoryInstance.Diff.Compare(parentCommitTree, commitTree); // Difference + patch = this.RepositoryInstance.Diff.Compare(parentCommitTree, commitTree); // Difference this.patchCache[commit.Sha] = patch; } } From 0e5359e2bcd3a00a09a003c6207fc97eaad44fc4 Mon Sep 17 00:00:00 2001 From: roeil Date: Wed, 19 Feb 2025 09:26:50 +0200 Subject: [PATCH 08/14] fix --- src/GitVersion.Core/VersionCalculation/PathFilter.cs | 1 - src/GitVersion.LibGit2Sharp/Git/GitRepository.cs | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index 3a75135d67..94ce4155da 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -23,7 +23,6 @@ public bool Exclude(IBaseVersion baseVersion, out string? reason) public bool Exclude(ICommit? commit, out string? reason) { - commit.NotNull(); reason = null; if (commit != null) diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index fac3a1b5bd..810850976b 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -71,6 +71,10 @@ public void DiscoverRepository(string? gitDirectory) this.patchCache[commit.Sha] = patch; } } + else + { + patch = this.patchCache[commit.Sha]; + } return patch?.Select(p => p.Path); } From 6c0e49faf69ace6bf808eb386d70bd714994dac7 Mon Sep 17 00:00:00 2001 From: roeil Date: Wed, 19 Feb 2025 09:31:59 +0200 Subject: [PATCH 09/14] refactor: prefix local field access with 'this' --- .../ConfiguredNextVersionVersionStrategy.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs index 5f6a8e41c9..9253986704 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/ConfiguredNextVersionVersionStrategy.cs @@ -18,16 +18,16 @@ public IEnumerable GetBaseVersions(EffectiveBranchConfiguration con { configuration.NotNull(); - if (!Context.Configuration.VersionStrategy.HasFlag(VersionStrategies.ConfiguredNextVersion)) + if (!this.Context.Configuration.VersionStrategy.HasFlag(VersionStrategies.ConfiguredNextVersion)) yield break; - var nextVersion = Context.Configuration.NextVersion; + var nextVersion = this.Context.Configuration.NextVersion; if (!nextVersion.IsNullOrEmpty()) { var semanticVersion = SemanticVersion.Parse( - nextVersion, Context.Configuration.TagPrefixPattern, Context.Configuration.SemanticVersionFormat + nextVersion, this.Context.Configuration.TagPrefixPattern, this.Context.Configuration.SemanticVersionFormat ); - var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); + var label = configuration.Value.GetBranchSpecificLabel(this.Context.CurrentBranch.Name, null); if (semanticVersion.IsMatchForBranchSpecificLabel(label)) { From a397bf514930934d4ec2dccedea3be634676d1c9 Mon Sep 17 00:00:00 2001 From: roeil Date: Thu, 27 Feb 2025 14:00:46 +0200 Subject: [PATCH 10/14] refactor(paths-filter): use regex in paths filter, remove filtering mode, defer filtering of commits --- .../VersionCalculation/PathFilterTests.cs | 9 -------- .../IncrementStrategyFinder.cs | 13 +++++------ .../Mainline/MainlineContext.cs | 4 +++- .../NonTrunk/MergeCommitOnNonTrunkBase.cs | 4 +++- .../Mainline/Trunk/MergeCommitOnTrunkBase.cs | 4 +++- .../VersionCalculation/PathFilter.cs | 22 +++++-------------- .../NextVersionCalculator.cs | 15 ++++++++----- .../MainlineVersionStrategy.cs | 19 +++++++++++----- 8 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs index 6e4610912f..12d2540e4c 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/PathFilterTests.cs @@ -1,5 +1,4 @@ using GitVersion.Core.Tests.Helpers; -using GitVersion.Git; using GitVersion.VersionCalculation; namespace GitVersion.Core.Tests; @@ -9,12 +8,4 @@ public class PathFilterTests : TestBase { [Test] public void VerifyNullGuard() => Should.Throw(() => new PathFilter(null!, null!, null!)); - - [Test] - public void VerifyNullGuard2() - { - var sut = new PathFilter(null!, null!, [""]); - - Should.Throw(() => sut.Exclude((ICommit?)null, out _)); - } } diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index 59c5aba866..4e4e8cb0cc 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -58,14 +58,11 @@ public VersionField DetermineIncrementedField( var pathFilters = configuration.Ignore.ToFilters(repository, versionContext.Value).OfType(); var increments = commits - .Where(c => !pathFilters.Any(f => f.Exclude(c, out _))) - .Select(c => GetIncrementFromCommit(c, majorRegex, minorRegex, patchRegex, noBumpRegex)) - .Where(v => v != null) - .ToList(); - - return increments.Count != 0 - ? increments.Max() - : null; + .Select(c => (commit: c, increment: GetIncrementFromCommit(c, majorRegex, minorRegex, patchRegex, noBumpRegex))) + .Where(pair => pair.increment != null) + .OrderByDescending(pair => pair.increment); + + return increments.FirstOrDefault(pair => !pathFilters.Any(f => f.Exclude(pair.commit, out _)), (null!, null)).increment; } private VersionField? FindCommitMessageIncrement( diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs b/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs index 3657484b37..9ee5af759d 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs @@ -4,11 +4,13 @@ namespace GitVersion.VersionCalculation.Mainline; -internal record MainlineContext(IIncrementStrategyFinder IncrementStrategyFinder, IGitVersionConfiguration Configuration) +internal record MainlineContext(IIncrementStrategyFinder IncrementStrategyFinder, IGitVersionConfiguration Configuration, IGitRepository Repository, GitVersionContext GitverContext) { public IIncrementStrategyFinder IncrementStrategyFinder { get; } = IncrementStrategyFinder.NotNull(); public IGitVersionConfiguration Configuration { get; } = Configuration.NotNull(); + public IGitRepository Repository { get; } = Repository.NotNull(); + public GitVersionContext GitverContext { get; } = GitverContext.NotNull(); public string? TargetLabel { get; init; } diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs b/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs index 18b41fe1e0..00083dc6f9 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs @@ -18,7 +18,9 @@ public virtual IEnumerable GetIncrements( iteration: commit.ChildIteration, targetLabel: context.TargetLabel, incrementStrategyFinder: context.IncrementStrategyFinder, - configuration: context.Configuration + configuration: context.Configuration, + repository: context.Repository, + gitverContext: context.GitverContext ); context.Label ??= baseVersion.Operator?.Label; diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs b/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs index c625137232..1e95994982 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs @@ -16,7 +16,9 @@ public virtual IEnumerable GetIncrements( iteration: commit.ChildIteration!, targetLabel: context.TargetLabel, incrementStrategyFinder: context.IncrementStrategyFinder, - configuration: context.Configuration + configuration: context.Configuration, + repository: context.Repository, + gitverContext: context.GitverContext ); context.Label ??= baseVersion.Operator?.Label; diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index 94ce4155da..88e5c407a3 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -1,14 +1,14 @@ +using System.Text.RegularExpressions; using GitVersion.Extensions; using GitVersion.Git; namespace GitVersion.VersionCalculation; -internal class PathFilter(IGitRepository repository, GitVersionContext context, IEnumerable paths, PathFilter.PathFilterMode mode = PathFilter.PathFilterMode.Inclusive) : IVersionFilter +internal class PathFilter(IGitRepository repository, GitVersionContext context, IEnumerable paths) : IVersionFilter { public enum PathFilterMode { Inclusive = 0, Exclusive = 1 } private readonly IEnumerable paths = paths.NotNull(); - private readonly PathFilterMode mode = mode; private readonly GitVersionContext context = context; public bool Exclude(IBaseVersion baseVersion, out string? reason) @@ -31,22 +31,10 @@ public bool Exclude(ICommit? commit, out string? reason) if (patchPaths != null) { - switch (this.mode) + if (this.paths.Any(path => patchPaths.All(p => Regex.IsMatch(p, path, RegexOptions.IgnoreCase)))) { - case PathFilterMode.Inclusive: - if (!this.paths.Any(path => patchPaths.Any(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) - { - reason = "Source was ignored due to commit path is not present"; - return true; - } - break; - case PathFilterMode.Exclusive: - if (this.paths.Any(path => patchPaths.All(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase)))) - { - reason = "Source was ignored due to commit path excluded"; - return true; - } - break; + reason = "Source was ignored due to commit path matching ignore regex"; + return true; } } } diff --git a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs index 39eadbd222..02813daabc 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs @@ -156,10 +156,10 @@ private SemanticVersion CalculateSemanticVersion( private NextVersion CalculateNextVersion(IBranch branch, IGitVersionConfiguration configuration) { - var nextVersions = GetNextVersions(branch, configuration); + var nextVersions = GetNextVersions(branch, configuration).OrderByDescending(v => v.IncrementedVersion); log.Separator(); - var maxVersion = nextVersions.Max() + var maxVersion = nextVersions.FirstOrDefault(v => ShouldIncludeVersion(configuration, v)) ?? throw new GitVersionException("No base versions determined on the current branch."); ICommit? latestBaseVersionSource; @@ -168,6 +168,7 @@ private NextVersion CalculateNextVersion(IBranch branch, IGitVersionConfiguratio .Where( element => element.BaseVersion.BaseVersionSource != null && element.IncrementedVersion == maxVersion.IncrementedVersion + && ShouldIncludeVersion(configuration, element) ).ToArray(); if (matchingVersionsOnceIncremented.Length > 1) { @@ -193,11 +194,11 @@ private NextVersion CalculateNextVersion(IBranch branch, IGitVersionConfiguratio .Where(v => v.BaseVersion.BaseVersionSource != null) .OrderByDescending(v => v.IncrementedVersion) .ThenByDescending(v => v.BaseVersion.BaseVersionSource?.When) - .FirstOrDefault(); + .FirstOrDefault(v => ShouldIncludeVersion(configuration, v)); version ??= versions.Where(v => v.BaseVersion.BaseVersionSource == null) .OrderByDescending(v => v.IncrementedVersion) - .First(); + .First(v => ShouldIncludeVersion(configuration, v)); latestBaseVersionSource = version.BaseVersion.BaseVersionSource; } @@ -217,6 +218,9 @@ private NextVersion CalculateNextVersion(IBranch branch, IGitVersionConfiguratio return new(maxVersion.IncrementedVersion, calculatedBase, maxVersion.BranchConfiguration); } + private bool ShouldIncludeVersion(IGitVersionConfiguration configuration, NextVersion version) => + configuration.Ignore.ToFilters(repository, this.Context).All(filter => !filter.Exclude(version.BaseVersion, out _)); + private static NextVersion CompareVersions(NextVersion version1, NextVersion version2) { if (version1.BaseVersion.BaseVersionSource == null) @@ -265,7 +269,8 @@ IEnumerable GetNextVersionsInternal() foreach (var baseVersion in versionStrategy.GetBaseVersions(effectiveBranchConfiguration)) { log.Info(baseVersion.ToString()); - if (IncludeVersion(baseVersion, configuration.Ignore)) + if (versionStrategy is not FallbackVersionStrategy || IncludeVersion(baseVersion, configuration.Ignore)) + //Defer the version inclusion check to the caller, for strategies other than FallbackVersionStrategy { atLeastOneBaseVersionReturned = true; diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs index 1e0dd74209..5a7aafafe5 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs @@ -11,6 +11,7 @@ namespace GitVersion.VersionCalculation; internal sealed class MainlineVersionStrategy( Lazy contextLazy, + IGitRepository repository, IRepositoryStore repositoryStore, ITaggedSemanticVersionService taggedSemanticVersionService, IIncrementStrategyFinder incrementStrategyFinder) @@ -19,6 +20,7 @@ internal sealed class MainlineVersionStrategy( private volatile int iterationCounter; private readonly Lazy contextLazy = contextLazy.NotNull(); private readonly ITaggedSemanticVersionService taggedSemanticVersionService = taggedSemanticVersionService.NotNull(); + private readonly IGitRepository repository = repository.NotNull(); private readonly IRepositoryStore repositoryStore = repositoryStore.NotNull(); private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull(); @@ -323,16 +325,16 @@ private bool IterateOverCommitsRecursive( return result; } - private static BaseVersion DetermineBaseVersion(MainlineIteration iteration, string? targetLabel, + private BaseVersion DetermineBaseVersion(MainlineIteration iteration, string? targetLabel, IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration) - => DetermineBaseVersionRecursive(iteration, targetLabel, incrementStrategyFinder, configuration); + => DetermineBaseVersionRecursive(iteration, targetLabel, incrementStrategyFinder, configuration, this.repository, this.Context); internal static BaseVersion DetermineBaseVersionRecursive(MainlineIteration iteration, string? targetLabel, - IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration) + IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration, IGitRepository repository, GitVersionContext gitverContext) { iteration.NotNull(); - var incrementSteps = GetIncrements(iteration, targetLabel, incrementStrategyFinder, configuration).ToArray(); + var incrementSteps = GetIncrements(iteration, targetLabel, incrementStrategyFinder, configuration, repository, gitverContext).ToArray(); BaseVersion? result = null; foreach (var baseVersionIncrement in incrementSteps) @@ -355,15 +357,20 @@ internal static BaseVersion DetermineBaseVersionRecursive(MainlineIteration iter } private static IEnumerable GetIncrements(MainlineIteration iteration, string? targetLabel, - IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration) + IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration, IGitRepository repository, GitVersionContext gitverContext) { - MainlineContext context = new(incrementStrategyFinder, configuration) + MainlineContext context = new(incrementStrategyFinder, configuration, repository, gitverContext) { TargetLabel = targetLabel }; foreach (var commit in iteration.Commits) { + if (configuration.Ignore.ToFilters(repository, gitverContext).OfType().Any(f => f.Exclude(commit.Value, out _))) + { + continue; + } + foreach (var item in TrunkContextPreEnricherCollection) { item.Enrich(iteration, commit, context); From e84e12bc4e4869a574e5fd1c34549e6d92c64088 Mon Sep 17 00:00:00 2001 From: roeil Date: Fri, 14 Mar 2025 09:56:32 +0200 Subject: [PATCH 11/14] refactor: compile and cache regexes --- .../Configuration/IIgnoreConfiguration.cs | 2 +- .../VersionCalculation/PathFilter.cs | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs b/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs index ab3ebb9da3..d94c778fb1 100644 --- a/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs +++ b/src/GitVersion.Core/Configuration/IIgnoreConfiguration.cs @@ -8,5 +8,5 @@ public interface IIgnoreConfiguration IReadOnlyCollection Paths { get; } - public bool IsEmpty => Before == null && Shas.Count == 0 && Paths.Count == 0; + bool IsEmpty => Before == null && Shas.Count == 0 && Paths.Count == 0; } diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index 88e5c407a3..1c9f81326f 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -6,10 +6,9 @@ namespace GitVersion.VersionCalculation; internal class PathFilter(IGitRepository repository, GitVersionContext context, IEnumerable paths) : IVersionFilter { - public enum PathFilterMode { Inclusive = 0, Exclusive = 1 } - - private readonly IEnumerable paths = paths.NotNull(); private readonly GitVersionContext context = context; + private readonly List pathsRegexes = paths.Select(path => new Regex(path, RegexOptions.IgnoreCase | RegexOptions.Compiled)).ToList(); + private readonly Dictionary pathMatchCache = []; public bool Exclude(IBaseVersion baseVersion, out string? reason) { @@ -31,10 +30,19 @@ public bool Exclude(ICommit? commit, out string? reason) if (patchPaths != null) { - if (this.paths.Any(path => patchPaths.All(p => Regex.IsMatch(p, path, RegexOptions.IgnoreCase)))) + foreach (var path in patchPaths) { - reason = "Source was ignored due to commit path matching ignore regex"; - return true; + if (!pathMatchCache.TryGetValue(path, out var isMatch)) + { + isMatch = this.pathsRegexes.Any(regex => regex.IsMatch(path)); + pathMatchCache[path] = isMatch; + } + + if (isMatch) + { + reason = "Source was ignored due to commit path matching ignore regex"; + return true; + } } } } From 001b6739ed0051447b4f71ccf21e16631e3b2507 Mon Sep 17 00:00:00 2001 From: roeil Date: Fri, 14 Mar 2025 10:43:11 +0200 Subject: [PATCH 12/14] revert: mainline defer filtering of commits --- .../Mainline/MainlineContext.cs | 4 +--- .../NonTrunk/MergeCommitOnNonTrunkBase.cs | 4 +--- .../Mainline/Trunk/MergeCommitOnTrunkBase.cs | 4 +--- .../MainlineVersionStrategy.cs | 19 ++++++------------- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs b/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs index 9ee5af759d..3657484b37 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/MainlineContext.cs @@ -4,13 +4,11 @@ namespace GitVersion.VersionCalculation.Mainline; -internal record MainlineContext(IIncrementStrategyFinder IncrementStrategyFinder, IGitVersionConfiguration Configuration, IGitRepository Repository, GitVersionContext GitverContext) +internal record MainlineContext(IIncrementStrategyFinder IncrementStrategyFinder, IGitVersionConfiguration Configuration) { public IIncrementStrategyFinder IncrementStrategyFinder { get; } = IncrementStrategyFinder.NotNull(); public IGitVersionConfiguration Configuration { get; } = Configuration.NotNull(); - public IGitRepository Repository { get; } = Repository.NotNull(); - public GitVersionContext GitverContext { get; } = GitverContext.NotNull(); public string? TargetLabel { get; init; } diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs b/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs index 00083dc6f9..18b41fe1e0 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/NonTrunk/MergeCommitOnNonTrunkBase.cs @@ -18,9 +18,7 @@ public virtual IEnumerable GetIncrements( iteration: commit.ChildIteration, targetLabel: context.TargetLabel, incrementStrategyFinder: context.IncrementStrategyFinder, - configuration: context.Configuration, - repository: context.Repository, - gitverContext: context.GitverContext + configuration: context.Configuration ); context.Label ??= baseVersion.Operator?.Label; diff --git a/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs b/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs index 1e95994982..c625137232 100644 --- a/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs +++ b/src/GitVersion.Core/VersionCalculation/Mainline/Trunk/MergeCommitOnTrunkBase.cs @@ -16,9 +16,7 @@ public virtual IEnumerable GetIncrements( iteration: commit.ChildIteration!, targetLabel: context.TargetLabel, incrementStrategyFinder: context.IncrementStrategyFinder, - configuration: context.Configuration, - repository: context.Repository, - gitverContext: context.GitverContext + configuration: context.Configuration ); context.Label ??= baseVersion.Operator?.Label; diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs index 5a7aafafe5..1e0dd74209 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MainlineVersionStrategy.cs @@ -11,7 +11,6 @@ namespace GitVersion.VersionCalculation; internal sealed class MainlineVersionStrategy( Lazy contextLazy, - IGitRepository repository, IRepositoryStore repositoryStore, ITaggedSemanticVersionService taggedSemanticVersionService, IIncrementStrategyFinder incrementStrategyFinder) @@ -20,7 +19,6 @@ internal sealed class MainlineVersionStrategy( private volatile int iterationCounter; private readonly Lazy contextLazy = contextLazy.NotNull(); private readonly ITaggedSemanticVersionService taggedSemanticVersionService = taggedSemanticVersionService.NotNull(); - private readonly IGitRepository repository = repository.NotNull(); private readonly IRepositoryStore repositoryStore = repositoryStore.NotNull(); private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull(); @@ -325,16 +323,16 @@ private bool IterateOverCommitsRecursive( return result; } - private BaseVersion DetermineBaseVersion(MainlineIteration iteration, string? targetLabel, + private static BaseVersion DetermineBaseVersion(MainlineIteration iteration, string? targetLabel, IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration) - => DetermineBaseVersionRecursive(iteration, targetLabel, incrementStrategyFinder, configuration, this.repository, this.Context); + => DetermineBaseVersionRecursive(iteration, targetLabel, incrementStrategyFinder, configuration); internal static BaseVersion DetermineBaseVersionRecursive(MainlineIteration iteration, string? targetLabel, - IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration, IGitRepository repository, GitVersionContext gitverContext) + IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration) { iteration.NotNull(); - var incrementSteps = GetIncrements(iteration, targetLabel, incrementStrategyFinder, configuration, repository, gitverContext).ToArray(); + var incrementSteps = GetIncrements(iteration, targetLabel, incrementStrategyFinder, configuration).ToArray(); BaseVersion? result = null; foreach (var baseVersionIncrement in incrementSteps) @@ -357,20 +355,15 @@ internal static BaseVersion DetermineBaseVersionRecursive(MainlineIteration iter } private static IEnumerable GetIncrements(MainlineIteration iteration, string? targetLabel, - IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration, IGitRepository repository, GitVersionContext gitverContext) + IIncrementStrategyFinder incrementStrategyFinder, IGitVersionConfiguration configuration) { - MainlineContext context = new(incrementStrategyFinder, configuration, repository, gitverContext) + MainlineContext context = new(incrementStrategyFinder, configuration) { TargetLabel = targetLabel }; foreach (var commit in iteration.Commits) { - if (configuration.Ignore.ToFilters(repository, gitverContext).OfType().Any(f => f.Exclude(commit.Value, out _))) - { - continue; - } - foreach (var item in TrunkContextPreEnricherCollection) { item.Enrich(iteration, commit, context); From ec630ba9fac67e5afa52106a8eea6f1ddf9faec2 Mon Sep 17 00:00:00 2001 From: roeil Date: Fri, 14 Mar 2025 10:56:27 +0200 Subject: [PATCH 13/14] refactor: patch finding --- src/GitVersion.Core/Git/IGitRepository.cs | 2 +- .../Git/GitRepository.cs | 39 ++++++++++++------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/GitVersion.Core/Git/IGitRepository.cs b/src/GitVersion.Core/Git/IGitRepository.cs index e98632a970..1984f52a47 100644 --- a/src/GitVersion.Core/Git/IGitRepository.cs +++ b/src/GitVersion.Core/Git/IGitRepository.cs @@ -16,7 +16,7 @@ public interface IGitRepository : IDisposable IRemoteCollection Remotes { get; } ICommit? FindMergeBase(ICommit commit, ICommit otherCommit); - IEnumerable? FindPatchPaths(ICommit commit, string? tagPrefix); + IReadOnlyList? FindPatchPaths(ICommit commit, string? tagPrefix); int UncommittedChangesCount(); void DiscoverRepository(string? gitDirectory); } diff --git a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs index 810850976b..709ed3c303 100644 --- a/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs +++ b/src/GitVersion.LibGit2Sharp/Git/GitRepository.cs @@ -1,4 +1,4 @@ -using System.Text.RegularExpressions; +using System.Collections.Concurrent; using GitVersion.Extensions; using GitVersion.Helpers; using LibGit2Sharp; @@ -8,7 +8,7 @@ namespace GitVersion.Git; internal sealed partial class GitRepository { private Lazy? repositoryLazy; - private readonly Dictionary patchCache = []; + private readonly ConcurrentDictionary?> patchPathsCache = new(); private IRepository RepositoryInstance { @@ -55,28 +55,37 @@ public void DiscoverRepository(string? gitDirectory) }); } - public IEnumerable? FindPatchPaths(ICommit commit, string? tagPrefix) + public IReadOnlyList? FindPatchPaths(ICommit commit, string? tagPrefix) { - Patch? patch = null; - var innerCommit = this.RepositoryInstance.Commits.First(c => c.Sha == commit.Sha); - var match = new Regex($"^({tagPrefix ?? ""}).*$", RegexOptions.Compiled); + ArgumentNullException.ThrowIfNull(commit); - if (!this.patchCache.ContainsKey(commit.Sha)) + return patchPathsCache.GetOrAdd(commit.Sha, commitSha => { - if (!this.RepositoryInstance.Tags.Any(t => t.Target.Sha == commit.Sha && match.IsMatch(t.FriendlyName))) + if (PatchPathsNeedsToBeDetermined(commitSha, tagPrefix)) { + var innerCommit = this.RepositoryInstance.Commits.First(c => c.Sha == commitSha); Tree commitTree = innerCommit.Tree; // Main Tree Tree? parentCommitTree = innerCommit.Parents.FirstOrDefault()?.Tree; // Secondary Tree - patch = this.RepositoryInstance.Diff.Compare(parentCommitTree, commitTree); // Difference - this.patchCache[commit.Sha] = patch; + Patch patch = this.RepositoryInstance.Diff.Compare(parentCommitTree, commitTree); // Difference + return patch.Select(element => element.Path).ToList(); } - } - else + return null; + }); + } + + private bool PatchPathsNeedsToBeDetermined(string commitSha, string? tagPrefix) + { + if (!string.IsNullOrEmpty(tagPrefix)) { - patch = this.patchCache[commit.Sha]; + foreach (var tag in this.RepositoryInstance.Tags.Where(element => element.Target.Sha == commitSha)) + { + if (tag.FriendlyName.StartsWith(tagPrefix, StringComparison.InvariantCulture)) + { + return false; + } + } } - - return patch?.Select(p => p.Path); + return true; } public int UncommittedChangesCount() From dd643e2d7512face730ea296b12e2b5562f002f0 Mon Sep 17 00:00:00 2001 From: roeil Date: Fri, 14 Mar 2025 11:24:05 +0200 Subject: [PATCH 14/14] build --- src/GitVersion.Core/PublicAPI.Unshipped.txt | 4 +++- src/GitVersion.Core/VersionCalculation/PathFilter.cs | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index de4c753804..2ef5f789ae 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -2,7 +2,8 @@ GitVersion.Configuration.EffectiveConfiguration.EffectiveConfiguration(GitVersion.Configuration.IGitVersionConfiguration! configuration, GitVersion.Configuration.IBranchConfiguration! branchConfiguration, GitVersion.Git.IGitRepository? repository = null, System.Lazy? versionContext = null, GitVersion.Configuration.EffectiveConfiguration? fallbackConfiguration = null) -> void GitVersion.Configuration.EffectiveConfiguration.VersionFilters.get -> System.Collections.Generic.IEnumerable! GitVersion.Configuration.IIgnoreConfiguration.Paths.get -> System.Collections.Generic.IReadOnlyCollection! -GitVersion.Git.IGitRepository.FindPatchPaths(GitVersion.Git.ICommit! commit, string? tagPrefix) -> System.Collections.Generic.IEnumerable? +GitVersion.Extensions.FileSystemExtensions +GitVersion.Git.IGitRepository.FindPatchPaths(GitVersion.Git.ICommit! commit, string? tagPrefix) -> System.Collections.Generic.IReadOnlyList? GitVersion.VersionCalculation.BaseVersion.BaseVersion(string! source, GitVersion.SemanticVersion! semanticVersion, GitVersion.Git.ICommit? baseVersionSource = null, GitVersion.VersionCalculation.VersionIncrementSourceType sourceType = GitVersion.VersionCalculation.VersionIncrementSourceType.Tree) -> void GitVersion.VersionCalculation.BaseVersion.SourceType.get -> GitVersion.VersionCalculation.VersionIncrementSourceType GitVersion.VersionCalculation.BaseVersion.SourceType.init -> void @@ -16,3 +17,4 @@ GitVersion.VersionCalculation.VersionIncrementSourceType.Fallback = 2 -> GitVers GitVersion.VersionCalculation.VersionIncrementSourceType.NextVersionConfig = 3 -> GitVersion.VersionCalculation.VersionIncrementSourceType GitVersion.VersionCalculation.VersionIncrementSourceType.Tag = 1 -> GitVersion.VersionCalculation.VersionIncrementSourceType GitVersion.VersionCalculation.VersionIncrementSourceType.Tree = 0 -> GitVersion.VersionCalculation.VersionIncrementSourceType +static GitVersion.Extensions.FileSystemExtensions.GetLastDirectoryWrite(this System.IO.Abstractions.IFileSystem! fileSystem, string! path) -> long diff --git a/src/GitVersion.Core/VersionCalculation/PathFilter.cs b/src/GitVersion.Core/VersionCalculation/PathFilter.cs index 1c9f81326f..566c899cf7 100644 --- a/src/GitVersion.Core/VersionCalculation/PathFilter.cs +++ b/src/GitVersion.Core/VersionCalculation/PathFilter.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using GitVersion.Extensions; using GitVersion.Git; namespace GitVersion.VersionCalculation;