public static Diff Compare(string fileOnePath, string fileOneContent, string fileTwoPath, string fileTwoContent, CompareOptions options) { if (fileOneContent == null && fileTwoContent == null) throw new InvalidOperationException("Both files were null"); if (options.BomMode == BomMode.Ignore) { if (fileOneContent != null) fileOneContent = RemoveBom(fileOneContent); if (fileTwoContent != null) fileTwoContent = RemoveBom(fileTwoContent); } if (fileTwoContent == null) return DeletedFileDiff(fileOneContent, fileOnePath); if (fileOneContent == null) return NewFileDiff(fileTwoContent, fileTwoPath); if (IsBinary(fileOneContent)) throw new BinaryFileException(fileOnePath); if (IsBinary(fileTwoContent)) throw new BinaryFileException(fileTwoPath); var patchMaker = new PatchMaker(); var patches = patchMaker.MakePatch(fileOneContent, fileTwoContent, options); var chunks = new List<Chunk>(); foreach (var patch in patches) { var originalRange = new ChangeRange(patch.start1 + 1, patch.length1); var newRange = new ChangeRange(patch.start2 + 1, patch.length2); var range = new ChunkRange(originalRange, newRange); var snippets = new List<ISnippet>(); var lines = new List<DiffMatchPatch.Diff>(); Operation? previousOperation = null; var isModification = false; foreach (var diff in patch.diffs) { if (previousOperation == null) previousOperation = diff.operation; if (previousOperation == Operation.DELETE && diff.operation == Operation.INSERT) isModification = true; else if (previousOperation != diff.operation) { // different operation if (previousOperation == Operation.EQUAL) snippets.Add(new ContextSnippet(lines.Select(x => new ContextLine(x.text)).Cast<ILine>())); else if (isModification) snippets.Add(new ModificationSnippet( lines .Where(x => x.operation == Operation.DELETE) .Select(x => new SubtractionLine(x.text)) .Cast<ILine>(), lines .Where(x => x.operation == Operation.INSERT) .Select(x => new AdditionLine(x.text)) .Cast<ILine>() )); else if (previousOperation == Operation.INSERT) snippets.Add(new AdditionSnippet(lines.Select(x => new AdditionLine(x.text)).Cast<ILine>())); else if (previousOperation == Operation.DELETE) snippets.Add(new SubtractionSnippet(lines.Select(x => new SubtractionLine(x.text)).Cast<ILine>())); lines.Clear(); isModification = false; } lines.Add(diff); previousOperation = diff.operation; } if (lines.Count > 0) { if (previousOperation == Operation.INSERT) snippets.Add(new AdditionSnippet(lines.Select(x => new AdditionLine(x.text)).Cast<ILine>())); else if (previousOperation == Operation.DELETE) snippets.Add(new SubtractionSnippet(lines.Select(x => new SubtractionLine(x.text)).Cast<ILine>())); else snippets.Add(new ContextSnippet(lines.Select(x => new ContextLine(x.text)).Cast<ILine>())); } chunks.Add(new Chunk(range, snippets)); } var fileOne = new File('a', fileOnePath); var fileTwo = new File('b', fileTwoPath); var header = new DiffHeader(new DiffFormatType("generated"), new[] { fileOne, fileTwo }); return new Diff(header, new IHeader[0], new ChunksHeader(fileOne, fileTwo), chunks); }
internal static Diff NewFileDiff(string content, string path) { var fileOne = new NullFile(); var fileTwo = new File('b', path); var header = new DiffHeader(new DiffFormatType("generated"), new IFile[] { fileOne, fileTwo }); var lines = content.SplitIntoLines() .Select(x => (ILine)new AdditionLine(x)); var range = new ChunkRange(new ChangeRange(0, 0), new ChangeRange(1, lines.Count())); var snippet = new AdditionSnippet(lines); var chunk = new Chunk(range, new[] { snippet }); return new Diff(header, new IHeader[0], new ChunksHeader(fileOne, fileTwo), new[] { chunk }); }