diff --git a/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs b/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs
index ed49a4e085..92aeb7b74c 100644
--- a/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs
+++ b/src/GitVersion.Core/Configuration/Abstractions/IBranchConfigurationCalculator.cs
@@ -7,5 +7,5 @@ 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 e83654615c..63191e0902 100644
--- a/src/GitVersion.Core/Configuration/BranchConfigurationCalculator.cs
+++ b/src/GitVersion.Core/Configuration/BranchConfigurationCalculator.cs
@@ -3,6 +3,7 @@
using GitVersion.Extensions;
using GitVersion.Logging;
using GitVersion.Model.Configuration;
+using GitVersion.Model.Exceptions;
namespace GitVersion.Configuration;
@@ -13,6 +14,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.NotNull();
@@ -22,8 +25,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)
@@ -41,7 +50,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
@@ -53,10 +62,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();
@@ -106,7 +117,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)
{
@@ -154,7 +165,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 c249ce2c38..2ca5f61e7a 100644
--- a/src/GitVersion.Core/Core/GitVersionContextFactory.cs
+++ b/src/GitVersion.Core/Core/GitVersionContextFactory.cs
@@ -36,7 +36,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)
+ {
+ }
+ }
+}