public override LinkChangeAction CreateLinkDeletionAction(string sourceItemUri, string targetArtifactUrl, string linkTypeReferenceName) { var link = new Toolkit.Linking.ArtifactLink( TfsWorkItemHandler.IdFromUri(sourceItemUri), new Toolkit.Linking.Artifact(sourceItemUri, s_sourceArtifactType), new Toolkit.Linking.Artifact(targetArtifactUrl, s_targetArtifactType), string.Empty, this); return(new LinkChangeAction(WellKnownChangeActionId.Delete, link, LinkChangeAction.LinkChangeActionStatus.Created, false)); }
public bool UpdateTfs(TfsUpdateDocument updateDoc, LinkChangeAction linkChangeAction) { if (null == updateDoc) { throw new ArgumentNullException("updateDoc"); } if (null == linkChangeAction) { throw new ArgumentNullException("linkChangeAction"); } if (!linkChangeAction.Link.LinkType.ReferenceName.Equals(ReferenceName)) { throw new ArgumentException("Link type mismatch."); } string targetId = TfsWorkItemHandler.IdFromUri(linkChangeAction.Link.TargetArtifact.Uri); string sourceId = TfsWorkItemHandler.IdFromUri(linkChangeAction.Link.SourceArtifact.Uri); int linkTypeId = WorkItemLinkTypeId(ReferenceName, true); string comment = linkChangeAction.Link.Comment ?? string.Empty; var tfs2010UpdateDoc = updateDoc as Tfs2010UpdateDocument; Debug.Assert(null != tfs2010UpdateDoc); if (linkChangeAction.ChangeActionId.Equals(WellKnownChangeActionId.Add)) { tfs2010UpdateDoc.AddWorkItemLink(sourceId, targetId, linkTypeId, comment, linkChangeAction.Link.IsLocked); } else if (linkChangeAction.ChangeActionId.Equals(WellKnownChangeActionId.Edit)) { tfs2010UpdateDoc.UpdateWorkItemLink(sourceId, targetId, linkTypeId, comment, linkChangeAction.Link.IsLocked); } else if (linkChangeAction.ChangeActionId.Equals(WellKnownChangeActionId.Delete)) { tfs2010UpdateDoc.RemoveWorkItemLink(sourceId, targetId, linkTypeId, comment); } else { throw new MigrationException(TfsWITAdapterResources.ErrorUnsupportedChangeAction); } return(true); }
private void ExtractDirectedLinks( WorkItem workItem, NonCyclicReferenceClosure closure) { List <int> workItemIdsToProcess = new List <int>(); foreach (WorkItemLink l in workItem.WorkItemLinks) { if (!TFStringComparer.LinkName.Equals(l.LinkTypeEnd.LinkType.ReferenceName, ReferenceName)) { continue; } var sourceIdStr = l.SourceId.ToString(CultureInfo.InvariantCulture); var targetIdStr = l.TargetId.ToString(CultureInfo.InvariantCulture); var sourceUri = TfsWorkItemHandler.UriFromId(sourceIdStr); var targetUri = TfsWorkItemHandler.UriFromId(targetIdStr); var sourceArtifact = new ToolkitLinking.Artifact(sourceUri, s_sourceArtifactType); var targetArtifact = new ToolkitLinking.Artifact(targetUri, s_targetArtifactType); if (!closure.SourceArtifactUris.Contains(targetUri) && !closure.TargetArtifactUris.Contains(targetUri)) { workItemIdsToProcess.Add(l.TargetId); } if (l.LinkTypeEnd.IsForwardLink) { var link = new ToolkitLinking.ArtifactLink(sourceIdStr, sourceArtifact, targetArtifact, l.Comment, this); closure.AddValidLink(link); } } foreach (var workItemId in workItemIdsToProcess) { var wi = m_store.GetWorkItem(workItemId); if (null == wi) { continue; } ExtractDirectedLinks(wi, closure); } }
public virtual void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store) { if (null == source) { throw new ArgumentNullException("source"); } if (null == source.WorkItem) { throw new ArgumentException("source.WorkItem is null"); } var linkChangeGroup = new LinkChangeGroup( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false); foreach (Link l in source.WorkItem.Links) { RelatedLink rl = l as RelatedLink; if (rl != null) { // v1 work item related link does not have direction info // to avoid generating two link change actions for the same link // we only pick one from the work item of smaller id if (source.WorkItem.Id >= rl.RelatedWorkItemId) { continue; } var link = new Toolkit.Linking.ArtifactLink( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType), new Toolkit.Linking.Artifact(TfsWorkItemHandler.UriFromId(rl.RelatedWorkItemId.ToString(CultureInfo.InvariantCulture)), s_targetArtifactType), rl.Comment, this); linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link, LinkChangeAction.LinkChangeActionStatus.Created, false)); } } linkChangeGroups.Add(linkChangeGroup); }
public bool UpdateTfs(TfsUpdateDocument updateDoc, LinkChangeAction linkChangeAction) { if (null == updateDoc) { throw new ArgumentNullException("updateDoc"); } if (null == linkChangeAction) { throw new ArgumentNullException("linkChangeAction"); } if (!linkChangeAction.Link.LinkType.ReferenceName.Equals(REFERENCE_NAME)) { throw new ArgumentException("Link type mismatch."); } //if (!linkChangeAction.ChangeActionId.Equals(WellKnownChangeActionId.Add)) //{ // Debug.Assert(false, "Unsupported action!"); // TraceManager.TraceError("Non-add action on external links is not supported."); //} string uri = linkChangeAction.Link.TargetArtifact.Uri; string comment = linkChangeAction.Link.Comment; if (linkChangeAction.ChangeActionId.Equals(WellKnownChangeActionId.Add)) { updateDoc.AddWorkItemLink(TfsWorkItemHandler.IdFromUri(uri), comment); } else if (linkChangeAction.ChangeActionId.Equals(WellKnownChangeActionId.Delete)) { updateDoc.RemoveWorkItemLink(TfsWorkItemHandler.IdFromUri(uri)); } else { throw new MigrationException(TfsWITAdapterResources.ErrorUnsupportedChangeAction); } return(true); }
public List <IArtifact> GetDirectedLinkParents(WorkItem workItem) { if (null == workItem) { throw new ArgumentNullException("workItem"); } var retVal = new List <IArtifact>(); foreach (WorkItemLink l in workItem.WorkItemLinks) { if (l.LinkTypeEnd.IsForwardLink) { continue; } if (!TFStringComparer.LinkName.Equals(l.LinkTypeEnd.LinkType.ReferenceName, ReferenceName)) { continue; } var targetIdStr = l.TargetId.ToString(CultureInfo.InvariantCulture); var targetUri = TfsWorkItemHandler.UriFromId(targetIdStr); var targetArtifact = new ToolkitLinking.Artifact(targetUri, s_targetArtifactType); var pos = retVal.BinarySearch(targetArtifact, s_artifactComparer); if (pos >= 0) { continue; } retVal.Add(targetArtifact); retVal.Sort(s_artifactComparer); } return(retVal); }
private LinkChangeAction GetAddLinkChangeActionFromWorkItemLink(WorkItemLink workItemLink, LinkType linkType) { var sourceIdStr = workItemLink.SourceId.ToString(CultureInfo.InvariantCulture); var targetIdStr = workItemLink.TargetId.ToString(CultureInfo.InvariantCulture); var sourceArtifact = new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(sourceIdStr), WorkItemLinkTypeBase.s_sourceArtifactType); var targetArtifact = new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(targetIdStr), WorkItemLinkTypeBase.s_targetArtifactType); ToolkitLinking.ArtifactLink link; if (workItemLink.LinkTypeEnd.IsForwardLink) { link = new ToolkitLinking.ArtifactLink(sourceIdStr, sourceArtifact, targetArtifact, workItemLink.Comment, linkType, workItemLink.IsLocked); } else { link = new ToolkitLinking.ArtifactLink(targetIdStr, targetArtifact, sourceArtifact, workItemLink.Comment, linkType, workItemLink.IsLocked); } LinkChangeAction addLinkChangeAction = new LinkChangeAction(WellKnownChangeActionId.Add, link, LinkChangeAction.LinkChangeActionStatus.Created, false); return(addLinkChangeAction); }
public override System.Collections.ObjectModel.ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice( LinkService linkService, int maxDeltaSliceSize) { try { var linkChangeGroups = new List <LinkChangeGroup>(); if (null == ExtractLinkChangeActionsCallback) { return(linkChangeGroups.AsReadOnly()); } // load main Highwater Mark m_hwmLink.Reload(); DateTime hwmLinkValue = m_hwmLink.Value; // search back 60 seconds to deal with potential WIT race condition if (!hwmLinkValue.Equals(default(DateTime))) { hwmLinkValue = hwmLinkValue.AddSeconds(-60); } string hwmLinkValueStr = hwmLinkValue.ToString(CultureInfo.InvariantCulture); // load Work Items for extracting links string sourceId = m_migrationSource.UniqueId; string storeName = m_migrationSource.WorkItemStore.StoreName; // Get items based on primary Highwater Mark TraceManager.TraceInformation(TfsWITAdapterResources.GettingModifiedItems, sourceId, storeName); IEnumerable <TfsMigrationWorkItem> items = m_migrationSource.WorkItemStore.GetItems(ref hwmLinkValueStr); TraceManager.TraceInformation(TfsWITAdapterResources.ReceivedModifiedItems, sourceId, storeName); // Record the updated HWM value DateTime wiqlExecutionTime = Convert.ToDateTime(hwmLinkValueStr, CultureInfo.InvariantCulture); // store to be used to analyze deleted links WorkItemLinkStore store = new WorkItemLinkStore(new Guid(sourceId)); // extract links DateTime lastWorkITemUpdateTime = DateTime.MinValue; var inMaxDeltaSliceSize = maxDeltaSliceSize; foreach (TfsMigrationWorkItem tfsMigrationWorkItem in items) { if (tfsMigrationWorkItem.WorkItem == null) { continue; } TraceManager.TraceInformation("Generating linking delta for Work Item: {0}", tfsMigrationWorkItem.WorkItem.Id.ToString()); var detectedLinkChangeGroups = new List <LinkChangeGroup>(); ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, detectedLinkChangeGroups, store); if (detectedLinkChangeGroups.Count == 0) { TraceManager.TraceInformation("Number of links: {0}", 0); continue; } Dictionary <string, LinkChangeGroup> perWorkItemConsolidatedLinkChangeGroup = new Dictionary <string, LinkChangeGroup>(); for (int i = 0; i < detectedLinkChangeGroups.Count; ++i) { foreach (LinkChangeAction action in detectedLinkChangeGroups[i].Actions) { if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(action.Link.SourceArtifact.Uri)) { var linkChangeGroup = new LinkChangeGroup( action.Link.SourceArtifactId, LinkChangeGroup.LinkChangeGroupStatus.Created, false); perWorkItemConsolidatedLinkChangeGroup.Add(action.Link.SourceArtifact.Uri, linkChangeGroup); } perWorkItemConsolidatedLinkChangeGroup[action.Link.SourceArtifact.Uri].AddChangeAction(action); } } // always make sure that the currently analyzed work item has a link change group to represent it // even though the group can be empty if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(tfsMigrationWorkItem.Uri)) { perWorkItemConsolidatedLinkChangeGroup.Add( tfsMigrationWorkItem.Uri, new LinkChangeGroup(TfsWorkItemHandler.IdFromUri(tfsMigrationWorkItem.Uri), LinkChangeGroup.LinkChangeGroupStatus.Created, false)); } foreach (var workItemLinkGroup in perWorkItemConsolidatedLinkChangeGroup) { string workItemIdStr = TfsWorkItemHandler.IdFromUri(workItemLinkGroup.Key); TraceManager.TraceInformation("Detected {0} links for Work Item '{1}'", workItemLinkGroup.Value.Actions.Count, workItemIdStr); if (workItemLinkGroup.Key.Equals(tfsMigrationWorkItem.Uri, StringComparison.OrdinalIgnoreCase)) { // VERY IMPORTANT: use the RelatedArtifactsStore to detect link deletion store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords( workItemLinkGroup.Key, workItemLinkGroup.Value, this); } else { store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecordsWithoutImplicitDelete( workItemLinkGroup.Key, workItemLinkGroup.Value, this); } if (workItemLinkGroup.Value.Actions.Count > 0) { linkChangeGroups.Add(workItemLinkGroup.Value); } maxDeltaSliceSize -= workItemLinkGroup.Value.Actions.Count; if (maxDeltaSliceSize <= 0) { // size limit reached - persist groups to DB linkService.AddChangeGroups(linkChangeGroups); linkChangeGroups.Clear(); maxDeltaSliceSize = inMaxDeltaSliceSize; } } DateTime lastRevChangedDate = tfsMigrationWorkItem.WorkItem.ChangedDate; if (lastWorkITemUpdateTime.CompareTo(lastRevChangedDate) <= 0) { lastWorkITemUpdateTime = lastRevChangedDate; } } // persist remaining groups to DB linkService.AddChangeGroups(linkChangeGroups); // clean up the returned link change group collection // when the caller (toolkit) receives an empty collection, it understands there is no more // delta to generate for the moment, and proceeds to next phase linkChangeGroups.Clear(); // update primary Highwater Mark //m_hwmLink.Update(newHwmLinkValue); string newHwmValueStr = hwmLinkValueStr; if (lastWorkITemUpdateTime.Equals(DateTime.MinValue)) { // no changes in this sync cycle, record the wiql query execution time m_hwmLink.Update(wiqlExecutionTime); } else { // hwm is recorded in UTC, so does the WIQL query asof time lastWorkITemUpdateTime = lastWorkITemUpdateTime.ToUniversalTime(); if (lastWorkITemUpdateTime.CompareTo(wiqlExecutionTime) <= 0) { // last work item rev time is earlier than wiql query execution time, use it as hwm m_hwmLink.Update(lastWorkITemUpdateTime); newHwmValueStr = lastWorkITemUpdateTime.ToString(); } else { m_hwmLink.Update(wiqlExecutionTime); } } TraceManager.TraceInformation("Persisted WIT linking HWM: {0}", Toolkit.Constants.HwmDeltaLink); TraceManager.TraceInformation(TfsWITAdapterResources.UpdatedHighWatermark, newHwmValueStr); return(linkChangeGroups.AsReadOnly()); } catch (Exception exception) { MigrationConflict genericeConflict = WitGeneralConflictType.CreateConflict(exception); var conflictManager = m_conflictManager.GetService(typeof(ConflictManager)) as ConflictManager; Debug.Assert(null != conflictManager); List <MigrationAction> resolutionActions; ConflictResolutionResult resolveRslt = conflictManager.TryResolveNewConflict(conflictManager.SourceId, genericeConflict, out resolutionActions); Debug.Assert(!resolveRslt.Resolved); return(new List <LinkChangeGroup>().AsReadOnly()); } }
private LinkChangeGroup GetLinkChangeGroupFromLinkChanges(TfsMigrationWorkItem source) { LinkChangeGroup linkChangeGroup = new LinkChangeGroup( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false); Dictionary <string, LinkType> linkTypesByName = new Dictionary <string, LinkType>(); foreach (WorkItemLinkChange linkChange in source.LinkChanges) { LinkType linkType; if (!linkTypesByName.TryGetValue(linkChange.LinkType, out linkType)) { ExtendedLinkProperties extendedLinkProperties = new ExtendedLinkProperties(); linkType = new WorkItemLinkTypeBase(linkChange.LinkType, linkChange.LinkType, extendedLinkProperties, m_migrationSource.WorkItemStore.WorkItemStore); linkTypesByName.Add(linkChange.LinkType, linkType); } bool actionAdded = false; if (linkChange.IsActive) // Link added { // Get matching link l from WorkItem links collection WorkItemLink l = GetWorkItemLinkFromLinkChange(source, linkChange); if (l != null) { LinkChangeAction addLinkChangeAction = GetAddLinkChangeActionFromWorkItemLink(l, linkType); addLinkChangeAction.ServerLinkChangeId = linkChange.RowVersion.ToString(); linkChangeGroup.AddChangeAction(addLinkChangeAction); actionAdded = true; } else { TraceManager.TraceInformation(String.Format( "Unable to find link on work item {0} corresponding to detected link addition from {1} to {2} of type {3}; it may have been recently deleted", source.WorkItem.Id, linkChange.SourceID, linkChange.TargetID, linkChange.LinkType)); } } else // Link deleted { var deleteLinkChangeAction = new LinkChangeAction( WellKnownChangeActionId.Delete, new ToolkitLinking.ArtifactLink(linkChange.SourceID.ToString(), new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(linkChange.SourceID.ToString()), WorkItemLinkTypeBase.s_sourceArtifactType), new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(linkChange.TargetID.ToString()), WorkItemLinkTypeBase.s_targetArtifactType), string.Empty, linkType), LinkChangeAction.LinkChangeActionStatus.Created, false); deleteLinkChangeAction.ServerLinkChangeId = linkChange.RowVersion.ToString(); linkChangeGroup.AddChangeAction(deleteLinkChangeAction); actionAdded = true; } if (actionAdded) { TraceManager.TraceVerbose("Adapter: Generating link change action: {0} '{1}'->'{2}' (Type: {3})", linkChange.IsActive ? "Add" : "Delete", linkChange.SourceID, linkChange.TargetID, linkChange.LinkType); } } return(linkChangeGroup); }
private void CreateLinkChangeGroupsForForceSyncItem(TfsMigrationWorkItem tfsMigrationWorkItem) { if (m_linkService == null) { Debug.Fail("LinkService is null"); return; } var linkChangeGroups = new List <LinkChangeGroup>(); var detectedLinkChangeGroups = new List <LinkChangeGroup>(); ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, detectedLinkChangeGroups, null); if (detectedLinkChangeGroups.Count == 0) { TraceManager.TraceInformation("Number of non-Work Item links: {0}", 0); } else { Dictionary <string, LinkChangeGroup> perWorkItemConsolidatedLinkChangeGroup = new Dictionary <string, LinkChangeGroup>(); for (int i = 0; i < detectedLinkChangeGroups.Count; ++i) { foreach (LinkChangeAction action in detectedLinkChangeGroups[i].Actions) { if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(action.Link.SourceArtifact.Uri)) { var linkChangeGroup = new LinkChangeGroup( action.Link.SourceArtifactId, LinkChangeGroup.LinkChangeGroupStatus.Created, false); perWorkItemConsolidatedLinkChangeGroup.Add(action.Link.SourceArtifact.Uri, linkChangeGroup); } perWorkItemConsolidatedLinkChangeGroup[action.Link.SourceArtifact.Uri].AddChangeAction(action); } } foreach (var workItemLinkGroup in perWorkItemConsolidatedLinkChangeGroup) { string workItemIdStr = TfsWorkItemHandler.IdFromUri(workItemLinkGroup.Key); TraceManager.TraceInformation("Detected {0} non-Work Item links for force sync Work Item '{1}'", workItemLinkGroup.Value.Actions.Count, workItemIdStr); if (workItemLinkGroup.Value.Actions.Count > 0) { workItemLinkGroup.Value.IsForcedSync = true; linkChangeGroups.Add(workItemLinkGroup.Value); } } } if (tfsMigrationWorkItem.WorkItem.WorkItemLinks.Count > 0) { // Handle work item to work item links LinkChangeGroup workItemlinkChangeGroup = new LinkChangeGroup( tfsMigrationWorkItem.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false); Dictionary <string, LinkType> linkTypesByName = new Dictionary <string, LinkType>(); foreach (WorkItemLink workItemLink in tfsMigrationWorkItem.WorkItem.WorkItemLinks) { string linkTypeName = workItemLink.LinkTypeEnd.LinkType.ReferenceName; LinkType linkType; if (!linkTypesByName.TryGetValue(linkTypeName, out linkType)) { ExtendedLinkProperties extendedLinkProperties = new ExtendedLinkProperties(); linkType = new WorkItemLinkTypeBase(linkTypeName, linkTypeName, extendedLinkProperties, m_migrationSource.WorkItemStore.WorkItemStore); linkTypesByName.Add(linkTypeName, linkType); } LinkChangeAction addLinkChangeAction = GetAddLinkChangeActionFromWorkItemLink(workItemLink, linkType); workItemlinkChangeGroup.AddChangeAction(addLinkChangeAction); } if (workItemlinkChangeGroup.Actions.Count > 0) { workItemlinkChangeGroup.IsForcedSync = true; linkChangeGroups.Add(workItemlinkChangeGroup); TraceManager.TraceInformation("Detected {0} Work Item links for force sync Work Item '{1}'", workItemlinkChangeGroup.Actions.Count, tfsMigrationWorkItem.WorkItem.Id); } } // Persist link change groups to DB if (linkChangeGroups.Count > 0) { m_linkService.AddChangeGroups(linkChangeGroups); } }
public void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store) { if (null == source) { throw new ArgumentNullException("source"); } if (null == source.WorkItem) { throw new ArgumentException("source.WorkItem is null"); } var linkChangeGroup = new LinkChangeGroup( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false); List <string> revertedLinkSourceWorkItemUris = new List <string>(); if (null != store) { revertedLinkSourceWorkItemUris = store.GetRevertedLinkSourceItems(source.Uri, ReferenceName); } foreach (WorkItemLink l in source.WorkItem.WorkItemLinks) { #region obsolete //// always recognize the "ForwardLink" //if (!l.LinkTypeEnd.IsForwardLink) //{ // continue; //} #endregion // always recognize the WorkItem with smaller Id for non-directional link if (!l.LinkTypeEnd.LinkType.IsDirectional && l.SourceId > l.TargetId) { continue; } if (!TFStringComparer.LinkName.Equals(l.LinkTypeEnd.LinkType.ReferenceName, ReferenceName)) { continue; } var sourceIdStr = l.SourceId.ToString(CultureInfo.InvariantCulture); var targetIdStr = l.TargetId.ToString(CultureInfo.InvariantCulture); var sourceArtifact = new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(sourceIdStr), s_sourceArtifactType); var targetArtifact = new ToolkitLinking.Artifact(TfsWorkItemHandler.UriFromId(targetIdStr), s_targetArtifactType); ToolkitLinking.ArtifactLink link; if (l.LinkTypeEnd.IsForwardLink) { link = new ToolkitLinking.ArtifactLink(sourceIdStr, sourceArtifact, targetArtifact, l.Comment, this, l.IsLocked); } else { link = new ToolkitLinking.ArtifactLink(targetIdStr, targetArtifact, sourceArtifact, l.Comment, this, l.IsLocked); if (revertedLinkSourceWorkItemUris.Contains(targetArtifact.Uri)) { revertedLinkSourceWorkItemUris.Remove(targetArtifact.Uri); } } var linkChangeAction = new LinkChangeAction(WellKnownChangeActionId.Add, link, LinkChangeAction.LinkChangeActionStatus.Created, false); linkChangeGroup.AddChangeAction(linkChangeAction); } foreach (string revertedLinkSrcItemUri in revertedLinkSourceWorkItemUris) { string sourceWorkItemId = TfsWorkItemHandler.IdFromUri(revertedLinkSrcItemUri); LinkChangeGroup group = new LinkChangeGroup(sourceWorkItemId, LinkChangeGroup.LinkChangeGroupStatus.Created, false); var deleteLinkChangeAction = new LinkChangeAction( WellKnownChangeActionId.Delete, new ToolkitLinking.ArtifactLink(sourceWorkItemId, new ToolkitLinking.Artifact(revertedLinkSrcItemUri, s_sourceArtifactType), new ToolkitLinking.Artifact(source.Uri, s_targetArtifactType), string.Empty, this), LinkChangeAction.LinkChangeActionStatus.Created, false); group.AddChangeAction(deleteLinkChangeAction); linkChangeGroups.Add(group); } linkChangeGroups.Add(linkChangeGroup); }
public override void ExtractLinkChangeActions(TfsMigrationWorkItem source, List <LinkChangeGroup> linkChangeGroups, WorkItemLinkStore store) { if (null == source) { throw new ArgumentNullException("source"); } if (null == source.WorkItem) { throw new ArgumentException("source.WorkItem is null"); } var linkChangeGroup = new LinkChangeGroup( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), LinkChangeGroup.LinkChangeGroupStatus.Created, false); foreach (Link l in source.WorkItem.Links) { RelatedLink rl = l as RelatedLink; if (rl != null) { // v1 work item related link does not have direction info // to avoid generating two link change actions for the same link // we only pick one from the work item of smaller id if (source.WorkItem.Id >= rl.RelatedWorkItemId) { continue; } #region TFS 2010 specific logic if (rl.LinkTypeEnd != null && rl.LinkTypeEnd.LinkType != null) { if (rl.LinkTypeEnd.LinkType.ReferenceName.Equals(Tfs2010RelatedLinkTypeReferenceName, StringComparison.OrdinalIgnoreCase)) { #endregion var link = new Toolkit.Linking.ArtifactLink( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType), new Toolkit.Linking.Artifact(TfsWorkItemHandler.UriFromId(rl.RelatedWorkItemId.ToString(CultureInfo.InvariantCulture)), s_targetArtifactType), rl.Comment, this, rl.IsLocked); linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link, LinkChangeAction.LinkChangeActionStatus.Created, false)); } } else { var link = new Toolkit.Linking.ArtifactLink( source.WorkItem.Id.ToString(CultureInfo.InvariantCulture), new Toolkit.Linking.Artifact(source.Uri, s_sourceArtifactType), new Toolkit.Linking.Artifact(TfsWorkItemHandler.UriFromId(rl.RelatedWorkItemId.ToString(CultureInfo.InvariantCulture)), s_targetArtifactType), rl.Comment, this); linkChangeGroup.AddChangeAction(new LinkChangeAction(WellKnownChangeActionId.Add, link, LinkChangeAction.LinkChangeActionStatus.Created, false)); } } } linkChangeGroups.Add(linkChangeGroup); }