Skip to content

Commit 7e1f875

Browse files
committed
CommitFilter proxy
1 parent 7d47880 commit 7e1f875

File tree

7 files changed

+228
-113
lines changed

7 files changed

+228
-113
lines changed

src/GitVersionCore.Tests/Mocks/MockCommitCollection.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using GitVersion;
4-
using LibGit2Sharp;
5-
using Commit = GitVersion.Commit;
64

75
namespace GitVersionCore.Tests.Mocks
86
{
@@ -48,6 +46,7 @@ public bool Remove(Commit item)
4846

4947
public bool IsReadOnly => false;
5048

49+
5150
public override CommitCollection QueryBy(CommitFilter commitFilter)
5251
{
5352
return this;

src/GitVersionCore.Tests/Mocks/MockRepository.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using GitVersion;
35
using GitVersion.Logging;
46
namespace GitVersionCore.Tests.Mocks
@@ -33,6 +35,46 @@ public CommitCollection Commits
3335
public void CreateBranchForPullRequestBranch(ILog log, AuthenticationInfo auth) => throw new NotImplementedException();
3436
public bool GitRepoHasMatchingRemote(string targetUrl) => throw new NotImplementedException();
3537
public void CleanupDuplicateOrigin(string defaultRemoteName) => throw new NotImplementedException();
38+
public bool GetMatchingCommitBranch(Commit baseVersionSource, Branch branch, Commit firstMatchingCommit)
39+
{
40+
throw new NotImplementedException();
41+
}
42+
public IEnumerable<Commit> GetCommitsReacheableFrom(Commit commit, Branch branch)
43+
{
44+
throw new NotImplementedException();
45+
}
46+
public List<Commit> GetCommitsReacheableFromHead(Commit headCommit)
47+
{
48+
var filter = new CommitFilter
49+
{
50+
IncludeReachableFrom = headCommit,
51+
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
52+
};
53+
54+
var commitCollection = Commits.QueryBy(filter);
55+
56+
return commitCollection.ToList();
57+
}
58+
public Commit GetForwardMerge(Commit commitToFindCommonBase, Commit findMergeBase)
59+
{
60+
throw new NotImplementedException();
61+
}
62+
public IEnumerable<Commit> GetMergeBaseCommits(Commit mergeCommit, Commit mergedHead, Commit findMergeBase)
63+
{
64+
throw new NotImplementedException();
65+
}
66+
public Commit GetBaseVersionSource(Commit currentBranchTip)
67+
{
68+
throw new NotImplementedException();
69+
}
70+
public List<Commit> GetMainlineCommitLog(Commit baseVersionSource, Commit mainlineTip)
71+
{
72+
throw new NotImplementedException();
73+
}
74+
public CommitCollection GetCommitLog(Commit baseVersionSource, Commit currentCommit)
75+
{
76+
throw new NotImplementedException();
77+
}
3678
public Remote EnsureOnlyOneRemoteIsDefined(ILog log) => throw new NotImplementedException();
3779
public void Dispose() => throw new NotImplementedException();
3880
}

src/GitVersionCore/Core/Abstractions/IGitRepository.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using GitVersion.Logging;
34

45
namespace GitVersion
@@ -22,5 +23,13 @@ public interface IGitRepository : IDisposable
2223
Remote EnsureOnlyOneRemoteIsDefined(ILog log);
2324
bool GitRepoHasMatchingRemote(string targetUrl);
2425
void CleanupDuplicateOrigin(string defaultRemoteName);
26+
bool GetMatchingCommitBranch(Commit baseVersionSource, Branch branch, Commit firstMatchingCommit);
27+
IEnumerable<Commit> GetCommitsReacheableFrom(Commit commit, Branch branch);
28+
List<Commit> GetCommitsReacheableFromHead(Commit headCommit);
29+
Commit GetForwardMerge(Commit commitToFindCommonBase, Commit findMergeBase);
30+
IEnumerable<Commit> GetMergeBaseCommits(Commit mergeCommit, Commit mergedHead, Commit findMergeBase);
31+
Commit GetBaseVersionSource(Commit currentBranchTip);
32+
List<Commit> GetMainlineCommitLog(Commit baseVersionSource, Commit mainlineTip);
33+
CommitCollection GetCommitLog(Commit baseVersionSource, Commit currentCommit);
2534
}
2635
}

