1+ using System . Collections . Concurrent ;
12using GitVersion . Extensions ;
23using GitVersion . Helpers ;
34using LibGit2Sharp ;
@@ -8,6 +9,10 @@ internal sealed partial class GitRepository
89{
910 private Lazy < IRepository > ? repositoryLazy ;
1011
12+ private readonly ConcurrentDictionary < string , Branch > cachedBranches = new ( ) ;
13+ private readonly ConcurrentDictionary < string , Commit > cachedCommits = new ( ) ;
14+ private readonly ConcurrentDictionary < string , Tag > cachedTags = new ( ) ;
15+
1116 private IRepository RepositoryInstance
1217 {
1318 get
@@ -20,12 +25,12 @@ private IRepository RepositoryInstance
2025 public string WorkingDirectory => RepositoryInstance . Info . WorkingDirectory ;
2126 public bool IsHeadDetached => RepositoryInstance . Info . IsHeadDetached ;
2227 public bool IsShallow => RepositoryInstance . Info . IsShallow ;
23- public IBranch Head => new Branch ( RepositoryInstance . Head , RepositoryInstance . Diff ) ;
28+ public IBranch Head => GetOrCreate ( RepositoryInstance . Head , RepositoryInstance . Diff ) ;
2429
25- public ITagCollection Tags => new TagCollection ( RepositoryInstance . Tags , RepositoryInstance . Diff ) ;
30+ public ITagCollection Tags => new TagCollection ( RepositoryInstance . Tags , RepositoryInstance . Diff , this ) ;
2631 public IReferenceCollection Refs => new ReferenceCollection ( RepositoryInstance . Refs ) ;
27- public IBranchCollection Branches => new BranchCollection ( RepositoryInstance . Branches , RepositoryInstance . Diff ) ;
28- public ICommitCollection Commits => new CommitCollection ( RepositoryInstance . Commits , RepositoryInstance . Diff ) ;
32+ public IBranchCollection Branches => new BranchCollection ( RepositoryInstance . Branches , RepositoryInstance . Diff , this ) ;
33+ public ICommitCollection Commits => new CommitCollection ( RepositoryInstance . Commits , RepositoryInstance . Diff , this ) ;
2934 public IRemoteCollection Remotes => new RemoteCollection ( RepositoryInstance . Network . Remotes ) ;
3035
3136 public void DiscoverRepository ( string ? gitDirectory )
@@ -48,7 +53,7 @@ public void DiscoverRepository(string? gitDirectory)
4853 var first = ( Commit ) commit ;
4954 var second = ( Commit ) otherCommit ;
5055 var mergeBase = RepositoryInstance . ObjectDatabase . FindMergeBase ( first , second ) ;
51- return mergeBase == null ? null : new Commit ( mergeBase , RepositoryInstance . Diff ) ;
56+ return mergeBase == null ? null : GetOrCreate ( mergeBase , RepositoryInstance . Diff ) ;
5257 } ) ;
5358 }
5459
@@ -58,6 +63,26 @@ public int UncommittedChangesCount()
5863 return retryAction . Execute ( GetUncommittedChangesCountInternal ) ;
5964 }
6065
66+ public Branch GetOrCreate ( LibGit2Sharp . Branch innerBranch , Diff repoDiff )
67+ {
68+ if ( innerBranch . Tip is null )
69+ {
70+ return new Branch ( innerBranch , repoDiff , this ) ;
71+ }
72+
73+ var cacheKey = $ "{ innerBranch . CanonicalName } |{ innerBranch . Tip . Sha } |{ innerBranch . RemoteName } ";
74+ return cachedBranches . GetOrAdd ( cacheKey , new Branch ( innerBranch , repoDiff , this ) ) ;
75+ }
76+
77+ public Commit GetOrCreate ( LibGit2Sharp . Commit innerCommit , Diff repoDiff ) =>
78+ cachedCommits . GetOrAdd ( innerCommit . Sha , new Commit ( innerCommit , repoDiff , this ) ) ;
79+
80+ public Tag GetOrCreate ( LibGit2Sharp . Tag innerTag , Diff repoDiff )
81+ {
82+ var cacheKey = $ "{ innerTag . CanonicalName } |{ innerTag . Target . Sha } ";
83+ return cachedTags . GetOrAdd ( cacheKey , new Tag ( innerTag , repoDiff , this ) ) ;
84+ }
85+
6186 public void Dispose ( )
6287 {
6388 if ( this . repositoryLazy is { IsValueCreated : true } ) RepositoryInstance . Dispose ( ) ;
0 commit comments