Skip to content

Commit

Permalink
Merge pull request #4208 from david-driscoll/fix/slow-on-branch
Browse files Browse the repository at this point in the history
attempt to fix performance issues with a cache
  • Loading branch information
arturcic authored Oct 15, 2024
2 parents dad5d2c + 1200ae1 commit 4255a15
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 50 deletions.
16 changes: 4 additions & 12 deletions src/GitVersion.Core/Configuration/IgnoreConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,20 @@ namespace GitVersion.Configuration;

internal static class IgnoreConfigurationExtensions
{
public static IEnumerable<ITag> Filter(this IIgnoreConfiguration ignore, IEnumerable<ITag> source)
public static IEnumerable<ITag> Filter(this IIgnoreConfiguration ignore, ITag[] source)
{
ignore.NotNull();
source.NotNull();

if (!ignore.IsEmpty)
{
return source.Where(element => ShouldBeIgnored(element.Commit, ignore));
}
return source;
return !ignore.IsEmpty ? source.Where(element => ShouldBeIgnored(element.Commit, ignore)) : source;
}

public static IEnumerable<ICommit> Filter(this IIgnoreConfiguration ignore, IEnumerable<ICommit> source)
public static IEnumerable<ICommit> Filter(this IIgnoreConfiguration ignore, ICommit[] source)
{
ignore.NotNull();
source.NotNull();

if (!ignore.IsEmpty)
{
return source.Where(element => ShouldBeIgnored(element, ignore));
}
return source;
return !ignore.IsEmpty ? source.Where(element => ShouldBeIgnored(element, ignore)) : source;
}

private static bool ShouldBeIgnored(ICommit commit, IIgnoreConfiguration ignore)
Expand Down
21 changes: 11 additions & 10 deletions src/GitVersion.Core/Core/RepositoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal class RepositoryStore(ILog log, IGitRepository repository) : IRepositor
this.log.Info("Using latest commit on specified branch");
}

commits = ignore.Filter(commits);
commits = ignore.Filter(commits.ToArray());
return commits.FirstOrDefault();
}

Expand Down Expand Up @@ -219,8 +219,7 @@ public IReadOnlyList<ICommit> GetCommitLog(ICommit? baseVersionSource, ICommit c
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time
};

var commits = this.repository.Commits.QueryBy(filter).ToArray();

var commits = FilterCommits(filter).ToArray();
return ignore.Filter(commits).ToList();
}

Expand All @@ -232,16 +231,16 @@ public IReadOnlyList<ICommit> GetCommitsReacheableFromHead(ICommit? headCommit,
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
};

var commits = this.repository.Commits.QueryBy(filter);
var commits = FilterCommits(filter).ToArray();
return ignore.Filter(commits).ToList();
}

public IReadOnlyList<ICommit> GetCommitsReacheableFrom(IGitObject commit, IBranch branch)
{
var filter = new CommitFilter { IncludeReachableFrom = branch };
var commitCollection = this.repository.Commits.QueryBy(filter);

return commitCollection.Where(c => c.Sha == commit.Sha).ToList();
var commits = FilterCommits(filter);
return commits.Where(c => c.Sha == commit.Sha).ToList();
}

public ICommit? GetForwardMerge(ICommit? commitToFindCommonBase, ICommit? findMergeBase)
Expand All @@ -251,18 +250,20 @@ public IReadOnlyList<ICommit> GetCommitsReacheableFrom(IGitObject commit, IBranc
IncludeReachableFrom = commitToFindCommonBase,
ExcludeReachableFrom = findMergeBase
};
var commitCollection = this.repository.Commits.QueryBy(filter);

return commitCollection.FirstOrDefault(c => c.Parents.Contains(findMergeBase));
var commits = FilterCommits(filter);
return commits.FirstOrDefault(c => c.Parents.Contains(findMergeBase));
}

