Skip to content

Commit ba7992f

Browse files
authored
Merge pull request #2261 from asbjornu/feature/case-insensitive-equals
Make branch name comparison case insensitive
2 parents ab9cf1e + f3a50b6 commit ba7992f

12 files changed

+442
-27
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
using GitTools.Testing;
2+
using GitVersion.Logging;
3+
using GitVersion.Extensions;
4+
using GitVersionCore.Tests.Helpers;
5+
using LibGit2Sharp;
6+
using NUnit.Framework;
7+
using System.Linq;
8+
using NSubstitute;
9+
using System;
10+
using System.Collections.Generic;
11+
using GitVersion;
12+
13+
namespace GitVersionCore.Tests
14+
{
15+
[TestFixture]
16+
public class RepositoryExtensionsTests : TestBase
17+
{
18+
[Test]
19+
public void EnsureLocalBranchExistsForCurrentBranch_CaseInsensitivelyMatchesBranches()
20+
{
21+
var log = Substitute.For<ILog>();
22+
var repository = MockRepository();
23+
var remote = MockRemote(repository);
24+
25+
repository.EnsureLocalBranchExistsForCurrentBranch(log, remote, "refs/heads/featurE/feat-test");
26+
}
27+
28+
private IGitRepository MockRepository()
29+
{
30+
var repository = Substitute.For<IGitRepository>();
31+
var commands = Substitute.For<IGitRepositoryCommands>();
32+
repository.Commands.Returns(commands);
33+
return repository;
34+
}
35+
36+
private Remote MockRemote(IGitRepository repository)
37+
{
38+
var branches = new TestableBranchCollection(repository);
39+
var tipId = new ObjectId("c6d8764d20ff16c0df14c73680e52b255b608926");
40+
var tip = new TestableCommit(repository, tipId);
41+
var head = branches.Add("refs/heads/feature/feat-test", tip);
42+
var remote = new TesatbleRemote("origin");
43+
var references = new TestableReferenceCollection();
44+
var reference = references.Add("develop", "refs/heads/develop");
45+
46+
repository.Refs.Returns(references);
47+
repository.Head.Returns(head);
48+
repository.Branches.Returns(branches);
49+
return remote;
50+
}
51+
52+
private class TestableBranchCollection : BranchCollection
53+
{
54+
private readonly IRepository repository;
55+
public TestableBranchCollection(IRepository repository)
56+
{
57+
}
58+
59+
IDictionary<string, Branch> branches = new Dictionary<string, Branch>();
60+
61+
public override Branch this[string name] =>
62+
this.branches.ContainsKey(name)
63+
? this.branches[name]
64+
: null;
65+
66+
public override Branch Add(string name, Commit commit)
67+
{
68+
var branch = new TestableBranch(name, commit);
69+
this.branches.Add(name, branch);
70+
return branch;
71+
}
72+
73+
public override Branch Add(string name, string committish)
74+
{
75+
var id = new ObjectId(committish);
76+
var commit = new TestableCommit(this.repository, id);
77+
return Add(name, commit);
78+
}
79+
80+
public override Branch Add(string name, Commit commit, bool allowOverwrite)
81+
{
82+
return Add(name, commit);
83+
}
84+
85+
public override Branch Add(string name, string committish, bool allowOverwrite)
86+
{
87+
return Add(name, committish);
88+
}
89+
90+
public override IEnumerator<Branch> GetEnumerator()
91+
{
92+
return this.branches.Values.GetEnumerator();
93+
}
94+
95+
public override void Remove(string name)
96+
{
97+
this.branches.Remove(name);
98+
}
99+
100+
public override void Remove(string name, bool isRemote)
101+
{
102+
this.branches.Remove(name);
103+
}
104+
105+
public override void Remove(Branch branch)
106+
{
107+
this.branches.Remove(branch.CanonicalName);
108+
}
109+
110+
public override Branch Update(Branch branch, params Action<BranchUpdater>[] actions)
111+
{
112+
return base.Update(branch, actions);
113+
}
114+
}
115+
116+
private class TestableBranch : Branch
117+
{
118+
private readonly string canonicalName;
119+
private readonly Commit tip;
120+
121+
public TestableBranch(string canonicalName, Commit tip)
122+
{
123+
this.tip = tip;
124+
this.canonicalName = canonicalName;
125+
}
126+
127+
public override string CanonicalName => this.canonicalName;
128+
public override Commit Tip => this.tip;
129+
}
130+
131+
private class TestableCommit : Commit, IBelongToARepository
132+
{
133+
private IRepository repository;
134+
private ObjectId id;
135+
136+
public TestableCommit(IRepository repository, ObjectId id)
137+
{
138+
this.repository = repository;
139+
this.id = id;
140+
}
141+
142+
public override ObjectId Id => this.id;
143+
public IRepository Repository => this.repository;
144+
}
145+
146+
private class TesatbleRemote : Remote
147+
{
148+
private string name;
149+
150+
public TesatbleRemote(string name)
151+
{
152+
this.name = name;
153+
}
154+
155+
public override string Name => this.name;
156+
}
157+
158+
private class TestableReferenceCollection : ReferenceCollection
159+
{
160+
Reference reference;
161+
162+
public override DirectReference Add(string name, ObjectId targetId)
163+
{
164+
throw new InvalidOperationException("Update should be invoked when case-insensitively comparing branches.");
165+
}
166+
167+
public override Reference Add(string name, string canonicalRefNameOrObjectish)
168+
{
169+
return this.reference = new TestableReference(canonicalRefNameOrObjectish);
170+
}
171+
172+
public override Reference UpdateTarget(Reference directRef, ObjectId targetId)
173+
{
174+
return this.reference;
175+
}
176+
177+
public override Reference this[string name] => this.reference;
178+
}
179+
180+
private class TestableReference : Reference
181+
{
182+
private readonly string canonicalName;
183+
184+
public TestableReference(string canonicalName)
185+
{
186+
this.canonicalName = canonicalName;
187+
}
188+
189+
public override string CanonicalName => this.canonicalName;
190+
191+
public override DirectReference ResolveToDirectReference()
192+
{
193+
throw new NotImplementedException();
194+
}
195+
}
196+
}
197+
}

