Skip to content

Commit 7393ace

Browse files
committed
caches git objects correctly
Caches git objects using canonical names for better performance.
1 parent b462ee7 commit 7393ace

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

src/GitVersion.LibGit2Sharp/Git/GitRepository.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ internal sealed partial class GitRepository
1212
private readonly ConcurrentDictionary<string, Branch> cachedBranches = new();
1313
private readonly ConcurrentDictionary<string, Commit> cachedCommits = new();
1414
private readonly ConcurrentDictionary<string, Tag> cachedTags = new();
15+
private readonly ConcurrentDictionary<string, Reference> cachedReferences = new();
16+
private readonly ConcurrentDictionary<string, Remote> cachedRemotes = new();
1517

1618
private IRepository RepositoryInstance
1719
{
@@ -28,10 +30,10 @@ private IRepository RepositoryInstance
2830
public IBranch Head => GetOrWrap(RepositoryInstance.Head, RepositoryInstance.Diff);
2931

3032
public ITagCollection Tags => new TagCollection(RepositoryInstance.Tags, RepositoryInstance.Diff, this);
31-
public IReferenceCollection Refs => new ReferenceCollection(RepositoryInstance.Refs);
33+
public IReferenceCollection Refs => new ReferenceCollection(RepositoryInstance.Refs, this);
3234
public IBranchCollection Branches => new BranchCollection(RepositoryInstance.Branches, RepositoryInstance.Diff, this);
3335
public ICommitCollection Commits => new CommitCollection(RepositoryInstance.Commits, RepositoryInstance.Diff, this);
34-
public IRemoteCollection Remotes => new RemoteCollection(RepositoryInstance.Network.Remotes);
36+
public IRemoteCollection Remotes => new RemoteCollection(RepositoryInstance.Network.Remotes, this);
3537

3638
public void DiscoverRepository(string? gitDirectory)
3739
{
@@ -77,6 +79,12 @@ public Commit GetOrWrap(LibGit2Sharp.Commit innerCommit, Diff repoDiff)
7779
public Tag GetOrWrap(LibGit2Sharp.Tag innerTag, Diff repoDiff)
7880
=> cachedTags.GetOrAdd(innerTag.CanonicalName, _ => new Tag(innerTag, repoDiff, this));
7981

82+
public Reference GetOrWrap(LibGit2Sharp.Reference innerReference)
83+
=> cachedReferences.GetOrAdd(innerReference.CanonicalName, _ => new Reference(innerReference));
84+
85+
public Remote GetOrWrap(LibGit2Sharp.Remote innerRemote)
86+
=> cachedRemotes.GetOrAdd(innerRemote.Name, _ => new Remote(innerRemote));
87+
8088
public void Dispose()
8189
{
8290
if (this.repositoryLazy is { IsValueCreated: true }) RepositoryInstance.Dispose();

src/GitVersion.LibGit2Sharp/Git/ReferenceCollection.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@ namespace GitVersion.Git;
55
internal sealed class ReferenceCollection : IReferenceCollection
66
{
77
private readonly LibGit2Sharp.ReferenceCollection innerCollection;
8+
private readonly GitRepository repo;
89
private readonly Lazy<IReadOnlyCollection<IReference>> references;
910

10-
internal ReferenceCollection(LibGit2Sharp.ReferenceCollection collection)
11+
internal ReferenceCollection(LibGit2Sharp.ReferenceCollection collection, GitRepository repo)
1112
{
1213
this.innerCollection = collection.NotNull();
13-
this.references = new Lazy<IReadOnlyCollection<IReference>>(() => [.. this.innerCollection.Select(reference => new Reference(reference))]);
14+
this.repo = repo.NotNull();
15+
this.references = new Lazy<IReadOnlyCollection<IReference>>(() => [.. this.innerCollection.Select(repo.GetOrWrap)]);
1416
}
1517

1618
public IEnumerator<IReference> GetEnumerator() => this.references.Value.GetEnumerator();
1719

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

20-
public void Add(string name, string canonicalRefNameOrObject, bool allowOverwrite = false) => this.innerCollection.Add(name, canonicalRefNameOrObject, allowOverwrite);
22+
public void Add(string name, string canonicalRefNameOrObject, bool allowOverwrite = false)
23+
=> this.innerCollection.Add(name, canonicalRefNameOrObject, allowOverwrite);
2124

2225
public void UpdateTarget(IReference directRef, IObjectId targetId)
2326
=> RepositoryExtensions.RunSafe(() => this.innerCollection.UpdateTarget((Reference)directRef, (ObjectId)targetId));
@@ -27,13 +30,13 @@ public IReference? this[string name]
2730
get
2831
{
2932
var reference = this.innerCollection[name];
30-
return reference is null ? null : new Reference(reference);
33+
return reference is null ? null : this.repo.GetOrWrap(reference);
3134
}
3235
}
3336

3437
public IReference? this[ReferenceName referenceName] => this[referenceName.Canonical];
3538

3639
public IReference? Head => this["HEAD"];
3740

38-
public IEnumerable<IReference> FromGlob(string prefix) => this.innerCollection.FromGlob(prefix).Select(reference => (IReference)new Reference(reference));
41+
public IEnumerable<IReference> FromGlob(string prefix) => this.innerCollection.FromGlob(prefix).Select(reference => (IReference)this.repo.GetOrWrap(reference));
3942
}

src/GitVersion.LibGit2Sharp/Git/Remote.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace GitVersion.Git;
1717
public string Name => this.innerRemote.Name;
1818
public string Url => this.innerRemote.Url;
1919

20-
public IEnumerable<IRefSpec> RefSpecs
20+
private IEnumerable<IRefSpec> RefSpecs
2121
{
2222
get
2323
{

src/GitVersion.LibGit2Sharp/Git/RemoteCollection.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ namespace GitVersion.Git;
55
internal sealed class RemoteCollection : IRemoteCollection
66
{
77
private readonly LibGit2Sharp.RemoteCollection innerCollection;
8+
private readonly GitRepository repo;
89
private readonly Lazy<IReadOnlyCollection<IRemote>> remotes;
910

10-
internal RemoteCollection(LibGit2Sharp.RemoteCollection collection)
11+
internal RemoteCollection(LibGit2Sharp.RemoteCollection collection, GitRepository repo)
1112
{
1213
this.innerCollection = collection.NotNull();
13-
this.remotes = new Lazy<IReadOnlyCollection<IRemote>>(() => [.. this.innerCollection.Select(reference => new Remote(reference))]);
14+
this.repo = repo.NotNull();
15+
this.remotes = new Lazy<IReadOnlyCollection<IRemote>>(() => [.. this.innerCollection.Select(repo.GetOrWrap)]);
1416
}
1517

1618
public IEnumerator<IRemote> GetEnumerator() => this.remotes.Value.GetEnumerator();
@@ -22,7 +24,7 @@ public IRemote? this[string name]
2224
get
2325
{
2426
var remote = this.innerCollection[name];
25-
return remote is null ? null : new Remote(remote);
27+
return remote is null ? null : this.repo.GetOrWrap(remote);
2628
}
2729
}
2830

0 commit comments

Comments
 (0)