Example #1
0
 private static void ProcessUserChange(FileInformation<string> fileInfo, VisualDiffOutput output)
 {
     string[] newlines =
         Common.Utility.StandardizeLineBreaks(fileInfo.UserFile.GetContents(),
                                              Common.Utility.LineBreaks.Unix).Split('\n');
     ProcessSingleChange(fileInfo, output, newlines, ChangeType.User);
 }
        public void Line_Is_In_Conflict()
        {
            VisualDiffOutput vdo = new VisualDiffOutput();
            vdo.AddLine("line 1", Algorithm.Diff.ChangeType.User, true);
            vdo.AddLine("line 2", Algorithm.Diff.ChangeType.Template, true);
            vdo.AddLine("line 3", Algorithm.Diff.ChangeType.None);
            vdo.ConflictRanges.Add(new VisualDiffOutput.ConflictRange(0, 2));

            Assert.That(vdo.IsLineInConflict(0), "First line is in conflict.");
            Assert.That(vdo.IsLineInConflict(1), "Second line is in conflict.");
            Assert.That(vdo.IsLineInConflict(2), Is.False, "Third line is not a conflict.");
        }
Example #3
0
        /// <summary>
        /// Take a TextFileInformation object, diff it if it hasn't been diffed, and create a VisualDiffOutput object that
        /// represents the output of the diff in a form that can be displayed to the user.
        /// </summary>
        /// <remarks>
        /// If the Prevgen file does not exist, it will perform a diff, then copy the NewGen file into the PrevGen temporarily,
        /// so that all changes will show as User changes.
        /// </remarks>
        /// <param name="fileInfo">The TextFileInformation object that has the information on the diffed files.</param>
        /// <returns>A VisualDiffOutput object containing all of the information needed to show the output of the diff to the user.</returns>
        private VisualDiffOutput ProcessDiff(FileInformation<string> fileInfo)
        {
            if (fileInfo == null) throw new ArgumentNullException("fileInfo");

            VisualDiffOutput output = new VisualDiffOutput();

            bool virtualPrevGen = false;
            string oldPrevGenFilePath = null;

            if (fileInfo.CurrentDiffResult.DiffPerformedSuccessfully == false)
                fileInfo.PerformDiff();

            if (fileInfo.PrevGenFile.HasContents == false)
            {
                virtualPrevGen = true;
                oldPrevGenFilePath = fileInfo.PrevGenFile.FilePath;
                fileInfo.PrevGenFile.ReplaceContents(fileInfo.NewGenFile.GetContents(), true);
            }

            output.DiffType = fileInfo.CurrentDiffResult.DiffType;

            switch (fileInfo.CurrentDiffResult.DiffType)
            {
                case TypeOfDiff.ExactCopy:
                    ProcessExactCopy(fileInfo, output);
                    break;
                case TypeOfDiff.TemplateChangeOnly:
                    ProcessTemplateChange(fileInfo, output);
                    break;
                case TypeOfDiff.UserChangeOnly:
                    ProcessUserChange(fileInfo, output);
                    break;
                case TypeOfDiff.UserAndTemplateChange:
                    ProcessUserAndTemplateChange(fileInfo, output);
                    break;
                case TypeOfDiff.Conflict:
                case TypeOfDiff.Warning:
                    ProcessUserAndTemplateChange(fileInfo, output);
                    break;
            }

            if (virtualPrevGen)
            {
                fileInfo.PrevGenFile.FilePath = oldPrevGenFilePath;
                if (oldPrevGenFilePath != null)
                {
                    fileInfo.PrevGenFile.ReplaceContents("", false);
                }
            }

            return output;
        }
