/// <summary> /// Converts a <see cref="MergedEntry"/> <paramref name="item"/> into a /// <see cref="IDirectoryDiffEntry"/> item and returns it. /// </summary> /// <param name="basePath"></param> /// <param name="item"></param> /// <returns></returns> private IDirectoryDiffEntry ConvertDirEntry(string basePath, MergedEntry item) { DirectoryDiffEntry newEntry = null; DateTime lastUpdateA = default(DateTime); DateTime lastUpdateB = default(DateTime); if (item.InfoA != null) { lastUpdateA = item.InfoA.LastWriteTime; } if (item.InfoB != null) { lastUpdateB = item.InfoB.LastWriteTime; } if (item.InfoA != null && item.InfoB != null) { // The item is in both directories if (this._ShowDifferent || this._ShowSame) { newEntry = new DirectoryDiffEntry(basePath, item.InfoA.Name, false, true, true, lastUpdateA, lastUpdateB); } } else if (item.InfoA != null && item.InfoB == null) { // The item is only in A if (this._ShowOnlyInA) { newEntry = new DirectoryDiffEntry(basePath, item.InfoA.Name, false, true, false, lastUpdateA, lastUpdateB); } } else { // The item is only in B if (this._ShowOnlyInB) { newEntry = new DirectoryDiffEntry(basePath, item.InfoB.Name, false, false, true, lastUpdateA, lastUpdateB); } } return(newEntry); }
/// <summary> /// Builds an initial directory structure that contains all sub-directories being contained /// in A and B (the structure ends at any point where a given directory occurs only in A or /// only in B). /// /// The structure is build with a Level Order traversal algorithm. /// /// Tip: Use a Post Order algorithm to look at each directory in the structure and aggregate /// results up-wards within the directory structure. /// </summary> /// <param name="dirA"></param> /// <param name="dirB"></param> /// <param name="recursive"></param> /// <param name="filter"></param> /// <param name="diffRoot"></param> /// <returns>A root diff entry that describes directory differences through its properties.</returns> private int BuildSubDirs(IDirectoryInfo dirA, IDirectoryInfo dirB, bool recursive, DirectoryDiffFileFilter filter, DirectoryDiffRoot diffRoot) { var queue = new Queue <Tuple <int, MergedEntry> >(); var index = new Dictionary <string, IDirectoryDiffEntry>(); // Associate root level entry with empty path since path associations // below works with RELATIVE path references to given root entries index.Add(string.Empty, diffRoot.RootEntry); // Assign base directories of level order traversal var root = new MergedEntry(dirA, dirB); queue.Enqueue(new Tuple <int, MergedEntry>(0, root)); while (queue.Count() > 0) { var queueItem = queue.Dequeue(); int iLevel = queueItem.Item1; MergedEntry current = queueItem.Item2; if (iLevel > 0) { string basePath = GetBasePath(diffRoot.RootPathA, current.InfoA, diffRoot.RootPathB, current.InfoB); string parentPath = GetParentPath(basePath); IDirectoryDiffEntry parentItem; if (index.TryGetValue(parentPath, out parentItem) == true) { var entry = ConvertDirEntry(basePath, current); if (entry != null) { index.Add(basePath, entry); parentItem.AddSubEntry(entry); parentItem.SetDiffBasedOnChildren(_IgnoreDirectoryComparison); } } else { // FIXME continue; // There are conditions for this case but these needs to be specified and tested here // // parentPath should always been pushed before since we do Level Order Traversal // So, it must be available here - something is horribly wrong if we ever got here ////throw new NotSupportedException(string.Format("ParentPath '{0}', BasePath '{1}'" //// , parentPath, basePath)); } } if (_Recursive || iLevel == 0) { // Process the node if either sub-directory has children IDirectoryInfo[] directoriesA = null; IDirectoryInfo[] directoriesB = null; // Get the arrays of subdirectories and merge them into 1 list if (current.InfoA != null) { directoriesA = ((IDirectoryInfo)current.InfoA).GetDirectories(); } else { directoriesA = null; } if (current.InfoB != null) { directoriesB = ((IDirectoryInfo)current.InfoB).GetDirectories(); } else { directoriesB = null; } // Merge them and Diff them var mergeIdx = new Merge.MergeIndex(directoriesA, directoriesB, false, _ShowOnlyInA, _ShowOnlyInB); mergeIdx.Merge(); foreach (var item in mergeIdx.MergedEntries) { queue.Enqueue(new Tuple <int, MergedEntry>(iLevel + 1, item)); } } } return(index.Count); }