private void detectVCContentConflict() { foreach (var conflictedActionPairs in TargetChangeGroupService.DetectContentConflict()) { List <MigrationAction> resultMigrationActions; MigrationConflict contentConflict; if (conflictedActionPairs.Value.Action == WellKnownChangeActionId.Edit && conflictedActionPairs.Key.Action == WellKnownChangeActionId.Edit) { contentConflict = VCContentConflictType.CreateConflict(conflictedActionPairs.Key, conflictedActionPairs.Value); } else { contentConflict = VCNameSpaceContentConflictType.CreateConflict(conflictedActionPairs.Key); } var resolutionRslt = ConflictManager.TryResolveNewConflict(TargetSystemId, contentConflict, out resultMigrationActions); if (!resolutionRslt.Resolved) { int contentConflictId = contentConflict.InternalId; MigrationConflict chainOnConflictConflict = new MigrationConflict( new ChainOnConflictConflictType(), MigrationConflict.Status.Unresolved, ChainOnConflictConflictType.CreateConflictDetails(contentConflictId), ChainOnConflictConflictType.CreateScopeHint(contentConflictId)); chainOnConflictConflict.ConflictedChangeAction = conflictedActionPairs.Value; ConflictManager.BacklogUnresolvedConflict(TargetSystemId, chainOnConflictConflict, false); } } }
private bool TargetDeltaContainsMappedItem() { int pageNumber = 0; int pageSize = 50; IEnumerable <ChangeGroup> changeGroups = TargetChangeGroupService.NextDeltaTablePage(pageNumber++, pageSize, true); if (changeGroups.Count() == 0) { return(false); } do { foreach (ChangeGroup changeGroupEntry in changeGroups) { foreach (MigrationAction action in changeGroupEntry.Actions) { if (action.Action == WellKnownChangeActionId.Edit || action.Action == WellKnownChangeActionId.AddAttachment || action.Action == WellKnownChangeActionId.DelAttachment) { string targetWorkItemId = GetSourceWorkItemIdFromActionDescription(action.MigrationActionDescription); string sourceWorkItemId = TranslationService.TryGetTargetItemId(targetWorkItemId, TargetSystemId); if (!string.IsNullOrEmpty(sourceWorkItemId)) { return(true); } } } } changeGroups = TargetChangeGroupService.NextDeltaTablePage(pageNumber++, pageSize, true); }while (changeGroups.Count() > 0); return(false); }
private void FlattenDeltaTable( List <string> outMappedWorkItemUpdates, Dictionary <string, List <MigrationAction> > outMappedAttachmentUpdates, bool getSourceSideCopyInMigrationInstructionTable) { Guid sourceId = getSourceSideCopyInMigrationInstructionTable ? SourceSystemId : TargetSystemId; Guid targetId = getSourceSideCopyInMigrationInstructionTable ? TargetSystemId : SourceSystemId; int pageNumber = 0; int pageSize = 50; IEnumerable <ChangeGroup> changeGroups = null; do { changeGroups = getSourceSideCopyInMigrationInstructionTable ? TargetChangeGroupService.NextMigrationInstructionTablePage(pageNumber++, pageSize, true, true) : TargetChangeGroupService.NextDeltaTablePage(pageNumber++, pageSize, true); foreach (ChangeGroup changeGroupEntry in changeGroups) { foreach (MigrationAction action in changeGroupEntry.Actions) { if (action.Action.Equals(WellKnownChangeActionId.SyncContext)) { continue; } else if (action.Action == WellKnownChangeActionId.Add) { // do nothing for adding item, be it created by sync engine or not continue; } else if (action.Action == WellKnownChangeActionId.Edit) { string sourceSideItemId = GetSourceWorkItemIdFromActionDescription(action.MigrationActionDescription); string targetWorkItemId = TryGetTargetWorkItemId( action.MigrationActionDescription, sourceId, getSourceSideCopyInMigrationInstructionTable); if (string.IsNullOrEmpty(targetWorkItemId)) { // the source work item has never been migrated yet continue; } if (getSourceSideCopyInMigrationInstructionTable) { if (ConflictManager.IsItemInBacklog(sourceId, targetId, sourceSideItemId)) { // previous revision of the work item has conflict, push this revision to backlog as well string conflictDetails = ChainOnBackloggedItemConflictType.CreateConflictDetails(sourceSideItemId, action.Version); string scopeHint = ChainOnBackloggedItemConflictType.CreateScopeHint(sourceSideItemId); if (changeGroupEntry.ReflectedChangeGroupId.HasValue) { // we reactivate the original delta entry and discard this migration instruction entry // and then backlog the delta entry, to preserve correct order of the revisions ChangeGroup deltaChangeGroupEntry = TargetChangeGroupService.ReactivateDeltaEntry(changeGroupEntry); if (null != deltaChangeGroupEntry) { MigrationConflict chainedConflict = new ChainOnBackloggedItemConflictType().CreateConflict( conflictDetails, scopeHint, deltaChangeGroupEntry.Actions.First()); ConflictManager.BacklogUnresolvedConflict(ConflictManager.SourceId, chainedConflict, false); break; } } // if we can't find the original delta entry successfully, we block this migration instruction entry MigrationConflict conflict = new ChainOnBackloggedItemConflictType().CreateConflict( conflictDetails, scopeHint, action); ConflictManager.BacklogUnresolvedConflict(ConflictManager.SourceId, conflict, false); if (!m_conflictedWorkItems[targetId].Contains(targetWorkItemId)) { // record the target-side work item to be in conflict m_conflictedWorkItems[targetId].Add(targetWorkItemId); } break; } if (!m_perMappedItemEdits.ContainsKey(m_targetToSourceWorkItemIdMapping[targetWorkItemId])) { m_perMappedItemEdits.Add(m_targetToSourceWorkItemIdMapping[targetWorkItemId], new List <MigrationAction>()); } m_perMappedItemEdits[m_targetToSourceWorkItemIdMapping[targetWorkItemId]].Add(action); } else { // check if the revision is a sync copy from the other side if (TranslationService.IsSyncGeneratedAction(action, sourceId)) { continue; } if (m_conflictedWorkItems[sourceId].Contains(sourceSideItemId)) { string conflictDetails = ChainOnBackloggedItemConflictType.CreateConflictDetails(sourceSideItemId, action.Version); string scopeHint = ChainOnBackloggedItemConflictType.CreateScopeHint(sourceSideItemId); MigrationConflict conflict = new ChainOnBackloggedItemConflictType().CreateConflict( conflictDetails, scopeHint, action); ConflictManager.BacklogUnresolvedConflict(TargetSystemId, conflict, false); break; } if (!m_perMappedItemEditsTargetDelta.ContainsKey(targetWorkItemId)) { m_perMappedItemEditsTargetDelta.Add(targetWorkItemId, new List <MigrationAction>()); } m_perMappedItemEditsTargetDelta[targetWorkItemId].Add(action); } // item is mapped to an item on target system if (!outMappedWorkItemUpdates.Contains(targetWorkItemId)) { outMappedWorkItemUpdates.Add(targetWorkItemId); } } else if (action.Action == WellKnownChangeActionId.AddAttachment) { string targetWorkItemId = TryGetTargetWorkItemId( action.MigrationActionDescription, sourceId, getSourceSideCopyInMigrationInstructionTable); if (string.IsNullOrEmpty(targetWorkItemId)) { continue; } if (!outMappedAttachmentUpdates.ContainsKey(targetWorkItemId)) { outMappedAttachmentUpdates.Add(targetWorkItemId, new List <MigrationAction>()); } List <MigrationAction> attachmentList = outMappedAttachmentUpdates[targetWorkItemId]; IMigrationFileAttachment sourceItem = action.SourceItem as IMigrationFileAttachment; if (null == sourceItem) { throw new MigrationException(MigrationToolkitResources.InvalidSourceItemForAttachmentOperation); } if (!attachmentList.Contains(action)) { attachmentList.Add(action); } } else if (action.Action == WellKnownChangeActionId.DelAttachment) { // do nothing for now continue; } } } }while (changeGroups.Count() > 0); }
private void TryResolvePerWorkItemConflicts( string targetWiId) { string sourceSideItemId = m_targetToSourceWorkItemIdMapping[targetWiId]; TraceManager.TraceInformation("Edit/Edit conflicted work item: {0}", sourceSideItemId); int editeditConflictId = int.MinValue; bool previousConflictIsResolved = true; foreach (var migrInstrActionFromSource in m_perMappedItemEdits[sourceSideItemId]) { if (!previousConflictIsResolved) { // previous revision of the work item has conflict, push *this revision to backlog as well // *: this revision (migration instruction) will be obsoleted and the corresponding delta entry reactived ChangeGroup migrationInstructionEntry = migrInstrActionFromSource.ChangeGroup; ChangeGroup entryToBlock = null; if (migrationInstructionEntry.ReflectedChangeGroupId.HasValue) { entryToBlock = TargetChangeGroupService.ReactivateDeltaEntry(migrationInstructionEntry); } if (entryToBlock == null) { entryToBlock = migrationInstructionEntry; } if (entryToBlock.Actions.Count <= 0) { continue; } // an edit/edit conflict must have been backlogged already Debug.Assert(editeditConflictId != int.MinValue, "Edit/edit conflict Id is not available"); string conflictDetails = ChainOnBackloggedItemConflictType.CreateConflictDetails(sourceSideItemId, migrInstrActionFromSource.Version); string scopeHint = ChainOnBackloggedItemConflictType.CreateScopeHint(sourceSideItemId); MigrationConflict chainedConflict = new ChainOnBackloggedItemConflictType().CreateConflict(conflictDetails, scopeHint, entryToBlock.Actions.First()); ConflictManager.BacklogUnresolvedConflict(ConflictManager.SourceId, chainedConflict, false); } else { ChangeGroup sourceGroupForResolution = null; if (migrInstrActionFromSource.ChangeGroup.ReflectedChangeGroupId.HasValue) { sourceGroupForResolution = TargetChangeGroupService.ReactivateDeltaEntry(migrInstrActionFromSource.ChangeGroup); } if (sourceGroupForResolution == null) { sourceGroupForResolution = migrInstrActionFromSource.ChangeGroup; } ConflictResolutionResult resolutionResult = TryResolveSingleRevConflict(sourceSideItemId, sourceGroupForResolution.Actions.First(), targetWiId, m_perMappedItemEditsTargetDelta[targetWiId]); previousConflictIsResolved = resolutionResult.Resolved; if (previousConflictIsResolved) { // conflict is auto-resolved, // obsolete the reactivated delta entry and reactivate the migration instruction if (sourceGroupForResolution.Status != ChangeStatus.Skipped && sourceGroupForResolution != migrInstrActionFromSource.ChangeGroup) { TargetChangeGroupService.ReactivateMigrationInstruction(migrInstrActionFromSource.ChangeGroup, sourceGroupForResolution); } continue; } else { // save the persisted unresolved conflict id, so that the following changes can "chain-on" it editeditConflictId = resolutionResult.ConflictInternalId; } } } if (!previousConflictIsResolved) { bool chainOnBackloggedItemConflictIsCreated = false; foreach (var targetAction in m_perMappedItemEditsTargetDelta[targetWiId]) { Debug.Assert(editeditConflictId != int.MinValue, "Edit/edit conflict Id is not available"); MigrationConflict chainedConflict = new ChainOnConflictConflictType().CreateConflict( ChainOnConflictConflictType.CreateConflictDetails(editeditConflictId), ChainOnConflictConflictType.CreateScopeHint(editeditConflictId), targetAction); // action is from the target system, use the TargetSystem migration source Id ConflictManager.BacklogUnresolvedConflict(TargetSystemId, chainedConflict, false); if (!chainOnBackloggedItemConflictIsCreated) { string conflictDetails = ChainOnBackloggedItemConflictType.CreateConflictDetails(targetWiId, targetAction.Version); string scopeHint = ChainOnBackloggedItemConflictType.CreateScopeHint(sourceSideItemId); MigrationConflict conflict = new ChainOnBackloggedItemConflictType().CreateConflict(conflictDetails, scopeHint, targetAction); ConflictManager.BacklogUnresolvedConflict(TargetSystemId, conflict, false); chainOnBackloggedItemConflictIsCreated = true; } } } }