public void BuildDiffViewWithMargin(FileSet set)
        {
            var basePatch = LineFourWayDiff.MakePatch(set.Previous, set.Previous);

            var classifiedPatches = LineFourWayDiff.ClassifyPatches(set.PreviousLines, basePatch, set.ReviewPatch);

            var currentLines  = set.CurrentLines.Select((x, i) => new LineLine(i + 1, x)).ToList();
            var previousLines = set.PreviousLines.Select((x, i) => new LineLine(i + 1, x)).ToList();

            LineDiffView.AssignPatchesToLines(classifiedPatches, currentLines, previousLines);

            var cleared = new List <LineLine>();

            LineDiffView.RemoveDiffsFromIdenticalLines(currentLines, previousLines, cleared);

            Console.WriteLine("Cleared:");
            foreach (var line in cleared)
            {
                Console.WriteLine(line);
            }

            DumpLines(currentLines, previousLines);

            var hunks = LineDiffView.BuildHunks(currentLines, previousLines, true).ToList();

            Assert.That(hunks, Has.Count.EqualTo(set.ExpectedPatchesWithMargin.Count), "Proper number of hunks generated");

            AssertHunks(hunks, previousLines, currentLines, set.ExpectedPatchesWithMargin);
        }
            public async Task <Result> Execute(GetFileDiff_Line query)
            {
                var previousCommit = query.Hashes.PreviousHead;
                var currentCommit  = query.Hashes.CurrentHead;

                var previousBaseCommit = query.Hashes.PreviousBase;
                var currentBaseCommit  = query.Hashes.CurrentBase;

                var contents = (await new[]
                {
                    new { Commit = previousCommit, Path = query.OldPath },
                    new { Commit = currentCommit, Path = query.NewPath },
                    new { Commit = previousBaseCommit, Path = query.OldPath },
                    new { Commit = currentBaseCommit, Path = query.OldPath }
                }
                                .DistinctBy(x => x.Commit)
                                .Select(async c => new
                {
                    File = c,
                    Content = (await _api.GetFileContent(query.ReviewId.ProjectId, c.Commit, c.Path)).DecodeString()
                })
                                .WhenAll())
                               .ToDictionary(x => x.File.Commit, x => x.Content);

                if (contents[previousCommit] == "" && query.OldPath != query.NewPath)
                {
                    contents[previousCommit] =
                        (await _api.GetFileContent(query.ReviewId.ProjectId, previousCommit, query.NewPath)).DecodeString();
                }

                foreach (var content in contents)
                {
                    if (IsBinaryFile(content.Value))
                    {
                        return(HandleBinaryFile(contents[previousCommit], contents[currentCommit], previousBaseCommit, currentBaseCommit, previousCommit, currentCommit));
                    }
                }

                var basePatch   = LineFourWayDiff.MakePatch(contents[previousBaseCommit], contents[currentBaseCommit]);
                var reviewPatch = LineFourWayDiff.MakePatch(contents[previousCommit], contents[currentCommit]);

                var currentBaseSplitLines = contents[currentBaseCommit].SplitLinesNoRemove().ToList();
                var previousSplitLines    = contents[previousCommit].SplitLinesNoRemove().ToList();
                var currentSplitLines     = contents[currentCommit].SplitLinesNoRemove().ToList();

                var classifiedPatches = LineFourWayDiff.ClassifyPatches(previousSplitLines, basePatch, reviewPatch);


                var previousLines = previousSplitLines.Select((x, i) => new LineLine(i + 1, x)).ToList();
                var currentLines  = currentSplitLines.Select((x, i) => new LineLine(i + 1, x)).ToList();

                LineDiffView.AssignPatchesToLines(classifiedPatches, currentLines, previousLines);

                var cleared = new List <LineLine>();

                LineDiffView.RemoveDiffsFromIdenticalLines(currentLines, previousLines, cleared);

                HunkInfo MakeHunkInfo(LineDiffView.HunkInfo hunk)
                {
                    var lines = new List <LineInfo>();

                    foreach (var(previous, current) in hunk.Lines)
                    {
                        if (previous != null && current != null)
                        {
                            lines.Add(new LineInfo
                            {
                                Text           = previous.Text.TrimEnd('\n'),
                                Classification = previous.Classification.ToString(),
                                Operation      = previous.Diff?.Operation.ToString() ?? "Equal"
                            });

                            continue;
                        }

                        if (previous != null)
                        {
                            lines.Add(new LineInfo
                            {
                                Text           = previous.Text.TrimEnd('\n'),
                                Classification = previous.Classification.ToString(),
                                Operation      = previous.Diff?.Operation.ToString() ?? "Equal"
                            });
                        }

                        if (current != null)
                        {
                            lines.Add(new LineInfo
                            {
                                Text           = current.Text.TrimEnd('\n'),
                                Classification = current.Classification.ToString(),
                                Operation      = current.Diff?.Operation.ToString() ?? "Equal"
                            });
                        }
                    }

                    return(new HunkInfo
                    {
                        OldPosition = new PatchPosition
                        {
                            Start = hunk.StartPrevious,
                            End = hunk.EndPrevious,
                            Length = hunk.LengthPrevious
                        },
                        NewPosition = new PatchPosition
                        {
                            Start = hunk.StartCurrent,
                            End = hunk.EndCurrent,
                            Length = hunk.LengthCurrent
                        },
                        Lines = lines
                    });
                }

                var baseHunks = LineDiffView.BuildHunks(currentLines, previousLines, true);
                var hunks     = baseHunks.Select(MakeHunkInfo).ToList();

                return(new Result
                {
                    Commits = new ReviewDebugInfo
                    {
                        Review = new RevisionDebugInfo
                        {
                            Previous = previousCommit,
                            Current = currentCommit
                        },
                        Base = new RevisionDebugInfo
                        {
                            Previous = previousBaseCommit,
                            Current = currentBaseCommit
                        }
                    },

                    Contents = new ReviewDebugInfo
                    {
                        Review = new RevisionDebugInfo
                        {
                            Previous = contents[previousCommit],
                            PreviousTotalLines = previousLines.Count,
                            Current = contents[currentCommit],
                            CurrentTotalLines = currentLines.Count
                        },
                        Base = new RevisionDebugInfo
                        {
                            Previous = contents[previousBaseCommit],
                            Current = contents[currentBaseCommit]
                        }
                    },

                    Hunks = hunks
                });
            }