Example #1
0
            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);
            }
        }
Example #3
0
        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);
            }
        }
Example #5
0
        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);
                    }
                }
            }
        }