diff --git a/src/GitVersionCore.Tests/Core/RepositoryExtensionsTests.cs b/src/GitVersionCore.Tests/Core/RepositoryExtensionsTests.cs new file mode 100644 index 0000000000..1dc7ceb929 --- /dev/null +++ b/src/GitVersionCore.Tests/Core/RepositoryExtensionsTests.cs @@ -0,0 +1,197 @@ +using GitTools.Testing; +using GitVersion.Logging; +using GitVersion.Extensions; +using GitVersionCore.Tests.Helpers; +using LibGit2Sharp; +using NUnit.Framework; +using System.Linq; +using NSubstitute; +using System; +using System.Collections.Generic; +using GitVersion; + +namespace GitVersionCore.Tests +{ + [TestFixture] + public class RepositoryExtensionsTests : TestBase + { + [Test] + public void EnsureLocalBranchExistsForCurrentBranch_CaseInsensitivelyMatchesBranches() + { + var log = Substitute.For(); + var repository = MockRepository(); + var remote = MockRemote(repository); + + repository.EnsureLocalBranchExistsForCurrentBranch(log, remote, "refs/heads/featurE/feat-test"); + } + + private IGitRepository MockRepository() + { + var repository = Substitute.For(); + var commands = Substitute.For(); + repository.Commands.Returns(commands); + return repository; + } + + private Remote MockRemote(IGitRepository repository) + { + var branches = new TestableBranchCollection(repository); + var tipId = new ObjectId("c6d8764d20ff16c0df14c73680e52b255b608926"); + var tip = new TestableCommit(repository, tipId); + var head = branches.Add("refs/heads/feature/feat-test", tip); + var remote = new TesatbleRemote("origin"); + var references = new TestableReferenceCollection(); + var reference = references.Add("develop", "refs/heads/develop"); + + repository.Refs.Returns(references); + repository.Head.Returns(head); + repository.Branches.Returns(branches); + return remote; + } + + private class TestableBranchCollection : BranchCollection + { + private readonly IRepository repository; + public TestableBranchCollection(IRepository repository) + { + } + + IDictionary branches = new Dictionary(); + + public override Branch this[string name] => + this.branches.ContainsKey(name) + ? this.branches[name] + : null; + + public override Branch Add(string name, Commit commit) + { + var branch = new TestableBranch(name, commit); + this.branches.Add(name, branch); + return branch; + } + + public override Branch Add(string name, string committish) + { + var id = new ObjectId(committish); + var commit = new TestableCommit(this.repository, id); + return Add(name, commit); + } + + public override Branch Add(string name, Commit commit, bool allowOverwrite) + { + return Add(name, commit); + } + + public override Branch Add(string name, string committish, bool allowOverwrite) + { + return Add(name, committish); + } + + public override IEnumerator GetEnumerator() + { + return this.branches.Values.GetEnumerator(); + } + + public override void Remove(string name) + { + this.branches.Remove(name); + } + + public override void Remove(string name, bool isRemote) + { + this.branches.Remove(name); + } + + public override void Remove(Branch branch) + { + this.branches.Remove(branch.CanonicalName); + } + + public override Branch Update(Branch branch, params Action[] actions) + { + return base.Update(branch, actions); + } + } + + private class TestableBranch : Branch + { + private readonly string canonicalName; + private readonly Commit tip; + + public TestableBranch(string canonicalName, Commit tip) + { + this.tip = tip; + this.canonicalName = canonicalName; + } + + public override string CanonicalName => this.canonicalName; + public override Commit Tip => this.tip; + } + + private class TestableCommit : Commit, IBelongToARepository + { + private IRepository repository; + private ObjectId id; + + public TestableCommit(IRepository repository, ObjectId id) + { + this.repository = repository; + this.id = id; + } + + public override ObjectId Id => this.id; + public IRepository Repository => this.repository; + } + + private class TesatbleRemote : Remote + { + private string name; + + public TesatbleRemote(string name) + { + this.name = name; + } + + public override string Name => this.name; + } + + private class TestableReferenceCollection : ReferenceCollection + { + Reference reference; + + public override DirectReference Add(string name, ObjectId targetId) + { + throw new InvalidOperationException("Update should be invoked when case-insensitively comparing branches."); + } + + public override Reference Add(string name, string canonicalRefNameOrObjectish) + { + return this.reference = new TestableReference(canonicalRefNameOrObjectish); + } + + public override Reference UpdateTarget(Reference directRef, ObjectId targetId) + { + return this.reference; + } + + public override Reference this[string name] => this.reference; + } + + private class TestableReference : Reference + { + private readonly string canonicalName; + + public TestableReference(string canonicalName) + { + this.canonicalName = canonicalName; + } + + public override string CanonicalName => this.canonicalName; + + public override DirectReference ResolveToDirectReference() + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/GitVersionCore/Configuration/BranchConfigurationCalculator.cs b/src/GitVersionCore/Configuration/BranchConfigurationCalculator.cs index 918602d571..d3ab36e07c 100644 --- a/src/GitVersionCore/Configuration/BranchConfigurationCalculator.cs +++ b/src/GitVersionCore/Configuration/BranchConfigurationCalculator.cs @@ -41,7 +41,7 @@ public BranchConfig GetBranchConfiguration(Branch targetBranch, Commit currentCo if (matchingBranches.Increment == IncrementStrategy.Inherit) { matchingBranches = InheritBranchConfiguration(targetBranch, matchingBranches, currentCommit, configuration, excludedInheritBranches); - if (matchingBranches.Name == FallbackConfigName && matchingBranches.Increment == IncrementStrategy.Inherit) + if (matchingBranches.Name.IsEquivalentTo(FallbackConfigName) && matchingBranches.Increment == IncrementStrategy.Inherit) { // We tried, and failed to inherit, just fall back to patch matchingBranches.Increment = IncrementStrategy.Patch; @@ -152,7 +152,7 @@ private BranchConfig InheritBranchConfiguration(Branch targetBranch, BranchConfi var inheritingBranchConfig = GetBranchConfiguration(chosenBranch, currentCommit, configuration, excludedInheritBranches); var configIncrement = inheritingBranchConfig.Increment; - if (inheritingBranchConfig.Name == FallbackConfigName && configIncrement == IncrementStrategy.Inherit) + if (inheritingBranchConfig.Name.IsEquivalentTo(FallbackConfigName) && configIncrement == IncrementStrategy.Inherit) { log.Warning("Fallback config inherits by default, dropping to patch increment"); configIncrement = IncrementStrategy.Patch; diff --git a/src/GitVersionCore/Core/GitPreparer.cs b/src/GitVersionCore/Core/GitPreparer.cs index 1ab1a53af3..5bb502edd0 100644 --- a/src/GitVersionCore/Core/GitPreparer.cs +++ b/src/GitVersionCore/Core/GitPreparer.cs @@ -202,7 +202,7 @@ private void CloneRepository(string repositoryUrl, string gitDirectory, Authenti private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string currentBranch, bool isDynamicRepository) { var authentication = options.Value.Authentication; - using var repository = new Repository(gitDirectory); + using var repository = new GitRepository(() => gitDirectory); // Need to ensure the HEAD does not move, this is essentially a BugCheck var expectedSha = repository.Head.Tip.Sha; var expectedBranchName = repository.Head.CanonicalName; @@ -221,7 +221,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur else { log.Info($"Fetching from remote '{remote.Name}' using the following refspecs: {string.Join(", ", remote.FetchRefSpecs.Select(r => r.Specification))}."); - Commands.Fetch(repository, remote.Name, new string[0], authentication.ToFetchOptions(), null); + repository.Commands.Fetch(remote.Name, new string[0], authentication.ToFetchOptions(), null); } repository.EnsureLocalBranchExistsForCurrentBranch(log, remote, currentBranch); @@ -262,7 +262,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur if (matchingCurrentBranch != null) { log.Info($"Checking out local branch '{currentBranch}'."); - Commands.Checkout(repository, matchingCurrentBranch); + repository.Commands.Checkout(matchingCurrentBranch); } else if (localBranchesWhereCommitShaIsHead.Count > 1) { @@ -271,11 +271,11 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur const string moveBranchMsg = "Move one of the branches along a commit to remove warning"; log.Warning($"Found more than one local branch pointing at the commit '{headSha}' ({csvNames})."); - var master = localBranchesWhereCommitShaIsHead.SingleOrDefault(n => n.FriendlyName == "master"); + var master = localBranchesWhereCommitShaIsHead.SingleOrDefault(n => n.FriendlyName.IsEquivalentTo("master")); if (master != null) { log.Warning("Because one of the branches is 'master', will build master." + moveBranchMsg); - Commands.Checkout(repository, master); + repository.Commands.Checkout(master); } else { @@ -284,7 +284,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur { var branchWithoutSeparator = branchesWithoutSeparators[0]; log.Warning($"Choosing {branchWithoutSeparator.CanonicalName} as it is the only branch without / or - in it. " + moveBranchMsg); - Commands.Checkout(repository, branchWithoutSeparator); + repository.Commands.Checkout(branchWithoutSeparator); } else { @@ -300,7 +300,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur else { log.Info($"Checking out local branch 'refs/heads/{localBranchesWhereCommitShaIsHead[0].FriendlyName}'."); - Commands.Checkout(repository, repository.Branches[localBranchesWhereCommitShaIsHead[0].FriendlyName]); + repository.Commands.Checkout(repository.Branches[localBranchesWhereCommitShaIsHead[0].FriendlyName]); } } finally diff --git a/src/GitVersionCore/Core/GitRepository.cs b/src/GitVersionCore/Core/GitRepository.cs index b5c314bd7d..27a5121280 100644 --- a/src/GitVersionCore/Core/GitRepository.cs +++ b/src/GitVersionCore/Core/GitRepository.cs @@ -5,14 +5,20 @@ namespace GitVersion { - public class GitRepository : IRepository + public class GitRepository : IGitRepository { private Lazy repositoryLazy; private IRepository repositoryInstance => repositoryLazy.Value; public GitRepository(IOptions options) + : this(() => options.Value.DotGitDirectory) { - repositoryLazy = new Lazy(() => new Repository(options.Value.DotGitDirectory)); + } + + public GitRepository(Func getDotGitDirectory) + { + repositoryLazy = new Lazy(() => new Repository(getDotGitDirectory())); + Commands = new GitRepositoryCommands(repositoryLazy); } public void Dispose() @@ -161,5 +167,7 @@ public void RevParse(string revision, out Reference reference, out GitObject obj public Network Network => repositoryInstance.Network; public StashCollection Stashes => repositoryInstance.Stashes; + + public IGitRepositoryCommands Commands { get; } } } diff --git a/src/GitVersionCore/Core/GitRepositoryCommands.cs b/src/GitVersionCore/Core/GitRepositoryCommands.cs new file mode 100644 index 0000000000..ac12a5efb9 --- /dev/null +++ b/src/GitVersionCore/Core/GitRepositoryCommands.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using LibGit2Sharp; + +namespace GitVersion +{ + /// + /// Default implementation of using + /// the static class. + /// + public class GitRepositoryCommands : IGitRepositoryCommands + { + private readonly Lazy lazyRepository; + private IRepository repository => lazyRepository.Value; + + public GitRepositoryCommands(Lazy lazyRepository) + { + this.lazyRepository = lazyRepository ?? throw new System.ArgumentNullException(nameof(lazyRepository)); + } + + public Branch Checkout(string committishOrBranchSpec) + { + return Commands.Checkout(this.repository, committishOrBranchSpec); + } + + public Branch Checkout(string committishOrBranchSpec, CheckoutOptions options) + { + return Commands.Checkout(this.repository, committishOrBranchSpec, options); + } + + public Branch Checkout(Branch branch) + { + return Commands.Checkout(this.repository, branch); + } + + public Branch Checkout(Branch branch, CheckoutOptions options) + { + return Commands.Checkout(this.repository, branch, options); + } + + public Branch Checkout(Commit commit) + { + return Commands.Checkout(this.repository, commit); + } + + public Branch Checkout(Commit commit, CheckoutOptions options) + { + return Commands.Checkout(this.repository, commit, options); + } + + public void Checkout(Tree tree, CheckoutOptions checkoutOptions, string refLogHeadSpec) + { + Commands.Checkout(this.repository, tree, checkoutOptions, refLogHeadSpec); + } + + public void Fetch(string remote, IEnumerable refspecs, FetchOptions options, string logMessage) + { + Commands.Fetch((Repository)this.repository, remote, refspecs, options, logMessage); + } + + public void Move(string sourcePath, string destinationPath) + { + Commands.Move(this.repository, sourcePath, destinationPath); + } + + public void Move(IEnumerable sourcePaths, IEnumerable destinationPaths) + { + Commands.Move(this.repository, sourcePaths, destinationPaths); + } + + public MergeResult Pull(Signature merger, PullOptions options) + { + return Commands.Pull((Repository)this.repository, merger, options); + } + + public void Remove(string path, bool removeFromWorkingDirectory) + { + Commands.Remove(this.repository, path, removeFromWorkingDirectory); + } + + public void Remove(IEnumerable paths) + { + Commands.Remove(this.repository, paths); + } + + public void Remove(IEnumerable paths, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions) + { + Commands.Remove(this.repository, paths, removeFromWorkingDirectory, explicitPathsOptions); + } + + public void Remove(string path) + { + Commands.Remove(this.repository, path); + } + + public void Remove(string path, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions) + { + Commands.Remove(this.repository, path, removeFromWorkingDirectory, explicitPathsOptions); + } + + public void Stage(string path) + { + Commands.Stage(this.repository, path); + } + + public void Stage(string path, StageOptions stageOptions) + { + Commands.Stage(this.repository, path, stageOptions); + } + + public void Stage(IEnumerable paths) + { + Commands.Stage(this.repository, paths); + } + + public void Stage(IEnumerable paths, StageOptions stageOptions) + { + Commands.Stage(this.repository, paths, stageOptions); + } + + public void Unstage(string path) + { + Commands.Unstage(this.repository, path); + } + + public void Unstage(string path, ExplicitPathsOptions explicitPathsOptions) + { + Commands.Unstage(this.repository, path, explicitPathsOptions); + } + + public void Unstage(IEnumerable paths) + { + Commands.Unstage(this.repository, paths); + } + + public void Unstage(IEnumerable paths, ExplicitPathsOptions explicitPathsOptions) + { + Commands.Unstage(this.repository, paths, explicitPathsOptions); + } + } +} diff --git a/src/GitVersionCore/Core/IGitRepository.cs b/src/GitVersionCore/Core/IGitRepository.cs new file mode 100644 index 0000000000..a2d4817de9 --- /dev/null +++ b/src/GitVersionCore/Core/IGitRepository.cs @@ -0,0 +1,9 @@ +using LibGit2Sharp; + +namespace GitVersion +{ + public interface IGitRepository : IRepository + { + IGitRepositoryCommands Commands { get; } + } +} diff --git a/src/GitVersionCore/Core/IGitRepositoryCommands.cs b/src/GitVersionCore/Core/IGitRepositoryCommands.cs new file mode 100644 index 0000000000..da3a12a7a6 --- /dev/null +++ b/src/GitVersionCore/Core/IGitRepositoryCommands.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using LibGit2Sharp; + +namespace GitVersion +{ + /// + /// Mockable and testable interface wrapper for the static + /// class. + /// + public interface IGitRepositoryCommands + { + Branch Checkout(string committishOrBranchSpec); + Branch Checkout(string committishOrBranchSpec, CheckoutOptions options); + Branch Checkout(Branch branch); + Branch Checkout(Branch branch, CheckoutOptions options); + Branch Checkout(Commit commit); + Branch Checkout(Commit commit, CheckoutOptions options); + void Checkout(Tree tree, CheckoutOptions checkoutOptions, string refLogHeadSpec); + void Fetch(string remote, IEnumerable refspecs, FetchOptions options, string logMessage); + void Move(string sourcePath, string destinationPath); + void Move(IEnumerable sourcePaths, IEnumerable destinationPaths); + MergeResult Pull(Signature merger, PullOptions options); + void Remove(string path, bool removeFromWorkingDirectory); + void Remove(IEnumerable paths); + void Remove(IEnumerable paths, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions); + void Remove(string path); + void Remove(string path, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions); + void Stage(string path); + void Stage(string path, StageOptions stageOptions); + void Stage(IEnumerable paths); + void Stage(IEnumerable paths, StageOptions stageOptions); + void Unstage(string path); + void Unstage(string path, ExplicitPathsOptions explicitPathsOptions); + void Unstage(IEnumerable paths); + void Unstage(IEnumerable paths, ExplicitPathsOptions explicitPathsOptions); + } +} diff --git a/src/GitVersionCore/Core/RepositoryMetadataProvider.cs b/src/GitVersionCore/Core/RepositoryMetadataProvider.cs index 412e8a4a5d..5da1e859d1 100644 --- a/src/GitVersionCore/Core/RepositoryMetadataProvider.cs +++ b/src/GitVersionCore/Core/RepositoryMetadataProvider.cs @@ -184,9 +184,9 @@ public Branch GetTargetBranch(string targetBranch) // In the case where HEAD is not the desired branch, try to find the branch with matching name desiredBranch = repository.Branches? .SingleOrDefault(b => - b.CanonicalName == targetBranch || - b.FriendlyName == targetBranch || - b.NameWithoutRemote() == targetBranch); + b.CanonicalName.IsEquivalentTo(targetBranch) || + b.FriendlyName.IsEquivalentTo(targetBranch) || + b.NameWithoutRemote().IsEquivalentTo(targetBranch)); // Failsafe in case the specified branch is invalid desiredBranch ??= repository.Head; diff --git a/src/GitVersionCore/Extensions/LibGitExtensions.cs b/src/GitVersionCore/Extensions/LibGitExtensions.cs index f6bb5d012f..001dbf59a5 100644 --- a/src/GitVersionCore/Extensions/LibGitExtensions.cs +++ b/src/GitVersionCore/Extensions/LibGitExtensions.cs @@ -38,7 +38,7 @@ public static bool IsSameBranch(this Branch branch, Branch otherBranch) var otherBranchFriendlyName = otherBranch.NameWithoutRemote(); var branchFriendlyName = branch.NameWithoutRemote(); - return otherBranchFriendlyName == branchFriendlyName; + return otherBranchFriendlyName.IsEquivalentTo(branchFriendlyName); } /// diff --git a/src/GitVersionCore/Extensions/RepositoryExtensions.cs b/src/GitVersionCore/Extensions/RepositoryExtensions.cs index c719e34f4a..bd6420b356 100644 --- a/src/GitVersionCore/Extensions/RepositoryExtensions.cs +++ b/src/GitVersionCore/Extensions/RepositoryExtensions.cs @@ -34,13 +34,27 @@ public static void DumpGraph(this IRepository repository, Action writer LibGitExtensions.DumpGraph(repository.Info.Path, writer, maxCommits); } - public static void EnsureLocalBranchExistsForCurrentBranch(this IRepository repo, ILog log, Remote remote, string currentBranch) + public static void EnsureLocalBranchExistsForCurrentBranch(this IGitRepository repo, ILog log, Remote remote, string currentBranch) { + if (log is null) + { + throw new ArgumentNullException(nameof(log)); + } + + if (remote is null) + { + throw new ArgumentNullException(nameof(remote)); + } + if (string.IsNullOrEmpty(currentBranch)) return; var isRef = currentBranch.Contains("refs"); var isBranch = currentBranch.Contains("refs/heads"); - var localCanonicalName = !isRef ? "refs/heads/" + currentBranch : isBranch ? currentBranch : currentBranch.Replace("refs/", "refs/heads/"); + var localCanonicalName = !isRef + ? "refs/heads/" + currentBranch + : isBranch + ? currentBranch + : currentBranch.Replace("refs/", "refs/heads/"); var repoTip = repo.Head.Tip; @@ -54,7 +68,7 @@ public static void EnsureLocalBranchExistsForCurrentBranch(this IRepository repo var repoTipId = repoTip.Id; - if (repo.Branches.All(b => b.CanonicalName != localCanonicalName)) + if (repo.Branches.All(b => !b.CanonicalName.IsEquivalentTo(localCanonicalName))) { log.Info(isBranch ? $"Creating local branch {localCanonicalName}" : $"Creating local branch {localCanonicalName} pointing at {repoTipId}"); @@ -64,10 +78,11 @@ public static void EnsureLocalBranchExistsForCurrentBranch(this IRepository repo { log.Info(isBranch ? $"Updating local branch {localCanonicalName} to point at {repoTip.Sha}" : $"Updating local branch {localCanonicalName} to match ref {currentBranch}"); - repo.Refs.UpdateTarget(repo.Refs[localCanonicalName], repoTipId); + var localRef = repo.Refs[localCanonicalName]; + repo.Refs.UpdateTarget(localRef, repoTipId); } - Commands.Checkout(repo, localCanonicalName); + repo.Commands.Checkout(localCanonicalName); } public static void AddMissingRefSpecs(this IRepository repo, ILog log, Remote remote) @@ -83,7 +98,7 @@ public static void AddMissingRefSpecs(this IRepository repo, ILog log, Remote re r => r.FetchRefSpecs.Add(allBranchesFetchRefSpec)); } - public static void CreateFakeBranchPointingAtThePullRequestTip(this IRepository repo, ILog log, AuthenticationInfo authentication) + public static void CreateFakeBranchPointingAtThePullRequestTip(this IGitRepository repo, ILog log, AuthenticationInfo authentication) { var remote = repo.Network.Remotes.Single(); @@ -119,7 +134,7 @@ public static void CreateFakeBranchPointingAtThePullRequestTip(this IRepository if (canonicalName.StartsWith("refs/tags")) { log.Info($"Checking out tag '{canonicalName}'"); - Commands.Checkout(repo, reference.Target.Sha); + repo.Commands.Checkout(reference.Target.Sha); return; } @@ -135,24 +150,27 @@ public static void CreateFakeBranchPointingAtThePullRequestTip(this IRepository repo.Refs.Add(fakeBranchName, new ObjectId(headTipSha)); log.Info($"Checking local branch '{fakeBranchName}' out."); - Commands.Checkout(repo, fakeBranchName); + repo.Commands.Checkout(fakeBranchName); } public static void CreateOrUpdateLocalBranchesFromRemoteTrackingOnes(this IRepository repo, ILog log, string remoteName) { var prefix = $"refs/remotes/{remoteName}/"; var remoteHeadCanonicalName = $"{prefix}HEAD"; + var remoteTrackingReferences = repo.Refs + .FromGlob(prefix + "*") + .Where(r => !r.CanonicalName.IsEquivalentTo(remoteHeadCanonicalName)); - foreach (var remoteTrackingReference in repo.Refs.FromGlob(prefix + "*").Where(r => r.CanonicalName != remoteHeadCanonicalName)) + foreach (var remoteTrackingReference in remoteTrackingReferences) { var remoteTrackingReferenceName = remoteTrackingReference.CanonicalName; var branchName = remoteTrackingReferenceName.Substring(prefix.Length); var localCanonicalName = "refs/heads/" + branchName; // We do not want to touch our current branch - if (branchName == repo.Head.FriendlyName) continue; + if (branchName.IsEquivalentTo(repo.Head.FriendlyName)) continue; - if (repo.Refs.Any(x => x.CanonicalName == localCanonicalName)) + if (repo.Refs.Any(x => x.CanonicalName.IsEquivalentTo(localCanonicalName))) { var localRef = repo.Refs[localCanonicalName]; var remotedirectReference = remoteTrackingReference.ResolveToDirectReference(); diff --git a/src/GitVersionCore/Extensions/StringExtensions.cs b/src/GitVersionCore/Extensions/StringExtensions.cs index 38e376ce46..7e457f0ef9 100644 --- a/src/GitVersionCore/Extensions/StringExtensions.cs +++ b/src/GitVersionCore/Extensions/StringExtensions.cs @@ -129,5 +129,10 @@ public static string RegexReplace(this string input, string pattern, string repl { return Regex.Replace(input, pattern, replace, options); } + + public static bool IsEquivalentTo(this string self, string other) + { + return String.Equals(self, other, StringComparison.OrdinalIgnoreCase); + } } } diff --git a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs index 3cfbc0ba0d..8a2a0361ca 100644 --- a/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersionCore/VersionCalculation/NextVersionCalculator.cs @@ -109,7 +109,7 @@ private void UpdatePreReleaseTag(SemanticVersion semanticVersion, string branchN var lastTag = repositoryMetadataProvider .GetVersionTagsOnBranch(context.CurrentBranch, context.Configuration.GitTagPrefix) - .FirstOrDefault(v => v.PreReleaseTag.Name == tagToUse); + .FirstOrDefault(v => v.PreReleaseTag.Name.IsEquivalentTo(tagToUse)); if (lastTag != null && MajorMinorPatchEqual(lastTag, semanticVersion) &&