Esempio n. 1
0
 public Synchronizer(ILogger logger, ISourceRepository sourceRepository, ITargetRepository targetRepository, IMergeStrategy mergeStrategy)
 {
     _logger           = logger;
     _sourceRepository = sourceRepository;
     _targetRepository = targetRepository;
     _mergeStrategy    = mergeStrategy;
 }
Esempio n. 2
0
        public void GetItemsDelegatesToTheStrategy()
        {
            MergedDataSet dataSet = new MergedDataSet();

            IDataSet provider = Mocks.Stub <IDataSet>();

            dataSet.AddDataSet(provider);

            IMergeStrategy strategy = Mocks.StrictMock <IMergeStrategy>();

            dataSet.Strategy = strategy;

            IEnumerable <IDataItem> results = Mocks.Stub <IEnumerable <IDataItem> >();

            DataBinding[] bindings = new DataBinding[0];

            using (Mocks.Record())
            {
                Expect.Call(strategy.Merge(null, null, false)).IgnoreArguments().Do((MergeDelegate) delegate(IList <IDataProvider> mergeProviders, ICollection <DataBinding> mergeBindings,
                                                                                                             bool includeDynamicItems)
                {
                    Assert.IsTrue(includeDynamicItems);

                    Assert.AreElementsEqual(new IDataProvider[] { provider }, mergeProviders);
                    Assert.AreSame(bindings, mergeBindings);
                    return(results);
                });
            }

            using (Mocks.Playback())
            {
                Assert.AreSame(results, dataSet.GetItems(bindings, true));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Merges a collection of view models with a list of models
        /// </summary>
        public static void MergeCollection <TViewModel, TModel>(
            this ICollection <TViewModel> collection,
            IReadOnlyList <TModel> updated,
            IMergeStrategy <TModel, TViewModel> strategy)
            where TViewModel : IIdentifiableObject
            where TModel : IIdentifiableObject
        {
            // Remove those without id or not existing in the updated collection
            var removed = collection.Where(r => r.Id == 0 || updated.All(u => u.Id != r.Id)).ToList();

            foreach (var obj in removed)
            {
                collection.Remove(obj);
            }

            foreach (var updatedModel in updated)
            {
                var match = collection.FirstOrDefault(r => r.Id == updatedModel.Id);
                if (match != null)
                {
                    strategy.UpdateModel(match, updatedModel);
                }
                else
                {
                    var vm = strategy.FromModel(updatedModel);
                    collection.Add(vm);
                }
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Used by tests (and public constructor), which prefer to give us raw contents rather than paths
 /// </summary>
 internal LiftMerger(string alphaLiftContents, string betaLiftContents, string ancestorLiftContents, IMergeStrategy mergeStrategy)
 {
     _alphaLift = alphaLiftContents;
     _betaLift = betaLiftContents;
     _ancestorLift = ancestorLiftContents;
     _mergingStrategy = mergeStrategy;
 }
Esempio n. 5
0
 /// <summary>
 /// Used by tests (and public constructor), which prefer to give us raw contents rather than paths
 /// </summary>
 internal LiftMerger(string alphaLiftContents, string betaLiftContents, string ancestorLiftContents, IMergeStrategy mergeStrategy)
 {
     _alphaLift       = alphaLiftContents;
     _betaLift        = betaLiftContents;
     _ancestorLift    = ancestorLiftContents;
     _mergingStrategy = mergeStrategy;
 }
        public void RenderToFileHelper <T>(string filePath, IMergeStrategy strategy) where T : EntityCodeTemplate, new()
        {
            var template = this.Create <T>();

            CopyPropertiesTo(template, true, PropertyIgnoreList);

            template.RenderToFile(filePath, strategy);
        }
Esempio n. 7
0
        public MergeActivity(string name, IMergeStrategy strategy)
            : base(name)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException(nameof(strategy));
            }

            Strategy = strategy;
        }
 public GitignoreGetCommandHandler(IGitignoreService gitignoreService,
                                   IConcatedNamesProcessor concatedNamesProcessor,
                                   IMergeStrategy mergeStrategy,
                                   IGitignoreFileWriter gitignoreFileWriter)
 {
     _gitignoreService       = gitignoreService ?? throw new ArgumentNullException(nameof(gitignoreService));
     _concatedNamesProcessor = concatedNamesProcessor ?? throw new ArgumentNullException(nameof(concatedNamesProcessor));
     _mergeStrategy          = mergeStrategy ?? throw new ArgumentNullException(nameof(mergeStrategy));
     _gitignoreFileWriter    = gitignoreFileWriter ?? throw new ArgumentNullException(nameof(gitignoreFileWriter));
 }
Esempio n. 9
0
        private Lift2WayDiffer(IMergeStrategy mergeStrategy, string parentXml, string childXml,IMergeEventListener eventListener)
        {
            _childDom = new XmlDocument();
            _parentDom = new XmlDocument();

            _childDom.LoadXml(childXml);
            _parentDom.LoadXml(parentXml);
            _parentIdToNodeIndex = new Dictionary<string, XmlNode>();

            EventListener = eventListener;
        }
Esempio n. 10
0
        private Lift2WayDiffer(IMergeStrategy mergeStrategy, string parentXml, string childXml, IMergeEventListener eventListener)
        {
            _childDom  = new XmlDocument();
            _parentDom = new XmlDocument();

            _childDom.LoadXml(childXml);
            _parentDom.LoadXml(parentXml);
            _parentIdToNodeIndex = new Dictionary <string, XmlNode>();

            EventListener = eventListener;
        }
Esempio n. 11
0
        /// <summary>
        /// Merge a recursive model structure into an existing observable view model structure
        /// </summary>
        public static void MergeTree <TModel>(
            this Collection <TreeItemViewModel> current,
            IReadOnlyList <TModel> updated,
            IMergeStrategy <TModel, TreeItemViewModel> strategy)
            where TModel : class, ITreeItemModel <TModel>
        {
            // Use 'for'-loop, because it is modification tolerant
            int currentIndex = 0, updatedIndex = 0;

            while (currentIndex < current.Count || updatedIndex < updated.Count)
            {
                var currentItem = GetItem(current, currentIndex);
                var updatedItem = GetItem(updated, updatedIndex);
                // Default: Update the model if it matches
                if (currentItem != null && currentItem.Id == updatedItem?.Id)
                {
                    strategy.UpdateModel(currentItem, updatedItem);
                    currentIndex++;
                    updatedIndex++;
                    MergeTree(currentItem.Children, updatedItem.Children, strategy);
                }
                // Item was appended or inserted
                else if (currentItem == null || HasId(updated, currentItem.Id, updatedIndex))
                {
                    currentItem = strategy.FromModel(updatedItem);
                    current.Insert(currentIndex, currentItem);
                    currentIndex++;
                    updatedIndex++;
                    MergeTree(currentItem.Children, updatedItem.Children, strategy);
                }
                // In any other case: Remove
                else
                {
                    current.RemoveAt(currentIndex);
                    updatedIndex++;
                }
            }
        }
Esempio n. 12
0
        private static void ReportEditConflictsForBothAddedNewObjectsWithDifferentContent(
			MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
			string pathToWinner,
			IDictionary<string, string> allLoserData, IDictionary<string, XmlNode> fluffedUpLoserNodes,
			IEnumerable<string> allNewIdsFromBothWithSameData, IEnumerable<string> allNewIdsFromBoth,
			IDictionary<string, string> allWinnerData, IDictionary<string, XmlNode> fluffedUpWinnerNodes)
        {
            foreach (var identifier in allNewIdsFromBoth.Except(allNewIdsFromBothWithSameData))
            {
                //// These were added by both, but they do not have the same content.
                XmlNode winnerNode;
                if (!fluffedUpWinnerNodes.TryGetValue(identifier, out winnerNode))
                {
                    winnerNode = XmlUtilities.GetDocumentNodeFromRawXml(allWinnerData[identifier], new XmlDocument());
                    fluffedUpWinnerNodes.Add(identifier, winnerNode);
                }
                XmlNode loserNode;
                if (!fluffedUpLoserNodes.TryGetValue(identifier, out loserNode))
                {
                    loserNode = XmlUtilities.GetDocumentNodeFromRawXml(allLoserData[identifier], new XmlDocument());
                    fluffedUpLoserNodes.Add(identifier, loserNode);
                }

                var elementStrategy = mergeStrategy.GetElementStrategy(winnerNode);
                var generator = elementStrategy.ContextDescriptorGenerator;
                if (generator != null)
                {
                    mergeOrder.EventListener.EnteringContext(generator.GenerateContextDescriptor(allWinnerData[identifier],
                                                                                                 pathToWinner));
                }
                var mergedResult = mergeStrategy.MakeMergedEntry(
                    mergeOrder.EventListener,
                    mergeOrder.MergeSituation.ConflictHandlingMode == MergeOrder.ConflictHandlingModeChoices.WeWin
                        ? winnerNode
                        : loserNode,
                    mergeOrder.MergeSituation.ConflictHandlingMode == MergeOrder.ConflictHandlingModeChoices.WeWin
                        ? loserNode
                        : winnerNode,
                    null);
                allWinnerData[identifier] = mergedResult;
                fluffedUpWinnerNodes.Remove(identifier);
                allLoserData[identifier] = mergedResult;
                    // They really are the same now, but is it a good idea to make them the same?
                fluffedUpLoserNodes.Remove(identifier);
            }
        }
Esempio n. 13
0
        private static Dictionary<string, string> MakeRecordDictionary(IMergeEventListener mainMergeEventListener,
			IMergeStrategy mergeStrategy,
			string pathname,
			string firstElementMarker,
			string recordStartingTag,
			string identifierAttribute)
        {
            var records = new Dictionary<string, string>(EstimatedObjectCount(pathname),
                                                         StringComparer.InvariantCultureIgnoreCase);
            using (var fastSplitter = new FastXmlElementSplitter(pathname))
            {
                bool foundOptionalFirstElement;
                foreach (var record in fastSplitter.GetSecondLevelElementStrings(firstElementMarker, recordStartingTag, out foundOptionalFirstElement))
                {
                    if (foundOptionalFirstElement)
                    {
                        var key = firstElementMarker.ToLowerInvariant();
                        if (records.ContainsKey(key))
                        {
                            mainMergeEventListener.WarningOccurred(
                                new MergeWarning(string.Format("{0}: There is more than one optional first element '{1}'", pathname, key)));
                        }
                        else
                        {
                            if (RemoveAmbiguousChildNodes)
                            {
                                var possiblyRevisedRecord = RemoveAmbiguousChildren(mainMergeEventListener, mergeStrategy.GetStrategies(), record, pathname);
                                records.Add(key, possiblyRevisedRecord);
                            }
                            else
                            {
                                records.Add(key, record);
                            }
                        }
                        foundOptionalFirstElement = false;
                    }
                    else
                    {
                        var attrValues = XmlUtils.GetAttributes(record, new HashSet<string> {"dateDeleted", identifierAttribute});

                        // Eat tombstones.
                        if (attrValues["dateDeleted"] != null)
                            continue;

                        var identifier = attrValues[identifierAttribute];
                        if (string.IsNullOrEmpty(identifierAttribute))
                        {
                            mainMergeEventListener.WarningOccurred(
                                new MergeWarning(string.Format("{0}: There was no identifier for the record", pathname)));
                            continue;
                        }
                        if (records.ContainsKey(identifier))
                        {
                            mainMergeEventListener.WarningOccurred(
                                new MergeWarning(string.Format("{0}: There is more than one element with the identifier '{1}'", pathname,
                                                               identifier)));
                        }
                        else
                        {
                            if (RemoveAmbiguousChildNodes)
                            {
                                var possiblyRevisedRecord = RemoveAmbiguousChildren(mainMergeEventListener, mergeStrategy.GetStrategies(), record, pathname);
                                records.Add(identifier, possiblyRevisedRecord);
                            }
                            else
                            {
                                records.Add(identifier, record);
                            }
                        }
                    }
                }
            }

            return records;
        }
Esempio n. 14
0
        private static void ProcessEntry(XmlWriter writer, IMergeEventListener eventListener, IMergeStrategy mergingStrategy,
                                         XmlNode ancestorDom, HashSet <string> processedIds,
                                         XmlNode sourceEntry, string sourceLabel, string sourcePath,
                                         IDictionary <string, XmlNode> otherIdNodeIndex, string otherLabel, string otherPath)
        {
            var id = LiftUtils.GetId(sourceEntry);

            if (processedIds.Contains(id))
            {
                return;                 // Already handled the id.
            }
            XmlNode otherEntry;
            var     commonEntry = FindEntry(ancestorDom, id);

            if (!otherIdNodeIndex.TryGetValue(id, out otherEntry))
            {
                // It is in source, but not in target, so it clearly has been deleted by target (new style deletion).
                if (LiftUtils.GetIsMarkedAsDeleted(sourceEntry))
                {
                    if (!LiftUtils.GetIsMarkedAsDeleted(commonEntry))
                    {
                        // source and target both deleted but in different ways, so make deletion change report.
                        // There is no need to write anything.
                        eventListener.ChangeOccurred(new XmlDeletionChangeReport(sourcePath, commonEntry, sourceEntry));
                    }
                    //else
                    //{
                    //    // Make it go away without fanfare by doing nothing to writer, since target actually removed the dead entry.
                    //}
                    processedIds.Add(id);
                    return;
                }

                if (commonEntry == null)
                {
                    // source added it
                    eventListener.ChangeOccurred(new XmlAdditionChangeReport(sourcePath, sourceEntry));
                    writer.WriteNode(sourceEntry.CreateNavigator(), false);
                }
                else
                {
                    if (AreTheSame(sourceEntry, commonEntry))
                    {
                        // target's deletion wins with a plain vanilla deletion report.
                        eventListener.ChangeOccurred(new XmlDeletionChangeReport(sourcePath, commonEntry, otherEntry));
                    }
                    else
                    {
                        // source wins over target's new style deletion on the least loss priciple.
                        // Add an edit vs remove conflict report.
                        eventListener.ConflictOccurred(new RemovedVsEditedElementConflict("entry", sourceEntry, otherEntry, commonEntry, new MergeSituation(sourcePath, sourceLabel, "", otherLabel, "", MergeOrder.ConflictHandlingModeChoices.WeWin), null, sourceLabel));
                        writer.WriteNode(sourceEntry.CreateNavigator(), false);
                    }
                    processedIds.Add(id);
                    return;
                }
            }
            else if (AreTheSame(sourceEntry, otherEntry))
            {
                //unchanged or both made same change
                writer.WriteNode(sourceEntry.CreateNavigator(), false);
            }
            else if (LiftUtils.GetIsMarkedAsDeleted(otherEntry))
            {
                // source edited, target deleted (old style deletion using dateDeleted attr).
                eventListener.ConflictOccurred(new RemovedVsEditedElementConflict("entry", sourceEntry, otherEntry, commonEntry, new MergeSituation(sourcePath, sourceLabel, "", otherLabel, "", MergeOrder.ConflictHandlingModeChoices.WeWin), null, sourceLabel));
            }
            else if (LiftUtils.GetIsMarkedAsDeleted(sourceEntry))
            {
                // source deleted (old style), but target edited.
                // target wins with the least loss principle.
                // But generate a conflict report.
                eventListener.ConflictOccurred(new RemovedVsEditedElementConflict("entry", otherEntry, sourceEntry, commonEntry, new MergeSituation(otherPath, otherLabel, "", sourceLabel, "", MergeOrder.ConflictHandlingModeChoices.TheyWin), null, sourceLabel));
                writer.WriteNode(otherEntry.CreateNavigator(), false);
            }
            else
            {
                // One or both of them edited it, so merge the hard way.
                using (var reader = XmlReader.Create(new StringReader(
                                                         mergingStrategy.MakeMergedEntry(eventListener, sourceEntry, otherEntry, commonEntry)
                                                         )))
                {
                    writer.WriteNode(reader, false);
                }
            }
            processedIds.Add(id);
        }
Esempio n. 15
0
 public static Lift2WayDiffer CreateFromStrings(IMergeStrategy mergeStrategy, string parentXml, string childXml, IMergeEventListener eventListener)
 {
     return new Lift2WayDiffer(mergeStrategy, parentXml, childXml, eventListener);
 }
Esempio n. 16
0
 private Lift2WayDiffer(IMergeStrategy mergeStrategy, string parentXml, string childXml , IMergeEventListener listener, FileInRevision parentFileInRevision, FileInRevision childFileInRevision)
     : this(mergeStrategy,parentXml, childXml, listener)
 {
     _parentFileInRevision = parentFileInRevision;
     _childFileInRevision = childFileInRevision;
 }
 public static IWorkflowBuilder Merge(this IWorkflowBuilder builder, string name, IMergeStrategy strategy)
 {
     return(builder.Activity(activity => activity.Merge(name, strategy)));
 }
Esempio n. 18
0
        private static void ProcessEntry(XmlWriter writer, IMergeEventListener eventListener, IMergeStrategy mergingStrategy,
			XmlNode ancestorDom, HashSet<string> processedIds,
			XmlNode sourceEntry, string sourceLabel, string sourcePath,
			IDictionary<string, XmlNode> otherIdNodeIndex, string otherLabel, string otherPath)
        {
            var id = LiftUtils.GetId(sourceEntry);
            if (processedIds.Contains(id))
                return; // Already handled the id.
            XmlNode otherEntry;
            var commonEntry = FindEntry(ancestorDom, id);
            if (!otherIdNodeIndex.TryGetValue(id, out otherEntry))
            {
                // It is in source, but not in target, so it clearly has been deleted by target (new style deletion).
                if (LiftUtils.GetIsMarkedAsDeleted(sourceEntry))
                {
                    if (!LiftUtils.GetIsMarkedAsDeleted(commonEntry))
                    {
                        // source and target both deleted but in different ways, so make deletion change report.
                        // There is no need to write anything.
                        eventListener.ChangeOccurred(new XmlDeletionChangeReport(sourcePath, commonEntry, sourceEntry));
                    }
                    //else
                    //{
                    //    // Make it go away without fanfare by doing nothing to writer, since target actually removed the dead entry.
                    //}
                    processedIds.Add(id);
                    return;
                }

                if (commonEntry == null)
                {
                    // source added it
                    eventListener.ChangeOccurred(new XmlAdditionChangeReport(sourcePath, sourceEntry));
                    writer.WriteNode(sourceEntry.CreateNavigator(), false);
                }
                else
                {
                    if (AreTheSame(sourceEntry, commonEntry))
                    {
                        // target's deletion wins with a plain vanilla deletion report.
                        eventListener.ChangeOccurred(new XmlDeletionChangeReport(sourcePath, commonEntry, otherEntry));
                    }
                    else
                    {
                        // source wins over target's new style deletion on the least loss priciple.
                        // Add an edit vs remove conflict report.
                        eventListener.ConflictOccurred(new RemovedVsEditedElementConflict("entry", sourceEntry, otherEntry, commonEntry, new MergeSituation(sourcePath, sourceLabel, "", otherLabel, "", MergeOrder.ConflictHandlingModeChoices.WeWin), null, sourceLabel));
                        writer.WriteNode(sourceEntry.CreateNavigator(), false);
                    }
                    processedIds.Add(id);
                    return;
                }
            }
            else if (AreTheSame(sourceEntry, otherEntry))
            {
                //unchanged or both made same change
                writer.WriteNode(sourceEntry.CreateNavigator(), false);
            }
            else if (LiftUtils.GetIsMarkedAsDeleted(otherEntry))
            {
                // source edited, target deleted (old style deletion using dateDeleted attr).
                eventListener.ConflictOccurred(new RemovedVsEditedElementConflict("entry", sourceEntry, otherEntry, commonEntry, new MergeSituation(sourcePath, sourceLabel, "", otherLabel, "", MergeOrder.ConflictHandlingModeChoices.WeWin), null, sourceLabel));
            }
            else if (LiftUtils.GetIsMarkedAsDeleted(sourceEntry))
            {
                // source deleted (old style), but target edited.
                // target wins with the least loss principle.
                // But generate a conflict report.
                eventListener.ConflictOccurred(new RemovedVsEditedElementConflict("entry", otherEntry, sourceEntry, commonEntry, new MergeSituation(otherPath, otherLabel, "", sourceLabel, "", MergeOrder.ConflictHandlingModeChoices.TheyWin), null, sourceLabel));
                writer.WriteNode(otherEntry.CreateNavigator(), false);
            }
            else
            {
                // One or both of them edited it, so merge the hard way.
                using (var reader = XmlReader.Create(new StringReader(
                    mergingStrategy.MakeMergedEntry(eventListener, sourceEntry, otherEntry, commonEntry)
                )))
                {
                    writer.WriteNode(reader, false);
                }
            }
            processedIds.Add(id);
        }
Esempio n. 19
0
 public object Merge(IMergeStrategy strategy)
 {
     return(strategy.Merge(Value));
 }
Esempio n. 20
0
        private static void ReportEditVsDeleteConflicts(MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
														IDictionary<string, XmlNode> fluffedUpWinnerNodes,
														IDictionary<string, string> allWinnerData,
														string winnerId,
														IEnumerable<string> allDeletedByLoserButEditedByWinnerIds,
														IDictionary<string, string> allCommonAncestorData,
														IDictionary<string, XmlNode> fluffedUpAncestorNodes,
														string pathToWinner)
        {
            foreach (var allDeletedByLoserButEditedByWinnerId in allDeletedByLoserButEditedByWinnerIds)
            {
                // Report winner edited vs loser deleted
                XmlNode commonNode;
                if (!fluffedUpAncestorNodes.TryGetValue(allDeletedByLoserButEditedByWinnerId, out commonNode))
                {
                    commonNode = XmlUtilities.GetDocumentNodeFromRawXml(allCommonAncestorData[allDeletedByLoserButEditedByWinnerId],
                                                                        new XmlDocument());
                    fluffedUpAncestorNodes.Add(allDeletedByLoserButEditedByWinnerId, commonNode);
                }
                XmlNode winnerNode;
                if (!fluffedUpWinnerNodes.TryGetValue(allDeletedByLoserButEditedByWinnerId, out winnerNode))
                {
                    winnerNode = XmlUtilities.GetDocumentNodeFromRawXml(allWinnerData[allDeletedByLoserButEditedByWinnerId],
                                                                        new XmlDocument());
                    fluffedUpWinnerNodes.Add(allDeletedByLoserButEditedByWinnerId, winnerNode);
                }
                var elementStrategy = mergeStrategy.GetElementStrategy(winnerNode);
                var generator = elementStrategy.ContextDescriptorGenerator;
                if (generator != null)
                {
                    mergeOrder.EventListener.EnteringContext(generator.GenerateContextDescriptor(allWinnerData[allDeletedByLoserButEditedByWinnerId],
                                                                                                 pathToWinner));
                }
                AddConflictToListener(
                    mergeOrder.EventListener,
                    new EditedVsRemovedElementConflict(commonNode.Name, winnerNode, null, commonNode, mergeOrder.MergeSituation,
                                                       mergeStrategy.GetElementStrategy(commonNode), winnerId),
                    winnerNode, null, commonNode, generator as IGenerateHtmlContext ?? new SimpleHtmlGenerator());
            }
        }
Esempio n. 21
0
 private static void ProcessEntries(XmlWriter writer, IMergeEventListener eventListener, IMergeStrategy mergingStrategy,
                                    XmlNode ancestorDom, HashSet <string> processedIds,
                                    XmlNode sourceDom, string sourceLabel, string sourcePath,
                                    IDictionary <string, XmlNode> otherIdNodeIndex, string otherLabel, string otherPath)
 {
     foreach (XmlNode sourceEntry in sourceDom.SafeSelectNodes("lift/entry"))
     {
         ProcessEntry(writer, eventListener, mergingStrategy, ancestorDom, processedIds,
                      sourceEntry, sourceLabel, sourcePath,
                      otherIdNodeIndex, otherLabel, otherPath);
     }
 }
Esempio n. 22
0
 private Lift2WayDiffer(IMergeStrategy mergeStrategy, string parentXml, string childXml, IMergeEventListener listener, FileInRevision parentFileInRevision, FileInRevision childFileInRevision)
     : this(mergeStrategy, parentXml, childXml, listener)
 {
     _parentFileInRevision = parentFileInRevision;
     _childFileInRevision  = childFileInRevision;
 }
Esempio n. 23
0
 public static Lift2WayDiffer CreateFromStrings(IMergeStrategy mergeStrategy, string parentXml, string childXml, IMergeEventListener eventListener)
 {
     return(new Lift2WayDiffer(mergeStrategy, parentXml, childXml, eventListener));
 }
Esempio n. 24
0
 public static Lift2WayDiffer CreateFromFileInRevision(IMergeStrategy mergeStrategy, FileInRevision parent, FileInRevision child, IMergeEventListener eventListener, HgRepository repository)
 {
     return(new Lift2WayDiffer(mergeStrategy, parent.GetFileContents(repository), child.GetFileContents(repository), eventListener, parent, child));
 }
Esempio n. 25
0
        public static void BuildSubTemplate(CodeTemplate parent, CodeTemplate template, IMergeStrategy strategy, string pathAndFile, string outputDir)
        {
            // instantiate the sub-template

                parent.Response.WriteLine(string.Format("Begin Build SubTemplate for file {0}...",Path.GetFileName(pathAndFile)));
                // Set up the DL project
                parent.CopyPropertiesTo(template);

                //Render the file
                if(strategy == null)
                    template.RenderToFile(Path.Combine(outputDir,pathAndFile), true);
                else
                    template.RenderToFile(Path.Combine(outputDir,pathAndFile), strategy);

                parent.Response.WriteLine(string.Format("Build of {0} Complete.",Path.GetFileName(pathAndFile)));
        }
Esempio n. 26
0
        private static void ReportNormalEditConflicts(MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
													  IDictionary<string, string> allLoserData,
													  IDictionary<string, XmlNode> fluffedUpAncestorNodes,
													  IDictionary<string, string> allCommonAncestorData,
													  IEnumerable<string> allIdsWhereUsersMadeDifferentChanges,
													  IDictionary<string, XmlNode> fluffedUpWinnerNodes,
													  IDictionary<string, XmlNode> fluffedUpLoserNodes,
													  IDictionary<string, string> allWinnerData)
        {
            foreach (var identifier in allIdsWhereUsersMadeDifferentChanges)
            {
                // Report normal edit conflicts for 'allIdsWhereUsersMadeDifferentChanges'
                XmlNode winnerNode;
                if (!fluffedUpWinnerNodes.TryGetValue(identifier, out winnerNode))
                {
                    winnerNode = XmlUtilities.GetDocumentNodeFromRawXml(allWinnerData[identifier], new XmlDocument());
                    fluffedUpWinnerNodes.Add(identifier, winnerNode);
                }
                XmlNode loserNode;
                if (!fluffedUpLoserNodes.TryGetValue(identifier, out loserNode))
                {
                    loserNode = XmlUtilities.GetDocumentNodeFromRawXml(allLoserData[identifier], new XmlDocument());
                    fluffedUpLoserNodes.Add(identifier, loserNode);
                }
                XmlNode commonNode;
                if (!fluffedUpAncestorNodes.TryGetValue(identifier, out commonNode))
                {
                    commonNode = XmlUtilities.GetDocumentNodeFromRawXml(allCommonAncestorData[identifier], new XmlDocument());
                    fluffedUpAncestorNodes.Add(identifier, commonNode);
                }
                var mergedResult = mergeStrategy.MakeMergedEntry(
                    mergeOrder.EventListener,
                    mergeOrder.MergeSituation.ConflictHandlingMode == MergeOrder.ConflictHandlingModeChoices.WeWin
                        ? winnerNode
                        : loserNode,
                    mergeOrder.MergeSituation.ConflictHandlingMode == MergeOrder.ConflictHandlingModeChoices.WeWin
                        ? loserNode
                        : winnerNode,
                    commonNode);
                allWinnerData[identifier] = mergedResult;
                fluffedUpWinnerNodes.Remove(identifier);
                allLoserData[identifier] = mergedResult;
                    // They really are the same now, but is it a good idea to make them the same?
                fluffedUpLoserNodes.Remove(identifier);
                allCommonAncestorData[identifier] = mergedResult;
                // They really are the same now, but is it a good idea to make them the same?
                fluffedUpAncestorNodes.Remove(identifier);
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Perform the 3-way merge.
        /// </summary>
        public static void Do3WayMerge(MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
									   // Get from mergeOrder: IMergeEventListener listener,
									   bool sortRepeatingRecordOutputByKeyIdentifier,
									   string optionalFirstElementMarker,
									   string repeatingRecordElementName, string repeatingRecordKeyIdentifier)
        {
            // NB: The FailureSimulator is *only* used in tests.
            FailureSimulator.IfTestRequestsItThrowNow("LiftMerger.FindEntryById");

            Guard.AgainstNull(mergeStrategy, string.Format("'{0}' is null.", mergeStrategy));
            Guard.AgainstNull(mergeOrder, string.Format("'{0}' is null.", mergeOrder));
            Guard.AgainstNull(mergeOrder.EventListener, string.Format("'{0}' is null.", "mergeOrder.EventListener"));
            Guard.AgainstNullOrEmptyString(repeatingRecordElementName, "No primary record element name.");
            Guard.AgainstNullOrEmptyString(repeatingRecordKeyIdentifier, "No identifier attribute for primary record element.");

            var commonAncestorPathname = mergeOrder.pathToCommonAncestor;
            Require.That(File.Exists(commonAncestorPathname), string.Format("'{0}' does not exist.", commonAncestorPathname));

            string pathToWinner;
            string pathToLoser;
            string winnerId;
            string loserId;
            switch (mergeOrder.MergeSituation.ConflictHandlingMode)
            {
                case MergeOrder.ConflictHandlingModeChoices.WeWin:
                    pathToWinner = mergeOrder.pathToOurs;
                    pathToLoser = mergeOrder.pathToTheirs;
                    winnerId = mergeOrder.MergeSituation.AlphaUserId;
                    loserId = mergeOrder.MergeSituation.BetaUserId;
                    break;
                default: //case MergeOrder.ConflictHandlingModeChoices.TheyWin:
                    pathToWinner = mergeOrder.pathToTheirs;
                    pathToLoser = mergeOrder.pathToOurs;
                    winnerId = mergeOrder.MergeSituation.BetaUserId;
                    loserId = mergeOrder.MergeSituation.AlphaUserId;
                    break;
            }
            Require.That(File.Exists(pathToWinner), string.Format("'{0}' does not exist.", pathToWinner));
            Require.That(File.Exists(pathToLoser), string.Format("'{0}' does not exist.", pathToLoser));
            SortedDictionary<string, string> sortedAttributes;
            var rootElementName = GetRootElementData(mergeOrder.pathToOurs, mergeOrder.pathToTheirs,
                                                     mergeOrder.pathToCommonAncestor, out sortedAttributes);
            EnsureCommonAncestorFileHasMinimalXmlContent(commonAncestorPathname, rootElementName, sortedAttributes);

            // Do main merge work.
            var allWritableData = DoMerge(mergeOrder, mergeStrategy,
                                          sortRepeatingRecordOutputByKeyIdentifier, optionalFirstElementMarker,
                                          repeatingRecordElementName, repeatingRecordKeyIdentifier,
                                          pathToLoser, winnerId, pathToWinner, loserId, commonAncestorPathname);

            GC.Collect(2, GCCollectionMode.Forced); // Not nice, but required for the 164Meg ChorusNotes file.

            // Write all objects.
            WriteMainOutputData(allWritableData,
                                mergeOrder.pathToOurs,
                                // Do not change to another output file, or be ready to fix SyncScenarioTests.CanCollaborateOnLift()!
                                optionalFirstElementMarker, rootElementName, sortedAttributes, mergeStrategy.SuppressIndentingChildren());
        }
Esempio n. 28
0
        private static void ProcessEntries(XmlWriter writer, IMergeEventListener eventListener, IMergeStrategy mergingStrategy,
			XmlNode ancestorDom, HashSet<string> processedIds,
			XmlNode sourceDom, string sourceLabel, string sourcePath,
			IDictionary<string, XmlNode> otherIdNodeIndex, string otherLabel, string otherPath)
        {
            foreach (XmlNode sourceEntry in sourceDom.SafeSelectNodes("lift/entry"))
            {
                ProcessEntry(writer, eventListener, mergingStrategy, ancestorDom, processedIds,
                             sourceEntry, sourceLabel, sourcePath,
                             otherIdNodeIndex, otherLabel, otherPath);
            }
        }
 public async Task MergeFromMetaDataAsync(IFullAlbumDescriptor iad, IMergeStrategy Strategy)
 {
     await Task.Run( () => MergeFromMetaData(iad, Strategy));
 }
Esempio n. 30
0
 /// <summary>
 /// Here, "alpha" is the guy who wins when there's no better way to decide, and "beta" is the loser.
 /// </summary>
 public LiftMerger(IMergeStrategy mergeStrategy, string alphaLiftPath, string betaLiftPath, string ancestorLiftPath)
     : this(File.ReadAllText(alphaLiftPath), File.ReadAllText(betaLiftPath), File.ReadAllText(ancestorLiftPath), mergeStrategy)
 {
 }
Esempio n. 31
0
 public static IActivityFactorableBuilder Merge(this IActivityBuilder builder, string name, IMergeStrategy strategy)
 {
     return(builder.Proxy(new MergeActivity(name, strategy)));
 }
Esempio n. 32
0
        private static HashSet<string> CollectDataAndReportNormalEditConflicts(MergeOrder mergeOrder,
																			   IMergeStrategy mergeStrategy,
																			   IDictionary<string, XmlNode>
																				   fluffedUpLoserNodes,
																			   IDictionary<string, string>
																				   allCommonAncestorData,
																			   IDictionary<string, XmlNode>
																				   fluffedUpAncestorNodes,
																			   IDictionary<string, XmlNode>
																				   fluffedUpWinnerNodes,
																			   IDictionary<string, string> allLoserData,
																			   IDictionary<string, string> allWinnerData,
																			   IEnumerable<string> allWinnerIds,
																			   IEnumerable<string> allLoserIds,
																			   HashSet<string> allCommonAncestorIds,
																			   out HashSet<string> allIdsForUniqueLoserChanges,
																			   out HashSet<string> allIdsWinnerModified)
        {
            HashSet<string> allIdsLoserModified;
            HashSet<string> allIdsWhereUsersMadeDifferentChanges;
            CollectModifiedIdsFromWinnerAndLoser(allWinnerData, allLoserData, allWinnerIds, allCommonAncestorIds, allLoserIds,
                                                 allCommonAncestorData, out allIdsWhereUsersMadeDifferentChanges,
                                                 out allIdsLoserModified, out allIdsWinnerModified,
                                                 out allIdsForUniqueLoserChanges);
            ReportNormalEditConflicts(mergeOrder, mergeStrategy, // current
                                      allLoserData, fluffedUpAncestorNodes, allCommonAncestorData,
                                      allIdsWhereUsersMadeDifferentChanges,
                                      fluffedUpWinnerNodes, fluffedUpLoserNodes, allWinnerData);
            return allIdsLoserModified;
        }
Esempio n. 33
0
        private static IDictionary<string, string> DoMerge(MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
														   bool sortRepeatingRecordOutputByKeyIdentifier,
														   string optionalFirstElementMarker,
														   string repeatingRecordElementName,
														   string repeatingRecordKeyIdentifier,
														   string pathToLoser, string winnerId, string pathToWinner,
														   string loserId,
														   string commonAncestorPathname)
        {
            // Step 1. Load each of the three files.
            HashSet<string> allCommonAncestorIds;
            HashSet<string> allWinnerIds;
            HashSet<string> allLoserIds;
            Dictionary<string, string> allLoserData;
            Dictionary<string, string> allWinnerData;
            Dictionary<string, string> allCommonAncestorData;
            LoadDataFiles(mergeOrder, mergeStrategy,
                          optionalFirstElementMarker, repeatingRecordElementName, repeatingRecordKeyIdentifier,
                          commonAncestorPathname, pathToWinner, pathToLoser,
                          out allCommonAncestorData, out allCommonAncestorIds,
                          out allWinnerData, out allWinnerIds,
                          out allLoserData, out allLoserIds);

            var originalValue = RemoveAmbiguousChildNodes;
            RemoveAmbiguousChildNodes = false;

            // Step 2. Collect up new items from winner and loser and report relevant conflicts.
            var fluffedUpAncestorNodes = new Dictionary<string, XmlNode>();
            var fluffedUpLoserNodes = new Dictionary<string, XmlNode>();
            var fluffedUpWinnerNodes = new Dictionary<string, XmlNode>();
            var allNewIdsFromBoth = CollectDataAndReportEditConflictsForBothAddedNewObjectsWithDifferentContent(mergeOrder,
                                                                                                                mergeStrategy,
                                                                                                                pathToWinner,
                                                                                                                fluffedUpWinnerNodes,
                                                                                                                fluffedUpLoserNodes,
                                                                                                                allCommonAncestorIds,
                                                                                                                allWinnerIds,
                                                                                                                allWinnerData,
                                                                                                                allLoserData,
                                                                                                                allLoserIds);

            // Step 3. Collect up deleted items from winner and loser.
            HashSet<string> allIdsRemovedByWinner;
            HashSet<string> allIdsRemovedByLoser;
            HashSet<string> allIdsRemovedByBoth;
            CollectDeletedIdsFromWinnerAndLoser(allLoserIds, allCommonAncestorIds, allWinnerIds,
                                                out allIdsRemovedByWinner, out allIdsRemovedByLoser, out allIdsRemovedByBoth);

            // Step 4. Collect up modified items from winner and loser and report all other conflicts.
            HashSet<string> allDeletedByLoserButEditedByWinnerIds;
            HashSet<string> allDeletedByWinnerButEditedByLoserIds;
            var allIdsForUniqueLoserChanges = CollectDataAndReportAllConflicts(mergeOrder, mergeStrategy, winnerId, loserId,
                                                                               allLoserIds, allWinnerData,
                                                                               allIdsRemovedByWinner, allIdsRemovedByLoser,
                                                                               allCommonAncestorIds, allCommonAncestorData,
                                                                               fluffedUpLoserNodes, allWinnerIds, allLoserData,
                                                                               fluffedUpWinnerNodes, fluffedUpAncestorNodes,
                                                                               pathToWinner,
                                                                               pathToLoser,
                                                                               out allDeletedByLoserButEditedByWinnerIds,
                                                                               out allDeletedByWinnerButEditedByLoserIds);

            // Step 5. Collect all ids that are to be written out.
            var allWritableIds = new HashSet<string>(allCommonAncestorIds, StringComparer.InvariantCultureIgnoreCase);
            allWritableIds.UnionWith(allWinnerIds);
            allWritableIds.UnionWith(allLoserIds);
            allWritableIds.UnionWith(allNewIdsFromBoth); // Adds new ones from winner & loser
            allWritableIds.ExceptWith(allIdsRemovedByWinner); // Removes deletions by winner.
            allWritableIds.ExceptWith(allIdsRemovedByLoser); // Removes deletions by loser.
            allWritableIds.ExceptWith(allIdsRemovedByBoth); // Removes deletions by both.
            allWritableIds.UnionWith(allDeletedByWinnerButEditedByLoserIds); // Puts back the loser edited vs winner deleted ids.
            allWritableIds.UnionWith(allDeletedByLoserButEditedByWinnerIds); // Puts back the winner edited vs loser deleted ids.
            // Write out data in sorted identifier order or 'ot luck' order.
            var allWritableData = sortRepeatingRecordOutputByKeyIdentifier
                                      ? new SortedDictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
                                      : new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) as
                                        IDictionary<string, string>;
            foreach (var identifier in allWritableIds)
            {
                string updatedData;
                if (allIdsForUniqueLoserChanges.Contains(identifier))
                {
                    // Loser made change. Winner did nothing.
                    updatedData = allLoserData[identifier];
                }
                else
                {
                    allWinnerData.TryGetValue(identifier, out updatedData);
                    if (updatedData == null)
                        updatedData = allLoserData[identifier];
                }
                allWinnerData.Remove(identifier);
                allLoserData.Remove(identifier);
                allWritableData.Add(identifier, updatedData);
            }

            RemoveAmbiguousChildNodes = originalValue;

            return allWritableData;
        }
Esempio n. 34
0
 public static Lift2WayDiffer CreateFromFileInRevision(IMergeStrategy mergeStrategy, FileInRevision parent, FileInRevision child, IMergeEventListener eventListener, HgRepository repository)
 {
     return new Lift2WayDiffer(mergeStrategy, parent.GetFileContents(repository), child.GetFileContents(repository), eventListener, parent, child);
 }
Esempio n. 35
0
        private static void LoadDataFiles(MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
										  string optionalFirstElementMarker, string repeatingRecordElementName,
										  string repeatingRecordKeyIdentifier,
										  string commonAncestorPathname, string pathToWinner, string pathToLoser,
										  out Dictionary<string, string> allCommonAncestorData,
										  out HashSet<string> allCommonAncestorIds,
										  out Dictionary<string, string> allWinnerData, out HashSet<string> allWinnerIds,
										  out Dictionary<string, string> allLoserData, out HashSet<string> allLoserIds)
        {
            allCommonAncestorData = MakeRecordDictionary(mergeOrder.EventListener, mergeStrategy,
                                                         commonAncestorPathname, optionalFirstElementMarker,
                                                         repeatingRecordElementName, repeatingRecordKeyIdentifier);
            allCommonAncestorIds = new HashSet<string>(allCommonAncestorData.Keys, StringComparer.InvariantCultureIgnoreCase);
            allWinnerData = MakeRecordDictionary(mergeOrder.EventListener, mergeStrategy,
                                                 pathToWinner, optionalFirstElementMarker,
                                                 repeatingRecordElementName, repeatingRecordKeyIdentifier);
            allWinnerIds = new HashSet<string>(allWinnerData.Keys, StringComparer.InvariantCultureIgnoreCase);
            allLoserData = MakeRecordDictionary(mergeOrder.EventListener, mergeStrategy,
                                                pathToLoser, optionalFirstElementMarker, repeatingRecordElementName,
                                                repeatingRecordKeyIdentifier);
            allLoserIds = new HashSet<string>(allLoserData.Keys, StringComparer.InvariantCultureIgnoreCase);
        }
Esempio n. 36
0
        private static HashSet<string> CollectDataAndReportAllConflicts(MergeOrder mergeOrder, IMergeStrategy mergeStrategy,
																		string winnerId, string loserId,
																		IEnumerable<string> allLoserIds,
																		IDictionary<string, string> allWinnerData,
																		IEnumerable<string> allIdsRemovedByWinner,
																		IEnumerable<string> allIdsRemovedByLoser,
																		HashSet<string> allCommonAncestorIds,
																		IDictionary<string, string> allCommonAncestorData,
																		IDictionary<string, XmlNode> fluffedUpLoserNodes,
																		IEnumerable<string> allWinnerIds,
																		IDictionary<string, string> allLoserData,
																		IDictionary<string, XmlNode> fluffedUpWinnerNodes,
																		IDictionary<string, XmlNode> fluffedUpAncestorNodes,
																		string pathToWinner,
																		string pathToLoser,
																		out HashSet<string>
																			allDeletedByLoserButEditedByWinnerIds,
																		out HashSet<string>
																			allDeletedByWinnerButEditedByLoserIds)
        {
            HashSet<string> allIdsForUniqueLoserChanges;
            HashSet<string> allIdsWinnerModified;
            var allIdsLoserModified = CollectDataAndReportNormalEditConflicts(mergeOrder, mergeStrategy, fluffedUpLoserNodes,
                                                                              allCommonAncestorData,
                                                                              fluffedUpAncestorNodes, fluffedUpWinnerNodes,
                                                                              allLoserData, allWinnerData, allWinnerIds,
                                                                              allLoserIds, allCommonAncestorIds,
                                                                              out allIdsForUniqueLoserChanges,
                                                                              out allIdsWinnerModified);

            // Step 5. Collect up items modified by one user, but deleted by the other.
            CollectIdsOfEditVsDelete(allIdsRemovedByLoser, allIdsWinnerModified, allIdsLoserModified, allIdsRemovedByWinner,
                                     out allDeletedByWinnerButEditedByLoserIds, out allDeletedByLoserButEditedByWinnerIds);
            allIdsWinnerModified.Clear();
            allIdsLoserModified.Clear();

            // Step 6. Do merging and report conflicts.
            ReportDeleteVsEditConflicts(mergeOrder, mergeStrategy,
                                        fluffedUpLoserNodes, allLoserData, loserId, allDeletedByWinnerButEditedByLoserIds,
                                        allCommonAncestorData, fluffedUpAncestorNodes, pathToLoser);
            ReportEditVsDeleteConflicts(mergeOrder, mergeStrategy,
                                        fluffedUpWinnerNodes, allWinnerData, winnerId, allDeletedByLoserButEditedByWinnerIds,
                                        allCommonAncestorData, fluffedUpAncestorNodes, pathToWinner);

            return allIdsForUniqueLoserChanges;
        }
Esempio n. 37
0
 /// <summary>
 /// Here, "alpha" is the guy who wins when there's no better way to decide, and "beta" is the loser.
 /// </summary>
 public LiftMerger(IMergeStrategy mergeStrategy, string alphaLiftPath, string betaLiftPath, string ancestorLiftPath)
     : this(File.ReadAllText(alphaLiftPath), File.ReadAllText(betaLiftPath), File.ReadAllText(ancestorLiftPath), mergeStrategy)
 {
 }
        public void MergeFromMetaData(IFullAlbumDescriptor iad, IMergeStrategy Strategy)
        {
            if (Strategy.AlbumMetaData != IndividualMergeStategy.Never)
            {
                if ((Year == 0) || Strategy.AlbumMetaData == IndividualMergeStategy.Always)
                    Year = iad.Year;

                if (string.IsNullOrEmpty(Name) || Strategy.AlbumMetaData == IndividualMergeStategy.Always)
                    Name = iad.Name;

                if ((_Artists.MofifiableCollection.Count == 0) || (Strategy.AlbumMetaData == IndividualMergeStategy.Always))
                {
                    _Artists.MofifiableCollection.Clear();
                    _Artists.MofifiableCollection.AddCollection(this._IT.GetArtistFromName(iad.Artist));
                }

                if ((string.IsNullOrEmpty(Genre)) || (Strategy.AlbumMetaData == IndividualMergeStategy.Always))
                    Genre = iad.Genre;
            }

            if ((Strategy.InjectAlbumImage == IndividualMergeStategy.Always) || ((Strategy.InjectAlbumImage == IndividualMergeStategy.IfDummyValue) && Images.Count == 0))
            {
                int i = 0;
                if (iad.Images != null)
                {
                    foreach (IIMageInfo Im in iad.Images)
                    {
                        if (AddImage(AlbumImage.GetFromBuffer(_AM, Im.ImageBuffer), i) != null)
                            i++;
                    }
                }
            }

            if (Strategy.TrackMetaData == IndividualMergeStategy.Never)
                return;

            //var OrderedTracksInput = (from r in iad.TrackDescriptors orderby r.Duration.TotalMilliseconds ascending select r).ToList();
            //var OrderedTracks = (from r in Tracks orderby r.Duration.TotalMilliseconds ascending select r).ToList();

            var OrderedTracksInput = iad.TrackDescriptors.OrderBy(r => r.DiscNumber).ThenBy(r=>r.TrackNumber).ToList();
            var OrderedTracks = Tracks.OrderBy(r => r.DiscNumber).ThenBy(r=>r.TrackNumber).ToList();

            if (OrderedTracksInput.Count != OrderedTracks.Count)
                return;

            int j = 0;

            foreach (IModifiableTrack INT in OrderedTracks)
            {
                ITrackMetaDataDescriptor Tr = OrderedTracksInput[j++];

                if ((Strategy.TrackMetaData == IndividualMergeStategy.Always) || (new StringTrackParser(INT.Name, false).IsDummy))
                    INT.Name = Tr.Name;

                if ((Strategy.TrackMetaData == IndividualMergeStategy.Always) || string.IsNullOrEmpty(INT.Artist))
                    INT.Artist = Tr.Artist;

                if ((Strategy.TrackMetaData == IndividualMergeStategy.Always) || (INT.TrackNumber == 0))
                    INT.TrackNumber = Tr.TrackNumber;

                TimeSpan delta = (Tr.Duration - INT.Duration);
                Trace.WriteLine(delta);
            }
        }
Esempio n. 39
0
        private static IEnumerable<string> CollectDataAndReportEditConflictsForBothAddedNewObjectsWithDifferentContent(
			MergeOrder mergeOrder, IMergeStrategy mergeStrategy, string pathToWinner,
			IDictionary<string, XmlNode> fluffedUpWinnerNodes,
			IDictionary<string, XmlNode> fluffedUpLoserNodes, HashSet<string> allCommonAncestorIds,
			IEnumerable<string> allWinnerIds, IDictionary<string, string> allWinnerData,
			IDictionary<string, string> allLoserData, IEnumerable<string> allLoserIds)
        {
            HashSet<string> allNewIdsFromBoth;
            HashSet<string> allNewIdsFromBothWithSameData;
            CollectNewItemsFromWinnerAndLoser(allWinnerData, allWinnerIds, allLoserIds, allLoserData, allCommonAncestorIds,
                                              out allNewIdsFromBoth, out allNewIdsFromBothWithSameData, fluffedUpLoserNodes,
                                              fluffedUpWinnerNodes);
            ReportEditConflictsForBothAddedNewObjectsWithDifferentContent(mergeOrder, mergeStrategy, pathToWinner,
                                                                          allLoserData, fluffedUpLoserNodes,
                                                                          allNewIdsFromBothWithSameData, allNewIdsFromBoth,
                                                                          allWinnerData, fluffedUpWinnerNodes);
            return allNewIdsFromBoth;
        }