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)); }
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); }
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); }
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); }
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); }
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); }
/// <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); }