Example #4
0
        private static void ProcessExactCopy(FileInformation<string> fileInfo, VisualDiffOutput output)
        {
            {
                string fileText = fileInfo.NewGenFile.GetContents();
                string[] lines =
                    Common.Utility.StandardizeLineBreaks(fileText, Common.Utility.LineBreaks.Unix).Split('\n');

                foreach (string line in lines)
                {
                    output.LeftLines.Add(new DiffLine(line, ChangeType.None));
                    output.RightLines.Add(new DiffLine(line, ChangeType.None));
                }
            }
        }
        public void Conflict_Range_Moves_Correctly()
        {
            VisualDiffOutput vdo = new VisualDiffOutput();
            vdo.AddLine("line 0", Algorithm.Diff.ChangeType.None);
            vdo.AddLine("line 1", Algorithm.Diff.ChangeType.User, true);
            vdo.AddLine("line 2", Algorithm.Diff.ChangeType.Template, true);
            vdo.ConflictRanges.Add(new VisualDiffOutput.ConflictRange(1, 3));

            Assert.That(vdo.IsLineInConflict(0), Is.False, "First line is not in conflict.");
            Assert.That(vdo.IsLineInConflict(1), "Second line is in conflict.");
            Assert.That(vdo.IsLineInConflict(2), "Third line is in conflict.");

            vdo.RemoveLine(0);

            Assert.That(vdo.LineCount, Is.EqualTo(2));
            Assert.That(vdo.IsLineInConflict(0), "First line is in conflict.");
            Assert.That(vdo.IsLineInConflict(1), "Second line is in conflict.");
        }
Example #6
0
        private static void ProcessUserAndTemplateChange(FileInformation<string> fileInfo, VisualDiffOutput output)
        {
            string[] newlines = Common.Utility.StandardizeLineBreaks(
                fileInfo.NewGenFile.GetContents(),
                Common.Utility.LineBreaks.Unix)
                .Split('\n');

            ProcessSingleChange(fileInfo, output, newlines, ChangeType.Template);

            newlines = Common.Utility.StandardizeLineBreaks(
                fileInfo.UserFile.GetContents(),
                Common.Utility.LineBreaks.Unix)
                .Split('\n');

            VisualDiffOutput secondOutput = new VisualDiffOutput();
            ProcessSingleChange(fileInfo, secondOutput, newlines, ChangeType.User);

            output.MergeOutput(secondOutput, ChangeType.Template, ChangeType.User);
        }
