private void AddHunk(int lcount, int rcount, bool same) { if (hunks.Count > 0 && same == ((Diff.Hunk)hunks[hunks.Count - 1]).Same) { Diff.Hunk prev = (Diff.Hunk)hunks[hunks.Count - 1]; hunks[hunks.Count - 1] = new Diff.Hunk( leftlist, rightlist, prev.Left.Start, prev.Left.End + lcount, prev.Right.Start, prev.Right.End + rcount, same); return; } int le = -1; int re = -1; if (hunks.Count > 0) { Diff.Hunk prev = (Diff.Hunk)hunks[hunks.Count - 1]; le = prev.Left.End; re = prev.Right.End; } hunks.Add(new Diff.Hunk( leftlist, rightlist, le + 1, le + lcount, re + 1, re + rcount, same)); }
private static void WriteUnifiedDiffSection(TextWriter writer, ArrayList hunks) { Diff.Hunk first = (Diff.Hunk)hunks[0]; Diff.Hunk last = (Diff.Hunk)hunks[hunks.Count - 1]; //writer.Write("@@ -"); //writer.Write(first.Left.Start+1); //writer.Write(","); //writer.Write(last.Left.End-first.Left.Start+1); //writer.Write(" +"); //writer.Write(first.Right.Start+1); //writer.Write(","); //writer.Write(last.Right.End-first.Right.Start+1); //writer.WriteLine(" @@"); foreach (Diff.Hunk hunk in hunks) { if (hunk.Same) { WriteBlock(writer, ' ', hunk.Left); continue; } WriteBlock(writer, '-', hunk.Left); WriteBlock(writer, '+', hunk.Right); } }
public Merge (IDiff [] diffs) { this.diffs = diffs; // initialize data structures IEnumerator[] enumerators = new IEnumerator[diffs.Length]; ArrayList[] hunks = new ArrayList[diffs.Length]; for (int i = 0; i < hunks.Length; i++) { enumerators [i] = ((IEnumerable) diffs [i]).GetEnumerator (); hunks [i] = new ArrayList (); } int startline = 0; while (true) { int endline = -1; bool hasmore = false; // Get the next hunk for each diff, and find the longest // hunk for which there are changes. for (int i = 0; i < hunks.Length; i++) { if (hunks [i].Count > 0) continue; if (!enumerators [i].MoveNext ()) return; hasmore = true; Diff.Hunk hunk = (Diff.Hunk) enumerators [i].Current; hunks [i].Add (hunk); if (!hunk.Same && hunk.Left.End > endline) endline = hunk.Left.End; } if (!hasmore) return; if (endline == -1) { // All of the hunks represented no change. Find the shortest hunk, // create a hunk from the current start line to the end of the // shortest hunk, and retain all of the hunks that overlap into that // hunk's next region. (Clear the rest.) int start = int.MaxValue; for (int i = 0; i < hunks.Length; i++) { Diff.Hunk h = (Diff.Hunk) hunks [i] [0]; if (h.Left.End < start) start = h.Left.End; } // Crop all of the hunks to the shortest region. Diff.Hunk[][] h2 = new Diff.Hunk[hunks.Length][]; for (int i = 0; i < hunks.Length; i++) { h2 [i] = new Diff.Hunk[1]; h2 [i] [0] = (Diff.Hunk) hunks [i] [0]; h2 [i] [0] = h2 [i] [0].Crop ( startline - h2[i][0].Left.Start, h2[i][0].Left.End - start ); } this.hunks.Add (new Hunk (this, h2, startline, start - startline + 1, true)); for (int i = 0; i < hunks.Length; i++) { Diff.Hunk h = (Diff.Hunk) hunks [i] [0]; if (h.Left.End == start) hunks [i].Clear (); } startline = start + 1; continue; } // For each diff, add in all of the non-same hunks that fall // at least partially within the largest hunk region. If // a hunk crosses the edge, push the edge further and then // add more hunks again. bool moreToAdd = true; while (moreToAdd) { moreToAdd = false; for (int i = 0; i < hunks.Length; i++) { Diff.Hunk last = (Diff.Hunk) hunks [i] [hunks [i].Count - 1]; while (last.Left.End < endline) { if (!enumerators [i].MoveNext ()) continue; last = (Diff.Hunk) enumerators [i].Current; hunks [i].Add (last); if (last.Same) continue; if (last.Left.End > endline) { endline = last.Left.End; moreToAdd = true; } } } } Diff.Hunk[][] hunks2 = new Diff.Hunk[hunks.Length][]; for (int i = 0; i < hunks.Length; i++) { // any same hunks that overlap the start or end need to be replaced ArrayList hunks3 = new ArrayList (); foreach (Diff.Hunk h in hunks[i]) { Diff.Hunk h2 = h; int shiftstart = 0, shiftend = 0; if (h2.Same && h2.Left.Start < startline) shiftstart = startline - h2.Left.Start; if (h2.Same && h2.Left.End > endline) shiftend = h2.Left.End - endline; if (shiftstart != 0 || shiftend != 0) h2 = h2.Crop (shiftstart, shiftend); hunks3.Add (h2); } hunks2 [i] = (Diff.Hunk []) hunks3.ToArray (typeof(Diff.Hunk)); } this.hunks.Add (new Hunk ( this, hunks2, startline, endline - startline + 1, false )); // In each hunk list, retain only the last hunk if it // overlaps into the next region. startline = endline + 1; for (int i = 0; i < hunks.Length; i++) { if (hunks [i].Count == 0) continue; Diff.Hunk h = (Diff.Hunk) hunks [i] [hunks [i].Count - 1]; hunks [i].Clear (); if (h.Left.End >= startline) hunks [i].Add (h); } } }
public static void WriteUnifiedDiff(Diff diff, TextWriter writer, string fromfile, string tofile, int context) { writer.Write("--- "); writer.WriteLine(fromfile); writer.Write("+++ "); writer.WriteLine(tofile); ArrayList hunkset = new ArrayList(); foreach (Diff.Hunk hunk in diff) { Diff.Hunk lasthunk = null; if (hunkset.Count > 0) { lasthunk = (Diff.Hunk)hunkset[hunkset.Count - 1]; } if (hunk.Same) { // At the start of a hunk set, keep only context lines of context. if (lasthunk == null) { if (hunk.Left.Count > context) { hunkset.Add(hunk.Crop(hunk.Left.Count - context, 0)); } else { hunkset.Add(hunk); } // Can't have two same hunks in a row, so the last one was a difference. } else { // Small enough context that this unified diff range will not stop. if (hunk.Left.Count <= context * 2) { hunkset.Add(hunk); // Too much of the same. Keep context lines and end this section. // And then keep the last context lines as context for the next section. } else { hunkset.Add(hunk.Crop(0, hunk.Left.Count - context)); WriteUnifiedDiffSection(writer, hunkset); hunkset.Clear(); if (hunk.Left.Count > context) { hunkset.Add(hunk.Crop(hunk.Left.Count - context, 0)); } else { hunkset.Add(hunk); } } } } else { hunkset.Add(hunk); } } if (hunkset.Count > 0 && !(hunkset.Count == 1 && ((Diff.Hunk)hunkset[0]).Same)) { WriteUnifiedDiffSection(writer, hunkset); } }
public Merge(IDiff[] diffs) { this.diffs = diffs; // initialize data structures IEnumerator[] enumerators = new IEnumerator[diffs.Length]; ArrayList[] hunks = new ArrayList[diffs.Length]; for (int i = 0; i < hunks.Length; i++) { enumerators[i] = diffs[i].GetEnumerator(); hunks[i] = new ArrayList(); } int startline = 0; while (true) { int endline = -1; bool hasmore = false; // Get the next hunk for each diff, and find the longest // hunk for which there are changes. for (int i = 0; i < hunks.Length; i++) { if (hunks[i].Count > 0) { continue; } if (!enumerators[i].MoveNext()) { return; } hasmore = true; Diff.Hunk hunk = (Diff.Hunk)enumerators[i].Current; hunks[i].Add(hunk); if ((!hunk.Same || hunk.Left.Count != hunk.Right.Count) && hunk.Left.End > endline) { endline = hunk.Left.End; } } if (!hasmore) { return; } if (endline == -1) { // All of the hunks represented no change. Find the shortest hunk, // create a hunk from the current start line to the end of the // shortest hunk, and retain all of the hunks that overlap into that // hunk's next region. (Clear the rest.) int start = int.MaxValue; for (int i = 0; i < hunks.Length; i++) { Diff.Hunk h = (Diff.Hunk)hunks[i][0]; if (h.Left.End < start) { start = h.Left.End; } } // Crop all of the hunks to the shortest region. Diff.Hunk[][] h2 = new Diff.Hunk[hunks.Length][]; for (int i = 0; i < hunks.Length; i++) { h2[i] = new Diff.Hunk[1]; h2[i][0] = (Diff.Hunk)hunks[i][0]; h2[i][0] = h2[i][0].Crop(startline - h2[i][0].Left.Start, h2[i][0].Left.End - start); } this.hunks.Add(new Hunk(this, h2, startline, start - startline + 1, true)); for (int i = 0; i < hunks.Length; i++) { Diff.Hunk h = (Diff.Hunk)hunks[i][0]; if (h.Left.End == start) { hunks[i].Clear(); } } startline = start + 1; continue; } // For each diff, add in all of the non-same hunks that fall // at least partially within the largest hunk region. If // a hunk crosses the edge, push the edge further and then // add more hunks again. bool moreToAdd = true; while (moreToAdd) { moreToAdd = false; for (int i = 0; i < hunks.Length; i++) { Diff.Hunk last = (Diff.Hunk)hunks[i][hunks[i].Count - 1]; while (last.Left.End < endline) { if (!enumerators[i].MoveNext()) { continue; } last = (Diff.Hunk)enumerators[i].Current; hunks[i].Add(last); if (last.Same) { continue; } if (last.Left.End > endline) { endline = last.Left.End; moreToAdd = true; } } } } Diff.Hunk[][] hunks2 = new Diff.Hunk[hunks.Length][]; for (int i = 0; i < hunks.Length; i++) { // any same hunks that overlap the start or end need to be replaced ArrayList hunks3 = new ArrayList(); foreach (Diff.Hunk h in hunks[i]) { Diff.Hunk h2 = h; int shiftstart = 0, shiftend = 0; if (h2.Same && h2.Left.Start < startline) { shiftstart = startline - h2.Left.Start; } if (h2.Same && h2.Left.End > endline) { shiftend = h2.Left.End - endline; } if (shiftstart != 0 || shiftend != 0) { h2 = h2.Crop(shiftstart, shiftend); } hunks3.Add(h2); } hunks2[i] = (Diff.Hunk[])hunks3.ToArray(typeof(Diff.Hunk)); } this.hunks.Add(new Hunk(this, hunks2, startline, endline - startline + 1, false)); // In each hunk list, retain only the last hunk if it // overlaps into the next region. startline = endline + 1; for (int i = 0; i < hunks.Length; i++) { if (hunks[i].Count == 0) { continue; } Diff.Hunk h = (Diff.Hunk)hunks[i][hunks[i].Count - 1]; hunks[i].Clear(); if (h.Left.End >= startline) { hunks[i].Add(h); } } } }