コード例 #1
0
        public void DisplayDiff(string filename, string fullpath, string author, string old, string updated)
        {
            grid.RowDefinitions.Clear();
              var rd = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
              grid.RowDefinitions.Add(rd);

              // Remove the line number blocks and such. actionsThem is the last item in the XAML
              int x = grid.Children.IndexOf(message);
              grid.Children.RemoveRange(x + 1, grid.Children.Count - x);

              message.Visibility = Visibility.Collapsed;
              if (filename.EndsWith(".docx") || filename.EndsWith(".doc")) {
            // Word document. So let the user open the doc in Word
            message.Visibility = Visibility.Visible;
            message.Text = "This is a Word document. Please save it to view its contents.";
            message.Inlines.Add(" You can also ");
            var fakeUri = new Uri("http://asdf.com");
            var link = new Hyperlink(new Run("view the changes")) { NavigateUri = fakeUri };
            link.RequestNavigate += (s, e) => CompareInWord(old, updated, filename, Path.GetDirectoryName(fullpath), author);
            message.Inlines.Add(link);
            message.Inlines.Add(" in Word.");
              } else if (SentenceFilter.IsBinary(old) || SentenceFilter.IsBinary(updated)) {
            message.Visibility = Visibility.Visible;
            message.Text = "This file is in binary. Please save it to view its contents.";
              } else {
            // Compute the diff, break it into blocks
            if (old == null) old = "";
            if (updated == null) updated = "";
            var d = new Differ();
            var dr = d.CreateLineDiffs(old, updated, false);
            int curBlock = 0, numBlocks = dr.DiffBlocks.Count;

            List<LineBlock> lineBlocks = new List<LineBlock>();
            for (int i = 0; i <= dr.PiecesOld.Length; i++) {
              while (curBlock < numBlocks && dr.DiffBlocks[curBlock].DeleteStartA < i) {
            curBlock++;
              }

              if (curBlock < numBlocks && dr.DiffBlocks[curBlock].DeleteStartA == i) {
            var db = dr.DiffBlocks[curBlock];
            if (db.DeleteCountA > 0) {
              lineBlocks.Add(new LineBlock(Util.ArraySlice(dr.PiecesOld, db.DeleteStartA, db.DeleteCountA), BlockType.ChangeDelete));
            }
            if (db.InsertCountB > 0) {
              lineBlocks.Add(new LineBlock(Util.ArraySlice(dr.PiecesNew, db.InsertStartB, db.InsertCountB), BlockType.ChangeAdd));
            }
            i += db.DeleteCountA;
            curBlock++;
              }

              if (i < dr.PiecesOld.Length) {
            lineBlocks.Add(new LineBlock(Util.ArraySlice(dr.PiecesOld, i, 1)));
              }
            }

            // Draw the actual blocks.
            DrawLineBlocks(lineBlocks);
              }
        }
コード例 #2
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]);
        }
コード例 #3
0
        private void ProcessBlockDiff(LineBlock oldLineBlock, LineBlock newLineBlock, bool modifyOld = true)
        {
            // Do block-by-block diffs inside LineBlocks.
              var oldBlocks = new List<Block>();
              var newBlocks = new List<Block>();

              foreach (var line in oldLineBlock.lines) {
            oldBlocks.AddRange(line.blocks);
              }

              foreach (var line in newLineBlock.lines) {
            newBlocks.AddRange(line.blocks);
              }

              var d = new Differ();
              DiffResult diff = d.CreateLineDiffs(String.Join("\n", oldBlocks.Select(x => x.ToString()).ToArray()),
            String.Join("\n", newBlocks.Select(x => x.ToString()).ToArray()), false);

              foreach (DiffBlock dblock in diff.DiffBlocks) {
            if (modifyOld) {
              for (int i = 0; i < dblock.DeleteCountA && dblock.DeleteStartA + i < oldBlocks.Count; i++) {
            oldBlocks[i + dblock.DeleteStartA].type = BlockType.ChangeDelete;
              }
            }
            for (int i = 0; i < dblock.InsertCountB && dblock.InsertStartB + i < newBlocks.Count; i++) {
              newBlocks[i + dblock.InsertStartB].type = BlockType.ChangeAdd;
            }
              }
        }