private int GetLowerWorkItemId(LinkChangeAction action)
        {
            int sourceId = int.Parse(action.Link.SourceArtifactId);
            int targetId = int.Parse(TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri));

            return(Math.Min(sourceId, targetId));
        }
コード例 #2
0
        private static void ParseException(
            Exception linkSubmissionException,
            LinkChangeAction action,
            out string sourceItem,
            out string targetItem, out string linkType)
        {
            /*
             * Example Exception:
             * System.Web.Services.Protocols.SoapException
             *
             * Example Message
             * AddLink: The specified link type enforces noncircularity in its hierarchy.
             * The target work item is ancestor of the source work item and cannot be its child: %SourceID="960";%, %TargetID="962";%, %LinkType="2";%
             * ---> AddLink: The specified link type enforces noncircularity in its hierarchy. The target work item is ancestor of the source work item
             * and cannot be its child: %SourceID="960";%, %TargetID="962";%, %LinkType="2";%
             */
            Debug.Assert(linkSubmissionException is System.Web.Services.Protocols.SoapException,
                         "linkSubmissionException is not System.Web.Services.Protocols.SoapException");
            Debug.Assert(!string.IsNullOrEmpty(linkSubmissionException.Message), "linkSubmissionException.Message is null or empty");
            Debug.Assert(linkSubmissionException.Message.StartsWith(CircularityLinkHierarchyViolationMessage, StringComparison.OrdinalIgnoreCase),
                         string.Format("linkSubmissionException.Message does not start with '{0}'", CircularityLinkHierarchyViolationMessage));

            sourceItem = action.Link.SourceArtifactId;
            targetItem = TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri);
            linkType   = action.Link.LinkType.ReferenceName;
        }
        private static void ParseExceptionMessage(Exception linkSubmissionException, LinkChangeAction action, out string scopeHint, out string conflictDetails)
        {
            /*
             * Example Exception:
             * System.Web.Services.Protocols.SoapException
             *
             * Example Message
             * AddLink: The specified link type requires that work items have a single parent.
             * The target work item already has a parent of that type: %SourceID="969";%, %TargetID="967";%, %LinkType="2";%
             * ---> AddLink: The specified link type requires that work items have a single parent. The target work item already
             * has a parent of that type: %SourceID="969";%, %TargetID="967";%, %LinkType="2";%
             */
            Debug.Assert(linkSubmissionException is System.Web.Services.Protocols.SoapException,
                         "linkSubmissionException is not System.Web.Services.Protocols.SoapException");
            Debug.Assert(!string.IsNullOrEmpty(linkSubmissionException.Message), "linkSubmissionException.Message is null or empty");
            Debug.Assert(linkSubmissionException.Message.StartsWith(SingleParentViolationMessage, StringComparison.OrdinalIgnoreCase),
                         string.Format("linkSubmissionException.Message does not start with '{0}'", SingleParentViolationMessage));

            string sourceItem = action.Link.SourceArtifactId;
            string targetItem = TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri);
            string linkType   = action.Link.LinkType.ReferenceName;

            scopeHint       = string.Format("/{0}/{1}/{2}", linkType, sourceItem, targetItem);
            conflictDetails = InvalidWorkItemLinkDetails.CreateConflictDetails(sourceItem, targetItem, linkType);
        }
コード例 #4
0
        private static void ParseExceptionMessage(
            Exception linkSubmissionException,
            LinkChangeAction action,
            out string scopeHint,
            out string conflictDetails)
        {
            /*
             * Example Exception:
             * System.Web.Services.Protocols.SoapException
             *
             * Example Message
             * Failed to modify links. The following linked work items have been locked by an administrator:
             * %LinkFailures="1954;1955;2;2,";% ---> Failed to modify links. The following linked work items
             * have been locked by an administrator: %LinkFailures="1954;1955;2;2,";%
             */
            Debug.Assert(linkSubmissionException is System.Web.Services.Protocols.SoapException,
                         "linkSubmissionException is not System.Web.Services.Protocols.SoapException");
            Debug.Assert(!string.IsNullOrEmpty(linkSubmissionException.Message), "linkSubmissionException.Message is null or empty");
            Debug.Assert(linkSubmissionException.Message.StartsWith(ModifyLockedWorkItemLinkViolationMessage, StringComparison.OrdinalIgnoreCase),
                         string.Format("linkSubmissionException.Message does not start with '{0}'", ModifyLockedWorkItemLinkViolationMessage));

            string sourceItem = action.Link.SourceArtifactId;
            string targetItem = TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri);
            string linkType   = action.Link.LinkType.ReferenceName;

            scopeHint       = string.Format("/{0}/{1}/{2}", linkType, sourceItem, targetItem);
            conflictDetails = InvalidWorkItemLinkDetails.CreateConflictDetails(sourceItem, targetItem, linkType);
        }
