Exemple #1
0
        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));
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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());
            }
        }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
        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);
        }