src/GitVersionCore/Configuration/BranchConfigurationCalculator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public BranchConfig GetBranchConfiguration(Branch targetBranch, Commit currentCo
4141
if (matchingBranches.Increment == IncrementStrategy.Inherit)
4242
{
4343
matchingBranches = InheritBranchConfiguration(targetBranch, matchingBranches, currentCommit, configuration, excludedInheritBranches);
44-
if (matchingBranches.Name == FallbackConfigName && matchingBranches.Increment == IncrementStrategy.Inherit)
44+
if (matchingBranches.Name.IsEquivalentTo(FallbackConfigName) && matchingBranches.Increment == IncrementStrategy.Inherit)
4545
{
4646
// We tried, and failed to inherit, just fall back to patch
4747
matchingBranches.Increment = IncrementStrategy.Patch;
@@ -152,7 +152,7 @@ private BranchConfig InheritBranchConfiguration(Branch targetBranch, BranchConfi
152152

153153
var inheritingBranchConfig = GetBranchConfiguration(chosenBranch, currentCommit, configuration, excludedInheritBranches);
154154
var configIncrement = inheritingBranchConfig.Increment;
155-
if (inheritingBranchConfig.Name == FallbackConfigName && configIncrement == IncrementStrategy.Inherit)
155+
if (inheritingBranchConfig.Name.IsEquivalentTo(FallbackConfigName) && configIncrement == IncrementStrategy.Inherit)
156156
{
157157
log.Warning("Fallback config inherits by default, dropping to patch increment");
158158
configIncrement = IncrementStrategy.Patch;

src/GitVersionCore/Core/GitPreparer.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ private void CloneRepository(string repositoryUrl, string gitDirectory, Authenti
202202
private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string currentBranch, bool isDynamicRepository)
203203
{
204204
var authentication = options.Value.Authentication;
205-
using var repository = new Repository(gitDirectory);
205+
using var repository = new GitRepository(() => gitDirectory);
206206
// Need to ensure the HEAD does not move, this is essentially a BugCheck
207207
var expectedSha = repository.Head.Tip.Sha;
208208
var expectedBranchName = repository.Head.CanonicalName;
@@ -221,7 +221,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur
221221
else
222222
{
223223
log.Info($"Fetching from remote '{remote.Name}' using the following refspecs: {string.Join(", ", remote.FetchRefSpecs.Select(r => r.Specification))}.");
224-
Commands.Fetch(repository, remote.Name, new string[0], authentication.ToFetchOptions(), null);
224+
repository.Commands.Fetch(remote.Name, new string[0], authentication.ToFetchOptions(), null);
225225
}
226226

227227
repository.EnsureLocalBranchExistsForCurrentBranch(log, remote, currentBranch);
@@ -262,7 +262,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur
262262
if (matchingCurrentBranch != null)
263263
{
264264
log.Info($"Checking out local branch '{currentBranch}'.");
265-
Commands.Checkout(repository, matchingCurrentBranch);
265+
repository.Commands.Checkout(matchingCurrentBranch);
266266
}
267267
else if (localBranchesWhereCommitShaIsHead.Count > 1)
268268
{
@@ -271,11 +271,11 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur
271271
const string moveBranchMsg = "Move one of the branches along a commit to remove warning";
272272

273273
log.Warning($"Found more than one local branch pointing at the commit '{headSha}' ({csvNames}).");
274-
var master = localBranchesWhereCommitShaIsHead.SingleOrDefault(n => n.FriendlyName == "master");
274+
var master = localBranchesWhereCommitShaIsHead.SingleOrDefault(n => n.FriendlyName.IsEquivalentTo("master"));
275275
if (master != null)
276276
{
277277
log.Warning("Because one of the branches is 'master', will build master." + moveBranchMsg);
278-
Commands.Checkout(repository, master);
278+
repository.Commands.Checkout(master);
279279
}
280280
else
281281
{
@@ -284,7 +284,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur
284284
{
285285
var branchWithoutSeparator = branchesWithoutSeparators[0];
286286
log.Warning($"Choosing {branchWithoutSeparator.CanonicalName} as it is the only branch without / or - in it. " + moveBranchMsg);
287-
Commands.Checkout(repository, branchWithoutSeparator);
287+
repository.Commands.Checkout(branchWithoutSeparator);
288288
}
289289
else
290290
{
@@ -300,7 +300,7 @@ private void NormalizeGitDirectory(string gitDirectory, bool noFetch, string cur
300300
else
301301
{
302302
log.Info($"Checking out local branch 'refs/heads/{localBranchesWhereCommitShaIsHead[0].FriendlyName}'.");
303-
Commands.Checkout(repository, repository.Branches[localBranchesWhereCommitShaIsHead[0].FriendlyName]);
303+
repository.Commands.Checkout(repository.Branches[localBranchesWhereCommitShaIsHead[0].FriendlyName]);
304304
}
305305
}
306306
finally

src/GitVersionCore/Core/GitRepository.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@
55

66
namespace GitVersion
77
{
8-
public class GitRepository : IRepository
8+
public class GitRepository : IGitRepository
99
{
1010
private Lazy<IRepository> repositoryLazy;
1111
private IRepository repositoryInstance => repositoryLazy.Value;
1212

1313
public GitRepository(IOptions<GitVersionOptions> options)
14+
: this(() => options.Value.DotGitDirectory)
1415
{
15-
repositoryLazy = new Lazy<IRepository>(() => new Repository(options.Value.DotGitDirectory));
16+
}
17+
18+
public GitRepository(Func<string> getDotGitDirectory)
19+
{
20+
repositoryLazy = new Lazy<IRepository>(() => new Repository(getDotGitDirectory()));
21+
Commands = new GitRepositoryCommands(repositoryLazy);
1622
}
1723

1824
public void Dispose()
@@ -161,5 +167,7 @@ public void RevParse(string revision, out Reference reference, out GitObject obj
161167
public Network Network => repositoryInstance.Network;
162168

163169
public StashCollection Stashes => repositoryInstance.Stashes;
170+
171+
public IGitRepositoryCommands Commands { get; }
164172
}
165173
}

0 commit comments

Comments
 (0)