src/GitVersionCore/Core/GitModel.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,71 @@ public virtual IEnumerator<Commit> GetEnumerator()
336336

337337
public virtual CommitCollection QueryBy(CommitFilter commitFilter)
338338
{
339-
var commitLog = ((IQueryableCommitLog)innerCollection).QueryBy(commitFilter);
339+
static object GetReacheableFrom(object item)
340+
{
341+
return item switch
342+
{
343+
Commit c => (LibGit2Sharp.Commit)c,
344+
Branch b => (LibGit2Sharp.Branch)b,
345+
_ => null
346+
};
347+
}
348+
349+
var includeReachableFrom = GetReacheableFrom(commitFilter.IncludeReachableFrom);
350+
var excludeReachableFrom = GetReacheableFrom(commitFilter.ExcludeReachableFrom);
351+
var filter = new LibGit2Sharp.CommitFilter
352+
{
353+
IncludeReachableFrom = includeReachableFrom,
354+
ExcludeReachableFrom = excludeReachableFrom,
355+
FirstParentOnly = commitFilter.FirstParentOnly,
356+
SortBy = (LibGit2Sharp.CommitSortStrategies)commitFilter.SortBy,
357+
};
358+
var commitLog = ((IQueryableCommitLog)innerCollection).QueryBy(filter);
340359
return FromCommitLog(commitLog);
341360
}
342361
}
362+
363+
public class CommitFilter
364+
{
365+
366+
public bool FirstParentOnly { get; set; }
367+
public object IncludeReachableFrom { get; set; }
368+
public object ExcludeReachableFrom { get; set; }
369+
public CommitSortStrategies SortBy { get; set; }
370+
}
371+
372+
/// <summary>
373+
/// Determines the sorting strategy when iterating through the commits of the repository
374+
/// </summary>
375+
[Flags]
376+
public enum CommitSortStrategies
377+
{
378+
/// <summary>
379+
/// Sort the commits in no particular ordering;
380+
/// this sorting is arbitrary, implementation-specific
381+
/// and subject to change at any time.
382+
/// </summary>
383+
None = 0,
384+
385+
/// <summary>
386+
/// Sort the commits in topological order
387+
/// (parents before children); this sorting mode
388+
/// can be combined with time sorting.
389+
/// </summary>
390+
Topological = (1 << 0),
391+
392+
/// <summary>
393+
/// Sort the commits by commit time;
394+
/// this sorting mode can be combined with
395+
/// topological sorting.
396+
/// </summary>
397+
Time = (1 << 1),
398+
399+
/// <summary>
400+
/// Iterate through the commits in reverse
401+
/// order; this sorting mode can be combined with
402+
/// any of the above.
403+
/// </summary>
404+
Reverse = (1 << 2)
405+
}
343406
}

src/GitVersionCore/Core/GitRepository.cs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using GitVersion.Logging;
45
using LibGit2Sharp;
6+
using LibGit2Sharp.Handlers;
57
using Microsoft.Extensions.Options;
68