Example #7
0
        private static void ProcessSingleChange(FileInformation<string> fileInfo, VisualDiffOutput output, string[] newlines, ChangeType changeType)
        {
            string[] prevGenLines =
                Common.Utility.StandardizeLineBreaks(fileInfo.PrevGenFile.GetContents(), Common.Utility.LineBreaks.Unix).Split('\n');

            Diff diff = new Diff(prevGenLines, newlines, true, true);

            // loop through parts of the diff
            foreach (Diff.Hunk hunk in diff)
            {
                if (hunk.Same)
                {
                    for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                    {
                        output.LeftLines.Add(new DiffLine(newlines[i]));
                        output.RightLines.Add(new DiffLine(newlines[i]));
                    }
                }
                else
                {
                    // If the left and right of the hunk both have lines in the hunk, this is a change.
                    if (hunk.Right.Count != 0 && hunk.Left.Count != 0)
                    {
                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            output.RightLines.Add(new DiffLine(newlines[i], changeType));
                        }
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            output.LeftLines.Add(new DiffLine(prevGenLines[i], ChangeType.None));
                        }

                        while (output.LeftLines.Count < output.RightLines.Count)
                        {
                            output.LeftLines.Add(new DiffLine("", changeType, true));
                        }
                        while (output.RightLines.Count < output.LeftLines.Count)
                        {
                            output.RightLines.Add(new DiffLine("", changeType, true));
                        }
                    }
                    else if (hunk.Right.Count != 0) // The right hand side has added lines.
                    {
                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            output.LeftLines.Add(new DiffLine("", changeType, true));
                            output.RightLines.Add(new DiffLine(newlines[i], changeType));
                        }
                    }
                    else // The left hand side has extra lines.
                    {
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            output.LeftLines.Add(new DiffLine(prevGenLines[i], ChangeType.None));
                            output.RightLines.Add(new DiffLine("", changeType, true));
                        }
                    }

                }
            }
        }
        /// <summary>
        /// Forces the control to update the contents of its editors, and display the diff results.
        /// </summary>
        internal void Fill()
        {
            BusyPopulatingEditors = true;
            if (fileInformation == null)
            {
                editorOriginal.Text = "";
                editorResolved.Text = "";
                BusyPopulatingEditors = false;
                return;
            }

            if (string.IsNullOrEmpty(fileInformation.CurrentDiffResult.DiffWarningDescription) == false)
            {
                WarningText = (string.IsNullOrEmpty(WarningText) ? "" : WarningText + Environment.NewLine) + fileInformation.CurrentDiffResult.DiffWarningDescription;
            }
            else
                panelWarning.Visible = false;

            editorOriginal.SuspendPainting();
            editorResolved.SuspendPainting();

            currentDiffInfo = displayAlgorithm.GetDiffOutput();
            editorOriginal.Document.Text = "";
            editorResolved.Document.Text = "";

            if (CurrentDiffInfo.DiffType == TypeOfDiff.Conflict)
                EnableEditing(true);

            FillEditors();

            editorOriginal.SelectedView.ScrollToDocumentStart();
            editorResolved.SelectedView.ScrollToDocumentStart();

            displayAlgorithm.AddButtons();
            HasUnsavedChanges = false;
            Refresh();

            editorOriginal.ResumePainting();
            editorResolved.ResumePainting();
            BusyPopulatingEditors = false;
        }
        public VisualDiffOutput ProcessMergeOutput()
        {
            if (fileInformation.UserFile.HasContents == false)
            {
                throw new InvalidOperationException("Cannot merge: User file has no contents");
            }
            if (fileInformation.NewGenFile.HasContents == false)
            {
                throw new InvalidOperationException("Cannot merge: Template file has no contents");
            }

            VisualDiffOutput vdo = new VisualDiffOutput();

            string leftText  = Common.Utility.StandardizeLineBreaks(fileInformation.NewGenFile.GetContents(), Common.Utility.LineBreaks.Unix);
            string rightText = Common.Utility.StandardizeLineBreaks(fileInformation.UserFile.GetContents(), Common.Utility.LineBreaks.Unix);

            StringUtility.RemoveTrailingLineBreaks(ref leftText);
            StringUtility.RemoveTrailingLineBreaks(ref rightText);

            leftText  = Common.Utility.StandardizeLineBreaks(leftText, Common.Utility.LineBreaks.Unix);
            rightText = Common.Utility.StandardizeLineBreaks(rightText, Common.Utility.LineBreaks.Unix);

            string[] leftLines  = leftText.Split('\n');
            string[] rightLines = rightText.Split('\n');

            Diff diff = new Diff(leftLines, rightLines, true, true);

            foreach (Diff.Hunk h in diff)
            {
                if (h.Same)
                {
                    foreach (string line in h.Original())
                    {
                        vdo.AddLine(line, ChangeType.None);
                    }
                    continue;
                }

                // Is this a conflict?
                if (h.Left.Count > 0 && h.Right.Count > 0)
                {
                    int startIndex = vdo.LineCount;

                    foreach (string line in h.Right)
                    {
                        vdo.LeftLines.Add(new DiffLine(line, ChangeType.User));
                    }
                    foreach (string line in h.Left)
                    {
                        vdo.LeftLines.Add(new DiffLine(line, ChangeType.Template));
                    }

                    for (int i = 0; i < h.Right.Count; i++)
                    {
                        vdo.RightLines.Add(new DiffLine("", ChangeType.None, true));
                    }
                    for (int i = 0; i < h.Left.Count; i++)
                    {
                        vdo.RightLines.Add(new DiffLine("", ChangeType.None, true));
                    }

                    vdo.ConflictRanges.Add(new VisualDiffOutput.ConflictRange(startIndex, vdo.LineCount));

                    continue;
                }

                // Not a conflict. Just add the new lines and put virtual lines on the left.

                // Only one of these will actually run - we've already handled the case where
                // both sides of the hunk have lines.
                foreach (string line in h.Left)
                {
                    vdo.RightLines.Add(new DiffLine(line, ChangeType.Template));
                    vdo.LeftLines.Add(new DiffLine("", ChangeType.None, true));
                }
                foreach (string line in h.Right)
                {
                    vdo.RightLines.Add(new DiffLine(line, ChangeType.User));
                    vdo.LeftLines.Add(new DiffLine("", ChangeType.None, true));
                }
            }
            if (vdo.LineCount > 0)
            {
                vdo.RemoveLine(vdo.LineCount - 1);
            }

            return(vdo);
        }
