Esempio n. 1
0
        /// <summary>
        /// Entry point to start traversing and comparing files
        /// </summary>
        /// <param name="source">Source folder</param>
        /// <param name="destination">Destination folder</param>
        /// <param name="startDirScan">IProgress to indicate number of folders scanned so far and the name of the folder being currently inspected</param>
        /// <returns></returns>
        public async Task Compare(string source, string destination, IProgress<string> startDirScan)
        {
            await Task.Run(() =>
            {
                AllDifferences = new ConcurrentBag<FileDiff>();
                SourceRootFolder = source;
                DestinationRootFolder = destination;
                try
                {
                    TraverseTreeParallelForEach(
                        (sourceDirectory, destinationDirectory) =>
                        {
                            try
                            {
                                startDirScan.Report(string.Format("Comparing {0} :: {1}", TotalDirectories, sourceDirectory.FullName));

                                var sourceFiles = sourceDirectory.EnumerateFiles();
                                var destinationFiles = destinationDirectory.EnumerateFiles();

                                FileSystemCompare compareByName = new FileSystemCompare();
                                FileCompare comparer = new FileCompare();

                                var onlyInSource = sourceFiles.Except(destinationFiles, compareByName);
                                var onlyInDest = destinationFiles.Except(sourceFiles, compareByName);
                                var inBothLists = sourceFiles.Intersect(destinationFiles, compareByName);

                                foreach (var item in onlyInSource)
                                {
                                    if (!isExclusion(item.FullName))
                                        AllDifferences.Add(new FileDiff()
                                        {
                                            Source = item,
                                            Destination = null,
                                            DifferenceType = DiffType.ExistInSourceOnly,
                                            ItemType = ItemType.File
                                        });
                                }
                                foreach (var item in onlyInDest)
                                {
                                    if (!isExclusion(item.FullName))
                                        AllDifferences.Add(new FileDiff()
                                        {
                                            Source = null,
                                            Destination = item,
                                            DifferenceType = DiffType.ExistInDestinationOnly,
                                            ItemType = ItemType.File
                                        });
                                }
                                foreach (var item in inBothLists)
                                {
                                    FileInfo destItem = destinationFiles.FirstOrDefault(x => x.Name == item.Name);
                                    if (!isExclusion(item.FullName) && !comparer.ExternalCompare(item as FileInfo, destItem))
                                    {
                                        var itemFile = item as FileInfo;
                                        DiffType type = DiffType.None;

                                        if (!itemFile.LastWriteTimeUtc.ToString("yyyyMMMddHHmmss").Equals(destItem.LastWriteTimeUtc.ToString("yyyyMMMddHHmmss")))
                                            type = DiffType.LastWritten;

                                        if (!itemFile.Length.Equals(destItem.Length))
                                            type = DiffType.Lenght;

                                        AllDifferences.Add(new FileDiff()
                                        {
                                            Source = item,
                                            Destination = destItem,
                                            DifferenceType = type,
                                            ItemType = ItemType.File
                                        });
                                    }
                                }
                            }
                            catch (FileNotFoundException) { }
                            catch (IOException) { }
                            catch (UnauthorizedAccessException) { }
                            catch (SecurityException) { }
                        }
                    );
                }
                catch (ArgumentException)
                {
                    Console.WriteLine(string.Format("The directory {0} does not exist", source));
                }
            });
        }
