Exemple #1
1
 public static void WriteUnifiedDiff (string [] leftLines, string leftName, string [] rightLines, string rightName, System.IO.TextWriter writer, int context, bool caseSensitive, bool compareWhitespace)
 {
     Diff diff = new Diff (
         leftLines,
         rightLines,
         caseSensitive,
         compareWhitespace
     );
     WriteUnifiedDiff (diff, writer, leftName, rightName, context);
 }
Exemple #2
0
 private static IDiff[] makediffs (IList original, IList [] changed, IComparer comparer, IHashCodeProvider hashcoder)
 {
     IDiff[] diffs = new IDiff[changed.Length];
     for (int i = 0; i < changed.Length; i++)
         diffs [i] = new Diff (original, changed [i], comparer, hashcoder);
     return diffs;
 }
Exemple #3
0
        public static void WriteUnifiedDiff(Diff diff, TextWriter writer, string fromfile, string tofile, int context)
        {
            writer.Write("--- ");
            writer.WriteLine(fromfile);
            writer.Write("+++ ");
            writer.WriteLine(tofile);

            ArrayList hunkset = new ArrayList();

            foreach (Diff.Hunk hunk in diff)
            {
                Diff.Hunk lasthunk = null;
                if (hunkset.Count > 0) lasthunk = (Diff.Hunk)hunkset[hunkset.Count - 1];

                if (hunk.Same)
                {
                    // At the start of a hunk set, keep only context lines of context.
                    if (lasthunk == null)
                    {
                        if (hunk.Left.Count > context)
                            hunkset.Add(hunk.Crop(hunk.Left.Count - context, 0));
                        else
                            hunkset.Add(hunk);
                        // Can't have two same hunks in a row, so the last one was a difference.
                    }
                    else
                    {
                        // Small enough context that this unified diff range will not stop.
                        if (hunk.Left.Count <= context * 2)
                        {
                            hunkset.Add(hunk);

                            // Too much of the same.  Keep context lines and end this section.
                            // And then keep the last context lines as context for the next section.
                        }
                        else
                        {
                            hunkset.Add(hunk.Crop(0, hunk.Left.Count - context));
                            WriteUnifiedDiffSection(writer, hunkset);
                            hunkset.Clear();

                            if (hunk.Left.Count > context)
                                hunkset.Add(hunk.Crop(hunk.Left.Count - context, 0));
                            else
                                hunkset.Add(hunk);
                        }
                    }

                }
                else
                {
                    hunkset.Add(hunk);
                }
            }

            if (hunkset.Count > 0 && !(hunkset.Count == 1 && ((Diff.Hunk)hunkset[0]).Same))
                WriteUnifiedDiffSection(writer, hunkset);
        }
        public void TestDeleteLines()
        {
            string[] leftLines = new string[] { "line1", "line2" };
            string[] rightLines = new string[] { "line1" };
            Diff diff = new Diff(leftLines, rightLines, true, true);
            Diff.Hunk[] hunks = Diff.GetHunkList(diff);

            Assert.That(hunks.Length, Is.EqualTo(2));
            Assert.That(hunks[0].Left, Has.Count(1));
            Assert.That(hunks[0].Right, Has.Count(1));
            Assert.That(hunks[1].Left, Has.Count(1));
            Assert.That(hunks[1].Right, Has.Count(0));
        }
 public Enumerator(Diff diff)
 {
     this.diff = diff;
     Reset();
 }
Exemple #6
0
 internal Hunk (Merge merge, Diff.Hunk [][] hunks, int start, int count, bool same)
 {
     this.merge = merge;
     this.hunks = hunks;
     this.start = start;
     this.count = count;
     this.same = same;
                     
     int ct = 0;
     foreach (Diff.Hunk[] hh in hunks) {
         foreach (Diff.Hunk h in hh) {
             if (!h.Same) {
                 ct++;
                 break;
             }
         }
     }
     conflict = (ct > 1);
 }
