Esempio n. 1
0
        /// <summary>
        ///
        /// </summary>
        /// <remarks>
        /// Ok to assume that we can delete files and directories in directories that are already deleted. (Operations will be executed in idempotent manner.)
        /// </remarks>
        public FileSystemCloningDifference PerformDifference(
            IEnumerable <FileSystemEntry> sourceFileSystemEntries,
            IEnumerable <FileSystemEntry> destinationFileSystemEntries,
            FileSystemCloningOptions options)
        {
            var sourceDirectoryEntries      = sourceFileSystemEntries.Where(x => x.IsDirectory());
            var sourceFileEntries           = sourceFileSystemEntries.Where(x => x.IsFile());
            var destinationDirectoryEntries = destinationFileSystemEntries.Where(x => x.IsDirectory());
            var destinationFileEntries      = destinationFileSystemEntries.Where(x => x.IsFile());

            var pathOnlyEqualityComparer = new PathOnlyFileSystemEntryEqualityComparer();

            var difference = new FileSystemCloningDifference();

            // Create all directories that exist in the source, but not in the destination.
            var directoriesToCreate = sourceDirectoryEntries.Except(destinationDirectoryEntries, pathOnlyEqualityComparer);

            difference.RelativeDirectoryPathsToCreate.AddRange(directoriesToCreate.Select(x => x.Path));

            if (options.DeleteExtraneousDestinationDirectories)
            {
                // Delete all directories that exist in the destination, but not in the source. (Make this an option!)
                var directoriesToDelete = destinationDirectoryEntries.Except(sourceDirectoryEntries, pathOnlyEqualityComparer);

                difference.RelativeDirectoryPathsToDelete.AddRange(directoriesToDelete.Select(x => x.Path));
            }

            // Copy all files that exist in the source, but not in the destination.
            var filesToCopy = sourceFileEntries.Except(destinationFileEntries, pathOnlyEqualityComparer);

            difference.RelativeFilePathsToCopy.AddRange(filesToCopy.Select(x => x.Path));

            // Copy all files that exist in both the source and the destination, but the last modified date in the source is greater than the last modified date in the destination.
            var filesToUpdate = sourceFileEntries
                                .Join(destinationFileEntries, source => source.Path, destination => destination.Path, (source, destination) => (Destination: destination, Source: source))
                                .Where(x => x.Destination.LastModifiedUTC < x.Source.LastModifiedUTC)
                                .Select(x => x.Source);

            difference.RelativeFilePathsToUpdate.AddRange(filesToUpdate.Select(x => x.Path));

            if (options.DeleteExtraneousDestinationFiles)
            {
                // Delete all files that are in the destination, but not the source. (Make this an option!)
                var filesToDelete = destinationFileEntries.Except(sourceFileEntries, pathOnlyEqualityComparer);

                difference.RelativeFilePathsToDelete.AddRange(filesToDelete.Select(x => x.Path));
            }

            return(difference);
        }
        public void Clone(FileSystemSite source, FileSystemSite destination, FileSystemCloningOptions options)
        {
            // Ensure the source and destination directories are directory indicated.
            var ensuredSource      = source.EnsureSiteDirectoryPathIsDirectoryIndicated(this.StringlyTypedPathOperator);
            var ensuredDestination = destination.EnsureSiteDirectoryPathIsDirectoryIndicated(this.StringlyTypedPathOperator);

            // Get all source file-system entries.
            var sourceFileSystemEntries = ensuredSource.FileSystemOperator.EnumerateFileSystemEntries(ensuredSource.DirectoryPath, true)
                                          .ToList();

            // Get all destination file-system entries.
            var destinationFileSystemEntries = ensuredDestination.FileSystemOperator.EnumerateFileSystemEntries(ensuredDestination.DirectoryPath, true)
                                               .ToList();

            // Create relative-path source and destination file-system entries.
            FileSystemEntry MakeRelativeEntry(string baseDirectoryPath, FileSystemEntry entry)
            {
                var sourceBaseDirectoryRelativeEntryPath = this.StringlyTypedPathOperator.GetRelativePath(baseDirectoryPath, entry.Path);

                var relativeEntry = FileSystemEntry.New(sourceBaseDirectoryRelativeEntryPath, entry.Type, entry.LastModifiedUTC);

                return(relativeEntry);
            }

            var sourceBaseDirectoryRelativePathEntries = sourceFileSystemEntries.Select(entry => MakeRelativeEntry(ensuredSource.DirectoryPath, entry))
                                                         .Select(fileSystemEntry =>
            {
                // Make sure we are using a common path format.
                var standardPathFileSystemEntry = fileSystemEntry.GetStandardPathFormatEntry(this.StringlyTypedPathOperator);
                return(standardPathFileSystemEntry);
            })
                                                         .ToList();

            var destinationBaseDirectoryRelativePathEntries = destinationFileSystemEntries.Select(entry => MakeRelativeEntry(ensuredDestination.DirectoryPath, entry))
                                                              .Select(fileSystemEntry =>
            {
                // Make sure we are using a common path format.
                var standardPathFileSystemEntry = fileSystemEntry.GetStandardPathFormatEntry(this.StringlyTypedPathOperator);
                return(standardPathFileSystemEntry);
            })
                                                              .ToList();

            // Write out source and destination data.

            // Get the file-system cloning difference.
            var difference = this.FileSystemCloningDifferencer.PerformDifference(sourceBaseDirectoryRelativePathEntries, destinationBaseDirectoryRelativePathEntries, options);

            // Create a list of operations, using absolute paths.
            var operations = new List <IFileSystemCloningOperation>();

            // Special case: the destination directory does not exist. If so, make sure it is created first to allow files to be copied into it!
            var destinationDirectoryExists = ensuredDestination.FileSystemOperator.ExistsDirectory(ensuredDestination.DirectoryPath);

            if (!destinationDirectoryExists)
            {
                var createDestinationDirectoryOperation = new CreateDirectoryOperation(ensuredDestination.DirectoryPath);

                operations.Add(createDestinationDirectoryOperation);
            }

            foreach (var directoryToCreate in difference.RelativeDirectoryPathsToCreate)
            {
                string destinationDirectoryToCreate = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, directoryToCreate);

                var createDirectoryOperation = new CreateDirectoryOperation(destinationDirectoryToCreate);

                operations.Add(createDirectoryOperation);
            }

            foreach (var directoryToDelete in difference.RelativeDirectoryPathsToDelete)
            {
                string destinationDirectoryToDelete = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, directoryToDelete);

                var deleteDirectoryOperation = new DeleteDirectoryOperation(destinationDirectoryToDelete);

                operations.Add(deleteDirectoryOperation);
            }

            foreach (var fileToCopy in difference.RelativeFilePathsToCopy)
            {
                string sourceFilePath      = this.StringlyTypedPathOperator.Combine(ensuredSource.DirectoryPath, fileToCopy);
                string destinationFilePath = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, fileToCopy);

                var copyFileOperation = new CopyFileOperation(sourceFilePath, destinationFilePath);

                operations.Add(copyFileOperation);
            }

            foreach (var fileToUpdate in difference.RelativeFilePathsToUpdate)
            {
                string sourceFilePath      = this.StringlyTypedPathOperator.Combine(ensuredSource.DirectoryPath, fileToUpdate);
                string destinationFilePath = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, fileToUpdate);

                var copyFileOperation = new CopyFileOperation(sourceFilePath, destinationFilePath);

                operations.Add(copyFileOperation);
            }

            foreach (var fileToDelete in difference.RelativeFilePathsToDelete)
            {
                string destinationFilePath = this.StringlyTypedPathOperator.Combine(ensuredDestination.DirectoryPath, fileToDelete);

                var deleteFileOperation = new DeleteFileOperation(destinationFilePath);

                operations.Add(deleteFileOperation);
            }

            // Write out and allow approval of the list of operations?

            // Execute the list of operations.
            foreach (var operation in operations)
            {
                operation.Execute(ensuredSource.FileSystemOperator, ensuredDestination.FileSystemOperator);
            }
        }
 public Task CloneAsync(FileSystemSite source, FileSystemSite destination, FileSystemCloningOptions options, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
 public FileSystemCloningOperatorTestFixture(FileSystemSite source, FileSystemSite destination,
                                             IFileSystemCloningOperator fileSystemCloningOperator, FileSystemCloningOptions options,
                                             IStringlyTypedPathOperator stringlyTypedPathOperator, TextWriter writer)
 {
     this.Source      = source;
     this.Destination = destination;
     this.FileSystemCloningOperator = fileSystemCloningOperator;
     this.Options = options;
     this.StringlyTypedPathOperator = stringlyTypedPathOperator;
     this.Writer = writer;
 }