Esempio n. 2
0
        /// <summary>
        /// Traverse routine using TPL, for each directory spawn a thread and compare the files in it against the source folder (if a matching file exists).
        /// https://msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx
        /// </summary>
        /// <param name="directoryCompareAction">Delegated action of what to do for comparing files in a direcotry level</param>
        private void TraverseTreeParallelForEach(Action<DirectoryInfo, DirectoryInfo> directoryCompareAction)
        {
            //Count of files traversed and timer for diagnostic output 
            int directoryCount = 0;
            var sw = Stopwatch.StartNew();

            // Determine whether to parallelize file processing on each folder based on processor count. 
            int procCount = Environment.ProcessorCount;

            // Data structure to hold names of subfolders to be examined for files.
            Stack<DirectoryInfo> sourceDirectories = new Stack<DirectoryInfo>();

            if (!Directory.Exists(SourceRootFolder))
            {
                throw new ArgumentException();
            }
            if (!Directory.Exists(DestinationRootFolder))
            {
                throw new ArgumentException();
            }

            directoryCompareAction(new DirectoryInfo(SourceRootFolder), new DirectoryInfo(DestinationRootFolder));
            sourceDirectories.Push(new DirectoryInfo(SourceRootFolder));

            while (sourceDirectories.Count > 0)
            {
                DirectoryInfo sourceDir = sourceDirectories.Pop();
                DirectoryInfo destinationDir = null;
                IEnumerable<DirectoryInfo> sourceSubDirs = null;
                IEnumerable<DirectoryInfo> destinationSubDirs = null;
                FileSystemCompare compareByName = new FileSystemCompare();

                try
                {
                    var destinationDirString = TranslateDirectoryPath(sourceDir.FullName);
                    if (isExclusion(destinationDirString) || isExclusion(sourceDir.FullName))
                    {
                        //This only prevents passing through the directory, but does not prevent adding the item to the list
                        continue;
                    }
                    else if (Directory.Exists(destinationDirString))
                    {
                        destinationDir = new DirectoryInfo(destinationDirString);
                        sourceSubDirs = sourceDir.EnumerateDirectories();
                        destinationSubDirs = destinationDir.EnumerateDirectories();
                        //extract source and dest and compare
                        var onlyInSource = sourceSubDirs.Except(destinationSubDirs, compareByName);
                        var onlyInDest = destinationSubDirs.Except(sourceSubDirs, compareByName);
                        //all exceptions add to list TODO
                        foreach (var item in onlyInSource)
                        {
                            if (!isExclusion(item.FullName))
                                AllDifferences.Add(new FileDiff()
                                {
                                    Source = item,
                                    Destination = null,
                                    DifferenceType = DiffType.ExistInSourceOnly,
                                    ItemType = ItemType.Folder
                                });
                        }
                        foreach (var item in onlyInDest)
                        {
                            if (!isExclusion(item.FullName))
                                AllDifferences.Add(new FileDiff()
                                {
                                    Source = null,
                                    Destination = item,
                                    DifferenceType = DiffType.ExistInDestinationOnly,
                                    ItemType = ItemType.Folder
                                });
                        }

                        //only navigate what exists in both
                        var inBothLists = sourceSubDirs.Intersect(destinationSubDirs, compareByName);
                        foreach (var item in inBothLists)
                        {
                            sourceDirectories.Push(item as DirectoryInfo);
                        }
                    }
                    else
                    {
                        //add to exceptions, destination folder does not exist
                        AllDifferences.Add(new FileDiff()
                        {
                            Source = sourceDir,
                            Destination = null,
                            DifferenceType = DiffType.ExistInSourceOnly,
                            ItemType = ItemType.Folder
                        });
                    }
                }
                // Thrown if we do not have discovery permission on the directory. 
                catch (UnauthorizedAccessException e)
                {
                    Console.WriteLine(e.Message);
                    continue;
                }
                // Thrown if another process has deleted the directory after we retrieved its name. 
                catch (DirectoryNotFoundException e)
                {
                    Console.WriteLine(e.Message);
                    continue;
                }

                try
                {
                    Parallel.ForEach(sourceSubDirs, () => 0, (sourceSubDir, loopState, localCount) =>
                    {
                        var destinationSubDir = TranslateDirectoryPath(sourceSubDir.FullName);
                        directoryCompareAction(sourceSubDir, new DirectoryInfo(destinationSubDir));
                        return (int)++localCount;
                    },
                    (c) =>
                    {
                        Interlocked.Add(ref directoryCount, c);
                    });
                    TotalDirectories = directoryCount;
                }
                catch (AggregateException ae)
                {
                    ae.Handle((ex) => {
                        if (ex is UnauthorizedAccessException)
                        {
                            // Here we just output a message and go on.
                            Console.WriteLine(ex.Message);
                            return true;
                        }
                        // Handle other exceptions here if necessary... 

                        return false;
                    });
                }
            }
            TotalDirectories = directoryCount;
        }