/// <summary> /// Perform a three-way merge of two commits, looking up their /// commit ancestor. The returned index will contain the results /// of the merge and can be examined for conflicts. The returned /// index must be disposed. /// </summary> /// <param name="ours">The first tree</param> /// <param name="theirs">The second tree</param> /// <param name="options">The <see cref="MergeTreeOptions"/> controlling the merge</param> /// <returns>The <see cref="Index"/> containing the merged trees and any conflicts</returns> public virtual MergeTreeResult MergeCommits(Commit ours, Commit theirs, MergeTreeOptions options) { Ensure.ArgumentNotNull(ours, "ours"); Ensure.ArgumentNotNull(theirs, "theirs"); options = options ?? new MergeTreeOptions(); var mergeOptions = new GitMergeOpts { Version = 1, MergeFileFavorFlags = options.MergeFileFavor, MergeTreeFlags = options.FindRenames ? GitMergeTreeFlags.GIT_MERGE_TREE_FIND_RENAMES : GitMergeTreeFlags.GIT_MERGE_TREE_NORMAL, RenameThreshold = (uint)options.RenameThreshold, TargetLimit = (uint)options.TargetLimit, }; using (var oneHandle = Proxy.git_object_lookup(repo.Handle, ours.Id, GitObjectType.Commit)) using (var twoHandle = Proxy.git_object_lookup(repo.Handle, theirs.Id, GitObjectType.Commit)) using (var indexHandle = Proxy.git_merge_commits(repo.Handle, oneHandle, twoHandle, mergeOptions)) { MergeTreeResult mergeResult; if (Proxy.git_index_has_conflicts(indexHandle)) { List <Conflict> conflicts = new List <Conflict>(); Conflict conflict; using (ConflictIteratorSafeHandle iterator = Proxy.git_index_conflict_iterator_new(indexHandle)) { while ((conflict = Proxy.git_index_conflict_next(iterator)) != null) { conflicts.Add(conflict); } } mergeResult = new MergeTreeResult(conflicts); } else { var treeId = Proxy.git_index_write_tree_to(indexHandle, repo.Handle); mergeResult = new MergeTreeResult(this.repo.Lookup <Tree>(treeId)); } return(mergeResult); } }
/// <summary> /// Perform a three-way merge of two commits, looking up their /// commit ancestor. The returned index will contain the results /// of the merge and can be examined for conflicts. The returned /// index must be disposed. /// </summary> /// <param name="ours">The first tree</param> /// <param name="theirs">The second tree</param> /// <param name="options">The <see cref="MergeTreeOptions"/> controlling the merge</param> /// <returns>The <see cref="Index"/> containing the merged trees and any conflicts</returns> public virtual MergeTreeResult MergeCommits(Commit ours, Commit theirs, MergeTreeOptions options) { Ensure.ArgumentNotNull(ours, "ours"); Ensure.ArgumentNotNull(theirs, "theirs"); options = options ?? new MergeTreeOptions(); // We throw away the index after looking at the conflicts, so we'll never need the REUC // entries to be there GitMergeFlag mergeFlags = GitMergeFlag.GIT_MERGE_NORMAL | GitMergeFlag.GIT_MERGE_SKIP_REUC; if (options.FindRenames) { mergeFlags |= GitMergeFlag.GIT_MERGE_FIND_RENAMES; } if (options.FailOnConflict) { mergeFlags |= GitMergeFlag.GIT_MERGE_FAIL_ON_CONFLICT; } var mergeOptions = new GitMergeOpts { Version = 1, MergeFileFavorFlags = options.MergeFileFavor, MergeTreeFlags = mergeFlags, RenameThreshold = (uint)options.RenameThreshold, TargetLimit = (uint)options.TargetLimit, }; bool earlyStop; using (var oneHandle = Proxy.git_object_lookup(repo.Handle, ours.Id, GitObjectType.Commit)) using (var twoHandle = Proxy.git_object_lookup(repo.Handle, theirs.Id, GitObjectType.Commit)) using (var indexHandle = Proxy.git_merge_commits(repo.Handle, oneHandle, twoHandle, mergeOptions, out earlyStop)) { MergeTreeResult mergeResult; // Stopped due to FailOnConflict so there's no index or conflict list if (earlyStop) { return(new MergeTreeResult(new Conflict[] { })); } if (Proxy.git_index_has_conflicts(indexHandle)) { List <Conflict> conflicts = new List <Conflict>(); Conflict conflict; using (ConflictIteratorSafeHandle iterator = Proxy.git_index_conflict_iterator_new(indexHandle)) { while ((conflict = Proxy.git_index_conflict_next(iterator)) != null) { conflicts.Add(conflict); } } mergeResult = new MergeTreeResult(conflicts); } else { var treeId = Proxy.git_index_write_tree_to(indexHandle, repo.Handle); mergeResult = new MergeTreeResult(this.repo.Lookup <Tree>(treeId)); } return(mergeResult); } }