Exemple #7
0
		private float CompareLists(IList left, IList right, float threshold, bool output) {
			// Given two lists, find the elements in the list that correspond.
			// Two elements correspond if their 'difference metric' is less than
			// or equal to threshold.  For the hunks of correspondent items,
			// recursively descend into items not truly equal.  For hunks of
			// irreconsiliable material, raise the threshold to the next useful
			// level and rescan the items.
			
			if (left == null) throw new ArgumentNullException("left");
			if (right == null) throw new ArgumentNullException("right");

			if (left.Count == 0 && right.Count == 0)
				return 0;
			
			NodeComparerWrapper comparer = new NodeComparerWrapper(threshold, this);
			
			Diff diff = new Diff(left, right, comparer, new HashCodeProvider(this));
			
			int nitems = 0, ndiffs = 0;
			
			foreach (Diff.Hunk hunk in diff) {
				if (hunk.Same || (hunk.Left.Count == 1 && hunk.Right.Count == 1)) {
					// This comprises a block of one-to-one correspondent items who
					// differ by no more than the threshold value.
					
					nitems += hunk.Left.Count;

					bool inSameRegion = false;
					
					for (int i = 0; i < hunk.Left.Count; i++) {
						object oleft = hunk.Left[i];
						object oright = hunk.Right[i];
						
						NodeInterface ileft = GetInterface(oleft);
						NodeInterface iright = GetInterface(oright);
						
						IList cleft = null, cright = null;
						cleft = ileft.GetChildren(oleft);
						cright = iright.GetChildren(oright);
						
						float comp = 0;
						if (ileft == iright)
							comp = ileft.Compare(oleft, oright, this);
						
						// If the nodes are equal, emit one node.
						if (ileft == iright && comp == 0) {
							if (output) {
								if (!inSameRegion) { WritePushSame(); inSameRegion = true; }
								WriteNodeSame(ileft, oleft, oright);
							}
							
						// Recurse into the lists of each node.
						} else if (ileft == iright && cleft != null && cright != null && cleft.Count > 0 && cright.Count > 0 && comp <= 1.0) {
							if (output && inSameRegion) { WritePopSame(); inSameRegion = false; }
							if (output) WritePushNode(ileft, oleft, oright);
							float d = CompareLists(cleft, cright, 0, output);
							d *= hunk.Left.Count;
							if (d < 1) d = 1;
							ndiffs += (int)d;
							if (output) WritePopNode();
							
						// The nodes are not equal, so emit removed and added nodes.
						} else {
							if (output && inSameRegion) { WritePopSame(); inSameRegion = false; }
							if (output) WriteNodeChange(ileft, oleft, iright, oright);
							ndiffs += hunk.Left.Count;
						}
					}
					
					if (output && inSameRegion) WritePopSame();
				} else {
					// We have some arbitrary sets on the left and right side.
					// Try to match nodes on the left with nodes on the right.
					
					ArrayList leftitems = new ArrayList(hunk.Left);
					ArrayList rightitems = new ArrayList(hunk.Right);
					
					while (leftitems.Count > 0 && rightitems.Count > 0) {
						// Find the first node on the left side that matches
						// a node on the right side.
						
						int li = -1, ri = -1;
						float bestD = 1;
							
						for (int lii = 0; lii < leftitems.Count; lii++) {
							object oleft = leftitems[lii];
							NodeInterface ileft = GetInterface(oleft);

							for (int rii = 0; rii < rightitems.Count; rii++) {
								object oright = rightitems[rii];
								NodeInterface iright = GetInterface(oright);
								
								float d = 1;
								if (ileft == iright)
									d = ileft.Compare(oleft, oright, this);
								
								if (d < bestD) {
									bestD = d;
									li = lii;
									ri = rii;
								}
							}
							
						}
						
						if (li == -1) break;
							
						// Try to extend the correspondence further down the right list.
						int count = 1;
						for (int ri2 = ri+1; ri2 < rightitems.Count && (li+(ri2-ri)) < leftitems.Count; ri2++) {
							object oleft2 = leftitems[li+(ri2-ri)];
							object oright2 = rightitems[ri2];
							NodeInterface ileft2 = GetInterface(oleft2);
							NodeInterface iright2 = GetInterface(oright2);
							
							float d2 = 1;
							if (ileft2 == iright2)
								d2 = ileft2.Compare(oleft2, oright2, this);
							
							if (d2 <= bestD)
								count++;
							else
								break;
						}
								
						// We have a correspondence starting at li and ri
						// over count items.
						
						// First, recurse on the first portion of the list that had no matches.
						CompareLists(leftitems.GetRange(0, li), rightitems.GetRange(0, ri), comparer.minimumDifference, output);
						
						// Then recurse on the correspondence range.
						CompareLists(leftitems.GetRange(li, count), rightitems.GetRange(ri, count), comparer.minimumDifference, output);
						
						// Lastly remove the items we just considered and do it again for the rest of the hunk.
						leftitems.RemoveRange(0, li+count);
						rightitems.RemoveRange(0, ri+count);
					}
					
					int ct = leftitems.Count + rightitems.Count;
					nitems += ct;
					ndiffs += ct;
					
					if (output) {
						bool noRecurse = comparer.minimumDifference >= 1;
						if (rightitems.Count == 0 || (leftitems.Count > 0 && noRecurse))
							WriteNodesRemoved(leftitems);
						if (leftitems.Count == 0 || (rightitems.Count > 0 && noRecurse))
							WriteNodesAdded(rightitems);
						if (rightitems.Count != 0 && leftitems.Count != 0 && !noRecurse)
							CompareLists(leftitems, rightitems, comparer.minimumDifference, output);
					}
				}
			}
			
			return (float)ndiffs / (float)nitems;
		}
