private async RecursiveCallResult <Commit?> ReferenceOrCopyCommitImpl( Repository sourceRepo, Commit commit, Repository targetRepo, int maxDepth) { if (maxDepth == 0) { return(null); } // fastest way: use copied commit if (TryGetCopiedCommit(commit, targetRepo, out var newCommit)) { return(newCommit); } switch (_callback.GetCommitCopyKind(commit)) { case CommitCopyKind.NoCommit: { // if source tree not found: this commit will be parent of top commit. newCommit = null; } break; case CommitCopyKind.UseParent: { // if maxDepth == 1 means deepest commit: parent never exists so force copy commit if (maxDepth == 1) { goto case CommitCopyKind.CopyCommit; } // if no difference: this commit is same as parent's commit _progressHandler?.OnFoundNewCommit(1); newCommit = await ReferenceOrCopyCommit(sourceRepo, commit.Parents.First(), targetRepo, NextDepth(maxDepth)); } break; case CommitCopyKind.CopyCommit: { // otherwise: copies commit // Count() will be fast because Parents implements Collection var parentCount = commit.Parents.Count(); _progressHandler?.OnFoundNewCommit(parentCount); Commit[] parentArray = new Commit[parentCount]; var parentsIndex = 0; RecursiveCallResult <Commit?>[] promises = new RecursiveCallResult <Commit?> [parentCount]; var promisesIndex = 0; foreach (var commitParent in commit.Parents) { promises[promisesIndex++] = ReferenceOrCopyCommit(sourceRepo, commitParent, targetRepo, NextDepth(maxDepth)); } foreach (var promise in promises) { var newParent = await promise; if (newParent != null) { parentArray[parentsIndex++] = newParent; } } Commit[] parents = parentArray.AsSpan().Slice(0, parentsIndex).ToArray(); targetRepo.Index.Clear(); var targetRepoIndexTree = _callback.CreateCommitTree(commit, parents, targetRepo); var message = _callback.GenerateCommitMessage(commit); var author = commit.Author; var committer = commit.Committer; newCommit = targetRepo.ObjectDatabase.CreateCommit(author, committer, message, targetRepoIndexTree, parents, false); _objectMapping[newCommit.Id] = commit.Id; } break; default: throw new ArgumentOutOfRangeException("", "result of GetCommitCopyKind"); } _objectMapping[commit.Id] = newCommit?.Id ?? PreDefinedHash.EmptyTreeId; return(newCommit); }