public Commit FindMergeBase(Branch branch, Branch otherBranch)
{
var key = Tuple.Create(branch, otherBranch);
if (mergeBaseCache.ContainsKey(key))
{
Logger.WriteDebug(string.Format(
"Cache hit for merge base between '{0}' and '{1}'.",
branch.FriendlyName, otherBranch.FriendlyName));
return mergeBaseCache[key].MergeBase;
}
using (Logger.IndentLog(string.Format("Finding merge base between '{0}' and '{1}'.", branch.FriendlyName, otherBranch.FriendlyName)))
{
// Otherbranch tip is a forward merge
var commitToFindCommonBase = otherBranch.Tip;
var commit = branch.Tip;
if (otherBranch.Tip.Parents.Contains(commit))
{
commitToFindCommonBase = otherBranch.Tip.Parents.First();
}
var findMergeBase = this.Repository.ObjectDatabase.FindMergeBase(commit, commitToFindCommonBase);
if (findMergeBase != null)
{
Logger.WriteInfo(string.Format("Found merge base of {0}", findMergeBase.Sha));
// We do not want to include merge base commits which got forward merged into the other branch
bool mergeBaseWasForwardMerge;
do
{
// Now make sure that the merge base is not a forward merge
mergeBaseWasForwardMerge = otherBranch.Commits
.SkipWhile(c => c != commitToFindCommonBase)
.TakeWhile(c => c != findMergeBase)
.Any(c => c.Parents.Contains(findMergeBase));
if (mergeBaseWasForwardMerge)
{
var second = commitToFindCommonBase.Parents.First();
var mergeBase = this.Repository.ObjectDatabase.FindMergeBase(commit, second);
if (mergeBase == findMergeBase)
{
break;
}
findMergeBase = mergeBase;
Logger.WriteInfo(string.Format("Merge base was due to a forward merge, next merge base is {0}", findMergeBase));
}
} while (mergeBaseWasForwardMerge);
}
// Store in cache.
mergeBaseCache.Add(key, new MergeBaseData(branch, otherBranch, this.Repository, findMergeBase));
return findMergeBase;
}
}