public static List<string> Generate(DiffResult diffresult)
        {
            var uniLines = new List<string>();
            int bPos = 0;

            foreach (DiffBlock diffBlock in diffresult.DiffBlocks)
            {
                for (; bPos < diffBlock.InsertStartB; bPos++)
                {
                    uniLines.Add(NoChangeSymbol + diffresult.PiecesNew[bPos]);
                }

                int i = 0;
                for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
                {
                    uniLines.Add(DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA]);
                    uniLines.Add(InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB]);
                    bPos++;
                }

                if (diffBlock.DeleteCountA > diffBlock.InsertCountB)
                {
                    for (; i < diffBlock.DeleteCountA; i++)
                    {
                        uniLines.Add(DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA]);
                    }
                }
                else
                {
                    for (; i < diffBlock.InsertCountB; i++)
                    {
                        uniLines.Add(InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB]);
                        bPos++;
                    }
                }
            }
            //***** added bugfix (thanks Wawel for pointing this out)
            for (; bPos < diffresult.PiecesNew.Length; bPos++)
            {
                // bugfix: uniLines.Add(diffresult.PiecesNew[bPos]);
                uniLines.Add(NoChangeSymbol + diffresult.PiecesNew[bPos]);
            }
            //**** end bugfix

            return uniLines;
        }
Example #2
0
        /// <summary>
        /// Format the result for a RichTextBox
        /// </summary>
        /// <param name="lineDiff"></param>
        /// <returns></returns>
        public static string Format(DiffResult lineDiff)
        {
            var uniLines = new StringBuilder();
            int bPos = 0;

            foreach (var diffBlock in lineDiff.DiffBlocks)
            {
                for (; bPos < diffBlock.InsertStartB; bPos++)
                    uniLines.Append(lineDiff.PiecesNew[bPos]);

                int i = 0;
                for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
                {
                    uniLines.Append(DeleteSymbolS + lineDiff.PiecesOld[i + diffBlock.DeleteStartA] + DeleteSymbolE);
                    //uniLines.Append(InsertSymbolS + lineDiff.PiecesNew[i + diffBlock.InsertStartB] + InsertSymbolE);
                    bPos++;
                }

                if (diffBlock.DeleteCountA > diffBlock.InsertCountB)
                {
                    uniLines.Append(DeleteSymbolS);
                    for (; i < diffBlock.DeleteCountA; i++)
                        uniLines.Append(lineDiff.PiecesOld[i + diffBlock.DeleteStartA]);
                    uniLines.Append(DeleteSymbolE);
                }
                else
                {
                    if (i < diffBlock.InsertCountB)
                    {
                        //uniLines.Append(InsertSymbolS);
                        for (; i < diffBlock.InsertCountB; i++)
                        {
                            //uniLines.Append(lineDiff.PiecesNew[i + diffBlock.InsertStartB]);
                            bPos++;
                        }
                        //uniLines.Append(InsertSymbolE);
                    }
                }
            }
            for (; bPos < lineDiff.PiecesNew.Length; bPos++)
                uniLines.Append(lineDiff.PiecesNew[bPos]);

            return uniLines.ToString();
        }
        private static void BuildDiffPieces(DiffResult diffResult, List<DiffPiece> pieces)
        {
            int bPos = 0;

            foreach (var diffBlock in diffResult.DiffBlocks)
            {
                for (; bPos < diffBlock.InsertStartB; bPos++)
                    pieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1));

                int i = 0;
                for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
                    pieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted));

                i = 0;
                for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
                {
                    pieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1));
                    bPos++;
                }

                if (diffBlock.DeleteCountA > diffBlock.InsertCountB)
                {
                    for (; i < diffBlock.DeleteCountA; i++)
                        pieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted));
                }
                else
                {
                    for (; i < diffBlock.InsertCountB; i++)
                    {
                        pieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1));
                        bPos++;
                    }
                }
            }

            for (; bPos < diffResult.PiecesNew.Length; bPos++)
                pieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1));
        }
        private static void BuildDiffPieces(DiffResult diffResult, List<DiffPiece> oldPieces, List<DiffPiece> newPieces, PieceBuilder subPieceBuilder)
        {
            int aPos = 0;
            int bPos = 0;

            foreach (var diffBlock in diffResult.DiffBlocks)
            {
                while (bPos < diffBlock.InsertStartB && aPos < diffBlock.DeleteStartA)
                {
                    oldPieces.Add(new DiffPiece(diffResult.PiecesOld[aPos], ChangeType.Unchanged, aPos + 1));
                    newPieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1));
                    aPos++;
                    bPos++;
                }

                int i = 0;
                for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
                {
                    var oldPiece = new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted, aPos + 1);
                    var newPiece = new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1);

                    if (subPieceBuilder != null)
                    {
                        subPieceBuilder(diffResult.PiecesOld[aPos], diffResult.PiecesNew[bPos], oldPiece.SubPieces, newPiece.SubPieces);
                        newPiece.Type = oldPiece.Type = ChangeType.Modified;
                    }

                    oldPieces.Add(oldPiece);
                    newPieces.Add(newPiece);
                    aPos++;
                    bPos++;
                }

                if (diffBlock.DeleteCountA > diffBlock.InsertCountB)
                {
                    for (; i < diffBlock.DeleteCountA; i++)
                    {
                        oldPieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted, aPos + 1));
                        newPieces.Add(new DiffPiece());
                        aPos++;
                    }
                }
                else
                {
                    for (; i < diffBlock.InsertCountB; i++)
                    {
                        newPieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1));
                        oldPieces.Add(new DiffPiece());
                        bPos++;
                    }
                }
            }

            while (bPos < diffResult.PiecesNew.Length && aPos < diffResult.PiecesOld.Length)
            {
                oldPieces.Add(new DiffPiece(diffResult.PiecesOld[aPos], ChangeType.Unchanged, aPos + 1));
                newPieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1));
                aPos++;
                bPos++;
            }
        }