Example #10
0
        public VisualDiffOutput ProcessMergeOutput()
        {
            vdo = new VisualDiffOutput();

            if (!fileInfo.NewGenFile.HasContents &&
               !fileInfo.UserFile.HasContents &&
               !fileInfo.PrevGenFile.HasContents)
            {
                vdo.DiffType = TypeOfDiff.ExactCopy;
                return vdo;
            }

            if (fileInfo.PrevGenFile.HasContents == false)
            {
                if (fileInfo.NewGenFile.HasContents == false)
                {
                    // prevGen and NewGen are missing. Copy everything from user and mark exact copy.
                    AddAllLinesFromList(user, ChangeType.None);
                    return vdo;
                }
                if (fileInfo.UserFile.HasContents == false)
                {
                    // prevGen and user are missing. Copy everything from NewGen and mark exact copy.
                    AddAllLinesFromList(newgen, ChangeType.None);
                    return vdo;
                }
                prevgen = ExtractFileToStringList(fileInfo.NewGenFile);
            }
            else
            {
                if (fileInfo.UserFile.HasContents == false && fileInfo.NewGenFile.HasContents)
                    user = ExtractFileToStringList(fileInfo.PrevGenFile);
                else if (fileInfo.NewGenFile.HasContents == false && fileInfo.UserFile.HasContents)
                    newgen = ExtractFileToStringList(fileInfo.PrevGenFile);
                else if (fileInfo.NewGenFile.HasContents == false && fileInfo.UserFile.HasContents == false)
                {
                    // User and NewGen are missing. Copy everything from prevgen and mark everything missing.
                    AddAllLinesFromList(prevgen, ChangeType.UserAndTemplate);
                    return vdo;
                }
            }

            Queue<Merge.Conflict> conflicts;
            Queue<ExtendedRange> ranges;

            // We need to add a blank line to the bottom of each file, or any lines that are added
            // at the bottom of the new files will be discarded by the diff/merge. I have spent far
            // too long trying to work out why, this work around works so I'm going with it. If someone
            // fixes the underlying problem, this should still work fine. We remove the last line of the
            // merged lines to compensate for this.
            /* Begin Hack */
            prevgen.Add("");
            user.Add("");
            newgen.Add("");
            /* End Hack */

            // Do the initial 3 way diff
            Merge.MergeLists(prevgen, user, newgen, out conflicts, out ranges);

            while (conflicts.Count + ranges.Count > 0)
            {
                // Get the next range or conflict
                int conflictStart = int.MaxValue, rangeStart = int.MaxValue;
                if (conflicts.Count > 0)
                {
                    conflictStart = conflicts.Peek().Ranges[0].Start;
                }
                if (ranges.Count > 0)
                {
                    rangeStart = ranges.Peek().ChangedRange.Start;
                }
                // If the next range came first, process it next. Otherwise process the next conflict.
                if (rangeStart < conflictStart)
                    ProcessRange(ranges.Dequeue());
                else
                    ProcessConflict(conflicts.Dequeue());
            }
            // Other half of the above hack.
            if (vdo.LeftLines[vdo.LeftLines.Count - 1].Text == "" && vdo.RightLines[vdo.RightLines.Count - 1].Text == "")
                vdo.RemoveLine(vdo.LeftLines.Count - 1);
            return vdo;
        }
