static void ResolveSingleVersion(List<string> result, Version original, Version version) { while (!version.Ended || !version.Ended) { if (CompareStrings(original.CurrentLine, version.CurrentLine)) { original.SkipLine(); version.SkipLine(); } else { version.AcceptLine(result); } } }
static void ResolveTwoWayLine(Version left, Version right, List<string> result) { result.Add(CheckForConflict(left.CurrentLine, right.CurrentLine)); left.SkipLine(); right.SkipLine(); return; }
/// <summary> /// Performs the three way merge operation upon lists of strings. /// </summary> /// <param name="originalList">The original list.</param> /// <param name="leftList">First version.</param> /// <param name="rightList">Second version.</param> /// <returns>The merged list.</returns> public static List<string> Merge(IEnumerable<string> originalList, IEnumerable<string> leftList, IEnumerable<string> rightList) { var result = new List<string>(); var source = new Version(originalList.ToList()); var one = new Version(leftList.ToList()); var two = new Version(rightList.ToList()); while (!one.Ended || !two.Ended) { if (one.Ended || two.Ended) { var whatNotEnded = one.Ended ? two : one; if (source.Ended) { whatNotEnded.AcceptUntilEnd(result); break; } else { ResolveSingleVersion(result, source, whatNotEnded); break; } } else if (source.Ended) { ResolveTwoWayLine(one, two, result); continue; } if (CompareStrings(source.CurrentLine, one.CurrentLine) && CompareStrings(source.CurrentLine, two.CurrentLine)) { one.AcceptLine(result); source.SkipLine(); two.SkipLine(); } else if (!CompareStrings(source.CurrentLine, one.CurrentLine) || !CompareStrings(source.CurrentLine, two.CurrentLine)) { var whichIsMaybeEqual = source.CurrentLine != one.CurrentLine ? two : one; var whichIsNotEqual = source.CurrentLine != one.CurrentLine ? one : two; if (CompareStrings(source.CurrentLine, whichIsMaybeEqual.CurrentLine)) { if (!whichIsNotEqual.FastForward(result, source.CurrentLine)) { source.SkipLine(); whichIsMaybeEqual.SkipLine(); } } else if (CompareStrings(one.CurrentLine, two.CurrentLine)) { one.AcceptLine(result); two.SkipLine(); } else { ResolveThreeWayConflict(one, two, source, result); } } } return result; }
static void ResolveThreeWayConflict(Version left, Version right, Version original, List<string> result) { var leftIndex = left.FindAnchor(original.CurrentLine); var rightIndex = right.FindAnchor(original.CurrentLine); if (!left.IndexFound(leftIndex) && !right.IndexFound(rightIndex)) { result.Add(CheckForConflict(left.CurrentLine, right.CurrentLine)); left.SkipLine(); right.SkipLine(); original.SkipLine(); } else if (!left.IndexFound(leftIndex)) { right.AcceptLines(result, rightIndex); } else if (!right.IndexFound(rightIndex)) { left.AcceptLines(result, leftIndex); } else { result.AddRange(ResolveTwoWayList(left.Slice(leftIndex), right.Slice(rightIndex))); left.SkipLines(leftIndex); right.SkipLines(rightIndex); } }