Beispiel #1
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;
            }
        }
        /// <summary>
        /// Processes the collision.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="change1">The change1.</param>
        /// <param name="change2">The change2.</param>
        /// <returns></returns>
        protected override IChange ProcessCollision(IReadOnlyList <string> source, IMergableChange change1,
                                                    IMergableChange change2)
        {
            IChange mergedChange = TryMerge(change1, change2);

            return(mergedChange ?? base.ProcessCollision(source, change1, change2));
        }
Beispiel #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));
                }
            }
        }
        /// <summary>
        /// Tries to merge.
        /// </summary>
        /// <param name="change1">The change1.</param>
        /// <param name="change2">The change2.</param>
        /// <returns></returns>
        private static IChange TryMerge(IMergableChange change1, IMergableChange change2)
        {
            if (change1.Start != change2.Start)
            {
                return null;
            }

            var addition = Utils.TryCastOneOf<Addition>(change1, change2);
            if (addition == null)
            {
                return null;
            }
            var removal = Utils.TryCastOneOf<Removal>(change1, change2);
            if (removal == null)
            {
                return null;
            }

            return new Replacement(removal.Start, removal.RemovedAmount, addition.NewContent.ToArray());
        }
Beispiel #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Conflict"/> class.
        /// </summary>
        /// <param name="change1">The change1.</param>
        /// <param name="change2">The change2.</param>
        /// <param name="source">The source.</param>
        /// <param name="conflictBlocks">The conflict blocks.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// </exception>
        /// <exception cref="System.ArgumentException"></exception>
        internal Conflict(IMergableChange change1, IMergableChange change2, IReadOnlyList <string> source,
                          ConflictBlocks conflictBlocks)
        {
            if ((change1 == null) || (change2 == null) || (source == null))
            {
                throw new ArgumentNullException();
            }

            int start = Math.Min(change1.Start, change2.Start);

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

            int afterFinish = Math.Max(change1.AfterFinish, change2.AfterFinish);

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

            if ((change1.Start >= change2.AfterFinish) || (change2.Start >= change1.AfterFinish))
            {
                if (change1.Start != change2.Start)
                {
                    throw new ArgumentException();
                }
            }

            int removedAmount = afterFinish - start;

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

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

            Initialize(start, removedAmount, newContent.ToArray());
        }
        /// <summary>
        /// Tries to merge.
        /// </summary>
        /// <param name="change1">The change1.</param>
        /// <param name="change2">The change2.</param>
        /// <returns></returns>
        private static IChange TryMerge(IMergableChange change1, IMergableChange change2)
        {
            if (change1.Start != change2.Start)
            {
                return(null);
            }

            var addition = Utils.TryCastOneOf <Addition>(change1, change2);

            if (addition == null)
            {
                return(null);
            }
            var removal = Utils.TryCastOneOf <Removal>(change1, change2);

            if (removal == null)
            {
                return(null);
            }

            return(new Replacement(removal.Start, removal.RemovedAmount, addition.NewContent.ToArray()));
        }
 /// <summary>
 /// Processes the collision.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="change1">The change1.</param>
 /// <param name="change2">The change2.</param>
 /// <returns></returns>
 protected override IChange ProcessCollision(IReadOnlyList<string> source, IMergableChange change1,
                                             IMergableChange change2)
 {
     IChange mergedChange = TryMerge(change1, change2);
     return mergedChange ?? base.ProcessCollision(source, change1, change2);
 }
        /// <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;
            }
        }
 /// <summary>
 /// Processes the collision.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="change1">The change1.</param>
 /// <param name="change2">The change2.</param>
 /// <returns></returns>
 protected virtual IChange ProcessCollision(IReadOnlyList<string> source, IMergableChange change1,
                                            IMergableChange change2)
 {
     return new Conflict(change1, change2, source, ConflictBlocks);
 }
Beispiel #10
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region Helpers
        /// <summary>
        /// Processes the collision.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="change1">The change1.</param>
        /// <param name="change2">The change2.</param>
        /// <returns></returns>
        protected virtual IChange ProcessCollision(IReadOnlyList <string> source, IMergableChange change1,
                                                   IMergableChange change2)
        {
            return(new Conflict(change1, change2, source, ConflictBlocks));
        }