internal static string Merge3Inputs(SlyceMergeResult merge, string userText, string prevGenText, string nextGenText) { //StringBuilder sb = new StringBuilder(1000); // DMW_Changed: this is not used bool newlineAppended = false; newlineAppended = AppendNewLine(ref userText, newlineAppended); newlineAppended = AppendNewLine(ref prevGenText, newlineAppended); newlineAppended = AppendNewLine(ref nextGenText, newlineAppended); // DMW_Changed: remove all CrLfs const string pilcrowEth = "¶Ð"; const char ethChar = 'Ð'; // standardise linebreaks userText = Common.Utility.StandardizeLineBreaks(userText, Common.Utility.LineBreaks.Windows); nextGenText = Common.Utility.StandardizeLineBreaks(nextGenText, Common.Utility.LineBreaks.Windows); prevGenText = Common.Utility.StandardizeLineBreaks(prevGenText, Common.Utility.LineBreaks.Windows); string[] userLines = userText.Replace("\r\n", pilcrowEth).Split(ethChar); string[] nextGenLines = nextGenText.Replace("\r\n", pilcrowEth).Split(ethChar); string[] prevGenLines = prevGenText.Replace("\r\n", pilcrowEth).Split(ethChar); //string[] userLines = Slyce.Common.Utility.StandardizeLineBreaks(userText, Slyce.Common.Utility.LineBreaks.Windows).Split('\r\n'); //string[] nextGenLines = Slyce.Common.Utility.StandardizeLineBreaks(nextGenText, Slyce.Common.Utility.LineBreaks.Windows).Split('\n'); //string[] prevGenLines = Slyce.Common.Utility.StandardizeLineBreaks(prevGenText, Slyce.Common.Utility.LineBreaks.Windows).Split('\n'); GetMergedOutput(merge, prevGenLines, userLines, nextGenLines); return(WriteLineTextArrayToList(merge.Lines, newlineAppended)); }
/// <summary> /// Merge three text files /// </summary> /// <param name="userText">File with user changes</param> /// <param name="prevGenText">Previously generated file</param> /// <param name="newGenText">Newly generated file</param> /// <param name="mergedText">Merged file</param> /// <returns></returns> /// <param name="compareWhitespace">True if the whitespace should be counted as a change.</param> public static SlyceMergeResult Perform3wayDiff(string userText, string prevGenText, string newGenText, out string mergedText, bool compareWhitespace) { SlyceMergeResult slyceMerge = new SlyceMergeResult(); mergedText = Merge3Inputs(slyceMerge, userText, prevGenText, newGenText); if (slyceMerge.DiffType == TypeOfDiff.ExactCopy) { // Successfully merged text (with no conflicts) always gets returned as 'EXACT_COPY', // so we need to perform a further test to see if it really is different. bool userFileIsIdentical = FilesAreTheSame(userText, mergedText, true, compareWhitespace); bool newGenFileIsIdentical = FilesAreTheSame(newGenText, mergedText, true, compareWhitespace); if (!userFileIsIdentical || !newGenFileIsIdentical) { if (!userFileIsIdentical && !newGenFileIsIdentical) { slyceMerge.DiffType = TypeOfDiff.UserAndTemplateChange; } else if (userFileIsIdentical) { slyceMerge.DiffType = TypeOfDiff.UserChangeOnly; } else // newGenFileIsIdentical { slyceMerge.DiffType = TypeOfDiff.TemplateChangeOnly; } } } return(slyceMerge); }
/// <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); }
internal static string Merge3Inputs(SlyceMergeResult merge, string userText, string prevGenText, string nextGenText) { //StringBuilder sb = new StringBuilder(1000); // DMW_Changed: this is not used bool newlineAppended = false; newlineAppended = AppendNewLine(ref userText, newlineAppended); newlineAppended = AppendNewLine(ref prevGenText, newlineAppended); newlineAppended = AppendNewLine(ref nextGenText, newlineAppended); // DMW_Changed: remove all CrLfs const string pilcrowEth = "¶Ð"; const char ethChar = 'Ð'; // standardise linebreaks userText = Common.Utility.StandardizeLineBreaks(userText, Common.Utility.LineBreaks.Windows); nextGenText = Common.Utility.StandardizeLineBreaks(nextGenText, Common.Utility.LineBreaks.Windows); prevGenText = Common.Utility.StandardizeLineBreaks(prevGenText, Common.Utility.LineBreaks.Windows); string[] userLines = userText.Replace("\r\n", pilcrowEth).Split(ethChar); string[] nextGenLines = nextGenText.Replace("\r\n", pilcrowEth).Split(ethChar); string[] prevGenLines = prevGenText.Replace("\r\n", pilcrowEth).Split(ethChar); //string[] userLines = Slyce.Common.Utility.StandardizeLineBreaks(userText, Slyce.Common.Utility.LineBreaks.Windows).Split('\r\n'); //string[] nextGenLines = Slyce.Common.Utility.StandardizeLineBreaks(nextGenText, Slyce.Common.Utility.LineBreaks.Windows).Split('\n'); //string[] prevGenLines = Slyce.Common.Utility.StandardizeLineBreaks(prevGenText, Slyce.Common.Utility.LineBreaks.Windows).Split('\n'); GetMergedOutput(merge, prevGenLines, userLines, nextGenLines); return WriteLineTextArrayToList(merge.Lines, newlineAppended); }
/// <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; }
/// <summary> /// Merge three text files /// </summary> /// <param name="userText">File with user changes</param> /// <param name="prevGenText">Previously generated file</param> /// <param name="newGenText">Newly generated file</param> /// <param name="mergedText">Merged file</param> /// <returns></returns> /// <param name="compareWhitespace">True if the whitespace should be counted as a change.</param> public static SlyceMergeResult Perform3wayDiff(string userText, string prevGenText, string newGenText, out string mergedText, bool compareWhitespace) { SlyceMergeResult slyceMerge = new SlyceMergeResult(); mergedText = Merge3Inputs(slyceMerge, userText, prevGenText, newGenText); if (slyceMerge.DiffType == TypeOfDiff.ExactCopy) { // Successfully merged text (with no conflicts) always gets returned as 'EXACT_COPY', // so we need to perform a further test to see if it really is different. bool userFileIsIdentical = FilesAreTheSame(userText, mergedText, true, compareWhitespace); bool newGenFileIsIdentical = FilesAreTheSame(newGenText, mergedText, true, compareWhitespace); if (!userFileIsIdentical || !newGenFileIsIdentical) { if (!userFileIsIdentical && !newGenFileIsIdentical) { slyceMerge.DiffType = TypeOfDiff.UserAndTemplateChange; } else if (userFileIsIdentical) { slyceMerge.DiffType = TypeOfDiff.UserChangeOnly; } else // newGenFileIsIdentical { slyceMerge.DiffType = TypeOfDiff.TemplateChangeOnly; } } } return slyceMerge; }