private void CompareWorkItemsFromOneSideToTheOther(
            string side1FilterString,
            string side1MigrationSourceId,
            MigrationSource side1MigrationSource,
            MigrationSource side2MigrationSource,
            IWITDiffProvider side1DiffProvider,
            IWITDiffProvider side2DiffProvider,
            string side1QueryCondition,
            HashSet <string> moreSide1FieldNamesToIgnore,
            HashSet <string> moreSide2FieldNamesToIgnore)
        {
            // Only left query condition specified
            side1DiffProvider.InitializeForDiff(side1FilterString, !m_serverDiffEngine.NoContentComparison);
            side2DiffProvider.InitializeForDiff(string.Empty, !m_serverDiffEngine.NoContentComparison);

            if (m_serverDiffEngine.NoContentComparison)
            {
                m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture, MigrationToolkitResources.WitDiffNoContentComparison));
            }

            foreach (IWITDiffItem side1WitDiffItem in side1DiffProvider.GetWITDiffItems(side1QueryCondition))
            {
                bool skipCurrentWorkItem      = false;
                bool fieldValuesMismatch      = false;
                Guid side1MigrationSourceGuid = new Guid(side1MigrationSourceId);

                IWITDiffItem side2WitDiffItem = null;
                string       side2WorkItemId  = TranslationService.TryGetTargetItemId(side1WitDiffItem.WorkItemId, side1MigrationSourceGuid);
                if (!string.IsNullOrEmpty(side2WorkItemId))
                {
                    side2WitDiffItem = side2DiffProvider.GetWITDiffItem(side2WorkItemId);
                }
                if (side2WitDiffItem == null)
                {
                    HandleDifference(new WitDiffPair(WitDiffType.NotMirrored,
                                                     side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem));
                    continue;
                }

                if (m_serverDiffEngine.NoContentComparison)
                {
                    /* Uncomment for debugging
                     * m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture, "Corresponding work item with Id {0} found on '{1}' for work item with Id {2} on '{3}",
                     *  side2WorkItemId, side2MigrationSource.FriendlyName, side1WitDiffItem.WorkItemId, side1MigrationSource.FriendlyName));
                     */
                }
                else
                {
                    TranslationService.MapWorkItemTypeFieldValues(side1WitDiffItem.WorkItemId, side1WitDiffItem.WorkItemDetails, side1MigrationSourceGuid);

                    XmlElement       side1RootElement     = side1WitDiffItem.WorkItemDetails.DocumentElement;
                    XmlElement       side2RootElement     = side2WitDiffItem.WorkItemDetails.DocumentElement;
                    HashSet <string> side2AttributesFound = new HashSet <string>();
                    foreach (XmlAttribute side1Attribute in side1RootElement.Attributes)
                    {
                        if (side1DiffProvider.IgnoreFieldInComparison(side1Attribute.Name) ||
                            side2DiffProvider.IgnoreFieldInComparison(side1Attribute.Name) ||
                            moreSide1FieldNamesToIgnore.Contains(side1Attribute.Name) ||
                            moreSide2FieldNamesToIgnore.Contains(side1Attribute.Name))
                        {
                            continue;
                        }

                        /* Uncomment for debugging
                         * m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture,
                         *  "Comparing field '{0}' from source '{1}'",
                         *  side1Attribute.Name, side1MigrationSource.FriendlyName));
                         */

                        string side2AttributeValue = side2RootElement.GetAttribute(side1Attribute.Name);
                        if (string.IsNullOrEmpty(side2AttributeValue))
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.DefinitionMismatch,
                                                                   side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                            diffPair.AddMissingField(new WitDiffMissingField(side1Attribute.Name, side1MigrationSource.FriendlyName));
                            skipCurrentWorkItem = HandleDifference(diffPair);
                            break;
                        }
                        side2AttributesFound.Add(side1Attribute.Name);
                        if (!string.Equals(side1Attribute.Value, side2AttributeValue, StringComparison.OrdinalIgnoreCase))
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.DataMismatch,
                                                                   side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                            diffPair.AddMismatchField(new WitDiffField(side1Attribute.Name, side1Attribute.Value, side2AttributeValue));
                            skipCurrentWorkItem = HandleDifference(diffPair);
                            break;
                        }
                        else
                        {
                            /* Uncomment for debugging
                             * m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture, "Match: The header field '{0}' for work item {1} has value '{2}' on both sides",
                             *  side1Attribute.Name, side1WitDiffItem.WorkItemId, side1Attribute.Value));
                             */
                        }
                    }
                    if (skipCurrentWorkItem)
                    {
                        continue;
                    }

                    foreach (XmlAttribute side2Attribute in side2RootElement.Attributes)
                    {
                        if (!side1DiffProvider.IgnoreFieldInComparison(side2Attribute.Name) &&
                            !side2DiffProvider.IgnoreFieldInComparison(side2Attribute.Name) &&
                            !moreSide1FieldNamesToIgnore.Contains(side2Attribute.Name) &&
                            !moreSide2FieldNamesToIgnore.Contains(side2Attribute.Name) &&
                            !side2AttributesFound.Contains(side2Attribute.Name))
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.DefinitionMismatch,
                                                                   side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                            diffPair.AddMissingField(new WitDiffMissingField(side2Attribute.Name, side2MigrationSource.FriendlyName));
                            skipCurrentWorkItem = HandleDifference(diffPair);
                            break;
                        }
                    }
                    if (skipCurrentWorkItem)
                    {
                        continue;
                    }

                    XmlNodeList side1Columns = side1RootElement.SelectNodes("/WorkItemChanges/Columns/Column");
                    if (null == side1Columns)
                    {
                        m_diffResult.ProcessingErrors.Add(String.Format(CultureInfo.InvariantCulture, ServerDiffResources.InvalidXMLDocumentForDiffItem,
                                                                        side1MigrationSource.FriendlyName));
                        continue;
                    }

                    XmlNodeList side2Columns = side2RootElement.SelectNodes("/WorkItemChanges/Columns/Column");
                    if (null == side2Columns)
                    {
                        m_diffResult.ProcessingErrors.Add(String.Format(CultureInfo.InvariantCulture, ServerDiffResources.InvalidXMLDocumentForDiffItem,
                                                                        side2MigrationSource.FriendlyName));
                        continue;
                    }

                    Dictionary <string, XmlNode> side2ColumnsByReferenceName = new Dictionary <string, XmlNode>();
                    foreach (XmlNode side2Column in side2Columns)
                    {
                        string referenceName = GetReferenceNameFromFieldColumn(side2Column);
                        if (referenceName != null)
                        {
                            if (!side2ColumnsByReferenceName.ContainsKey(referenceName))
                            {
                                side2ColumnsByReferenceName.Add(referenceName, side2Column);
                            }
                        }
                    }

                    for (int i = 0; i < side1Columns.Count; i++)
                    {
                        XmlNode side1Column        = side1Columns[i];
                        string  side1ReferenceName = GetReferenceNameFromFieldColumn(side1Column);
                        if (side1ReferenceName == null)
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.InvalidDefinition, side1MigrationSource.FriendlyName, side1WitDiffItem);
                            skipCurrentWorkItem = HandleDifference(diffPair, true);
                            break;
                        }
                        XmlNode side2Column;
                        if (!side2ColumnsByReferenceName.TryGetValue(side1ReferenceName, out side2Column))
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.DefinitionMismatch,
                                                                   side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);

                            diffPair.AddMissingField(new WitDiffMissingField(side1ReferenceName, side1MigrationSource.FriendlyName));

                            skipCurrentWorkItem = HandleDifference(diffPair, true);
                            break;
                        }
                        string side2ReferenceName = GetReferenceNameFromFieldColumn(side2Column);
                        // Remove the side2Column from the Dictionary
                        side2ColumnsByReferenceName.Remove(side2ReferenceName);

                        string fieldDisplayName = null;

                        const string c_displayName    = "DisplayName";
                        XmlAttribute side1DisplayName = side1Column.Attributes[c_displayName];
                        if (side1DisplayName != null && !string.IsNullOrEmpty(side1DisplayName.Value))
                        {
                            fieldDisplayName = side1DisplayName.Value;
                        }
                        else
                        {
                            fieldDisplayName = side1ReferenceName;
                        }

                        if (!side1DiffProvider.IgnoreFieldInComparison(side1ReferenceName) &&
                            !side2DiffProvider.IgnoreFieldInComparison(side1ReferenceName) &&
                            !moreSide1FieldNamesToIgnore.Contains(side1ReferenceName) &&
                            !moreSide2FieldNamesToIgnore.Contains(side1ReferenceName))
                        {
                            if (!side1Column.HasChildNodes)
                            {
                                m_diffResult.ProcessingErrors.Add(String.Format(MigrationToolkitResources.WitDiffWorkItemDescriptionMissingChildNodes,
                                                                                side1WitDiffItem.WorkItemId, side1MigrationSource.FriendlyName, side1Column.Name));
                                continue;
                            }
                            if (!side2Column.HasChildNodes)
                            {
                                m_diffResult.ProcessingErrors.Add(String.Format(MigrationToolkitResources.WitDiffWorkItemDescriptionMissingChildNodes,
                                                                                side2WitDiffItem.WorkItemId, side2MigrationSource.FriendlyName, side2Column.Name));
                                continue;
                            }

                            XmlNode side1ValueNode = side1Column.FirstChild;
                            XmlNode side2ValueNode = side2Column.FirstChild;
                            if (!string.Equals(side1ValueNode.InnerText.Replace("\r\n", "\n"), side2ValueNode.InnerText.Replace("\r\n", "\n"), StringComparison.OrdinalIgnoreCase))
                            {
                                WitDiffPair diffPair = new WitDiffPair(WitDiffType.DataMismatch,
                                                                       side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                                diffPair.AddMismatchField(new WitDiffField(fieldDisplayName, side1ValueNode.InnerText, side2ValueNode.InnerText));
                                skipCurrentWorkItem = HandleDifference(diffPair);
                                // If there's a data mismatch, continue to compare fields to report additional data mismatches
                                // unless HandleDifference returns true to skip the entire work item
                                if (skipCurrentWorkItem)
                                {
                                    break;
                                }
                                fieldValuesMismatch = true;
                            }
                            else
                            {
                                /* Uncomment for debugging
                                 * m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture, "Match: The field '{0}' for work item {1} has value '{2}' on both sides",
                                 *  fieldDisplayName, side1WitDiffItem.WorkItemId, side1ValueNode.InnerText));
                                 */
                            }
                        }
                    }

                    bool attachmentsMismatch = false;
                    bool linksMismatch       = false;
                    if (!skipCurrentWorkItem)
                    {
                        // Compare Attachments
                        if (side1WitDiffItem.Attachments.Count != side2WitDiffItem.Attachments.Count)
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.AttachmentCount,
                                                                   side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                            skipCurrentWorkItem = HandleDifference(diffPair);
                            attachmentsMismatch = true;
                        }
                        else
                        {
                            Dictionary <string, IMigrationFileAttachment> side2AttachmentsById = new Dictionary <string, IMigrationFileAttachment>();
                            foreach (IMigrationFileAttachment side2Attachment in side2WitDiffItem.Attachments)
                            {
                                string attachmentId = GetAttachmentId(side2Attachment);
                                if (!side2AttachmentsById.ContainsKey(attachmentId))
                                {
                                    side2AttachmentsById.Add(attachmentId, side2Attachment);
                                }
                            }
                            HashSet <string> side1AttachmentIds = new HashSet <string>();
                            foreach (IMigrationFileAttachment side1Attachment in side1WitDiffItem.Attachments)
                            {
                                string side1AttachmentId = GetAttachmentId(side1Attachment);
                                if (side1AttachmentIds.Contains(side1AttachmentId))
                                {
                                    // This is a duplicate attachment; continue to ignore the duplicate
                                    continue;
                                }
                                side1AttachmentIds.Add(side1AttachmentId);
                                IMigrationFileAttachment side2Attachment;
                                if (side2AttachmentsById.TryGetValue(side1AttachmentId, out side2Attachment))
                                {
                                    side2AttachmentsById.Remove(side1AttachmentId);
                                    WitDiffAttachment diffAttachment;
                                    if (!AttachmentsMatch(side1Attachment, side2Attachment, out diffAttachment))
                                    {
                                        WitDiffPair diffPair = new WitDiffPair(WitDiffType.AttachmentMismatch,
                                                                               side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                                        diffPair.AddMistmatchedAttachment(diffAttachment);
                                        skipCurrentWorkItem = HandleDifference(diffPair);
                                        attachmentsMismatch = true;
                                    }
                                }
                                else
                                {
                                    WitDiffPair diffPair = new WitDiffPair(WitDiffType.AttachmentMissing,
                                                                           side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                                    diffPair.AddMissingAttachment(side1Attachment.Name);
                                    skipCurrentWorkItem = HandleDifference(diffPair);
                                    attachmentsMismatch = true;
                                }
                                if (skipCurrentWorkItem)
                                {
                                    break;
                                }
                            }

                            if (!skipCurrentWorkItem)
                            {
                                // Any attachments still in side2AttachmentsByKey were not in side1
                                foreach (IMigrationFileAttachment side2Attachment in side2AttachmentsById.Values)
                                {
                                    WitDiffPair diffPair = new WitDiffPair(WitDiffType.AttachmentMissing,
                                                                           side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                                    diffPair.AddMissingAttachment(side2Attachment.Name);
                                    skipCurrentWorkItem = HandleDifference(diffPair);
                                    attachmentsMismatch = true;
                                }
                            }
                        }
                    }

                    if (!skipCurrentWorkItem)
                    {
                        // Compare links
                        if (side1WitDiffItem.Links.Count != side2WitDiffItem.Links.Count)
                        {
                            WitDiffPair diffPair = new WitDiffPair(WitDiffType.LinkCount,
                                                                   side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                            skipCurrentWorkItem = HandleDifference(diffPair);
                            linksMismatch       = true;
                        }

                        /* Commenting out the detailed comparison of each link for now as it does not work because the link artifact URIs
                         * need to be translated.  This requires some refactoring of translation methods current embedded in the LinkEngine
                         * that are not easily used outside the context of a full running migration/sync session.
                         * else
                         * {
                         *  Dictionary<string, ILink> side2LinksById = new Dictionary<string, ILink>();
                         *  foreach (ILink side2Link in side2WitDiffItem.Links)
                         *  {
                         *      string side2LinkId = GetLinkId(side2Link);
                         *      if (!side2LinksById.ContainsKey(side2LinkId))
                         *      {
                         *          side2LinksById.Add(side2LinkId, side2Link);
                         *      }
                         *  }
                         *  foreach (ILink side1Link in side1WitDiffItem.Links)
                         *  {
                         *      ILink side2Link;
                         *      string side1LinkId = GetLinkId(side1Link);
                         *      if (side2LinksById.TryGetValue(side1LinkId, out side2Link))
                         *      {
                         *          side2LinksById.Remove(side1LinkId);
                         *          WitDiffLink diffLink;
                         *          if (!LinksMatch(new Guid(side1MigrationSource.InternalUniqueId), side1Link, new Guid(side2MigrationSource.InternalUniqueId), side2Link, out diffLink))
                         *          {
                         *              WitDiffPair diffPair = new WitDiffPair(WitDiffType.LinkMismatch,
                         *                  side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                         *              diffPair.AddMistmatchedLink(diffLink);
                         *              skipCurrentWorkItem = HandleDifference(diffPair);
                         *              linksMismatch = true;
                         *              break;
                         *          }
                         *
                         *      }
                         *      else
                         *      {
                         *          WitDiffPair diffPair = new WitDiffPair(WitDiffType.LinkMisssing,
                         *              side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                         *          diffPair.AddMissingLink(side1LinkId);
                         *          skipCurrentWorkItem = HandleDifference(diffPair);
                         *          linksMismatch = true;
                         *      }
                         *  }
                         *
                         *  if (!skipCurrentWorkItem)
                         *  {
                         *      // Any links still in side2LinksById were not in side1
                         *      foreach (ILink side2link in side2LinksById.Values)
                         *      {
                         *          WitDiffPair diffPair = new WitDiffPair(WitDiffType.LinkMisssing,
                         *              side1MigrationSource.FriendlyName, side1WitDiffItem, side2MigrationSource.FriendlyName, side2WitDiffItem);
                         *          diffPair.AddMissingLink(GetLinkId(side2link));
                         *          skipCurrentWorkItem = HandleDifference(diffPair);
                         *          linksMismatch = true;
                         *      }
                         *  }
                         * }
                         */
                    }

                    if (skipCurrentWorkItem || fieldValuesMismatch || attachmentsMismatch || linksMismatch)
                    {
                        continue;
                    }

                    m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture, MigrationToolkitResources.WitDiffWorkItemsMatch,
                                                                side1WitDiffItem.WorkItemId, side1MigrationSource.FriendlyName, side2WorkItemId, side2MigrationSource.FriendlyName));
                }
            }
        }
        public bool VerifyContentsMatch(string sourceVersion, string targetVersion)
        {
            Stopwatch stopWatch = Stopwatch.StartNew();

            Trace.WriteLine(String.Format(CultureInfo.InvariantCulture,
                                          "Entering VCDiffComparer.VerifyContentsMatch: sourceVersion: {0}, targetVersion: {1}",
                                          sourceVersion == null ? "latest" : sourceVersion,
                                          targetVersion == null ? "latest" : targetVersion));

            List <IVCDiffItem> sourceRootDiffItems = new List <IVCDiffItem>();
            List <IVCDiffItem> targetRootDiffItems = new List <IVCDiffItem>();

            bool contentMatch     = true;
            int  foldersProcessed = 0;
            int  filesProcessed   = 0;

            try
            {
                Stack <IVCDiffItem> sourceFolders = new Stack <IVCDiffItem>();
                Queue <IVCDiffItem> sourceFiles   = new Queue <IVCDiffItem>();

                Dictionary <string, IVCDiffItem> targetFolders = new Dictionary <string, IVCDiffItem>(StringComparer.InvariantCultureIgnoreCase);
                Dictionary <string, IVCDiffItem> targetFiles   = new Dictionary <string, IVCDiffItem>(StringComparer.InvariantCultureIgnoreCase);

                List <string> sourceCloakList = new List <string>();
                List <string> targetCloakList = new List <string>();

                foreach (var filterPair in m_serverDiffEngine.Session.Filters.FilterPair)
                {
                    if (filterPair.Neglect)
                    {
                        // TODO: Need to deal with translating paths for cloaked filter pairs into the canonical relative form used by IVCDiffItem.Path !!!
                        sourceCloakList.Add(GetSourceFilterString(filterPair));
                        targetCloakList.Add(GetTargetFilterString(filterPair));
                    }
                }

                foreach (var filterPair in m_serverDiffEngine.Session.Filters.FilterPair)
                {
                    if (!filterPair.Neglect)
                    {
                        sourceFolders.Clear();
                        sourceFiles.Clear();
                        targetFolders.Clear();
                        targetFiles.Clear();

                        // Always go 1 level down to avoid too large query
                        string      sourceFilterString = GetSourceFilterString(filterPair);
                        IVCDiffItem sourceDiffRootItem = SourceVCDiffProvider.InitializeForDiff(sourceFilterString, sourceVersion);
                        if (sourceDiffRootItem != null)
                        {
                            if (sourceDiffRootItem.VCItemType == VCItemType.Folder)
                            {
                                sourceFolders.Push(sourceDiffRootItem);
                            }
                            else
                            {
                                sourceFiles.Enqueue(sourceDiffRootItem);
                            }
                            sourceRootDiffItems.Add(sourceDiffRootItem);
                        }

                        string      targetFilterString = GetTargetFilterString(filterPair);
                        IVCDiffItem targetDiffRootItem = TargetVCDiffProvider.InitializeForDiff(targetFilterString, targetVersion);
                        if (targetDiffRootItem != null)
                        {
                            if (targetDiffRootItem.VCItemType == VCItemType.Folder)
                            {
                                targetFolders.Add(targetDiffRootItem.ServerPath, targetDiffRootItem);
                            }
                            else
                            {
                                targetFiles.Add(targetDiffRootItem.ServerPath, targetDiffRootItem);
                            }
                            targetRootDiffItems.Add(targetDiffRootItem);
                        }

                        while (sourceFiles.Count > 0 | sourceFolders.Count > 0 | targetFiles.Count > 0 | targetFolders.Count > 0)
                        {
                            while (sourceFiles.Count > 0)
                            {
                                IVCDiffItem sourceItem = sourceFiles.Dequeue();
                                if (sourceItem.VCItemType != VCItemType.File)
                                {
                                    Debug.Fail("VerifyContentMatch: Found IVCDiffItem that is not type File in the sourceFiles queue");
                                    continue;
                                }
                                string targetPath = TranslationService.GetMappedPath(sourceItem.ServerPath, new Guid(m_serverDiffEngine.Session.LeftMigrationSourceUniqueId));

                                if (targetPath == null || !targetFiles.ContainsKey(targetPath))
                                {
                                    m_serverDiffEngine.LogError(string.Format(CultureInfo.InvariantCulture, ServerDiffResources.ItemOnlyFoundOnSource, sourceItem.ServerPath));
                                    contentMatch = false;
                                }
                                else
                                {
                                    bool fileContentsMatch = ContentsMatch(sourceItem.HashValue, targetFiles[targetPath].HashValue);
                                    if (fileContentsMatch)
                                    {
                                        m_serverDiffEngine.LogVerbose(String.Format(CultureInfo.InvariantCulture, ServerDiffResources.FilesMatch,
                                                                                    sourceItem.ServerPath, targetPath));
                                    }
                                    else
                                    {
                                        contentMatch = false;
                                        m_serverDiffEngine.LogError(string.Format(CultureInfo.InvariantCulture, ServerDiffResources.ItemContentDoesNotMatch, sourceItem.ServerPath));
                                    }
                                    targetFiles.Remove(targetPath);
                                }
                                filesProcessed++;
                            }

                            foreach (KeyValuePair <string, IVCDiffItem> remainingFile in targetFiles)
                            {
                                m_serverDiffEngine.LogError(string.Format(CultureInfo.InvariantCulture, ServerDiffResources.ItemOnlyFoundOnTarget, remainingFile.Key));
                                contentMatch = false;
                            }

                            Debug.Assert(sourceFiles.Count == 0);
                            targetFiles.Clear();

                            if (sourceFolders.Count > 0)
                            {
                                IVCDiffItem sourceFolder = sourceFolders.Pop();
                                m_serverDiffEngine.LogVerbose(string.Format(CultureInfo.InvariantCulture, ServerDiffResources.ProcessingSourceFolder, sourceFolder.ServerPath));

                                string targetFolder = TranslationService.GetMappedPath(sourceFolder.ServerPath, new Guid(m_serverDiffEngine.Session.LeftMigrationSourceUniqueId));

                                if (targetFolder != null && targetFolders.ContainsKey(targetFolder))
                                {
                                    // Always go 1 level down to avoid too large query
                                    IEnumerable <IVCDiffItem> sourceDiffItems = SourceVCDiffProvider.GetFolderSubDiffItems(sourceFolder);
                                    foreach (IVCDiffItem diffItem in sourceDiffItems)
                                    {
                                        if (isCloaked(SourceVCDiffProvider, diffItem, sourceCloakList))
                                        {
                                            continue;
                                        }
                                        if (diffItem.VCItemType == VCItemType.File)
                                        {
                                            sourceFiles.Enqueue(diffItem);
                                        }
                                        else
                                        {
                                            sourceFolders.Push(diffItem);
                                        }
                                    }

                                    IEnumerable <IVCDiffItem> targetDiffItems = TargetVCDiffProvider.GetFolderSubDiffItems(targetFolders[targetFolder]);
                                    foreach (IVCDiffItem diffItem in targetDiffItems)
                                    {
                                        if (isCloaked(TargetVCDiffProvider, diffItem, targetCloakList))
                                        {
                                            continue;
                                        }
                                        if (diffItem.VCItemType == VCItemType.File)
                                        {
                                            if (!targetFiles.ContainsKey(diffItem.ServerPath))
                                            {
                                                targetFiles.Add(diffItem.ServerPath, diffItem);
                                            }
                                        }
                                        else
                                        {
                                            if (!targetFolders.ContainsKey(diffItem.ServerPath))
                                            {
                                                targetFolders.Add(diffItem.ServerPath, diffItem);
                                            }
                                        }
                                    }
                                    targetFolders.Remove(targetFolder);
                                    if (++foldersProcessed % 100 == 0)
                                    {
                                        m_serverDiffEngine.LogInfo(String.Format(CultureInfo.InvariantCulture, "Processed {0} source folders containing {1} files ...",
                                                                                 foldersProcessed, filesProcessed));
                                    }
                                }
                                else
                                {
                                    m_serverDiffEngine.LogError(string.Format(CultureInfo.InvariantCulture, ServerDiffResources.ItemOnlyFoundOnSource, sourceFolder.ServerPath));
                                    contentMatch = false;
                                }
                            }
                            else
                            {
                                foreach (KeyValuePair <string, IVCDiffItem> remainingFolder in targetFolders)
                                {
                                    m_serverDiffEngine.LogError(string.Format(CultureInfo.InvariantCulture, ServerDiffResources.ItemOnlyFoundOnTarget, remainingFolder.Key));
                                    contentMatch = false;
                                }
                                targetFolders.Clear();
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Trace.WriteLine("Exception occurred while verifying contents match: " + e.ToString());
                throw;
            }
            finally
            {
                if (SourceVCDiffProvider != null)
                {
                    foreach (IVCDiffItem sourceRootDiffItem in sourceRootDiffItems)
                    {
                        SourceVCDiffProvider.Cleanup(sourceRootDiffItem);
                    }
                }
                if (TargetVCDiffProvider != null)
                {
                    foreach (IVCDiffItem targetRootDiffItem in targetRootDiffItems)
                    {
                        TargetVCDiffProvider.Cleanup(targetRootDiffItem);
                    }
                }
                stopWatch.Stop();
                m_serverDiffEngine.LogInfo(String.Format(CultureInfo.InvariantCulture, ServerDiffResources.VCServerDiffTimeToRun,
                                                         stopWatch.Elapsed.TotalSeconds));
                m_serverDiffEngine.LogInfo(String.Format(CultureInfo.InvariantCulture, "Processed a total of {0} source folders containing {1} files",
                                                         foldersProcessed, filesProcessed));
            }

            Trace.WriteLine("VCDiffComparer.VerifyContentsMatch result: " + contentMatch);

            return(contentMatch);
        }