Example #5
0
        private void ProcessDiff(string original, string myVersion, string newVersion)
        {
            // Do a line-by-line diff, marking changed line groups.
              // Also, find intersecting diffs and mark them as conflicted changes for resolution.
              var d = new Differ();
              var diffs = new DiffResult[2] {
            d.CreateLineDiffs(original, myVersion ?? "", false),
            d.CreateLineDiffs(original, newVersion ?? "", false)
              };

              string[][] newPieces = new string[2][];
              newPieces[0] = diffs[0].PiecesNew;
              newPieces[1] = diffs[1].PiecesNew;
              if (myVersion == "") newPieces[0] = new string[] { "" };
              if (newVersion == "") newPieces[1] = new string[] { "" };

              var dblocks = new List<Tuple<DiffBlock, int>>();
              for (int side = 0; side < 2; side++) {
            foreach (var block in diffs[side].DiffBlocks) {
              DiffBlock actualBlock = block;
              if (diffs[side].PiecesNew.Length == 0 && block.InsertCountB == 0 && block.InsertStartB == 0) {
            actualBlock = new DiffBlock(block.DeleteStartA, block.DeleteCountA, 0, 1);
              }
              dblocks.Add(new Tuple<DiffBlock, int>(actualBlock, side));
            }
              }
              dblocks.Sort((a, b) => a.Item1.DeleteStartA.CompareTo(b.Item1.DeleteStartA));

              content = new List<LineBlock>[2];
              for (int i = 0; i < 2; i++) {
            content[i] = new List<LineBlock>();
              }
              conflictOrigBlocks = new List<LineBlock>();

              string[] origLines = diffs[0].PiecesOld;
              int nextOriginalLine = 0;
              for (int i = 0; i < dblocks.Count; ) {
            DiffBlock block = dblocks[i].Item1;
            int owner = dblocks[i].Item2;
            // Add unchanged (original) lines.
            if (block.DeleteStartA > nextOriginalLine) {
              foreach (var lineBlocks in content) {
            lineBlocks.Add(new LineBlock(Util.ArraySlice(origLines, nextOriginalLine, block.DeleteStartA - nextOriginalLine)));
              }
              nextOriginalLine = block.DeleteStartA;
            }

            int rangeStart = block.DeleteStartA;
            int rangeEnd = rangeStart + block.DeleteCountA;
            int j = i;
            // If this change intersects any other changes, then merge them together to form a block.
            while (j < dblocks.Count && dblocks[j].Item1.DeleteStartA <= rangeEnd) {
              rangeEnd = Math.Max(rangeEnd, dblocks[j].Item1.DeleteStartA + dblocks[j].Item1.DeleteCountA);
              j++;
            }

            if (j == i + 1) {
              // A regular change.
              var oldBlock = new LineBlock(Util.ArraySlice(diffs[owner].PiecesOld, block.DeleteStartA, block.DeleteCountA), BlockType.ChangeDelete);
              var newBlock = new LineBlock(Util.ArraySlice(newPieces[owner], block.InsertStartB, block.InsertCountB), BlockType.ChangeAdd);
              if (block.DeleteCountA != 0 && block.InsertCountB != 0) {
            oldBlock.type = BlockType.Conflict;
            newBlock.type = BlockType.Conflict;
              } else if (block.DeleteCountA == 0) {
            oldBlock.type = BlockType.Blank;
              } else if (block.InsertCountB == 0) {
            newBlock.type = BlockType.Blank;
              } // can't both be empty!
              ProcessBlockDiff(oldBlock, newBlock);
              content[owner].Add(newBlock);
              content[1 - owner].Add(oldBlock);
              conflictOrigBlocks.Add(owner == 0 ? newBlock : oldBlock);
            } else {
              // Create a change block.
              for (int side = 0; side < 2; side++) {
            int curOriginalLine = rangeStart;
            var conflictBlock = new LineBlock();
            var origBlock = new LineBlock();
            conflictBlock.type = BlockType.Conflict;
            for (int k = i; k < j; k++) {
              DiffBlock subBlock = dblocks[k].Item1;
              if (dblocks[k].Item2 != side) continue;
              if (subBlock.DeleteStartA > curOriginalLine) {
                conflictBlock.AddLines(Util.ArraySlice(origLines, curOriginalLine, subBlock.DeleteStartA - curOriginalLine));
              }
              curOriginalLine = subBlock.DeleteStartA + subBlock.DeleteCountA;
              var oldBlock = new LineBlock(Util.ArraySlice(diffs[side].PiecesOld, subBlock.DeleteStartA, subBlock.DeleteCountA), BlockType.ChangeDelete);
              var newBlock = new LineBlock(Util.ArraySlice(newPieces[side], subBlock.InsertStartB, subBlock.InsertCountB), BlockType.ChangeAdd);
              ProcessBlockDiff(oldBlock, newBlock, false);
              origBlock.Append(oldBlock);
              conflictBlock.Append(newBlock);
            }
            if (rangeEnd > curOriginalLine) {
              conflictBlock.AddLines(Util.ArraySlice(origLines, curOriginalLine, rangeEnd - curOriginalLine));
            }
            if (conflictBlock.lines.Count == 0) {
              conflictBlock.type = BlockType.ChangeDelete;
            }
            content[side].Add(conflictBlock);
            if (side == 0) {
              conflictOrigBlocks.Add(origBlock);
            }
              }

              int last = content[0].Count - 1;
              if (content[0][last].ToString() == content[1][last].ToString()) {
            // Not actually a conflict if they're both the same change.
            if (content[0][last].lines.Count == 0) {
              // If both are deleted, just show nothing.
              content[0].RemoveAt(last);
              content[1].RemoveAt(last);
            } else {
              // Make them normal blocks.
              content[0][last] = new LineBlock(content[0][last].lines.Select(x => x.ToString()).ToArray());
              content[1][last] = new LineBlock(content[1][last].lines.Select(x => x.ToString()).ToArray());
            }
            conflictOrigBlocks.RemoveAt(conflictOrigBlocks.Count - 1);
              }
            }

            nextOriginalLine = rangeEnd;
            i = j;
              }

              // Add any remaining unchanged lines.
              if (origLines.Length > nextOriginalLine) {
            foreach (var lineBlocks in content) {
              lineBlocks.Add(new LineBlock(Util.ArraySlice(origLines, nextOriginalLine, origLines.Length - nextOriginalLine)));
            }
              }

              origBlocks = new LineBlock[2][];
              origBlocks[0] = new LineBlock[content[0].Count];
              origBlocks[1] = new LineBlock[content[1].Count];
              content[0].CopyTo(origBlocks[0]);
              content[1].CopyTo(origBlocks[1]);
        }
        public static List<UnidiffEntry> GenerateWithLineNumbers(DiffResult diffresult)
        {
            var uniLines = new List<UnidiffEntry>();
            int bPos = 0;

            foreach (DiffBlock diffBlock in diffresult.DiffBlocks)
            {
                for (; bPos < diffBlock.InsertStartB; bPos++)
                {
                    uniLines.Add(new UnidiffEntry(bPos, NoChangeSymbol + diffresult.PiecesNew[bPos], UnidiffType.NoChange));
                }

                int i = 0;
                for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++)
                {
                    uniLines.Add(new UnidiffEntry(bPos, DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA], UnidiffType.Delete));
                    uniLines.Add(new UnidiffEntry(bPos, InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB], UnidiffType.Insert));
                    bPos++;
                }

                if (diffBlock.DeleteCountA > diffBlock.InsertCountB)
                {
                    for (; i < diffBlock.DeleteCountA; i++)
                    {
                        uniLines.Add(new UnidiffEntry(bPos, DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA], UnidiffType.Delete));
                    }
                }
                else
                {
                    for (; i < diffBlock.InsertCountB; i++)
                    {
                        uniLines.Add(new UnidiffEntry(bPos, InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB], UnidiffType.Insert));
                        bPos++;
                    }
                }
            }
            //***** added bugfix (thanks Wawel for pointing this out)
            for (; bPos < diffresult.PiecesNew.Length; bPos++)
            {
                // bugfix: uniLines.Add(diffresult.PiecesNew[bPos]);
                uniLines.Add(new UnidiffEntry(bPos, NoChangeSymbol + diffresult.PiecesNew[bPos], UnidiffType.NoChange));
            }
            //**** end bugfix

            return uniLines;
        }
 public static string GenerateSeq(DiffResult diffresult, string insertSymbolS, string insertSymbolE, string deleteSymbolS, string deleteSymbolE)
 {
     List<string> result = Generate(diffresult);
     var outputSb = new StringBuilder();
     while (result.Count > 0)
     {
         if (result[0].StartsWith(DeleteSymbol))
         {
             int dix = 0;
             outputSb.Append(deleteSymbolS);
             while (dix < result.Count &&  result.Count > 0 && !result[dix].StartsWith(NoChangeSymbol))
             {
                 if (result[dix].StartsWith(DeleteSymbol))
                 {
                     outputSb.Append(result[dix].Substring(1));
                     result.RemoveAt(dix);
                 }
                 else
                 {
                     ++dix;
                 }
             }
             outputSb.Append(deleteSymbolE);
         }
         else if (result[0].StartsWith(InsertSymbol))
         {
             int dix = 0;
             outputSb.Append(insertSymbolS);
             while (dix < result.Count &&  result.Count > 0 && !result[dix].StartsWith(NoChangeSymbol))
             {
                 if (result[dix].StartsWith(InsertSymbol))
                 {
                     outputSb.Append(result[dix].Substring(1));
                     result.RemoveAt(dix);
                 }
                 else
                 {
                     ++dix;
                 }
             }
             outputSb.Append(insertSymbolE);
         }
         else
         {
             outputSb.Append(result[0].Substring(1));
             result.RemoveAt(0);
         }
     }
     return outputSb.ToString();
 }
 public static string GenerateSeq(DiffResult diffresult)
 {
     return GenerateSeq(diffresult,
                        "[+[",
                        "]+]",
                        "[-[",
                        "]-]");
 }
 public static string GenerateOnlyChangedSeq(DiffResult diffresult, string insertSymbolS, string insertSymbolE, string deleteSymbolS, string deleteSymbolE)
 {
     List<UnidiffEntry> result = GenerateWithLineNumbers(diffresult);
     var outputSb = new StringBuilder();
     while (result.Count > 0)
     {
         if (result[0].Type == UnidiffType.Delete)
         {
             int dix = 0;
             outputSb.Append(deleteSymbolS);
             while (dix < result.Count && result.Count > 0 && result[dix].Type != UnidiffType.NoChange)
             {
                 if (result[dix].Type == UnidiffType.Delete)
                 {
                     outputSb.Append(result[dix].Index + ":");
                     outputSb.Append(result[dix].Text.Substring(1));
                     result.RemoveAt(dix);
                 }
                 else
                 {
                     ++dix;
                 }
             }
             outputSb.Append(deleteSymbolE);
         }
         else if (result[0].Type == UnidiffType.Insert)
         {
             int dix = 0;
             outputSb.Append(insertSymbolS);
             while (dix < result.Count && result.Count > 0 && result[dix].Type != UnidiffType.NoChange)
             {
                 if (result[dix].Type == UnidiffType.Insert)
                 {
                     outputSb.Append(result[dix].Index + ":");
                     outputSb.Append(result[dix].Text.Substring(1));
                     result.RemoveAt(dix);
                 }
                 else
                 {
                     ++dix;
                 }
             }
             outputSb.Append(insertSymbolE);
         }
         else
         {
             //outputSb.Append(result[0].Index);
             //outputSb.Append(result[0].Text.Substring(1));
             result.RemoveAt(0);
         }
     }
     return outputSb.ToString();
 }