Exemple #8
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="editorLeft"></param>
        /// <param name="editorRight"></param>
        /// <param name="fileBodyLeft"></param>
        /// <param name="fileBodyRight"></param>
        /// <returns>Returns true if files the same, false if they differ</returns>
        public static bool PerformDiff(ActiproSoftware.SyntaxEditor.SyntaxEditor editorLeft, ActiproSoftware.SyntaxEditor.SyntaxEditor editorRight, ref string fileBodyLeft, ref string fileBodyRight)
        {
            bool filesTheSame = true;
            editorLeft.Text = "";
            editorRight.Text = "";
            string file1 = fileBodyLeft;
            string file2 = fileBodyRight;

            // Performs a line-by-line, case-insensitive comparison.
            string[] arrFile1 = file1.Split('\n');
            string[] arrFile2 = file2.Split('\n');
            Diff diff = new Diff(arrFile1, arrFile2, true, false);

            foreach (Diff.Hunk hunk in diff)
            {
                int lineMismatch = hunk.Right.Count - hunk.Left.Count;
                Color leftCol;
                Color rightCol;
                bool iii = hunk.Same;

                if (!hunk.Same) { filesTheSame = false; }

                if (hunk.Same)
                {
                    leftCol = Color.White;
                    rightCol = Color.White;
                }
                else if (lineMismatch < 0)
                {
                    leftCol = ColourNewGen;
                    rightCol = Color.Silver;
                }
                else
                {
                    leftCol = Color.Silver;
                    rightCol = leftCol = ColourUser;
                }
                for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                {
                    string leftLine = arrFile1[i];

                    if (!hunk.Same)
                    {
                        leftCol = ColourNewGen;
                        editorLeft.Document.AppendText(arrFile1[i]);

                        if (editorLeft.Document.Lines.Count > 1)
                        {
                            editorLeft.Document.Lines[editorLeft.Document.Lines.Count - 2].BackColor = leftCol;
                        }
                    }
                    else
                    {
                        editorLeft.Document.AppendText(arrFile1[i]);

                        if (editorLeft.Document.Lines.Count > 1)
                        {
                            editorLeft.Document.Lines[editorLeft.Document.Lines.Count - 2].BackColor = leftCol;
                        }
                    }
                }
                for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                {
                    string rightLine = arrFile2[i];

                    if (!hunk.Same)
                    {
                        leftCol = ColourUser;
                        editorRight.Document.AppendText(arrFile2[i]);

                        if (editorRight.Document.Lines.Count > 2)
                        {
                            editorRight.Document.Lines[editorRight.Document.Lines.Count - 2].BackColor = leftCol;
                        }
                    }
                    else
                    {
                        editorRight.Document.AppendText(arrFile2[i]);

                        if (editorRight.Document.Lines.Count > 1)
                        {
                            editorRight.Document.Lines[editorRight.Document.Lines.Count - 2].BackColor = rightCol;
                        }
                    }
                }
                if (hunk.Left.Count < hunk.Right.Count)
                {
                    for (int i = 0; i < hunk.Right.Count - hunk.Left.Count; i++)
                    {
                        editorLeft.Document.AppendText("" + Environment.NewLine);
                        editorLeft.Document.Lines[editorLeft.Document.Lines.Count - 2].BackColor = Color.Silver;
                    }
                }
                if (hunk.Right.Count < hunk.Left.Count)
                {
                    for (int i = 0; i < hunk.Left.Count - hunk.Right.Count; i++)
                    {
                        editorRight.Document.AppendText("" + Environment.NewLine);
                        editorRight.Document.Lines[editorRight.Document.Lines.Count - 2].BackColor = Color.Silver;
                    }
                }
            }
            return filesTheSame;
        }
        private void ProcessConflict(Merge.Conflict conflict)
        {
            string[] userLines = SlyceMerge.GetLinesFromRange(user, conflict.Ranges[Merge.UserIndex]);
            string[] newgenLines = SlyceMerge.GetLinesFromRange(newgen, conflict.Ranges[Merge.NewGenIndex]);

            if (userLines.Length == 0 && newgenLines.Length == 0)
            {
                // user and template have both deleted some lines. Add them in as virtual lines.
                foreach (string line in SlyceMerge.GetLinesFromRange(prevgen, conflict.Ranges[Merge.PrevGenIndex]))
                {
                    vdo.AddLineToLeft(line, ChangeType.UserAndTemplate);
                }

                return;
            }

            Diff diff = new Diff(userLines, newgenLines, true, true);

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

                // Conflict
                VisualDiffOutput.ConflictRange crange = new VisualDiffOutput.ConflictRange();
                crange.StartLineIndex = vdo.LeftLines.Count;
                for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                {
                    vdo.LeftLines.Add(new DiffLine(userLines[i], ChangeType.User));
                    vdo.RightLines.Add(new DiffLine("", ChangeType.User, true));
                }
                for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                {
                    vdo.LeftLines.Add(new DiffLine(newgenLines[i], ChangeType.Template));
                    vdo.RightLines.Add(new DiffLine("", ChangeType.Template, true));
                }
                crange.EndLineIndex = vdo.LeftLines.Count;
                vdo.ConflictRanges.Add(crange);
                vdo.DiffType = TypeOfDiff.Conflict;
            }
        }
        private float CompareLists(IList left, IList right, float threshold, bool output)
        {
            // Given two lists, find the elements in the list that correspond.
            // Two elements correspond if their 'difference metric' is less than
            // or equal to threshold.  For the hunks of correspondent items,
            // recursively descend into items not truly equal.  For hunks of
            // irreconsiliable material, raise the threshold to the next useful
            // level and rescan the items.

            if (left.Count == 0 && right.Count == 0)
                return 0;

            NodeComparerWrapper comparer = new NodeComparerWrapper(threshold, this);

            Diff diff = new Diff(left, right, comparer, new HashCodeProvider(this));

            int nitems = 0, ndiffs = 0;

            foreach (Diff.Hunk hunk in diff) {
                if (hunk.Same || (hunk.Left.Count == 1 && hunk.Right.Count == 1)) {
                    // This comprises a block of correspondent items who
                    // differ by no more than the threshold value.

                    nitems += hunk.Left.Count;

                    bool inSameRegion = false;

                    for (int i = 0; i < hunk.Left.Count; i++) {
                        object oleft = hunk.Left[i];
                        object oright = hunk.Right[i];

                        NodeInterface ileft = GetInterface(oleft);
                        NodeInterface iright = GetInterface(oright);

                        IList cleft = null, cright = null;
                        cleft = ileft.GetChildren(oleft);
                        cright = iright.GetChildren(oright);

                        float comp = 0;
                        if (ileft == iright)
                            comp = ileft.Compare(oleft, oright, this);

                        // If the nodes are equal, emit one node.
                        if (ileft == iright && comp == 0) {
                            if (output) {
                                if (!inSameRegion) { WritePushSame(); inSameRegion = true; }
                                WriteNodeSame(ileft, oleft, oright);
                            }

                        // Recurse into the lists of each node.
                        } else if (ileft == iright && cleft != null && cright != null && cleft.Count > 0 && cright.Count > 0 && comp <= 1.0) {
                            if (output && inSameRegion) { WritePopSame(); inSameRegion = false; }
                            if (output) WritePushNode(ileft, oleft, oright);
                            float d = CompareLists(cleft, cright, 0, output);
                            d *= hunk.Left.Count;
                            if (d < 1) d = 1;
                            ndiffs += (int)d;
                            if (output) WritePopNode();

                        // The nodes are not equal, so emit removed and added nodes.
                        } else {
                            if (output && inSameRegion) { WritePopSame(); inSameRegion = false; }
                            if (output) WriteNodeChange(ileft, oleft, iright, oright);
                            ndiffs += hunk.Left.Count;
                        }
                    }

                    if (output && inSameRegion) WritePopSame();
                } else {
                    int ct = hunk.Left.Count + hunk.Right.Count;
                    nitems += ct;
                    ndiffs += ct;

                    if (output) {
                        bool noRecurse = comparer.minimumDifference >= 1;
                        if (hunk.Right.Count == 0 || (hunk.Left.Count > 0 && noRecurse))
                            WriteNodesRemoved(hunk.Left);
                        if (hunk.Left.Count == 0 || (hunk.Right.Count > 0 && noRecurse))
                            WriteNodesAdded(hunk.Right);
                        if (hunk.Right.Count != 0 && hunk.Left.Count != 0 && !noRecurse)
                            CompareLists(hunk.Left, hunk.Right, comparer.minimumDifference, output);
                    }
                }
            }

            return (float)ndiffs / (float)nitems;
        }
        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));
                        }
                    }

                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Perform 3-way merge
        /// </summary>
        /// <returns>Merged text.</returns>
        /// <param name="merge"></param>
        /// <param name="prevGenLines">Previously generated version ie: 'base version'.</param>
        /// <param name="userLines">User-modified version of 'base'.</param>
        /// <param name="nextGenLines">Latest generated version of 'base'.</param>
        internal static string GetMergedOutput(SlyceMergeResult merge, string[] prevGenLines, string[] userLines, string[] nextGenLines)
        {
            // default values and initialisation
            merge.DiffType = TypeOfDiff.ExactCopy;
            merge.Lines = new List<LineText>(200);
            string output = "";
            int lineCounter = -1;
            const string pilcrowString = "¶";
            const char pilcrow = '¶';

            // diff the User version and LatestGenerated version against the PrevGenerated version
            IList res = Merge.MergeLists(prevGenLines, new[] { userLines, nextGenLines });

            // handle empty input
            if (res.Count == 1 && res[0].Equals(string.Empty))
            {
                return string.Empty;
            }
            string conflictTypeName = typeof(Merge.Conflict).FullName;

            // process each line from the diff
            foreach (object line in res)
            {
                lineCounter++;
                string lineTypeName = line.GetType().ToString();

                if (lineTypeName == "System.String")
                {
                    string thisLine = (string)line;
                    merge.Lines.Add(new LineText(thisLine.Replace(pilcrowString, ""), lineCounter, TypeOfLine.Normal));
                }
                else if (lineTypeName == conflictTypeName)
                {
                    Merge.Conflict conf = (Merge.Conflict)line;
                    Range[] ranges = conf.Ranges;
                    Range rangeUser = ranges[0];
                    Range rangeNewGen = ranges[1];

                    string[] conflictUserLines = GetLinesFromRange(userLines, rangeUser);
                    string[] conflictNewGenLines = GetLinesFromRange(nextGenLines, rangeNewGen);

                    // Get diff of the conflicts
                    Diff diff = new Diff(conflictUserLines, conflictNewGenLines, true, false);

                    foreach (Diff.Hunk hunk in diff)
                    {
                        if (hunk.Same)
                        {
                            string same = GetPortionOfString(conflictUserLines, hunk.Left.Start, hunk.Left.End);
                            same = RemoveTrailingCharacter(pilcrowString, same);
                            same = same.Replace(pilcrowString, "\r\n");
                            output += same;
                            merge.Lines.Add(new LineText(same, lineCounter, TypeOfLine.Normal));
                        }
                        else
                        {
                            // Get the user modified lines
                            string userPortion = GetPortionOfString(conflictUserLines, hunk.Left.Start, hunk.Left.End);
                            userPortion = RemoveTrailingCharacter(pilcrowString, userPortion);

                            // Get the newly generated lines
                            string newGenPortion = GetPortionOfString(conflictNewGenLines, hunk.Right.Start, hunk.Right.End);
                            newGenPortion = RemoveTrailingCharacter(pilcrowString, newGenPortion);

                            merge.SetDiffType(TypeOfDiff.Conflict);
                            TypeOfLine lineType = newGenPortion.Length > 0 ? TypeOfLine.User : TypeOfLine.Normal;

                            string[] userSplitLines = userPortion.Split(pilcrow);
                            if (userPortion.Length > 0)
                            {
                                merge.Lines.Add(new LineText(userSplitLines[0], lineCounter, lineType));
                            }
                            for (int myCount = 1; myCount < userSplitLines.Length; myCount++)
                            {
                                lineCounter++;
                                merge.Lines.Add(new LineText(userSplitLines[myCount], lineCounter, lineType));
                            }

                            lineType = userPortion.Length > 0 ? TypeOfLine.NewGen : TypeOfLine.Normal;
                            string[] newGenSplitLines = newGenPortion.Split(pilcrow);
                            if (newGenPortion.Length > 0)
                            {
                                merge.Lines.Add(new LineText(newGenSplitLines[0], lineCounter, lineType));
                            }
                            for (int myCount = 1; myCount < newGenSplitLines.Length; myCount++)
                            {
                                lineCounter++;
                                merge.Lines.Add(new LineText(newGenSplitLines[myCount], lineCounter, lineType));
                            }
                        }
                    }
                }
                else
                {
                    throw new Exception(string.Format("Unexpected line type: {0}\nText1:{1}\n\nText2:{2}\n\nText3:{3}", line.GetType(), prevGenLines, userLines, nextGenLines));
                }
            }
            return output;
        }