79
namespace GitVersion
@@ -222,5 +224,115 @@ private void AddMissingRefSpecs(ILog log, LibGit2Sharp.Remote remote)
222224
log.Info($"Adding refspec: {allBranchesFetchRefSpec}");
223225
repositoryInstance.Network.Remotes.Update(remote.Name, r => r.FetchRefSpecs.Add(allBranchesFetchRefSpec));
224226
}
227+
228+
public bool GetMatchingCommitBranch(Commit baseVersionSource, Branch branch, Commit firstMatchingCommit)
229+
{
230+
var filter = new CommitFilter
231+
{
232+
IncludeReachableFrom = branch,
233+
ExcludeReachableFrom = baseVersionSource,
234+
FirstParentOnly = true,
235+
};
236+
var commitCollection = Commits.QueryBy(filter);
237+
238+
return commitCollection.Contains(firstMatchingCommit);
239+
}
240+
public IEnumerable<Commit> GetCommitsReacheableFrom(Commit commit, Branch branch)
241+
{
242+
var filter = new CommitFilter
243+
{
244+
IncludeReachableFrom = branch
245+
};
246+
var commitCollection = Commits.QueryBy(filter);
247+
248+
return commitCollection.Where(c => c.Sha == commit.Sha);
249+
}
250+
public List<Commit> GetCommitsReacheableFromHead(Commit headCommit)
251+
{
252+
var filter = new CommitFilter
253+
{
254+
IncludeReachableFrom = headCommit,
255+
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
256+
};
257+
258+
var commitCollection = Commits.QueryBy(filter);
259+
260+
return commitCollection.ToList();
261+
}
262+
public Commit GetForwardMerge(Commit commitToFindCommonBase, Commit findMergeBase)
263+
{
264+
var filter = new CommitFilter
265+
{
266+
IncludeReachableFrom = commitToFindCommonBase,
267+
ExcludeReachableFrom = findMergeBase
268+
};
269+
var commitCollection = Commits.QueryBy(filter);
270+
271+
var forwardMerge = commitCollection
272+
.FirstOrDefault(c => c.Parents.Contains(findMergeBase));
273+
return forwardMerge;
274+
}
275+
public IEnumerable<Commit> GetMergeBaseCommits(Commit mergeCommit, Commit mergedHead, Commit findMergeBase)
276+
{
277+
var filter = new CommitFilter
278+
{
279+
IncludeReachableFrom = mergedHead,
280+
ExcludeReachableFrom = findMergeBase
281+
};
282+
var commitCollection = Commits.QueryBy(filter);
283+
284+
var commits = mergeCommit != null
285+
? new[]
286+
{
287+
mergeCommit
288+
}.Union(commitCollection)
289+
: commitCollection;
290+
return commits.ToList();
291+
}
292+
public Commit GetBaseVersionSource(Commit currentBranchTip)
293+
{
294+
try
295+
{
296+
var filter = new CommitFilter
297+
{
298+
IncludeReachableFrom = currentBranchTip
299+
};
300+
var commitCollection = Commits.QueryBy(filter);
301+
302+
var baseVersionSource = commitCollection.First(c => !c.Parents.Any());
303+
return baseVersionSource;
304+
}
305+
catch (NotFoundException exception)
306+
{
307+
throw new GitVersionException($"Cannot find commit {currentBranchTip.Sha}. Please ensure that the repository is an unshallow clone with `git fetch --unshallow`.", exception);
308+
}
309+
}
310+
public List<Commit> GetMainlineCommitLog(Commit baseVersionSource, Commit mainlineTip)
311+
{
312+
var filter = new CommitFilter
313+
{
314+
IncludeReachableFrom = mainlineTip,
315+
ExcludeReachableFrom = baseVersionSource,
316+
SortBy = CommitSortStrategies.Reverse,
317+
FirstParentOnly = true
318+
};
319+
var commitCollection = Commits.QueryBy(filter);
320+
321+
var mainlineCommitLog = commitCollection.ToList();
322+
return mainlineCommitLog;
323+
}
324+
public CommitCollection GetCommitLog(Commit baseVersionSource, Commit currentCommit)
325+
{
326+
var filter = new CommitFilter
327+
{
328+
IncludeReachableFrom = currentCommit,
329+
ExcludeReachableFrom = baseVersionSource,
330+
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time
331+
};
332+
333+
var commitCollection = Commits.QueryBy(filter);
334+
335+
return commitCollection;
336+
}
225337
}
226338
}

0 commit comments

Comments
 (0)