Example #11
0
        internal void MergeOutput(VisualDiffOutput otherOutput, ChangeType thisChangeType, ChangeType otherChangeType)
        {
            string[] thisTempLines  = LinesToStringArray(this.RightLines);
            string[] otherTempLines = LinesToStringArray(otherOutput.RightLines);

            this.LeftLines.Clear();
            this.RightLines.Clear();

            Diff diff = new Diff(thisTempLines, otherTempLines, true, true);

            // loop through parts of the diff
            foreach (Diff.Hunk hunk in diff)
            {
                int lineMismatch = hunk.Right.Start - hunk.Left.Start;
                if (hunk.Same)
                {
                    for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                    {
                        if (otherOutput.RightLines[i].Change != ChangeType.None)
                        {
                            //Both the user and template have changed to the same thing. Need to display this.
                            leftLines.Add(new DiffLine(otherOutput.LeftLines[i].Text, thisChangeType | otherChangeType, otherOutput.LeftLines[i].IsVirtual));
                            rightLines.Add(new DiffLine(otherTempLines[i], thisChangeType | otherChangeType));
                        }
                        else
                        {
                            leftLines.Add(new DiffLine(otherTempLines[i]));
                            rightLines.Add(new DiffLine(otherTempLines[i]));
                        }
                    }
                }
                else
                {
                    // If the left and right of the hunk both have lines, this could be a conflict.
                    if (hunk.Right.Count != 0 && hunk.Left.Count != 0)
                    {
                        ConflictRange conflictRange = new ConflictRange();
                        conflictRange.StartLineIndex = leftLines.Count;

                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            leftLines.Add(new DiffLine(otherTempLines[i], otherChangeType));
                            rightLines.Add(new DiffLine("", otherChangeType, true));
                        }
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            leftLines.Add(new DiffLine(thisTempLines[i], thisChangeType));
                            rightLines.Add(new DiffLine("", thisChangeType, true));
                        }

                        conflictRange.EndLineIndex = leftLines.Count;
                        conflictRanges.Add(conflictRange);
                    }
                    else if (hunk.Right.Count != 0)
                    {
                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            leftLines.Add(new DiffLine("", otherChangeType, true));
                            rightLines.Add(new DiffLine(otherTempLines[i], otherChangeType));
                        }
                    }
                    else
                    {
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            leftLines.Add(new DiffLine("", thisChangeType, true));
                            rightLines.Add(new DiffLine(thisTempLines[i], thisChangeType));
                        }
                    }
                }
            }
        }
 private static void ProcessUserChange(FileInformation<string> fileInfo, VisualDiffOutput output)
 {
     string[] newlines =
         Common.Utility.StandardizeLineBreaks(fileInfo.UserFile.GetContents(),
                                              Common.Utility.LineBreaks.Unix).Split('\n');
     ProcessSingleChange(fileInfo, output, newlines, ChangeType.User);
 }
        private static void ProcessUserAndTemplateChange(FileInformation<string> fileInfo, VisualDiffOutput output)
        {
            string[] newlines = Common.Utility.StandardizeLineBreaks(
                fileInfo.NewGenFile.GetContents(),
                Common.Utility.LineBreaks.Unix)
                .Split('\n');

            ProcessSingleChange(fileInfo, output, newlines, ChangeType.Template);

            newlines = Common.Utility.StandardizeLineBreaks(
                fileInfo.UserFile.GetContents(),
                Common.Utility.LineBreaks.Unix)
                .Split('\n');

            VisualDiffOutput secondOutput = new VisualDiffOutput();
            ProcessSingleChange(fileInfo, secondOutput, newlines, ChangeType.User);

            output.MergeOutput(secondOutput, ChangeType.Template, ChangeType.User);
        }
        private static void ProcessSingleChange(FileInformation<string> fileInfo, VisualDiffOutput output, string[] newlines, ChangeType changeType)
        {
            string[] prevGenLines =
                Common.Utility.StandardizeLineBreaks(fileInfo.PrevGenFile.GetContents(), Common.Utility.LineBreaks.Unix).Split('\n');

            Diff diff = new Diff(prevGenLines, newlines, true, true);

            // loop through parts of the diff
            foreach (Diff.Hunk hunk in diff)
            {
                if (hunk.Same)
                {
                    for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                    {
                        output.LeftLines.Add(new DiffLine(newlines[i]));
                        output.RightLines.Add(new DiffLine(newlines[i]));
                    }
                }
                else
                {
                    // If the left and right of the hunk both have lines in the hunk, this is a change.
                    if (hunk.Right.Count != 0 && hunk.Left.Count != 0)
                    {
                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            output.RightLines.Add(new DiffLine(newlines[i], changeType));
                        }
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            output.LeftLines.Add(new DiffLine(prevGenLines[i], ChangeType.None));
                        }

                        while (output.LeftLines.Count < output.RightLines.Count)
                        {
                            output.LeftLines.Add(new DiffLine("", changeType, true));
                        }
                        while (output.RightLines.Count < output.LeftLines.Count)
                        {
                            output.RightLines.Add(new DiffLine("", changeType, true));
                        }
                    }
                    else if (hunk.Right.Count != 0) // The right hand side has added lines.
                    {
                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            output.LeftLines.Add(new DiffLine("", changeType, true));
                            output.RightLines.Add(new DiffLine(newlines[i], changeType));
                        }
                    }
                    else // The left hand side has extra lines.
                    {
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            output.LeftLines.Add(new DiffLine(prevGenLines[i], ChangeType.None));
                            output.RightLines.Add(new DiffLine("", changeType, true));
                        }
                    }

                }
            }
        }
        /// <summary>
        /// Take a TextFileInformation object, diff it if it hasn't been diffed, and create a VisualDiffOutput object that
        /// represents the output of the diff in a form that can be displayed to the user.
        /// </summary>
        /// <remarks>
        /// If the Prevgen file does not exist, it will perform a diff, then copy the NewGen file into the PrevGen temporarily,
        /// so that all changes will show as User changes.
        /// </remarks>
        /// <param name="fileInfo">The TextFileInformation object that has the information on the diffed files.</param>
        /// <returns>A VisualDiffOutput object containing all of the information needed to show the output of the diff to the user.</returns>
        private VisualDiffOutput ProcessDiff(FileInformation<string> fileInfo)
        {
            if (fileInfo == null) throw new ArgumentNullException("fileInfo");

            VisualDiffOutput output = new VisualDiffOutput();

            bool virtualPrevGen = false;
            string oldPrevGenFilePath = null;

            if (fileInfo.CurrentDiffResult.DiffPerformedSuccessfully == false)
                fileInfo.PerformDiff();

            if (fileInfo.PrevGenFile.HasContents == false)
            {
                virtualPrevGen = true;
                oldPrevGenFilePath = fileInfo.PrevGenFile.FilePath;
                fileInfo.PrevGenFile.ReplaceContents(fileInfo.NewGenFile.GetContents(), true);
            }

            output.DiffType = fileInfo.CurrentDiffResult.DiffType;

            switch (fileInfo.CurrentDiffResult.DiffType)
            {
                case TypeOfDiff.ExactCopy:
                    ProcessExactCopy(fileInfo, output);
                    break;
                case TypeOfDiff.TemplateChangeOnly:
                    ProcessTemplateChange(fileInfo, output);
                    break;
                case TypeOfDiff.UserChangeOnly:
                    ProcessUserChange(fileInfo, output);
                    break;
                case TypeOfDiff.UserAndTemplateChange:
                    ProcessUserAndTemplateChange(fileInfo, output);
                    break;
                case TypeOfDiff.Conflict:
                case TypeOfDiff.Warning:
                    ProcessUserAndTemplateChange(fileInfo, output);
                    break;
            }

            if (virtualPrevGen)
            {
                fileInfo.PrevGenFile.FilePath = oldPrevGenFilePath;
                if (oldPrevGenFilePath != null)
                {
                    fileInfo.PrevGenFile.ReplaceContents("", false);
                }
            }

            return output;
        }
        public VisualDiffOutput ProcessMergeOutput()
        {
            vdo = new VisualDiffOutput();

            if (!fileInfo.NewGenFile.HasContents &&
               !fileInfo.UserFile.HasContents &&
               !fileInfo.PrevGenFile.HasContents)
            {
                vdo.DiffType = TypeOfDiff.ExactCopy;
                return vdo;
            }

            if (fileInfo.PrevGenFile.HasContents == false)
            {
                if (fileInfo.NewGenFile.HasContents == false)
                {
                    // prevGen and NewGen are missing. Copy everything from user and mark exact copy.
                    AddAllLinesFromList(user, ChangeType.None);
                    return vdo;
                }
                if (fileInfo.UserFile.HasContents == false)
                {
                    // prevGen and user are missing. Copy everything from NewGen and mark exact copy.
                    AddAllLinesFromList(newgen, ChangeType.None);
                    return vdo;
                }
                prevgen = ExtractFileToStringList(fileInfo.NewGenFile);
            }
            else
            {
                if (fileInfo.UserFile.HasContents == false && fileInfo.NewGenFile.HasContents)
                    user = ExtractFileToStringList(fileInfo.PrevGenFile);
                else if (fileInfo.NewGenFile.HasContents == false && fileInfo.UserFile.HasContents)
                    newgen = ExtractFileToStringList(fileInfo.PrevGenFile);
                else if (fileInfo.NewGenFile.HasContents == false && fileInfo.UserFile.HasContents == false)
                {
                    // User and NewGen are missing. Copy everything from prevgen and mark everything missing.
                    AddAllLinesFromList(prevgen, ChangeType.UserAndTemplate);
                    return vdo;
                }
            }

            Queue<Merge.Conflict> conflicts;
            Queue<ExtendedRange> ranges;

            // We need to add a blank line to the bottom of each file, or any lines that are added
            // at the bottom of the new files will be discarded by the diff/merge. I have spent far
            // too long trying to work out why, this work around works so I'm going with it. If someone
            // fixes the underlying problem, this should still work fine. We remove the last line of the
            // merged lines to compensate for this.
            /* Begin Hack */
            prevgen.Add("");
            user.Add("");
            newgen.Add("");
            /* End Hack */

            // Do the initial 3 way diff
            Merge.MergeLists(prevgen, user, newgen, out conflicts, out ranges);

            while (conflicts.Count + ranges.Count > 0)
            {
                // Get the next range or conflict
                int conflictStart = int.MaxValue, rangeStart = int.MaxValue;
                if (conflicts.Count > 0)
                {
                    conflictStart = conflicts.Peek().Ranges[0].Start;
                }
                if (ranges.Count > 0)
                {
                    rangeStart = ranges.Peek().ChangedRange.Start;
                }
                // If the next range came first, process it next. Otherwise process the next conflict.
                if (rangeStart < conflictStart)
                    ProcessRange(ranges.Dequeue());
                else
                    ProcessConflict(conflicts.Dequeue());
            }
            // Other half of the above hack.
            if (vdo.LeftLines[vdo.LeftLines.Count - 1].Text == "" && vdo.RightLines[vdo.RightLines.Count - 1].Text == "")
                vdo.RemoveLine(vdo.LeftLines.Count - 1);
            return vdo;
        }
