Ejemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Conflict"/> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <param name="conflictBlocks">The conflict blocks.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        internal Conflict(IReadOnlyList <string> source, MergableChangeset changeset1, MergableChangeset changeset2,
                          ConflictBlocks conflictBlocks)
        {
            if ((source == null) || (changeset1 == null) || (changeset2 == null))
            {
                throw new ArgumentNullException();
            }

            var allChanges  = new HashSet <IMergableChange>(changeset1.Values.Union(changeset2.Values));
            int start       = allChanges.Min(c => c.Start);
            int afterFinish = allChanges.Max(c => c.AfterFinish);

            if ((start > source.Count) || (afterFinish > source.Count))
            {
                throw new ArgumentOutOfRangeException();
            }

            int removedAmount = afterFinish - start;

            IEnumerable <string> originalBlock = Utils.GetSubArray(source, start, afterFinish);
            IEnumerable <string> changedBlock1 = GetChangedBlock(source, start, afterFinish, changeset1);
            IEnumerable <string> changedBlock2 = GetChangedBlock(source, start, afterFinish, changeset2);

            IEnumerable <string> newContent =
                GetNewContent(originalBlock, changedBlock1, changedBlock2, conflictBlocks);

            Initialize(start, removedAmount, newContent.ToArray());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Finds the colliding changes.
        /// </summary>
        /// <param name="current">The current change.</param>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <returns></returns>
        private static CollidingChanges FindCollidingChanges(IMergableChange current, MergableChangeset changeset1,
                                                             MergableChangeset changeset2)
        {
            var  collidingChangesFrom1 = new MergableChangeset();
            var  collidingChangesFrom2 = new MergableChangeset();
            bool swapped = false;

            while (true)
            {
                IMergableChange colliding = FindCollision(changeset2, current.Start, current.AfterFinish);
                if ((colliding == null) || colliding.Equals(current))
                {
                    if (swapped)
                    {
                        Utils.Swap(ref collidingChangesFrom1, ref collidingChangesFrom2);
                    }
                    return(new CollidingChanges(collidingChangesFrom1, collidingChangesFrom2));
                }

                collidingChangesFrom2.Add(colliding);
                current = colliding;
                Utils.Swap(ref changeset1, ref changeset2);
                Utils.Swap(ref collidingChangesFrom1, ref collidingChangesFrom2);
                swapped = !swapped;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Collects the changes.
        /// </summary>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <param name="source">The source.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException"></exception>
        private IEnumerable <IChange> CollectChanges(MergableChangeset changeset1, MergableChangeset changeset2,
                                                     IReadOnlyList <string> source)
        {
            if ((changeset1 == null) || (changeset2 == null) || (source == null))
            {
                throw new ArgumentNullException();
            }

            changeset1.Verify(source.Count);
            changeset2.Verify(source.Count);

            var  lines        = new SortedSet <int>(changeset1.Keys.Union(changeset2.Keys));
            var  removedLines = new HashSet <int>();
            bool swapped      = false;

            foreach (int line in lines.Where(l => !removedLines.Contains(l)))
            {
                if (!changeset1.ContainsKey(line))
                {
                    Utils.Swap(ref changeset1, ref changeset2);
                    swapped = !swapped;
                }

                IMergableChange  currentChange    = changeset1.Extract(line);
                CollidingChanges collidingChanges = FindCollidingChanges(currentChange, changeset1, changeset2);

                if (collidingChanges.IsEmpty())
                {
                    yield return(currentChange);

                    continue;
                }

                IMergableChange collidingChange = collidingChanges.TryGetSingle();
                if (collidingChange != null)
                {
                    removedLines.Add(collidingChange.Start);
                    if (swapped)
                    {
                        Utils.Swap(ref currentChange, ref collidingChange);
                    }
                    yield return(ProcessCollision(source, currentChange, collidingChange));
                }
                else
                {
                    foreach (int l in collidingChanges.Keys)
                    {
                        removedLines.Add(l);
                    }
                    collidingChanges.ChangesFrom1.Add(currentChange);
                    yield return(swapped
                        ? ProcessCollision(source, collidingChanges.ChangesFrom2, collidingChanges.ChangesFrom1)
                        : ProcessCollision(source, collidingChanges.ChangesFrom1, collidingChanges.ChangesFrom2));
                }
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Merges the specified changesets.
 /// </summary>
 /// <param name="changeset1">The changeset1.</param>
 /// <param name="changeset2">The changeset2.</param>
 /// <param name="source">The source.</param>
 /// <returns></returns>
 public Changeset<IChange> Merge(MergableChangeset changeset1, MergableChangeset changeset2,
                                 IReadOnlyList<string> source)
 {
     var result = new Changeset<IChange>();
     IEnumerable<IChange> changes = CollectChanges(changeset1, changeset2, source);
     foreach (IChange change in changes)
     {
         result.Add(change.Start, change);
     }
     return result;
 }
Ejemplo n.º 5
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region IChangeSetMerger implementation
        /// <summary>
        /// Merges the specified changesets.
        /// </summary>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <param name="source">The source.</param>
        /// <returns></returns>
        public Changeset <IChange> Merge(MergableChangeset changeset1, MergableChangeset changeset2,
                                         IReadOnlyList <string> source)
        {
            var result = new Changeset <IChange>();
            IEnumerable <IChange> changes = CollectChanges(changeset1, changeset2, source);

            foreach (IChange change in changes)
            {
                result.Add(change.Start, change);
            }
            return(result);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Finds the collision.
        /// </summary>
        /// <param name="changeset">The changeset.</param>
        /// <param name="start">The first line number.</param>
        /// <param name="afterFinish">The number of the line that is one past last.</param>
        /// <returns></returns>
        private static IMergableChange FindCollision(MergableChangeset changeset, int start, int afterFinish)
        {
            if (changeset.ContainsKey(start))
            {
                return(changeset.Extract(start));
            }

            for (int i = start + 1; i < afterFinish; ++i)
            {
                if (changeset.ContainsKey(i))
                {
                    return(changeset.Extract(i));
                }
            }
            return(null);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Performs the merge.
        /// </summary>
        /// <param name="source">The source content.</param>
        /// <param name="changed1">The first changed content.</param>
        /// <param name="changed2">The second changed content.</param>
        /// <param name="merger">The merger.</param>
        /// <returns></returns>
        public static Result Merge(IReadOnlyList <string> source, IReadOnlyList <string> changed1,
                                   IReadOnlyList <string> changed2, IChangesetMerger merger)
        {
            if (merger == null)
            {
                throw new ArgumentNullException();
            }

            var changeset1 = new MergableChangeset(source, changed1);
            var changeset2 = new MergableChangeset(source, changed2);

            Changeset <IChange> merged = merger.Merge(changeset1, changeset2, source);

            IEnumerable <string> result = merged.Apply(source);

            return(new Result(merged, result));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Performs the merge.
        /// </summary>
        /// <param name="source">The source content.</param>
        /// <param name="changed1">The first changed content.</param>
        /// <param name="changed2">The second changed content.</param>
        /// <param name="merger">The merger.</param>
        /// <returns></returns>
        public static Result Merge(IReadOnlyList<string> source, IReadOnlyList<string> changed1,
                                   IReadOnlyList<string> changed2, IChangesetMerger merger)
        {
            if (merger == null)
            {
                throw new ArgumentNullException();
            }

            var changeset1 = new MergableChangeset(source, changed1);
            var changeset2 = new MergableChangeset(source, changed2);

            Changeset<IChange> merged = merger.Merge(changeset1, changeset2, source);

            IEnumerable<string> result = merged.Apply(source);

            return new Result(merged, result);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the changed block.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="start">The start.</param>
        /// <param name="afterFinish">The after finish.</param>
        /// <param name="changeset">The changeset.</param>
        /// <returns></returns>
        private static IEnumerable <string> GetChangedBlock(IReadOnlyList <string> source, int start, int afterFinish,
                                                            MergableChangeset changeset)
        {
            int currentLine = start;

            foreach (IMergableChange change in changeset.OrderedValues)
            {
                foreach (string line in GetChangedBlock(source, currentLine, change.AfterFinish, change))
                {
                    yield return(line);
                }
                currentLine = change.AfterFinish;
            }
            for (int i = currentLine; i < afterFinish; ++i)
            {
                yield return(source[i]);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Merges the specified changesets.
        /// </summary>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <param name="source">The source.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException"></exception>
        public Changeset <IChange> Merge(MergableChangeset changeset1, MergableChangeset changeset2,
                                         IReadOnlyList <string> source)
        {
            if ((changeset1 == null) || (changeset2 == null) || (source == null))
            {
                throw new ArgumentNullException();
            }

            changeset1.Verify(source.Count);
            changeset2.Verify(source.Count);

            var result = new Changeset <IChange>();

            foreach (int key in changeset1.Keys)
            {
                result.Add(key, changeset1[key]);
            }

            return(result);
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CollidingChanges"/> class.
 /// </summary>
 /// <param name="changesFrom1">The changes changeset 1.</param>
 /// <param name="changesFrom2">The changes changeset 2.</param>
 internal CollidingChanges(MergableChangeset changesFrom1, MergableChangeset changesFrom2)
 {
     ChangesFrom1 = changesFrom1;
     ChangesFrom2 = changesFrom2;
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Finds the colliding changes.
        /// </summary>
        /// <param name="current">The current change.</param>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <returns></returns>
        private static CollidingChanges FindCollidingChanges(IMergableChange current, MergableChangeset changeset1,
                                                             MergableChangeset changeset2)
        {
            var collidingChangesFrom1 = new MergableChangeset();
            var collidingChangesFrom2 = new MergableChangeset();
            bool swapped = false;
            while (true)
            {
                IMergableChange colliding = FindCollision(changeset2, current.Start, current.AfterFinish);
                if ((colliding == null) || colliding.Equals(current))
                {
                    if (swapped)
                    {
                        Utils.Swap(ref collidingChangesFrom1, ref collidingChangesFrom2);
                    }
                    return new CollidingChanges(collidingChangesFrom1, collidingChangesFrom2);
                }

                collidingChangesFrom2.Add(colliding);
                current = colliding;
                Utils.Swap(ref changeset1, ref changeset2);
                Utils.Swap(ref collidingChangesFrom1, ref collidingChangesFrom2);
                swapped = !swapped;
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Processes the collision.
 /// </summary>
 /// <param name="source">The source content.</param>
 /// <param name="changeset1">The changeset1.</param>
 /// <param name="changeset2">The changeset2.</param>
 /// <returns></returns>
 protected virtual IChange ProcessCollision(IReadOnlyList<string> source, MergableChangeset changeset1,
                                            MergableChangeset changeset2)
 {
     return new Conflict(source, changeset1, changeset2, ConflictBlocks);
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Collects the changes.
        /// </summary>
        /// <param name="changeset1">The changeset1.</param>
        /// <param name="changeset2">The changeset2.</param>
        /// <param name="source">The source.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException"></exception>
        private IEnumerable<IChange> CollectChanges(MergableChangeset changeset1, MergableChangeset changeset2,
                                                    IReadOnlyList<string> source)
        {
            if ((changeset1 == null) || (changeset2 == null) || (source == null))
            {
                throw new ArgumentNullException();
            }

            changeset1.Verify(source.Count);
            changeset2.Verify(source.Count);

            var lines = new SortedSet<int>(changeset1.Keys.Union(changeset2.Keys));
            var removedLines = new HashSet<int>();
            bool swapped = false;
            foreach (int line in lines.Where(l => !removedLines.Contains(l)))
            {
                if (!changeset1.ContainsKey(line))
                {
                    Utils.Swap(ref changeset1, ref changeset2);
                    swapped = !swapped;
                }

                IMergableChange currentChange = changeset1.Extract(line);
                CollidingChanges collidingChanges = FindCollidingChanges(currentChange, changeset1, changeset2);

                if (collidingChanges.IsEmpty())
                {
                    yield return currentChange;
                    continue;
                }

                IMergableChange collidingChange = collidingChanges.TryGetSingle();
                if (collidingChange != null)
                {
                    removedLines.Add(collidingChange.Start);
                    if (swapped)
                    {
                        Utils.Swap(ref currentChange, ref collidingChange);
                    }
                    yield return ProcessCollision(source, currentChange, collidingChange);
                }
                else
                {
                    foreach (int l in collidingChanges.Keys)
                    {
                        removedLines.Add(l);
                    }
                    collidingChanges.ChangesFrom1.Add(currentChange);
                    yield return swapped
                        ? ProcessCollision(source, collidingChanges.ChangesFrom2, collidingChanges.ChangesFrom1)
                        : ProcessCollision(source, collidingChanges.ChangesFrom1, collidingChanges.ChangesFrom2);
                }
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Finds the collision.
        /// </summary>
        /// <param name="changeset">The changeset.</param>
        /// <param name="start">The first line number.</param>
        /// <param name="afterFinish">The number of the line that is one past last.</param>
        /// <returns></returns>
        private static IMergableChange FindCollision(MergableChangeset changeset, int start, int afterFinish)
        {
            if (changeset.ContainsKey(start))
            {
                return changeset.Extract(start);
            }

            for (int i = start + 1; i < afterFinish; ++i)
            {
                if (changeset.ContainsKey(i))
                {
                    return changeset.Extract(i);
                }
            }
            return null;
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Processes the collision.
 /// </summary>
 /// <param name="source">The source content.</param>
 /// <param name="changeset1">The changeset1.</param>
 /// <param name="changeset2">The changeset2.</param>
 /// <returns></returns>
 protected virtual IChange ProcessCollision(IReadOnlyList <string> source, MergableChangeset changeset1,
                                            MergableChangeset changeset2)
 {
     return(new Conflict(source, changeset1, changeset2, ConflictBlocks));
 }