Exemplo n.º 1
0
        private void MarkLinkChangeActionCompleted(LinkChangeAction action, WorkItemLinkStore relatedArtifactsStore)
        {
            if (action.Status == LinkChangeAction.LinkChangeActionStatus.ReadyForMigration)
            {
                action.Status = LinkChangeAction.LinkChangeActionStatus.Completed;
            }

            var actions = new List <LinkChangeAction>();

            actions.Add(action);
            relatedArtifactsStore.UpdateSyncedLinks(actions);
        }
        protected bool SubmitNonWorkItemLinkChanges(
            LinkChangeGroup linkChanges,
            ServiceContainer serviceContainer,
            ConfigurationService configService,
            ITranslationService translationService,
            TfsLinkingProviderBase.LinkSubmissionPhase submissionPhase)
        {
            // group non-WorkItemLink changes by work item Id
            Dictionary <int, List <LinkChangeAction> > perWorkItemLinkChanges = RegroupLinkChangeActions(linkChanges);
            var orderedWorkitemId = new Dictionary <int, int>();
            int index             = 0;

            foreach (int workItemId in perWorkItemLinkChanges.Keys)
            {
                orderedWorkitemId.Add(index++, workItemId);
            }

            // batch-submit links of each work item
            var updateDocs = new List <XmlDocument>(perWorkItemLinkChanges.Count);

            foreach (var perWorkItemLinkChange in perWorkItemLinkChanges)
            {
                if (perWorkItemLinkChange.Value.Count == 0)
                {
                    continue;
                }

                WorkItem workItem = WorkItemStore.GetWorkItem(perWorkItemLinkChange.Key);

                var tfsUpdateDocument = InitializeUpdateDocument();
                tfsUpdateDocument.CreateWorkItemUpdateDoc(workItem);
                bool hasNonWorkItemLinkChanges = false;
                foreach (LinkChangeAction linkChangeAction in perWorkItemLinkChange.Value)
                {
                    if (linkChangeAction.Status != LinkChangeAction.LinkChangeActionStatus.ReadyForMigration ||
                        linkChangeAction.IsConflicted ||
                        linkChangeAction.Link.LinkType is WorkItemLinkTypeBase)
                    {
                        continue;
                    }

                    if (!ProcessActionInCurrentSubmissionPhase(linkChangeAction, submissionPhase))
                    {
                        continue;
                    }

                    hasNonWorkItemLinkChanges = true;
                    var handler = linkChangeAction.Link.LinkType as ILinkHandler;
                    Debug.Assert(null != handler);
                    handler.UpdateTfs(tfsUpdateDocument, linkChangeAction);
                }

                if (hasNonWorkItemLinkChanges)
                {
                    updateDocs.Add(tfsUpdateDocument.UpdateDocument);
                }
            }

            if (updateDocs.Count == 0)
            {
                return(true);
            }

            UpdateResult[] results = TfsBatchUpdateHelper.Submit(Core, WorkItemServer, updateDocs.ToArray());

            if (results.Length != updateDocs.Count)
            {
                throw new SynchronizationEngineException("Wrong number of link update results.");
            }

            bool succeeded = true;

            for (int i = 0; i < results.Length; ++i)
            {
                UpdateResult rslt = results[i];

                if (rslt.Exception != null &&
                    !rslt.Exception.Message.Contains("The specified link already exists"))
                {
                    TraceManager.TraceError(rslt.Exception.ToString());
                    succeeded = false;
                    // TODO
                    // Try resolve conflict and push to backlog if resolution fails
                    foreach (LinkChangeAction action in perWorkItemLinkChanges[orderedWorkitemId[i]])
                    {
                        action.IsConflicted = true;
                    }
                }
                else
                {
                    foreach (LinkChangeAction action in perWorkItemLinkChanges[orderedWorkitemId[i]])
                    {
                        if (ProcessActionInCurrentSubmissionPhase(action, submissionPhase))
                        {
                            MarkLinkChangeActionCompleted(action);
                        }
                    }

                    if (rslt.Exception == null)
                    {
                        UpdateLinkConversionHistory(configService, translationService, rslt, perWorkItemLinkChanges[orderedWorkitemId[i]]);
                    }
                    else if (rslt.Exception.Message.Contains("The specified link already exists"))
                    {
                        WorkItemLinkStore relatedArtifactsStore = new WorkItemLinkStore(configService.SourceId);
                        relatedArtifactsStore.UpdateSyncedLinks(perWorkItemLinkChanges[orderedWorkitemId[i]]);
                    }
                }
            }
            return(succeeded);
        }