public bool IsCommitOnBranch(ICommit? baseVersionSource, IBranch branch, ICommit firstMatchingCommit)
{
var filter = new CommitFilter { IncludeReachableFrom = branch, ExcludeReachableFrom = baseVersionSource, FirstParentOnly = true };
var commitCollection = this.repository.Commits.QueryBy(filter);
return commitCollection.Contains(firstMatchingCommit);
var commits = FilterCommits(filter);
return commits.Contains(firstMatchingCommit);
}

private IEnumerable<ICommit> FilterCommits(CommitFilter filter) => this.repository.Commits.QueryBy(filter);

public ICommit? FindMergeBase(ICommit commit, ICommit mainlineTip) => this.repository.FindMergeBase(commit, mainlineTip);

private IBranch? FindBranch(string branchName) => this.repository.Branches.FirstOrDefault(x => x.Name.EquivalentTo(branchName));
Expand Down
6 changes: 3 additions & 3 deletions src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ IEnumerable<SemanticVersionWithTag> GetElements()
{
var semanticVersions = GetTaggedSemanticVersions(tagPrefix, format, ignore);

foreach (var commit in ignore.Filter(branch.Commits))
foreach (var commit in ignore.Filter(branch.Commits.ToArray()))
{
foreach (var semanticVersion in semanticVersions[commit])
{
Expand Down Expand Up @@ -88,7 +88,7 @@ public ILookup<ICommit, SemanticVersionWithTag> GetTaggedSemanticVersionsOfMerge
using (this.log.IndentLog($"Getting tagged semantic versions by track merge target '{branch.Name.Canonical}'. " +
$"TagPrefix: {tagPrefix} and Format: {format}"))
{
var shaHashSet = new HashSet<string>(ignore.Filter(branch.Commits).Select(element => element.Id.Sha));
var shaHashSet = new HashSet<string>(ignore.Filter(branch.Commits.ToArray()).Select(element => element.Id.Sha));

foreach (var semanticVersion in GetTaggedSemanticVersions(tagPrefix, format, ignore).SelectMany(v => v))
{
Expand Down Expand Up @@ -124,7 +124,7 @@ IEnumerable<SemanticVersionWithTag> GetElements()
{
this.log.Info($"Getting tagged semantic versions. TagPrefix: {tagPrefix} and Format: {format}");

foreach (var tag in ignore.Filter(this.repositoryStore.Tags))
foreach (var tag in ignore.Filter(this.repositoryStore.Tags.ToArray()))
{
if (SemanticVersion.TryParse(tag.Name.Friendly, tagPrefix, out var semanticVersion, format))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public IEnumerable<BaseVersion> GetBaseVersions(EffectiveBranchConfiguration con
configuration: branchConfiguration
);

var commitsInReverseOrder = Context.Configuration.Ignore.Filter(Context.CurrentBranchCommits);
var commitsInReverseOrder = Context.Configuration.Ignore.Filter(Context.CurrentBranchCommits.ToArray());

TaggedSemanticVersions taggedSemanticVersion = TaggedSemanticVersions.OfBranch;
if (branchConfiguration.TrackMergeTarget == true) taggedSemanticVersion |= TaggedSemanticVersions.OfMergeTargets;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ private IEnumerable<BaseVersion> GetBaseVersionsInternal(EffectiveBranchConfigur
|| !configuration.Value.TrackMergeMessage)
yield break;

foreach (var commit in configuration.Value.Ignore.Filter(Context.CurrentBranchCommits))
foreach (var commit in configuration.Value.Ignore.Filter(Context.CurrentBranchCommits.ToArray()))
{
if (MergeMessage.TryParse(commit, Context.Configuration, out var mergeMessage)
&& mergeMessage.Version is not null
Expand Down
13 changes: 8 additions & 5 deletions src/GitVersion.LibGit2Sharp/Git/BranchCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ namespace GitVersion.Git;
internal sealed class BranchCollection : IBranchCollection
{
private readonly LibGit2Sharp.BranchCollection innerCollection;
private readonly Lazy<IReadOnlyCollection<IBranch>> branches;

internal BranchCollection(LibGit2Sharp.BranchCollection collection)
=> this.innerCollection = collection.NotNull();
{
this.innerCollection = collection.NotNull();
this.branches = new Lazy<IReadOnlyCollection<IBranch>>(() => this.innerCollection.Select(branch => new Branch(branch)).ToArray());
}

public IEnumerator<IBranch> GetEnumerator()
=> this.innerCollection.Select(branch => new Branch(branch)).GetEnumerator();
=> this.branches.Value.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

Expand All @@ -27,12 +31,11 @@ public IBranch? this[string name]

public IEnumerable<IBranch> ExcludeBranches(IEnumerable<IBranch> branchesToExclude)
{
branchesToExclude = branchesToExclude.NotNull();
var toExclude = branchesToExclude as IBranch[] ?? branchesToExclude.ToArray();

return this.Where(BranchIsNotExcluded);

bool BranchIsNotExcluded(IBranch branch)
=> branchesToExclude.All(branchToExclude => !branch.Equals(branchToExclude));
bool BranchIsNotExcluded(IBranch branch) => toExclude.All(branchToExclude => !branch.Equals(branchToExclude));
}

public void UpdateTrackedBranch(IBranch branch, string remoteTrackingReferenceName)
Expand Down
17 changes: 14 additions & 3 deletions src/GitVersion.LibGit2Sharp/Git/CommitCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ namespace GitVersion.Git;
internal sealed class CommitCollection : ICommitCollection
{
private readonly ICommitLog innerCollection;
private readonly Lazy<IReadOnlyCollection<ICommit>> commits;

internal CommitCollection(ICommitLog collection) => this.innerCollection = collection.NotNull();
internal CommitCollection(ICommitLog collection)
{
this.innerCollection = collection.NotNull();
this.commits = new Lazy<IReadOnlyCollection<ICommit>>(() => this.innerCollection.Select(commit => new Commit(commit)).ToArray());
}

public IEnumerator<ICommit> GetEnumerator()
=> this.innerCollection.Select(commit => new Commit(commit)).GetEnumerator();
=> this.commits.Value.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

Expand All @@ -21,7 +26,13 @@ public IEnumerable<ICommit> QueryBy(CommitFilter commitFilter)
{
var includeReachableFrom = GetReacheableFrom(commitFilter.IncludeReachableFrom);
var excludeReachableFrom = GetReacheableFrom(commitFilter.ExcludeReachableFrom);
var filter = new LibGit2Sharp.CommitFilter { IncludeReachableFrom = includeReachableFrom, ExcludeReachableFrom = excludeReachableFrom, FirstParentOnly = commitFilter.FirstParentOnly, SortBy = (LibGit2Sharp.CommitSortStrategies)commitFilter.SortBy };
var filter = new LibGit2Sharp.CommitFilter
{
IncludeReachableFrom = includeReachableFrom,
ExcludeReachableFrom = excludeReachableFrom,
FirstParentOnly = commitFilter.FirstParentOnly,
SortBy = (LibGit2Sharp.CommitSortStrategies)commitFilter.SortBy
};
var commitLog = ((IQueryableCommitLog)this.innerCollection).QueryBy(filter);
return new CommitCollection(commitLog);

Expand Down
9 changes: 6 additions & 3 deletions src/GitVersion.LibGit2Sharp/Git/RefSpecCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ namespace GitVersion.Git;

internal sealed class RefSpecCollection : IRefSpecCollection
{
private readonly LibGit2Sharp.RefSpecCollection innerCollection;
private readonly Lazy<IReadOnlyCollection<IRefSpec>> refSpecs;

internal RefSpecCollection(LibGit2Sharp.RefSpecCollection collection)
=> this.innerCollection = collection.NotNull();
{
collection = collection.NotNull();
this.refSpecs = new Lazy<IReadOnlyCollection<IRefSpec>>(() => collection.Select(tag => new RefSpec(tag)).ToArray());
}

public IEnumerator<IRefSpec> GetEnumerator() => this.innerCollection.Select(tag => new RefSpec(tag)).GetEnumerator();
public IEnumerator<IRefSpec> GetEnumerator() => this.refSpecs.Value.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
16 changes: 12 additions & 4 deletions src/GitVersion.LibGit2Sharp/Git/ReferenceCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@ namespace GitVersion.Git;
internal sealed class ReferenceCollection : IReferenceCollection
{
private readonly LibGit2Sharp.ReferenceCollection innerCollection;
private IReadOnlyCollection<IReference>? references;

internal ReferenceCollection(LibGit2Sharp.ReferenceCollection collection)
=> this.innerCollection = collection.NotNull();
internal ReferenceCollection(LibGit2Sharp.ReferenceCollection collection) => this.innerCollection = collection.NotNull();

public IEnumerator<IReference> GetEnumerator() => this.innerCollection.Select(reference => new Reference(reference)).GetEnumerator();
public IEnumerator<IReference> GetEnumerator()
{
this.references ??= this.innerCollection.Select(reference => new Reference(reference)).ToArray();
return this.references.GetEnumerator();
}

public void Add(string name, string canonicalRefNameOrObject, bool allowOverwrite = false) => this.innerCollection.Add(name, canonicalRefNameOrObject, allowOverwrite);

public void UpdateTarget(IReference directRef, IObjectId targetId) => RepositoryExtensions.RunSafe(() => this.innerCollection.UpdateTarget((Reference)directRef, (ObjectId)targetId));
public void UpdateTarget(IReference directRef, IObjectId targetId)
{
RepositoryExtensions.RunSafe(() => this.innerCollection.UpdateTarget((Reference)directRef, (ObjectId)targetId));
this.references = null;
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

Expand Down
20 changes: 15 additions & 5 deletions src/GitVersion.LibGit2Sharp/Git/RemoteCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ namespace GitVersion.Git;
internal sealed class RemoteCollection : IRemoteCollection
{
private readonly LibGit2Sharp.RemoteCollection innerCollection;
private IReadOnlyCollection<IRemote>? remotes;

internal RemoteCollection(LibGit2Sharp.RemoteCollection collection)
=> this.innerCollection = collection.NotNull();
internal RemoteCollection(LibGit2Sharp.RemoteCollection collection) => this.innerCollection = collection.NotNull();

public IEnumerator<IRemote> GetEnumerator()
=> this.innerCollection.Select(reference => new Remote(reference)).GetEnumerator();
{
this.remotes ??= this.innerCollection.Select(reference => new Remote(reference)).ToArray();
return this.remotes.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

Expand All @@ -23,8 +26,15 @@ public IRemote? this[string name]
}
}

public void Remove(string remoteName) => this.innerCollection.Remove(remoteName);
public void Remove(string remoteName)
{
this.innerCollection.Remove(remoteName);
this.remotes = null;
}

public void Update(string remoteName, string refSpec)
=> this.innerCollection.Update(remoteName, r => r.FetchRefSpecs.Add(refSpec));
{
this.innerCollection.Update(remoteName, r => r.FetchRefSpecs.Add(refSpec));
this.remotes = null;
}
}
9 changes: 6 additions & 3 deletions src/GitVersion.LibGit2Sharp/Git/TagCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ namespace GitVersion.Git;

internal sealed class TagCollection : ITagCollection
{
private readonly LibGit2Sharp.TagCollection innerCollection;
private readonly Lazy<IReadOnlyCollection<ITag>> tags;

internal TagCollection(LibGit2Sharp.TagCollection collection)
=> this.innerCollection = collection.NotNull();
{
collection = collection.NotNull();
this.tags = new Lazy<IReadOnlyCollection<ITag>>(() => collection.Select(tag => new Tag(tag)).ToArray());
}

public IEnumerator<ITag> GetEnumerator()
=> this.innerCollection.Select(tag => new Tag(tag)).GetEnumerator();
=> this.tags.Value.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

0 comments on commit 4255a15

Please sign in to comment.