Example #17
0
        internal void MergeOutput(VisualDiffOutput otherOutput, ChangeType thisChangeType, ChangeType otherChangeType)
        {
            string[] thisTempLines = LinesToStringArray(this.RightLines);
            string[] otherTempLines = LinesToStringArray(otherOutput.RightLines);

            this.LeftLines.Clear();
            this.RightLines.Clear();

            Diff diff = new Diff(thisTempLines, otherTempLines, true, true);

            // loop through parts of the diff
            foreach (Diff.Hunk hunk in diff)
            {
                int lineMismatch = hunk.Right.Start - hunk.Left.Start;
                if (hunk.Same)
                {
                    for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                    {
                        if (otherOutput.RightLines[i].Change != ChangeType.None)
                        {
                            //Both the user and template have changed to the same thing. Need to display this.
                            leftLines.Add(new DiffLine(otherOutput.LeftLines[i].Text, thisChangeType | otherChangeType, otherOutput.LeftLines[i].IsVirtual));
                            rightLines.Add(new DiffLine(otherTempLines[i], thisChangeType | otherChangeType));
                        }
                        else
                        {
                            leftLines.Add(new DiffLine(otherTempLines[i]));
                            rightLines.Add(new DiffLine(otherTempLines[i]));
                        }
                    }
                }
                else
                {
                    // If the left and right of the hunk both have lines, this could be a conflict.
                    if (hunk.Right.Count != 0 && hunk.Left.Count != 0)
                    {
                        ConflictRange conflictRange = new ConflictRange();
                        conflictRange.StartLineIndex = leftLines.Count;

                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            leftLines.Add(new DiffLine(otherTempLines[i], otherChangeType));
                            rightLines.Add(new DiffLine("", otherChangeType, true));
                        }
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            leftLines.Add(new DiffLine(thisTempLines[i], thisChangeType));
                            rightLines.Add(new DiffLine("", thisChangeType, true));
                        }

                        conflictRange.EndLineIndex = leftLines.Count;
                        conflictRanges.Add(conflictRange);
                    }
                    else if (hunk.Right.Count != 0)
                    {
                        for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                        {
                            leftLines.Add(new DiffLine("", otherChangeType, true));
                            rightLines.Add(new DiffLine(otherTempLines[i], otherChangeType));
                        }
                    }
                    else
                    {
                        for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                        {
                            leftLines.Add(new DiffLine("", thisChangeType, true));
                            rightLines.Add(new DiffLine(thisTempLines[i], thisChangeType));
                        }
                    }

                }
            }
        }