コード例 #5
0
        private static void ParseExceptionMessage(
            Exception linkSubmissionException,
            LinkChangeAction action,
            out string scopeHint,
            out string conflictDetails)
        {
            Debug.Assert(linkSubmissionException is System.Web.Services.Protocols.SoapException,
                         "linkSubmissionException is not System.Web.Services.Protocols.SoapException");

            string sourceItem = action.Link.SourceArtifactId;
            string targetItem = TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri);
            string linkType   = action.Link.LinkType.ReferenceName;

            scopeHint       = string.Format("/{0}/{1}/{2}", linkType, sourceItem, targetItem);
            conflictDetails = InvalidWorkItemLinkDetails.CreateConflictDetails(sourceItem, targetItem, linkType);
        }
コード例 #6
0
        public CyclicLinkConflictDetails(
            string sourceItemId,
            string targetItemId,
            string linkTypeReferenceName,
            NonCyclicReferenceClosure linkReferenceClosure)
            : base(sourceItemId, targetItemId, linkTypeReferenceName)
        {
            LinkReferenceClosure = new List <LinkDescription>();

            if (null != linkReferenceClosure)
            {
                foreach (var link in linkReferenceClosure.Links)
                {
                    LinkReferenceClosure.Add(
                        new LinkDescription(link.SourceArtifactId, TfsWorkItemHandler.IdFromUri(link.TargetArtifact.Uri)));
                }
            }
        }
        private static void ParseExceptionMessage(
            Exception linkSubmissionException,
            LinkChangeAction action,
            out string scopeHint,
            out string conflictDetails)
        {
            Debug.Assert(linkSubmissionException is System.Web.Services.Protocols.SoapException,
                         "linkSubmissionException is not System.Web.Services.Protocols.SoapException");
            Debug.Assert(!string.IsNullOrEmpty(linkSubmissionException.Message), "linkSubmissionException.Message is null or empty");
            Debug.Assert(
                linkSubmissionException.Message.StartsWith(LinkAccessViolationMessage1, StringComparison.OrdinalIgnoreCase) ||
                linkSubmissionException.Message.StartsWith(LinkAccessViolationMessage2, StringComparison.OrdinalIgnoreCase),
                string.Format("linkSubmissionException.Message does not start with '{0}' or '{1}'",
                              LinkAccessViolationMessage1, LinkAccessViolationMessage2));

            string sourceItem = action.Link.SourceArtifactId;
            string targetItem = TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri);
            string linkType   = action.Link.LinkType.ReferenceName;

            scopeHint       = string.Format("/{0}/{1}/{2}", linkType, sourceItem, targetItem);
            conflictDetails = InvalidWorkItemLinkDetails.CreateConflictDetails(sourceItem, targetItem, linkType);
        }
