Beispiel #1
0
        private XmlDocument CreateWorkItemUpdateOperation(MigrationAction action)
        {
            XmlDocument desc     = action.RecordDetails.DetailsDocument;
            XmlElement  rootNode = desc.DocumentElement;

            Debug.Assert(null != rootNode,
                         "Wit IMigrationAction.MigrationActionDescription is invalid.");
            Debug.Assert(null != rootNode.Attributes["WorkItemType"],
                         "WorkItemType is missing in MigrationActionDescription.");
            Debug.Assert(null != rootNode.Attributes["Author"],
                         "Author is missing in MigrationActionDescription.");
            Debug.Assert(null != rootNode.Attributes["ChangeDate"],
                         "ChangeDate is missing in MigrationActionDescription.");
            string workItemType   = rootNode.Attributes["WorkItemType"].Value;
            string author         = rootNode.Attributes["Author"].Value;
            string changeDate     = rootNode.Attributes["ChangeDate"].Value;
            string targetRevision = rootNode.Attributes["TargetRevision"].Value;

            TfsUpdateDocument tfsUpdateDocument = InitializeUpdateDocument();

            tfsUpdateDocument.CreateWorkItemUpdateDoc(TargetWorkItem.Id.ToString(), targetRevision);
            tfsUpdateDocument.AddFields(action, workItemType, author, changeDate, false);

            tfsUpdateDocument.InsertConversionHistoryCommentToHistory(
                workItemType,
                GenerateMigrationHistoryComment(action));

            // insert source item Id to field TfsMigrationTool.ReflectedWorkItemId if it is in WITD
            tfsUpdateDocument.InsertConversionHistoryField(
                workItemType,
                action.SourceWorkItemId);

            return(tfsUpdateDocument.UpdateDocument);
        }
        protected override TfsUpdateDocument SubmitAttachmentChanges(IMigrationAction action, ConflictManager conflictMgrService)
        {
            /*
             * retrieve change details
             */
            XmlDocument desc     = action.MigrationActionDescription;
            XmlElement  rootNode = desc.DocumentElement;

            Debug.Assert(null != rootNode);
            XmlNode attachmentNode   = rootNode.FirstChild;
            string  originalName     = attachmentNode.Attributes["Name"].Value;
            string  utcCreationDate  = attachmentNode.Attributes["UtcCreationDate"].Value;
            string  utcLastWriteDate = attachmentNode.Attributes["UtcLastWriteDate"].Value;
            string  length           = attachmentNode.Attributes["Length"].Value;
            string  comment          = attachmentNode.FirstChild.InnerText;
            int     targetWorkItemId = FindTargetWorkItemId(action, conflictMgrService);
            string  targetRevision   = rootNode.Attributes["TargetRevision"].Value;

            /*
             * create operation document
             */
            TfsUpdateDocument tfsUpdateDocument = InitializeUpdateDocument();

            tfsUpdateDocument.CreateWorkItemUpdateDoc(targetWorkItemId.ToString(), targetRevision);

            /*
             * insert Connector specific comment
             */
            WorkItem item = WorkItemStore.GetWorkItem(targetWorkItemId);

            Debug.Assert(null != item, "target work item does not exist");
            tfsUpdateDocument.InsertConversionHistoryCommentToHistory(item.Type.Name, GenerateMigrationHistoryComment(action));

            int[] fileId = FindAttachmentFileId(targetWorkItemId, originalName,
                                                utcCreationDate, utcLastWriteDate, length, comment);

            /*
             * delete attachment
             */
            if (action.Action == WellKnownChangeActionId.DelAttachment)
            {
                if (fileId.Length == 0)
                {
                    action.State = ActionState.Skipped;
                    return(null);
                }
                else
                {
                    tfsUpdateDocument.RemoveAttachment(fileId[0]);
                    return(tfsUpdateDocument);
                }
            }

            /*
             * add attachment
             */
            try
            {
                string sourceStoreCountString = attachmentNode.Attributes["CountInSourceSideStore"].Value;
                int    sourceStoreCount;
                if (int.TryParse(sourceStoreCountString, out sourceStoreCount))
                {
                    if (sourceStoreCount <= fileId.Length)
                    {
                        action.State = ActionState.Skipped;
                        return(null);
                    }
                }
            }
            catch (Exception e)
            {
                TraceManager.TraceVerbose(e.ToString());
                // for backward compatibility, just proceed
            }

            if (AttachmentIsOversized(length))
            {
                MigrationConflict conflict = new FileAttachmentOversizedConflictType().CreateConflict(
                    originalName, length, MaxAttachmentSize, targetWorkItemId.ToString(), Core.ServerName, Core.Config.Project, action);

                List <MigrationAction>   actions;
                ConflictResolutionResult resolveRslt = conflictMgrService.TryResolveNewConflict(conflictMgrService.SourceId, conflict, out actions);

                if (!resolveRslt.Resolved)
                {
                    return(null);
                }

                if (resolveRslt.ResolutionType == ConflictResolutionType.SuppressedConflictedChangeAction)
                {
                    action.State = ActionState.Skipped;
                    return(null);
                }

                if (resolveRslt.ResolutionType == ConflictResolutionType.Other)
                {
                    // conflict resolved, just proceed
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            Guid fileGuid = Guid.NewGuid();

            tfsUpdateDocument.AddAttachment(originalName, XmlConvert.ToString(fileGuid),
                                            utcCreationDate, utcLastWriteDate, length, comment);

            // get areaNodeUri - required by Dev10 OM
            Project project        = item.Project;
            string  projectNodeUri = (project.Uri).ToString();
            string  areaNodeUri    = string.Empty;

            if (project.Id == item.AreaId)
            {
                areaNodeUri = Core.AreaNodeUri;
            }
            else
            {
                // Loop through the area root nodes looking for the one we're on
                foreach (Node node in project.AreaRootNodes)
                {
                    // It could be one of the root nodes
                    if (node.Id == item.AreaId)
                    {
                        areaNodeUri = node.Uri.ToString();
                        break;
                    }

                    // Now check if it is a child of the current area root node
                    try
                    {
                        Node node2 = node.FindNodeInSubTree(item.AreaId);
                        areaNodeUri = node2.Uri.ToString();
                        break;
                    }
                    catch (DeniedOrNotExistException)
                    {
                        // Ignore if not found, go onto the next area root node
                        continue;
                    }
                }
            }

            //Now upload the file since that has to be done before the Xml batch is executed.
            Debug.Assert(!string.IsNullOrEmpty(LocalWorkDir));
            string filePath = Path.Combine(LocalWorkDir, fileGuid.ToString());

            action.SourceItem.Download(filePath);
            using (var strm = File.OpenRead(filePath))
            {
                var f = new FileAttachment();
                f.AreaNodeUri  = areaNodeUri;
                f.ProjectUri   = projectNodeUri;
                f.FileNameGUID = fileGuid;
                f.LocalFile    = strm; // attachment.GetFileContents();

                WorkItemServer.UploadFile(f);
            }

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            return(tfsUpdateDocument);
        }
Beispiel #3
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);
        }