Example #18
0
        public VisualDiffOutput ProcessMergeOutput()
        {
            if (fileInformation.UserFile.HasContents == false)
                throw new InvalidOperationException("Cannot merge: User file has no contents");
            if (fileInformation.NewGenFile.HasContents == false)
                throw new InvalidOperationException("Cannot merge: Template file has no contents");

            VisualDiffOutput vdo = new VisualDiffOutput();

            string leftText = Common.Utility.StandardizeLineBreaks(fileInformation.NewGenFile.GetContents(), Common.Utility.LineBreaks.Unix);
            string rightText = Common.Utility.StandardizeLineBreaks(fileInformation.UserFile.GetContents(), Common.Utility.LineBreaks.Unix);

            StringUtility.RemoveTrailingLineBreaks(ref leftText);
            StringUtility.RemoveTrailingLineBreaks(ref rightText);

            leftText = Common.Utility.StandardizeLineBreaks(leftText, Common.Utility.LineBreaks.Unix);
            rightText = Common.Utility.StandardizeLineBreaks(rightText, Common.Utility.LineBreaks.Unix);

            string[] leftLines = leftText.Split('\n');
            string[] rightLines = rightText.Split('\n');

            Diff diff = new Diff(leftLines, rightLines, true, true);

            foreach(Diff.Hunk h in diff)
            {
                if(h.Same)
                {
                    foreach(string line in h.Original())
                    {
                        vdo.AddLine(line, ChangeType.None);
                    }
                    continue;
                }

                // Is this a conflict?
                if(h.Left.Count > 0 && h.Right.Count > 0)
                {
                    int startIndex = vdo.LineCount;

                    foreach (string line in h.Right)
                    {
                        vdo.LeftLines.Add(new DiffLine(line, ChangeType.User));
                    }
                    foreach (string line in h.Left)
                    {
                        vdo.LeftLines.Add(new DiffLine(line, ChangeType.Template));
                    }

                    for (int i = 0; i < h.Right.Count; i++)
                    {
                        vdo.RightLines.Add(new DiffLine("", ChangeType.None, true));
                    }
                    for (int i = 0; i < h.Left.Count; i++)
                    {
                        vdo.RightLines.Add(new DiffLine("", ChangeType.None, true));
                    }

                    vdo.ConflictRanges.Add(new VisualDiffOutput.ConflictRange(startIndex, vdo.LineCount));

                    continue;
                }

                // Not a conflict. Just add the new lines and put virtual lines on the left.

                // Only one of these will actually run - we've already handled the case where
                // both sides of the hunk have lines.
                foreach(string line in h.Left)
                {
                    vdo.RightLines.Add(new DiffLine(line, ChangeType.Template));
                    vdo.LeftLines.Add(new DiffLine("", ChangeType.None, true));
                }
                foreach (string line in h.Right)
                {
                    vdo.RightLines.Add(new DiffLine(line, ChangeType.User));
                    vdo.LeftLines.Add(new DiffLine("", ChangeType.None, true));
                }
            }
            if(vdo.LineCount > 0)
                vdo.RemoveLine(vdo.LineCount - 1);

            return vdo;
        }
 private VisualDiffOutput CreateVisualDiffOutput()
 {
     VisualDiffOutput vdo = new VisualDiffOutput();
     vdo.AddLine("line 0", Algorithm.Diff.ChangeType.None);
     vdo.AddLine("line 1", Algorithm.Diff.ChangeType.User, true);
     vdo.AddLine("line 2", Algorithm.Diff.ChangeType.Template, true);
     vdo.AddLine("line 3", Algorithm.Diff.ChangeType.None);
     vdo.ConflictRanges.Add(new VisualDiffOutput.ConflictRange(1, 3));
     return vdo;
 }
        private static void ProcessExactCopy(FileInformation<string> fileInfo, VisualDiffOutput output)
        {
            {
                string fileText = fileInfo.NewGenFile.GetContents();
                string[] lines =
                    Common.Utility.StandardizeLineBreaks(fileText, Common.Utility.LineBreaks.Unix).Split('\n');

                foreach (string line in lines)
                {
                    output.LeftLines.Add(new DiffLine(line, ChangeType.None));
                    output.RightLines.Add(new DiffLine(line, ChangeType.None));
                }
            }
        }