From 8263627e81db2508d96937499365b0a0880c0eef Mon Sep 17 00:00:00 2001 From: Willie Slepecki Date: Mon, 18 Oct 2021 16:49:28 -0400 Subject: [PATCH] Added Infinite loop protection --- .../IBranchConfigurationCalculator.cs | 2 +- .../BranchConfigurationCalculator.cs | 21 ++++++++++++++----- .../Core/GitVersionContextFactory.cs | 2 +- .../InfiniteLoopProtectionException.cs | 12 +++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 src/GitVersion.Core/Model/Exceptions/InfiniteLoopProtectionException.cs diff --git a/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs b/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs index 96c17b3489..243c6e49d9 100644 --- a/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs +++ b/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs @@ -8,6 +8,6 @@ public interface IBranchConfigurationCalculator /// /// Gets the for the current commit. /// - BranchConfig GetBranchConfiguration(IBranch targetBranch, ICommit? currentCommit, Config configuration, IList? excludedInheritBranches = null); + BranchConfig GetBranchConfiguration(int recursiveProtection, IBranch targetBranch, ICommit? currentCommit, Config configuration, IList? excludedInheritBranches = null); } } diff --git a/src/GitVersion.Core/Configuration/BranchConfigurationCalculator.cs b/src/GitVersion.Core/Configuration/BranchConfigurationCalculator.cs index 3434dcf2cd..ffcfc58068 100644 --- a/src/GitVersion.Core/Configuration/BranchConfigurationCalculator.cs +++ b/src/GitVersion.Core/Configuration/BranchConfigurationCalculator.cs @@ -6,6 +6,7 @@ using GitVersion.Extensions; using GitVersion.Logging; using GitVersion.Model.Configuration; +using GitVersion.Model.Exceptions; namespace GitVersion.Configuration { @@ -16,6 +17,8 @@ public class BranchConfigurationCalculator : IBranchConfigurationCalculator private readonly ILog log; private readonly IRepositoryStore repositoryStore; + private readonly int _infiniteLoopProtectionLevel = 50; + public BranchConfigurationCalculator(ILog log, IRepositoryStore repositoryStore) { this.log = log ?? throw new ArgumentNullException(nameof(log)); @@ -25,8 +28,14 @@ public BranchConfigurationCalculator(ILog log, IRepositoryStore repositoryStore) /// /// Gets the for the current commit. /// - public BranchConfig GetBranchConfiguration(IBranch targetBranch, ICommit? currentCommit, Config configuration, IList? excludedInheritBranches = null) + public BranchConfig GetBranchConfiguration(int recursiveLevel, IBranch targetBranch, ICommit? currentCommit, Config configuration, IList? excludedInheritBranches = null) { + + if (recursiveLevel >= _infiniteLoopProtectionLevel) + { + throw new InfiniteLoopProtectionException("Inherited branch configuration caused an infinite loop...breaking."); + } + var matchingBranches = configuration.GetConfigForBranch(targetBranch.Name.WithoutRemote); if (matchingBranches == null) @@ -44,7 +53,7 @@ public BranchConfig GetBranchConfiguration(IBranch targetBranch, ICommit? curren if (matchingBranches.Increment == IncrementStrategy.Inherit) { - matchingBranches = InheritBranchConfiguration(targetBranch, matchingBranches, currentCommit, configuration, excludedInheritBranches); + matchingBranches = InheritBranchConfiguration(recursiveLevel, targetBranch, matchingBranches, currentCommit, configuration, excludedInheritBranches); if (matchingBranches.Name!.IsEquivalentTo(FallbackConfigName) && matchingBranches.Increment == IncrementStrategy.Inherit) { // We tried, and failed to inherit, just fall back to patch @@ -56,10 +65,12 @@ public BranchConfig GetBranchConfiguration(IBranch targetBranch, ICommit? curren } // TODO I think we need to take a fresh approach to this.. it's getting really complex with heaps of edge cases - private BranchConfig InheritBranchConfiguration(IBranch targetBranch, BranchConfig branchConfiguration, ICommit? currentCommit, Config configuration, IList? excludedInheritBranches) + private BranchConfig InheritBranchConfiguration(int recursiveLevel, IBranch targetBranch, BranchConfig branchConfiguration, ICommit? currentCommit, Config configuration, IList? excludedInheritBranches) { using (this.log.IndentLog("Attempting to inherit branch configuration from parent branch")) { + recursiveLevel += 1; + var excludedBranches = new[] { targetBranch }; // Check if we are a merge commit. If so likely we are a pull request var parentCount = currentCommit?.Parents.Count(); @@ -107,7 +118,7 @@ private BranchConfig InheritBranchConfiguration(IBranch targetBranch, BranchConf if (possibleParents.Count == 1) { - var branchConfig = GetBranchConfiguration(possibleParents[0], currentCommit, configuration, excludedInheritBranches); + var branchConfig = GetBranchConfiguration(recursiveLevel, possibleParents[0], currentCommit, configuration, excludedInheritBranches); // If we have resolved a fallback config we should not return that we have got config if (branchConfig.Name != FallbackConfigName) { @@ -155,7 +166,7 @@ private BranchConfig InheritBranchConfiguration(IBranch targetBranch, BranchConf }; } - var inheritingBranchConfig = GetBranchConfiguration(chosenBranch, currentCommit, configuration, excludedInheritBranches)!; + var inheritingBranchConfig = GetBranchConfiguration(recursiveLevel, chosenBranch, currentCommit, configuration, excludedInheritBranches)!; var configIncrement = inheritingBranchConfig.Increment; if (inheritingBranchConfig.Name!.IsEquivalentTo(FallbackConfigName) && configIncrement == IncrementStrategy.Inherit) { diff --git a/src/GitVersion.Core/Core/GitVersionContextFactory.cs b/src/GitVersion.Core/Core/GitVersionContextFactory.cs index d6af78eb92..2f14e50362 100644 --- a/src/GitVersion.Core/Core/GitVersionContextFactory.cs +++ b/src/GitVersion.Core/Core/GitVersionContextFactory.cs @@ -37,7 +37,7 @@ public GitVersionContext Create(GitVersionOptions? gitVersionOptions) currentBranch = branchForCommit ?? currentBranch; } - var currentBranchConfig = this.branchConfigurationCalculator.GetBranchConfiguration(currentBranch, currentCommit, configuration); + var currentBranchConfig = this.branchConfigurationCalculator.GetBranchConfiguration(0, currentBranch, currentCommit, configuration); var effectiveConfiguration = configuration.CalculateEffectiveConfiguration(currentBranchConfig); var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, effectiveConfiguration); var numberOfUncommittedChanges = this.repositoryStore.GetNumberOfUncommittedChanges(); diff --git a/src/GitVersion.Core/Model/Exceptions/InfiniteLoopProtectionException.cs b/src/GitVersion.Core/Model/Exceptions/InfiniteLoopProtectionException.cs new file mode 100644 index 0000000000..e7cb11d303 --- /dev/null +++ b/src/GitVersion.Core/Model/Exceptions/InfiniteLoopProtectionException.cs @@ -0,0 +1,12 @@ +using System; + +namespace GitVersion.Model.Exceptions +{ + public class InfiniteLoopProtectionException : Exception + { + public InfiniteLoopProtectionException(string messageFormat) + : base(messageFormat) + { + } + } +}