Exemple #13
0
        /// <summary>
        /// Merge two text files, by performing a line-by-line, case-sensitive comparison
        /// </summary>
        /// <returns>Enum indicating Conflict, Warning or Exact Copy</returns>
        /// <param name="identifyConflictsOnly">Flag - if true, don't merge</param>
        /// <param name="fileBodyLeft">Contents of LEFT file</param>
        /// <param name="fileBodyRight">Contents of RIGHT file</param>
        /// <param name="leftConflictLines">Array of lines with conflict from LEFT file</param>
        /// <param name="rightConflictLines">Array of lines with conflict from RIGHT file</param>
        /// <param name="combinedText">Result of merging files.</param>
        public static TypeOfDiff PerformTwoWayDiff(
									bool identifyConflictsOnly,
									string fileBodyLeft,
									string fileBodyRight,
									out LineSpan[] leftConflictLines,
									out LineSpan[] rightConflictLines,
									out string combinedText)
        {
            TypeOfDiff returnValue = TypeOfDiff.ExactCopy;
            combinedText = "";
            StringUtility.RemoveTrailingLineBreaks(ref fileBodyLeft);
            StringUtility.RemoveTrailingLineBreaks(ref fileBodyRight);

            // break files into arrays of lines
            string[] leftLines = Common.Utility.StandardizeLineBreaks(fileBodyLeft, Common.Utility.LineBreaks.Unix).Split('\n');
            string[] rightLines = Common.Utility.StandardizeLineBreaks(fileBodyRight, Common.Utility.LineBreaks.Unix).Split('\n');

            // handle case where at least one file is empty
            if (fileBodyLeft.Length == 0 || fileBodyRight.Length == 0)
            {
                // both files are empty (unlikely in practice)
                if (fileBodyLeft.Length == 0 && fileBodyRight.Length == 0)
                {
                    leftConflictLines = new LineSpan[0];
                    rightConflictLines = new LineSpan[0];
                    return TypeOfDiff.ExactCopy;
                }

                // one file is empty
                if (fileBodyLeft.Length > 0)
                {
                    combinedText = fileBodyLeft;
                    leftConflictLines = new[] { new LineSpan(0, leftLines.Length - 1) };
                    rightConflictLines = new LineSpan[0];
                }
                else
                {
                    combinedText = fileBodyRight;
                    leftConflictLines = new LineSpan[0];
                    rightConflictLines = new[] { new LineSpan(0, rightLines.Length - 1) };
                }
                return TypeOfDiff.Warning;
            }

            // initialise variables for merging
            StringBuilder sbMerged = new StringBuilder(Math.Max(fileBodyLeft.Length, fileBodyRight.Length) + 1000);

            // DMW_Question Is a 'combinedLineCount' really a 'mergedLineCount'?
            int combinedLineCount = 0;
            ArrayList combinedLeftColouredLines = new ArrayList();
            ArrayList combinedRightColouredLines = new ArrayList();

            // perform the diff (case-sensitive, check white space)
            Diff diff = new Diff(leftLines, rightLines, true, true);

            // loop through parts of the diff
            foreach (Diff.Hunk hunk in diff)
            {
                if (hunk.Same)
                {
                    for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                    {
                        //DMW_Changed	sbMerged.Append(leftLines[i] + Environment.NewLine);
                        sbMerged.AppendLine(leftLines[i]);
                        combinedLineCount++;
                    }
                }
                else    // hunks are different
                {
                    if (hunk.Left.Count > 0 && hunk.Right.Count > 0)
                    {
                        returnValue = TypeOfDiff.Conflict;
                    }
                    else if (returnValue != TypeOfDiff.Conflict)
                    {
                        returnValue = TypeOfDiff.Warning;
                    }

                    // LEFT file
                    for (int i = hunk.Left.Start; i <= hunk.Left.End; i++)
                    {
                        //DMW_Changed	sbMerged.Append(leftLines[i] + Environment.NewLine);
                        sbMerged.AppendLine(leftLines[i]);

                        if (!identifyConflictsOnly || (hunk.Left.Count > 0 && hunk.Right.Count > 0))
                        {
                            combinedLeftColouredLines.Add(new LineSpan(combinedLineCount, combinedLineCount));
                        }
                        combinedLineCount++;
                    }

                    // RIGHT file
                    for (int i = hunk.Right.Start; i <= hunk.Right.End; i++)
                    {
                        //DMW_Changed	sbMerged.Append(leftLines[i] + Environment.NewLine);
                        sbMerged.AppendLine(rightLines[i]);

                        if (!identifyConflictsOnly || (hunk.Left.Count > 0 && hunk.Right.Count > 0))
                        {
                            combinedRightColouredLines.Add(new LineSpan(combinedLineCount, combinedLineCount));
                        }
                        combinedLineCount++;
                    }
                }
            }
            leftConflictLines = (LineSpan[])combinedLeftColouredLines.ToArray(typeof(LineSpan));
            rightConflictLines = (LineSpan[])combinedRightColouredLines.ToArray(typeof(LineSpan));
            combinedText = sbMerged.ToString();
            return returnValue;
        }