コード例 #8
0
        private static void ParseException(
            Exception linkSubmissionException,
            LinkChangeAction action,
            out string sourceItem,
            out string targetItem, out string linkType)
        {
            /*
             * Example Exception:
             * System.Web.Services.Protocols.SoapException
             *
             * Example Message
             * AddLink: The specified link type enforces noncircularity in its hierarchy.
             * The target work item is ancestor of the source work item and cannot be its child: %SourceID="960";%, %TargetID="962";%, %LinkType="2";%
             * ---> AddLink: The specified link type enforces noncircularity in its hierarchy. The target work item is ancestor of the source work item
             * and cannot be its child: %SourceID="960";%, %TargetID="962";%, %LinkType="2";%
             */
            Debug.Assert(linkSubmissionException is System.Web.Services.Protocols.SoapException,
                         "linkSubmissionException is not System.Web.Services.Protocols.SoapException");

            sourceItem = action.Link.SourceArtifactId;
            targetItem = TfsWorkItemHandler.IdFromUri(action.Link.TargetArtifact.Uri);
            linkType   = action.Link.LinkType.ReferenceName;
        }
        private bool LinkChangeMatchesLinkAction(WorkItemLinkChange linkChange, LinkChangeAction linkChangeAction)
        {
            // bool actionIsAdd = (linkChangeAction.ChangeActionId == WellKnownChangeActionId.Add);
            if (// Don't match on Add/Delete against IsActive because GetWorkItemLinkChanges() combines add/delete and IsActive is just latest status:
                // actionIsAdd == linkChange.IsActive &&
                string.Equals(linkChange.LinkType, linkChangeAction.Link.LinkType.ReferenceName, StringComparison.Ordinal))
            {
                string linkActionTargetIdString = TfsWorkItemHandler.IdFromUri(linkChangeAction.Link.TargetArtifact.Uri);

                if (string.Equals(linkChange.SourceID.ToString(), linkChangeAction.Link.SourceArtifactId, StringComparison.OrdinalIgnoreCase) &&
                    string.Equals(linkChange.TargetID.ToString(), linkActionTargetIdString, StringComparison.OrdinalIgnoreCase))
                {
                    return(true);
                }

                if (string.Equals(linkChange.SourceID.ToString(), linkActionTargetIdString, StringComparison.OrdinalIgnoreCase) &&
                    string.Equals(linkChange.TargetID.ToString(), linkChangeAction.Link.SourceArtifactId, StringComparison.OrdinalIgnoreCase))
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #10
0
        /// <summary>
        /// This method is called when an attempt to add a link in the force sync case fails because a parent link already exists
        /// In this case we attempt to delete the existing parent link and retry the add link operation
        /// </summary>
        /// <param name="linkChangeAction">The LinkChangeAction object</param>
        /// <param name="updateDocumentThatFailed">The XmlDocument that was submitted to add the link that resulted in the error</param>
        /// <returns>True if successful at removing the existing parent and adding the new parent; false if not</returns>
        private bool DeleteExistingParentLinkToForceSyncAddLink(LinkChangeAction linkChangeAction, XmlDocument updateDocumentThatFailed)
        {
            // Get target work item ...
            string targetItem = TfsWorkItemHandler.IdFromUri(linkChangeAction.Link.TargetArtifact.Uri);

            WorkItem targetWorkItem = null;

            try
            {
                int targetWorkItemId = int.Parse(targetItem);
                targetWorkItem = base.WorkItemStore.GetWorkItem(targetWorkItemId);
            }
            catch (FormatException)
            {
            }
            catch (DeniedOrNotExistException)
            {
            }

            if (targetWorkItem != null)
            {
                // Delete its parent link ...
                string       linkType     = linkChangeAction.Link.LinkType.ReferenceName;
                WorkItemLink linkToRemove = null;
                foreach (WorkItemLink link in targetWorkItem.WorkItemLinks)
                {
                    if (!link.LinkTypeEnd.IsForwardLink &&
                        string.Equals(link.LinkTypeEnd.LinkType.ReferenceName, linkType))
                    {
                        linkToRemove = link;
                        break;
                    }
                }
                if (linkToRemove != null)
                {
                    try
                    {
                        // Create a delete LinkChangeAction by copying from the add LinkChangeAction and
                        // changing the SourceId which is the parent in the add parent link case.
                        LinkChangeAction deletelinkChangeAction = new LinkChangeAction(WellKnownChangeActionId.Delete, linkChangeAction.Link, linkChangeAction.Status, false);
                        deletelinkChangeAction.Link.SourceArtifact.Uri = TfsWorkItemHandler.UriFromId(linkToRemove.TargetId.ToString());
                        TfsUpdateDocument tfsUpdateDocument = InitializeUpdateDocument();

                        var handler = deletelinkChangeAction.Link.LinkType as ILinkHandler;
                        Debug.Assert(null != handler);

                        handler.UpdateTfs(tfsUpdateDocument, deletelinkChangeAction);
                        XmlDocument[] xmlUpdateDocuments = new XmlDocument[] { tfsUpdateDocument.UpdateDocument };

                        UpdateResult[] deleteExistingParentResults = TfsBatchUpdateHelper.Submit(Core, WorkItemServer, xmlUpdateDocuments);
                        Debug.Assert(deleteExistingParentResults.Length == 1);
                        if (deleteExistingParentResults[0].Exception != null)
                        {
                            throw deleteExistingParentResults[0].Exception;
                        }
                    }
                    catch (Exception ex)
                    {
                        TraceManager.TraceWarning(String.Format(CultureInfo.InvariantCulture,
                                                                "An exception occurred while trying to remove the parent link to force sync a link change to target work item {0}: {1}",
                                                                targetWorkItem.Id, ex.ToString()));
                        targetWorkItem = null;
                    }

                    if (targetWorkItem != null)
                    {
                        // Retry the operation
                        XmlDocument[] retryDocuments = new XmlDocument[1] {
                            updateDocumentThatFailed
                        };
                        UpdateResult[] retryResults = TfsBatchUpdateHelper.Submit(Core, WorkItemServer, retryDocuments);
                        if (retryResults.Length != retryDocuments.Length)
                        {
                            throw new SynchronizationEngineException("Wrong number of link update results.");
                        }

                        if (retryResults[0].Exception == null)
                        {
                            // Successfully retried after removing existing parent; don't create conflict
                            return(true);
                        }
                        else
                        {
                            TraceManager.TraceWarning(String.Format(CultureInfo.InvariantCulture,
                                                                    "An exception occurred while trying to force sync a link change to target work item {0}: {1}",
                                                                    targetWorkItem.Id, retryResults[0].Exception.ToString()));
                        }
                    }
                }
            }
            return(false);
        }