Exemplo n.º 3
0
        private bool SubmitBatchedAddOrDeleteLinkChanges(
            List <XmlDocument> updateDocuments,
            Dictionary <int, LinkChangeAction> updateDocIndexToLinkChangeActionMap,
            ITranslationService translationService,
            ConfigurationService configService,
            ConflictManager conflictManager)
        {
            bool succeeded = true;

            UpdateResult[] results = TfsBatchUpdateHelper.Submit(Core, WorkItemServer, updateDocuments.ToArray());
            if (results.Length != updateDocuments.Count)
            {
                throw new SynchronizationEngineException("Wrong number of link update results.");
            }

            for (int i = 0; i < results.Length; ++i)
            {
                UpdateResult rslt = results[i];

                if (rslt.Exception != null)
                {
                    if (rslt.Exception.Message.Contains("The specified link already exists"))
                    {
                        // it is ok to eat this exception
                    }
                    else if (rslt.Exception is System.Web.Services.Protocols.SoapException &&
                             null != rslt.Exception.Message &&
                             rslt.Exception.Message.StartsWith(
                                 TFSMulitpleParentLinkConflictType.SingleParentViolationMessage,
                                 StringComparison.OrdinalIgnoreCase))
                    {
                        MigrationConflict conflict = TFSMulitpleParentLinkConflictType.CreateConflict(
                            updateDocIndexToLinkChangeActionMap[i], rslt.Exception);

                        List <MigrationAction> actions;
                        var resolutionRslt = conflictManager.TryResolveNewConflict(conflictManager.SourceId, conflict, out actions);
                        if (!resolutionRslt.Resolved)
                        {
                            updateDocIndexToLinkChangeActionMap[i].IsConflicted = true;
                            succeeded = false;
                        }
                    }
                    else if (rslt.Exception is System.Web.Services.Protocols.SoapException &&
                             null != rslt.Exception.Message &&
                             rslt.Exception.Message.StartsWith(
                                 TFSCyclicLinkConflictType.CircularityLinkHierarchyViolationMessage,
                                 StringComparison.OrdinalIgnoreCase))
                    {
                        ILinkProvider linkProvider = ServiceContainer.GetService(typeof(ILinkProvider)) as ILinkProvider;
                        Debug.Assert(null != linkProvider, "linkProvider is NULL");

                        LinkChangeAction          conflictedAction = updateDocIndexToLinkChangeActionMap[i];
                        NonCyclicReferenceClosure linkRefClosure   =
                            linkProvider.CreateNonCyclicLinkReferenceClosure(conflictedAction.Link.LinkType, conflictedAction.Link.SourceArtifact);

                        MigrationConflict conflict = TFSCyclicLinkConflictType.CreateConflict(conflictedAction, rslt.Exception, linkRefClosure);

                        List <MigrationAction> actions;
                        var resolutionRslt = conflictManager.TryResolveNewConflict(conflictManager.SourceId, conflict, out actions);
                        if (!resolutionRslt.Resolved)
                        {
                            updateDocIndexToLinkChangeActionMap[i].IsConflicted = true;
                            succeeded = false;
                        }
                    }
                    else if (rslt.Exception is System.Web.Services.Protocols.SoapException &&
                             null != rslt.Exception.Message &&
                             rslt.Exception.Message.StartsWith(
                                 TFSModifyLockedWorkItemLinkConflictType.ModifyLockedWorkItemLinkViolationMessage,
                                 StringComparison.OrdinalIgnoreCase))
                    {
                        MigrationConflict conflict = TFSModifyLockedWorkItemLinkConflictType.CreateConflict(
                            updateDocIndexToLinkChangeActionMap[i], rslt.Exception);

                        List <MigrationAction> actions;
                        var resolutionRslt = conflictManager.TryResolveNewConflict(conflictManager.SourceId, conflict, out actions);
                        if (!resolutionRslt.Resolved)
                        {
                            updateDocIndexToLinkChangeActionMap[i].IsConflicted = true;
                        }
                        // returning "not succeeded" so that the caller keeps this change group in "ReadyForMigration" status
                        succeeded = false;
                    }
                    else if (rslt.Exception is System.Web.Services.Protocols.SoapException &&
                             null != rslt.Exception.Message &&
                             (rslt.Exception.Message.StartsWith(TFSLinkAccessViolationConflictType.LinkAccessViolationMessage1, StringComparison.OrdinalIgnoreCase) ||
                              rslt.Exception.Message.StartsWith(TFSLinkAccessViolationConflictType.LinkAccessViolationMessage2, StringComparison.OrdinalIgnoreCase)))
                    {
                        MigrationConflict conflict = TFSLinkAccessViolationConflictType.CreateConflict(
                            updateDocIndexToLinkChangeActionMap[i], rslt.Exception);

                        List <MigrationAction> actions;
                        var resolutionRslt = conflictManager.TryResolveNewConflict(conflictManager.SourceId, conflict, out actions);
                        if (!resolutionRslt.Resolved)
                        {
                            updateDocIndexToLinkChangeActionMap[i].IsConflicted = true;
                        }
                        // returning "not succeeded" so that the caller keeps this change group in "ReadyForMigration" status
                        succeeded = false;
                    }
                    else
                    {
                        TraceManager.TraceError(rslt.Exception.ToString());
                        succeeded = false;
                        // TODO
                        // Try resolve conflict and push to backlog if resolution fails
                        updateDocIndexToLinkChangeActionMap[i].IsConflicted = true;
                    }
                }
                else
                {
                    foreach (LinkChangeAction action in updateDocIndexToLinkChangeActionMap.Values)
                    {
                        MarkLinkChangeActionCompleted(action);
                    }

                    List <LinkChangeAction> updatedActions = new List <LinkChangeAction>(updateDocIndexToLinkChangeActionMap.Values);
                    if (rslt.Exception == null)
                    {
                        UpdateLinkConversionHistory(configService, translationService, rslt, updatedActions);
                    }
                    else if (rslt.Exception.Message.Contains("The specified link already exists"))
                    {
                        WorkItemLinkStore relatedArtifactsStore = new WorkItemLinkStore(configService.SourceId);
                        relatedArtifactsStore.UpdateSyncedLinks(updatedActions);
                    }
                }
            }
            return(succeeded);
        }