private List <Revision> FindUnsyncedRevisions( DateTime tfsWitWaterMark, ITranslationService translationService, Guid sourceId, IsWorkItemRevisionProcessed isRevisionProcessed) { int workItemId = WorkItem.Id; bool workItemHasReflectionOnTheOtherSide = WorkItemHasReflectionOnTheOtherSide(translationService, WorkItem.Id.ToString(), sourceId); List <Revision> retVal = new List <Revision>(WorkItem.Revisions.Count); foreach (Revision rev in WorkItem.Revisions) { int workItemRev = (int)rev.Fields[CoreField.Rev].Value; if (!workItemHasReflectionOnTheOtherSide) { // NOTE: in the case that a work item is not migrated before, we should include all its revisions // (including Rev1) in the delta table. The only exception is that we recorded to have computed // delta for a particular revision // it's possible we are re-processing the rev as we go back 60 sec in history // use the call back to eliminate the possible duplicates if (null != isRevisionProcessed && isRevisionProcessed(workItemId, workItemRev)) { continue; } else { retVal.Add(rev); } } else { // 1. skipping all revs that are prior to (HWM - 15sec) DateTime revChangeDate = ((DateTime)rev.Fields[CoreField.ChangedDate].Value).ToUniversalTime(); if (revChangeDate <= tfsWitWaterMark) { continue; } // for work items that have been sync-ed by the tool, check if this revision is generated by it if (workItemHasReflectionOnTheOtherSide && translationService.IsSyncGeneratedItemVersion(workItemId.ToString(), workItemRev.ToString(), sourceId)) { continue; } // it's possible we are re-processing the rev as we go back 60 sec in history // use the call back to eliminate the possible duplicates if (null != isRevisionProcessed && isRevisionProcessed(workItemId, workItemRev)) { continue; } retVal.Add(rev); } } return(retVal); }
internal void ComputeFieldDelta( ChangeGroupService changeGroupService, DateTime waterMarkChangeStartTime, FieldValueComparer tfsValueComparer, ITranslationService translationService, ConfigurationService configService, List <ChangeGroup> groups, IsWorkItemRevisionProcessed processedRevCallBack) { Guid sourceId = configService.SourceId; List <Revision> revsToBeSynced = FindUnsyncedRevisions(waterMarkChangeStartTime, translationService, sourceId, processedRevCallBack); Dictionary <int, object> fieldValueBaseline = new Dictionary <int, object>(); TryEstablishFieldValueBaseline(fieldValueBaseline, revsToBeSynced); foreach (Revision rev in revsToBeSynced) { // get basic revision info: revision#, author#, and change time int revIndex = (int)rev.Fields[CoreField.Rev].Value; string author = (string)rev.Fields[CoreField.ChangedBy].Value; if (string.IsNullOrEmpty(author)) { author = (string)rev.Fields[CoreField.AuthorizedAs].Value; } DateTime changedDate = (DateTime)rev.Fields[CoreField.ChangedDate].Value; List <Field> fieldForSync = new List <Field>(); List <Field> skippingFields = new List <Field>(); foreach (Field f in rev.Fields) { // filter out System.History with empty new value if (TFStringComparer.FieldName.Equals(f.ReferenceName, CoreFieldReferenceNames.History)) { if (string.IsNullOrEmpty(f.Value as string)) { continue; } } if (MustTakeField(f.FieldDefinition)) { // find out fields that changed in this revision object oldValue; fieldValueBaseline.TryGetValue(f.Id, out oldValue); //***Note: When it is a new work item (unmatched on the other side), // we need to always include fields if ((null != f.Value && (!tfsValueComparer.Equals(oldValue, f.Value) || revIndex == 1)) || (null == f.Value && null != oldValue && revIndex != 1)) { fieldForSync.Add(f); fieldValueBaseline[f.Id] = f.Value; } else if (IsReferencedField(f, configService)) { skippingFields.Add(f); } } else if (IsReferencedField(f, configService)) { skippingFields.Add(f); } } if (fieldForSync.Count == 0) { continue; } XmlDocument migrationActionDetails = CreateFieldRevisionDescriptionDoc( revIndex, author, changedDate, fieldForSync, skippingFields); Guid changeActionId = revIndex == 1 ? WellKnownChangeActionId.Add : WellKnownChangeActionId.Edit; /// TODO: consider batching revs of different workitems in one change group ChangeGroup changeGroup = changeGroupService.CreateChangeGroupForDeltaTable( string.Format("{0}:{1}", WorkItem.Id, revIndex)); IMigrationAction action = changeGroup.CreateAction( changeActionId, new TfsWITMigrationItem(WorkItem, revIndex), WorkItem.Id.ToString(), "", revIndex.ToString(), "", WellKnownContentType.WorkItem.ReferenceName, migrationActionDetails); groups.Add(changeGroup); } }