public ClassifiedDiff(DiffMatchPatch.Diff diff, DiffClassification classification) { Diff = diff; Classification = classification; }
/// <summary> /// Writes a difference summary to the file system. /// </summary> /// <param name="differences">The differences.</param> /// <param name="referenceDatabase">Reference database definition</param> /// <param name="targetDatabase">Target database to update</param> public static void WriteDifferenceSummary(DBTypes.Database referenceDatabase, DBTypes.Database targetDatabase, DifferenceSet differences) { StreamWriter diffWriter = new StreamWriter(Path.Combine(RunOptions.Current.ScriptOutputDirectory, RunOptions.Current.DiffFile), false); var patchGenerator = new DiffMatchPatch.diff_match_patch(); foreach (var difference in differences) { if (difference.DifferenceType != DifferenceType.Modified) { continue; } diffWriter.WriteLine(difference.ToString()); diffWriter.WriteLine(); var referenceDefinition = referenceDatabase[difference.Item].GenerateCreateScript(); var targetDefinition = targetDatabase[difference.Item].GenerateCreateScript(); var diff = patchGenerator.diff_main(targetDefinition.Text, referenceDefinition.Text); //var patch = patchGenerator.diff_prettyHtml(diff); //patch = System.Web.HttpUtility.UrlDecode(patch); //diffWriter.WriteLine(patch); //Diffs aren't full lines... we need to fix that for readability var coalesced = new List <DiffMatchPatch.Diff>(); DiffMatchPatch.Diff lastEqual = null; DiffMatchPatch.Diff lastInsert = null; DiffMatchPatch.Diff lastDelete = null; foreach (var entry in diff) { if (entry.operation == DiffMatchPatch.Operation.INSERT) { lastInsert = lastInsert ?? new DiffMatchPatch.Diff(entry.operation, ""); lastInsert.text += entry.text; } else if (entry.operation == DiffMatchPatch.Operation.DELETE) { lastDelete = lastDelete ?? new DiffMatchPatch.Diff(entry.operation, ""); lastDelete.text += entry.text; } else if (entry.operation == DiffMatchPatch.Operation.EQUAL) { string content = entry.text; int linebreak = content.IndexOf("\n"); string donate = linebreak < 0 ? content : content.Substring(0, linebreak + 1); //see if there's a change that needs this to finish its line bool used = false; if (lastInsert != null) { lastInsert.text += donate; used = true; } if (lastDelete != null) { lastDelete.text += donate; used = true; } if (used) { content = content.Remove(0, donate.Length); } //stash anything that's left if (content.Length > 0) { //time to flush everything we've coalesced //see if there are any mods that need to grab a line start if (lastEqual != null && !lastEqual.text.EndsWith("\n") && (lastInsert != null || lastDelete != null)) { linebreak = lastEqual.text.LastIndexOf("\n"); donate = lastEqual.text.Substring(linebreak + 1); lastEqual.text = lastEqual.text.Remove(linebreak + 1); if (lastInsert != null) { lastInsert.text = donate + lastInsert.text; } if (lastDelete != null) { lastDelete.text = donate + lastDelete.text; } } //do the flush if (lastEqual != null) { coalesced.Add(lastEqual); lastEqual = null; } if (lastInsert != null) { coalesced.Add(lastInsert); lastInsert = null; } if (lastDelete != null) { coalesced.Add(lastDelete); lastDelete = null; } lastEqual = new DiffMatchPatch.Diff(DiffMatchPatch.Operation.EQUAL, content); } } else { throw new Exception("Unknown operation: " + entry.operation); } } if (lastEqual != null) { coalesced.Add(lastEqual); } if (lastInsert != null) { coalesced.Add(lastInsert); } if (lastDelete != null) { coalesced.Add(lastDelete); } //Finally spit out a nice diff for (int i = 0; i < coalesced.Count; i++) { var entry = coalesced[i]; if (entry.operation == DiffMatchPatch.Operation.EQUAL) { //(ab)use a stream to partition the content into lines using (var text = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(entry.text)))) { //write out the first two lines if (i > 0) { for (int j = 0; j < 2 && !text.EndOfStream; j++) { string line = text.ReadLine(); if (string.IsNullOrEmpty(line)) { j--; continue; } diffWriter.WriteLine(line); } } //write out the last two lines if (i < coalesced.Count - 1 && !text.EndOfStream) { var lines = new string[3]; while (!text.EndOfStream) { lines[0] = lines[1]; lines[1] = lines[2]; lines[2] = text.ReadLine(); } if (i > 0 && lines[0] != null) { diffWriter.WriteLine(); diffWriter.WriteLine(">> ... <<"); diffWriter.WriteLine(); } if (lines[1] != null) { diffWriter.WriteLine(lines[1]); } diffWriter.WriteLine(lines[2]); } } } else { string marker = entry.operation == DiffMatchPatch.Operation.INSERT ? "> > > >" : "< < < <"; diffWriter.WriteLine(marker); diffWriter.Write(entry.text); if (!entry.text.EndsWith("\n")) { diffWriter.WriteLine(); } diffWriter.WriteLine(marker); } } diffWriter.WriteLine(); } diffWriter.Close(); }