Exemple #14
0
        /// <summary>
        /// Gets whether two text files are the same or not. Linebreaks get standardized inside this function.
        /// </summary>
        /// <param name="fileBodyLeft">LEFT text.</param>
        /// <param name="fileBodyRight">RIGHT text.</param>
        /// <param name="caseSensitive">True to consider case, false to ignore differences due to case.</param>
        /// <param name="compareWhitespace">True to consider whitespace, false to ignore differences in whitespace.</param>
        public static bool FilesAreTheSame(string fileBodyLeft, string fileBodyRight, bool caseSensitive, bool compareWhitespace)
        {
            StringUtility.RemoveTrailingLineBreaks(ref fileBodyLeft);
            StringUtility.RemoveTrailingLineBreaks(ref fileBodyRight);
            // Performs a line-by-line, case-insensitive comparison.
            string[] arrFile1 = Common.Utility.StandardizeLineBreaks(fileBodyLeft, Common.Utility.LineBreaks.Unix).Split('\n');
            string[] arrFile2 = Common.Utility.StandardizeLineBreaks(fileBodyRight, Common.Utility.LineBreaks.Unix).Split('\n');
            Diff diff = new Diff(arrFile1, arrFile2, caseSensitive, compareWhitespace);

            foreach (Diff.Hunk hunk in diff)
            {
                if (!hunk.Same)
                {
                    return false;
                }
            }
            return true;
        }
        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;
        }
Exemple #16
0
 public static Hunk[] GetHunkList(Diff diff)
 {
     List<Hunk> hunks = new List<Hunk>();
     foreach(Hunk hunk in diff)
     {
         hunks.Add(hunk);
     }
     return hunks.ToArray();
 }
Exemple #17
0
 public static void WriteUnifiedDiff (Diff diff, TextWriter writer)
 {
     WriteUnifiedDiff (diff, writer, "Left", "Right", 2);
 }
        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));
                        }
                    }

                }
            }
        }