private void CorrectComment(WorkItem wi, WiItem wiItem, WiRevision rev) { var currentComment = wi.History; var commentUpdated = false; CorrectImagePath(wi, wiItem, rev, ref currentComment, ref commentUpdated); if (commentUpdated) { wi.Fields[CoreField.History].Value = currentComment; } }
private bool ApplyAttachments(WiRevision rev, WorkItem wi, Dictionary <string, Attachment> attachmentMap) { bool success = true; if (!wi.IsOpen) { wi.Open(); } foreach (var att in rev.Attachments) { try { Logger.Log(LogLevel.Debug, $"Adding attachment '{att.ToString()}'."); if (att.Change == ReferenceChangeType.Added) { var newAttachment = new Attachment(att.FilePath, att.Comment); wi.Attachments.Add(newAttachment); attachmentMap.Add(att.AttOriginId, newAttachment); } else if (att.Change == ReferenceChangeType.Removed) { Attachment existingAttachment = IdentifyAttachment(att, wi); if (existingAttachment != null) { wi.Attachments.Remove(existingAttachment); } else { success = false; Logger.Log(LogLevel.Error, $"Could not find migrated attachment '{att.ToString()}'."); } } } catch (AbortMigrationException) { throw; } catch (Exception ex) { Logger.Log(ex, $"Failed to apply attachments for '{wi.Id}'."); success = false; } } if (rev.Attachments.Any(a => a.Change == ReferenceChangeType.Removed)) { wi.Fields[CoreField.History].Value = $"Removed attachments(s): { string.Join(";", rev.Attachments.Where(a => a.Change == ReferenceChangeType.Removed).Select(a => a.ToString()))}"; } return(success); }
private void EnsureAssigneeField(WiRevision rev, WorkItem wi) { string assignedTo = wi.Fields[WiFieldReference.AssignedTo].Value.ToString(); if (rev.Fields.HasAnyByRefName(WiFieldReference.AssignedTo)) { var field = rev.Fields.First(f => f.ReferenceName.Equals(WiFieldReference.AssignedTo, StringComparison.InvariantCultureIgnoreCase)); assignedTo = field.Value?.ToString() ?? string.Empty; rev.Fields.RemoveAll(f => f.ReferenceName.Equals(WiFieldReference.AssignedTo, StringComparison.InvariantCultureIgnoreCase)); } rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.AssignedTo, Value = assignedTo }); }
private void EnsureAssigneeField(WiRevision rev, WorkItem wi) { string assignedToRef = "System.AssignedTo"; string assignedTo = wi.Fields[assignedToRef].Value.ToString(); if (rev.Fields.Any(f => f.ReferenceName.Equals(assignedToRef, StringComparison.InvariantCultureIgnoreCase))) { var field = rev.Fields.Where(f => f.ReferenceName.Equals(assignedToRef, StringComparison.InvariantCultureIgnoreCase)).First(); assignedTo = field.Value.ToString(); rev.Fields.RemoveAll(f => f.ReferenceName.Equals(assignedToRef, StringComparison.InvariantCultureIgnoreCase)); } rev.Fields.Add(new WiField() { ReferenceName = assignedToRef, Value = assignedTo }); }
private void EnsureAuthorFields(WiRevision rev) { if (rev.Index == 0 && !rev.Fields.HasAnyByRefName(WiFieldReference.CreatedBy)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.CreatedBy, Value = rev.Author }); } if (!rev.Fields.HasAnyByRefName(WiFieldReference.ChangedBy)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ChangedBy, Value = rev.Author }); } }
private void EnsureDateFields(WiRevision rev) { if (rev.Index == 0 && !rev.Fields.HasAnyByRefName(WiFieldReference.CreatedDate)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.CreatedDate, Value = rev.Time.ToString("o") }); } if (!rev.Fields.HasAnyByRefName(WiFieldReference.ChangedDate)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ChangedDate, Value = rev.Time.ToString("o") }); } }
private void EnsureDateFields(WiRevision rev) { if (rev.Index == 0 && !rev.Fields.Any(f => f.ReferenceName.Equals(WiFieldReference.CreatedDate, StringComparison.InvariantCultureIgnoreCase))) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.CreatedDate, Value = rev.Time.ToString("o") }); } if (!rev.Fields.Any(f => f.ReferenceName.Equals(WiFieldReference.ChangedDate, StringComparison.InvariantCultureIgnoreCase))) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ChangedDate, Value = rev.Time.ToString("o") }); } }
private void EnsureClassificationFields(WiRevision rev) { if (!rev.Fields.HasAnyByRefName(WiFieldReference.AreaPath)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.AreaPath, Value = "" }); } if (!rev.Fields.HasAnyByRefName(WiFieldReference.IterationPath)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.IterationPath, Value = "" }); } }
private void EnsureAuthorFields(WiRevision rev) { string changedByRef = "System.ChangedBy"; string createdByRef = "System.CreatedBy"; if (rev.Index == 0 && !rev.Fields.Any(f => f.ReferenceName.Equals(createdByRef, StringComparison.InvariantCultureIgnoreCase))) { rev.Fields.Add(new WiField() { ReferenceName = createdByRef, Value = rev.Author }); } if (!rev.Fields.Any(f => f.ReferenceName.Equals(changedByRef, StringComparison.InvariantCultureIgnoreCase))) { rev.Fields.Add(new WiField() { ReferenceName = changedByRef, Value = rev.Author }); } }
private void SaveWorkItem(WiRevision rev, WorkItem newWorkItem) { if (!newWorkItem.IsValid()) { var reasons = newWorkItem.Validate(); foreach (Microsoft.TeamFoundation.WorkItemTracking.Client.Field reason in reasons) { Logger.Log(LogLevel.Info, $"Field: '{reason.Name}', Status: '{reason.Status}', Value: '{reason.Value}'"); } } try { newWorkItem.Save(SaveFlags.MergeAll); } catch (FileAttachmentException faex) { Logger.Log(faex, $"[{faex.GetType().ToString()}] {faex.Message}. Attachment {faex.SourceAttachment.Name}({faex.SourceAttachment.Id}) in {rev.ToString()} will be skipped."); newWorkItem.Attachments.Remove(faex.SourceAttachment); SaveWorkItem(rev, newWorkItem); } }
public void RetryLinkImportRevision(WiRevision rev, WorkItem wi) { try { if (!wi.IsOpen || !wi.IsPartialOpen) { wi.PartialOpen(); } var authorField = rev.Fields.Where((field) => { return(field.ReferenceName == WiFieldReference.CreatedBy); }); UpdateWIFields(authorField, wi); bool applied = ApplyLinks(rev, wi); if (!applied) { Logger.Log(LogLevel.Warning, $"RETRY LINKS FAILED: '{rev.ToString()}' - not all changes were saved."); } else { SaveWorkItem(rev, wi); Logger.Log(LogLevel.Debug, $"RETRY LINKS: Imported revision."); } wi.Close(); } catch (AbortMigrationException) { throw; } catch (Exception ex) { Logger.Log(ex, $"RETRY LINKS: Failed to import revisions for '{wi.Id}'."); } }
private void EnsureFieldsOnStateChange(WiRevision rev, WorkItem wi) { if (rev.Index != 0 && rev.Fields.HasAnyByRefName(WiFieldReference.State)) { var wiState = wi.Fields[WiFieldReference.State]?.Value?.ToString() ?? string.Empty; var revState = rev.Fields.GetFieldValueOrDefault <string>(WiFieldReference.State) ?? string.Empty; if (wiState.Equals("Done", StringComparison.InvariantCultureIgnoreCase) && revState.Equals("New", StringComparison.InvariantCultureIgnoreCase)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ClosedDate, Value = null }); rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ClosedBy, Value = null }); } if (!wiState.Equals("New", StringComparison.InvariantCultureIgnoreCase) && revState.Equals("New", StringComparison.InvariantCultureIgnoreCase)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ActivatedDate, Value = null }); rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ActivatedBy, Value = null }); } if (revState.Equals("Done", StringComparison.InvariantCultureIgnoreCase) && !rev.Fields.HasAnyByRefName(WiFieldReference.ClosedBy)) { rev.Fields.Add(new WiField() { ReferenceName = WiFieldReference.ClosedBy, Value = rev.Author }); } } }
private void CorrectImagePath(WorkItem wi, WiItem wiItem, WiRevision rev, ref string textField, ref bool isUpdated) { foreach (var att in wiItem.Revisions.SelectMany(r => r.Attachments.Where(a => a.Change == ReferenceChangeType.Added))) { var fileName = att.FilePath.Split('\\')?.Last() ?? string.Empty; if (textField.Contains(fileName)) { var tfsAtt = IdentifyAttachment(att, wi); if (tfsAtt != null) { string imageSrcPattern = $"src.*?=.*?\"([^\"])(?=.*{att.AttOriginId}).*?\""; textField = Regex.Replace(textField, imageSrcPattern, $"src=\"{tfsAtt.Uri.AbsoluteUri}\""); isUpdated = true; } else { Logger.Log(LogLevel.Warning, $"Attachment '{att.ToString()}' referenced in text but is missing from work item {wiItem.OriginId}/{wi.Id}."); } } } if (isUpdated) { DateTime changedDate; if (wiItem.Revisions.Count > rev.Index + 1) { changedDate = RevisionUtility.NextValidDeltaRev(rev.Time, wiItem.Revisions[rev.Index + 1].Time); } else { changedDate = RevisionUtility.NextValidDeltaRev(rev.Time); } wi.Fields[WiFieldReference.ChangedDate].Value = changedDate; wi.Fields[WiFieldReference.ChangedBy].Value = rev.Author; } }
public bool ImportRevision(WiRevision rev, WorkItem wi) { var incomplete = false; try { if (rev.Index == 0) { EnsureClassificationFields(rev); } EnsureDateFields(rev, wi); EnsureAuthorFields(rev); EnsureAssigneeField(rev, wi); EnsureFieldsOnStateChange(rev, wi); var attachmentMap = new Dictionary <string, Attachment>(); if (rev.Attachments.Any() && !ApplyAttachments(rev, wi, attachmentMap)) { incomplete = true; } if (rev.Fields.Any() && !UpdateWIFields(rev.Fields, wi)) { incomplete = true; } if (rev.Links.Any() && !ApplyLinks(rev, wi)) { incomplete = true; } if (incomplete) { Logger.Log(LogLevel.Warning, $"'{rev.ToString()}' - not all changes were saved."); } if (rev.Attachments.All(a => a.Change != ReferenceChangeType.Added) && rev.AttachmentReferences) { Logger.Log(LogLevel.Debug, $"Correcting description on '{rev.ToString()}'."); CorrectDescription(wi, _context.GetItem(rev.ParentOriginId), rev); } if (!string.IsNullOrEmpty(wi.History)) { Logger.Log(LogLevel.Debug, $"Correcting comments on '{rev.ToString()}'."); CorrectComment(wi, _context.GetItem(rev.ParentOriginId), rev); } SaveWorkItem(rev, wi); foreach (var wiAtt in rev.Attachments) { if (attachmentMap.TryGetValue(wiAtt.AttOriginId, out Attachment tfsAtt) && tfsAtt.IsSaved) { _context.Journal.MarkAttachmentAsProcessed(wiAtt.AttOriginId, tfsAtt.Id); } } if (rev.Attachments.Any(a => a.Change == ReferenceChangeType.Added) && rev.AttachmentReferences) { Logger.Log(LogLevel.Debug, $"Correcting description on separate revision on '{rev.ToString()}'."); try { if (CorrectDescription(wi, _context.GetItem(rev.ParentOriginId), rev)) { SaveWorkItem(rev, wi); } } catch (Exception ex) { Logger.Log(ex, $"Failed to correct description for '{wi.Id}', rev '{rev.ToString()}'."); } } _context.Journal.MarkRevProcessed(rev.ParentOriginId, wi.Id, rev.Index); Logger.Log(LogLevel.Debug, $"Imported revision."); wi.Close(); return(true); } catch (AbortMigrationException) { throw; } catch (Exception ex) { Logger.Log(ex, $"Failed to import revisions for '{wi.Id}'."); return(false); } }
public bool ImportRevision(WiRevision rev, WorkItem wi) { try { bool incomplete = false; if (rev.Index == 0) { EnsureClasificationFields(rev); } EnsureDateFields(rev); EnsureAuthorFields(rev); var attachmentMap = new Dictionary <string, Attachment>(); if (rev.Attachments.Any() && !ApplyAttachments(rev, wi, attachmentMap)) { incomplete = true; } if (rev.Fields.Any() && !UpdateWIFields(rev.Fields, wi)) { incomplete = true; } if (rev.Links.Any() && !ApplyLinks(rev, wi)) { incomplete = true; } if (incomplete) { Logger.Log(LogLevel.Warning, $"{rev.ToString()} - not all changes were implemented"); } if (!rev.Attachments.Any(a => a.Change == ReferenceChangeType.Added) && rev.AttachmentReferences) { Logger.Log(LogLevel.Info, $"Correcting description on {rev.ToString()}"); CorrectDescription(wi, _context.GetItem(rev.ParentOriginId), rev); } SaveWorkItem(rev, wi); if (rev.Attachments.Any(a => a.Change == ReferenceChangeType.Added) && rev.AttachmentReferences) { Logger.Log(LogLevel.Info, $"Correcting description on separate revision on {rev.ToString()}"); try { if (CorrectDescription(wi, _context.GetItem(rev.ParentOriginId), rev)) { SaveWorkItem(rev, wi); } } catch (Exception ex) { Logger.Log(ex); } } _context.Journal.MarkRevProcessed(rev.ParentOriginId, wi.Id, rev.Index); foreach (var wiAtt in rev.Attachments) { if (attachmentMap.TryGetValue(wiAtt.AttOriginId, out Attachment tfsAtt) && tfsAtt.IsSaved) { _context.Journal.MarkAttachmentAsProcessed(wiAtt.AttOriginId, tfsAtt.Id); } } Logger.Log(LogLevel.Info, $"Imported {rev.ToString()}"); wi.Close(); return(true); } catch (AbortMigrationException ame) { throw new AbortMigrationException(ame.Reason) { Revision = rev }; } catch (Exception ex) { Logger.Log(ex); return(false); } }