Пример #1
0
        /// <summary>
        /// Создает Iterator для перебора файлов в папке, имена которых удовлетворяют заданной маске (<paramref name="patternNamesOfFilesMustMatch"/>).
        /// Работает рекурсивно - то есть перебирает и файлы во всех подпапках указанной папки.
        /// Note: генерирует исключение (<see cref="InvalidOperationException"/>), если папка, по которой производится обход, меняется во время обхода (итераторы не thread-safe, я бы их лучше не показывал, но это явно зафиксированное требования).
        /// </summary>
        /// <param name="folderToEnumerateFilesIn">Папка, в которой следует искать файлы.</param>
        /// <param name="patternNamesOfFilesMustMatch">Маска для поиска файлов. Звездочка означает любую последовательность символов. Знак вопроса - один любой символ.</param>
        /// <returns>Iterator для перебора файлов в папке, имена которых удовлетворяют заданной маске (<paramref name="patternNamesOfFilesMustMatch"/>)</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public IEnumerator <FileInfo> EnumerateFilesUnderFolder(string folderToEnumerateFilesIn, string patternNamesOfFilesMustMatch)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderToEnumerateFilesIn, "folderToEnumerateFilesIn");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(patternNamesOfFilesMustMatch, "patternNamesOfFilesMustMatch");

            Monitor.Enter(_operationExecutionCriticalSection);

            try
            {
                ThrowIfDisposed();

                var nodeResolvingResult = _nodeResolver.ResolveFolderNodeByPath(folderToEnumerateFilesIn);

                var folder = new FolderInfo(nodeResolvingResult.ResolvedNode, folderToEnumerateFilesIn);

                var enumerator = new FolderContentsEnumerator(folder, patternNamesOfFilesMustMatch, _folderEnumeratorRegistry, this);
                _folderEnumeratorRegistry.RegisterEnumerator(enumerator);

                return(enumerator);
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException(
                          "Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderToEnumerateFilesIn));
            }
            finally
            {
                Monitor.Exit(_operationExecutionCriticalSection);
            }
        }
Пример #2
0
        /// <summary>
        /// Открывает указанный файл для записи и чтения.
        /// </summary>
        /// <param name="fullPathForFile">Путь, указывающий открываемый файл.</param>
        /// <returns>Поток данных файла, допускающий чтение и запись данных</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public DataStreamReadableWritable OpenFileForWriting(string fullPathForFile)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFile, "fullPathForFile");

            try
            {
                NodeWithSurroundingsResolvingResult <FileNode> nodeResolvingResult;
                DataStreamStructureBuilder dataStreamStructureBuilder = GetDataStreamStructureBuilderResolvingTheFile(fullPathForFile, out nodeResolvingResult);

                Guid lockId = _lockingManager.AcquireLock(nodeResolvingResult, LockKind.Write);

                var stream = new DataStream(dataStreamStructureBuilder, AddressingSystemParameters.Default.BlockSize, _lockingManager, lockId);

                var nodeUpdatingStream = new DataStreamNodeUpdating(stream, nodeResolvingResult.ResolvedNode, _fileSystemNodeStorage);

                return(nodeUpdatingStream);
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Файл не найден по указанному пути (\"{0}\")".FormatWith(fullPathForFile));
            }
            catch (CannotAcquireLockException)
            {
                throw new FileLockedException(
                          "Не удалось открыть файл \"{0}\" с блокировкой на запись: он уже заблокирован на чтение или запись."
                          .FormatWith(fullPathForFile));
            }
        }
Пример #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="fileSystem"></param>
        /// <param name="exportingFolderPath"></param>
        /// <param name="virtualDestinationFolder"></param>
        /// <param name="taskToken"></param>
        /// <returns></returns>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="CannotGetImportedFolderStructureException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        internal static ReadOnlyCollection <FileSystemTaskResult> ImportFolderFromRealFileSystem(
            this VirtualFileSystem fileSystem,
            string exportingFolderPath,
            string virtualDestinationFolder,
            IFileSystemCancellableTaskToken taskToken)
        {
            if (fileSystem == null)
            {
                throw new ArgumentNullException("fileSystem");
            }
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(exportingFolderPath, "exportingFolderPath");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(virtualDestinationFolder, "virtualDestinationFolder");

            FolderAddressable folderAddressable = CreateFileSystemObjectStructureFromFolder(exportingFolderPath);

            int totalNumberOfFilesToTraverse = folderAddressable.GetTotalFileCount();

            // Note: можно уменьшить связность классов, передав сюда через интерфейс фабрику, которая уж знает, как сделать нужного Visitor-а.

            ImportingAddressableObjectVisitor visitor = new ImportingAddressableObjectVisitor(fileSystem, exportingFolderPath, virtualDestinationFolder,
                                                                                              new RealFileContentsBufferFactory(), taskToken, totalNumberOfFilesToTraverse);

            if (!fileSystem.FolderExists(virtualDestinationFolder))
            {
                throw new FolderNotFoundException("Не удалось найти папку \"{0}\", в которую следует произвести копирование/импорт.".FormatWith(virtualDestinationFolder));
            }

            folderAddressable.Accept(visitor);
            var results = visitor.GetResult();

            return(results);
        }
        /// <summary>
        /// Удаляет пустую папку, расположенную по указанному пути. Непустые папки в этой версии удалить вызовом одного метода
        /// нельзя.
        /// </summary>
        /// <param name="folderPath">Путь, указывающий, какую папку надо удалить.</param>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="FolderNotEmptyException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public void DeleteFolder(string folderPath)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderPath, "folderPath");

            if (_pathBuilder.PointsToRoot(folderPath))
            {
                throw new InvalidPathException("Не получилось удалить папку: нельзя удалить корень файловой системы.");
            }

            try
            {
                string folderName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(folderPath, out folderName);

                FolderNode folderToRemoveDirectoryFrom = parentFolderResolvingResult.ResolvedNode;

                var allFolders = _nodeResolver.GetAllFoldersFrom(folderToRemoveDirectoryFrom);

                FolderNode folderToRemove =
                    allFolders.FirstOrDefault(folderNode => _namesComparer.Equals(folderNode.Name, folderName));

                if (folderToRemove == null)
                {
                    throw new FolderNotFoundException("Не найдена папка для удаления (\"0\")".FormatWith(folderPath));
                }

                if ((folderToRemove.FileReferencesStreamDefinition.StreamLengthInBytes > 0) || (folderToRemove.FolderReferencesStreamDefinition.StreamLengthInBytes > 0))
                {
                    throw new FolderNotEmptyException("Не удалось удалить папку: она не пуста"); // Note: блокировки не проверяю. В пустой папке блокировать нечего.
                }

                var idsOfFolderUnderGivenOne = _nodeResolver.GetIdsOfAllFoldersUnderGivenOne(folderPath);

                // TODO: посмотреть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveDirectoryFrom, folderToRemove.DiskBlockIndex, folderToRemoveDirectoryFrom.FolderReferencesStreamDefinition);

                _freeBlockManager.MarkBlocksAsFree(new[]
                {
                    folderToRemove.FileReferencesStreamDefinition.ContentsBlockIndex,
                    folderToRemove.FolderReferencesStreamDefinition.ContentsBlockIndex,
                    folderToRemove.DiskBlockIndex
                });

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(folderToRemove.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(idsOfFolderUnderGivenOne);
            }
            catch (CannotResolvePathException)
            {
                throw new FolderNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderPath));
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderPath));
            }
        }
Пример #5
0
        /// <summary>
        /// Возвращает сведения о всех подпапках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>). Работает без рекурсии.
        /// </summary>
        /// <param name="folderToGetSubfoldersOf">Папка, поддиректории которой надо вернуть.</param>
        /// <returns>Сведения о всех папках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>)</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public ReadOnlyCollection <FolderInfo> GetAllFoldersFrom(string folderToGetSubfoldersOf)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderToGetSubfoldersOf, "folderToGetSubfoldersOf");

            lock (_operationExecutionCriticalSection)
            {
                ThrowIfDisposed();
                return(_nodeResolver.GetAllFoldersFrom(folderToGetSubfoldersOf));
            }
        }
Пример #6
0
        /// <summary>
        /// Переименовывает указанный файл.
        /// </summary>
        /// <param name="fullPathForFile">Путь, указывающий файл для переименования.</param>
        /// <param name="newFileName">Новое имя файла (без пути).</param>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="InvalidNameException"></exception>
        /// <exception cref="FileLockedException"></exception>
        public void RenameFile(string fullPathForFile, string newFileName)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFile, "fullPathForFile");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newFileName, "newFileName");

            if (_pathBuilder.PointsToRoot(fullPathForFile))
            {
                throw new InvalidPathException("Файл не был переименован: имя файла, который следует переименовать, не может указывать на корень файловой системы");
            }

            _nameValidator.Validate(newFileName);

            try
            {
                string fileName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(fullPathForFile, out fileName);

                string lastPartOfFullPath = _pathBuilder.GetFileOrFolderName(fullPathForFile);

                if (_namesComparer.Equals(newFileName, lastPartOfFullPath))
                {
                    return;
                }

                ReadOnlyCollection <FileNode> files;
                FileNode fileNode = this.ResolveFileNodeThrowingUserFriendlyErrors(fullPathForFile, parentFolderResolvingResult, fileName, "переименовать", out files);

                if (files.Any(node => _namesComparer.Equals(newFileName, node.Name)))
                {
                    throw new FileAlreadyExistsException("Не удалось переименовать файл: файл с именем \"{0}\" уже существует в папке, где вы производите переименование".FormatWith(newFileName));
                }

                fileNode.Name = newFileName;

                _fileSystemNodeStorage.WriteNode(fileNode);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
            }
            catch (CannotResolvePathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(fullPathForFile));
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(fullPathForFile));
            }
        }
Пример #7
0
        /// <summary>
        /// Копирует указанный файл.
        /// </summary>
        /// <param name="fullPathForFileToBeCopied">Полный путь (от корня), указывающий файл, который следует скопировать.</param>
        /// <param name="newPathThatWillPointToTheCopyOfFile">Полный путь (от корня), указывающий, где будет находиться и как называться копия файла.</param>
        /// <param name="taskToken"></param>
        /// <returns>Описание копии файла.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFileCountReachedException"></exception>
        /// <exception cref="TaskCancelledException"></exception>
        internal FileInfo CopyFile(string fullPathForFileToBeCopied, string newPathThatWillPointToTheCopyOfFile, IFileSystemCancellableTaskToken taskToken)
        {
            if (taskToken == null)
            {
                throw new ArgumentNullException("taskToken");
            }
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFileToBeCopied, "fullPathForFileToBeCopied");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newPathThatWillPointToTheCopyOfFile, "newPathThatWillPointToTheCopyOfFile");

            if (_namesComparer.Equals(fullPathForFileToBeCopied, newPathThatWillPointToTheCopyOfFile))
            {
                return
                    (new FileInfo(_nodeResolver.ResolveFileNodeByPath(newPathThatWillPointToTheCopyOfFile).ResolvedNode, newPathThatWillPointToTheCopyOfFile));
            }

            lock (_operationExecutionCriticalSection)
            {
                ThrowIfDisposed(); // так себе проверка на этот раз.
            }

            // Note: не смотрю, хватит ли там места. Хотя отрицательный ответ на такой вопрос мог бы стать поводом, чтобы ничего не копировать.
            try
            {
                CopyFileContents(taskToken, fullPathForFileToBeCopied, newPathThatWillPointToTheCopyOfFile);

                return
                    (new FileInfo(_nodeResolver.ResolveFileNodeByPath(newPathThatWillPointToTheCopyOfFile).ResolvedNode, newPathThatWillPointToTheCopyOfFile));
            }
            catch (Exception)
            {
                try
                {
                    this.DeleteFile(newPathThatWillPointToTheCopyOfFile);
                }
                catch (InvalidPathException)
                {
                }
                catch (ObjectDisposedException)
                {
                    throw new ObjectDisposedException("Работа с файловой системой была вами завершена принудительным вызовом метода Dispose() - до того, как был докопирован файл. Рекомендуется удалить следующий файл при очередном запуске системы (простите - в текущей версии ничего более удобного не сделано): \"{0}\"".FormatWith(newPathThatWillPointToTheCopyOfFile));
                }
                catch (FileNotFoundException)
                {
                }

                throw;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        internal string GetFileOrFolderName(string path)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(path, "fullPath");

            if (_nameComparer.Equals(_rootPath, path))
            {
                return(path);
            }

            if (path.IndexOf(_directorySeparator) < 0)
            {
                return(path);
            }

            return(path.Remove(0, path.LastIndexOf(_directorySeparator) + 1));
        }
        /// <summary>
        /// Делает из абсолютного пути к папке <paramref name="fullPathToTurnIntoRelative"/>, ее путь относительно папки <paramref name="fullPathForFolderToGetRelativePathAgainst"/>.
        /// </summary>
        /// <param name="fullPathForFolderToGetRelativePathAgainst"></param>
        /// <param name="fullPathToTurnIntoRelative"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        internal string GetRelativePath(string fullPathForFolderToGetRelativePathAgainst, string fullPathToTurnIntoRelative)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty("fullPathForFolderToGetRelativePathAgainst", fullPathForFolderToGetRelativePathAgainst);
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty("fullPathToTurnIntoRelative", fullPathToTurnIntoRelative);

            // Note: ordinal ignore case - выносить надо отсюда. Такие вещи надо настраивать в каком-то одном месте.
            if (!fullPathToTurnIntoRelative.StartsWith(fullPathForFolderToGetRelativePathAgainst, StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException("Чтобы получить путь одной папки относительно другой, необходимо, чтобы та папка, относительно которой считается путь, была родительской папкой (прямо или косвенно) для той, которой считается путь.");
            }

            return
                (fullPathToTurnIntoRelative
                 .Substring(fullPathForFolderToGetRelativePathAgainst.Length, fullPathToTurnIntoRelative.Length - fullPathForFolderToGetRelativePathAgainst.Length)
                 .TrimStart(new[] { _directorySeparator }));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        public ReadOnlyCollection <FileInfo> GetAllFilesFrom(string path)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(path, "path");

            try
            {
                var nodeResolvingResult = this.ResolveFolderNodeByPath(path);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                return(this.GetAllFilesFrom(parentFolder).Select(file => new FileInfo(file, _pathBuilder.CombinePaths(path, file.Name))).ToList().AsReadOnly());
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось получить файлы, содержащиеся в папке \"{0}\". {1}".FormatWith(path, exception.Message));
            }
        }
Пример #11
0
        /// <summary>
        /// Создает новый файл по указанному пути.
        /// Примечание: в текущей версии не создает недостающие папки.
        /// </summary>
        /// <param name="fullPathToFile">Полный путь (включая имя файла), указывающий, где будет находиться новый файл.</param>
        /// <returns>Сведения о только что созданном файле.</returns>
        /// <exception cref="InvalidPathException">Если указанный путь невалиден.</exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException">Если путь (<paramref name="fullPathToFile"/>), за исключением последней части (имени нового файла), указывает на несуществующую папку.</exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFileCountReachedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public FileInfo CreateFile(string fullPathToFile)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathToFile, "fullPathToFile");

            if (_pathBuilder.PointsToRoot(fullPathToFile))
            {
                throw new InvalidPathException("Не удалось создать файл: в качестве пути к файлу нельзя указать корень файловой системы");
            }

            _pathValidator.Validate(fullPathToFile);

            try
            {
                string fileName;

                var nodeResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(fullPathToFile, out fileName);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                var newFileInfo = new FileInfo(this.CreateFile(parentFolder, fileName), fullPathToFile);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(nodeResolvingResult.FoldersPassedWhileResolving);

                return(newFileInfo);
            }
            catch (InsufficientSpaceException)
            {
                throw new InsufficientSpaceException("Недостаточно свободного места на диске для создания файла.");
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFileCountReachedException("Не удалось добавить файл: папка, в которую вы добавляете файл, не может вместить их больше, чем уже вмещает.");
            }
            catch (NoFreeBlocksException)
            {
                throw new InsufficientSpaceException("Недостаточно свободного места на диске для создания файла.");
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException("Не получилось создать файл по указанному пути (\"{0}\"). Не найдена папка, в которой следует создать файл. (В текущей версии недостающие папки не создаются автоматически)".FormatWith(fullPathToFile));
            }
            catch (CannotResolvePathException)
            {
                throw new FolderNotFoundException("Не получилось создать файл по указанному пути (\"{0}\"). Не найдена папка, в которой следует создать файл. (В текущей версии недостающие папки не создаются автоматически)".FormatWith(fullPathToFile));
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="newFolderName"></param>
        /// <returns></returns>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFileSizeReachedException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderAlreadyExistsException"></exception>
        private FolderNode CreateFolder(FolderNode parentFolder, string newFolderName)
        {
            MethodArgumentValidator.ThrowIfNull(parentFolder, "parentFolder");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newFolderName, "newFolderName");

            var subfolders = _nodeResolver.GetAllFoldersFrom(parentFolder);

            var folderWithSameName = subfolders.FirstOrDefault(subfolder => _namesComparer.Equals(subfolder.Name, newFolderName));

            if (folderWithSameName != null)
            {
                throw new FolderAlreadyExistsException("Подпапка с именем \"{0}\" уже существует в папке \"{1}\"".FormatWith(newFolderName, parentFolder.Name));
            }

            var freeBlocks = _freeBlockManager.AcquireFreeBlocks(3);

            int blockToStoreFileReferencesIn      = freeBlocks[0];
            int blockToStoreFolderNodeIn          = freeBlocks[1];
            int blockToStoreSubfolderReferencesIn = freeBlocks[2];

            var fileReferencesStreamDefinition   = new DataStreamDefinition(blockToStoreFileReferencesIn, 0);
            var folderReferencesStreamDefinition = new DataStreamDefinition(blockToStoreSubfolderReferencesIn, 0);

            try
            {
                // Note: может стать последней каплей для переполненного диска, и тогда блоки придется отпустить
                _blockReferenceListsEditor.AddBlockReference(blockToStoreFolderNodeIn, parentFolder.FolderReferencesStreamDefinition, parentFolder);
            }
            catch (Exception)
            {
                _freeBlockManager.MarkBlocksAsFree(freeBlocks);

                throw;
            }

            var creationTime = DateTime.UtcNow;

            var newNode = new FolderNode(newFolderName, Guid.NewGuid(), blockToStoreFolderNodeIn, parentFolder.DiskBlockIndex, fileReferencesStreamDefinition, folderReferencesStreamDefinition, creationTime, Guid.NewGuid());

            _fileSystemNodeStorage.WriteNode(newNode);

            return(newNode);
        }
Пример #13
0
        /// <summary>
        /// Удаляет указанный файл.
        /// </summary>
        /// <param name="filePath">Путь, указывающий удаляемый файл.</param>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public void DeleteFile(string filePath)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(filePath, "filePath");

            if (_pathBuilder.PointsToRoot(filePath))
            {
                throw new InvalidPathException("Не получилось удалить файл: нельзя удалить корень файловой системы.");
            }

            try
            {
                string fileName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(filePath, out fileName);

                ReadOnlyCollection <FileNode> files;
                FolderNode folderToRemoveFileFrom = parentFolderResolvingResult.ResolvedNode;
                FileNode   fileToRemove           = ResolveFileNodeThrowingUserFriendlyErrors(filePath, parentFolderResolvingResult, fileName, "удалить", out files);

                // очистка всех данных.
                using (var dataStream = this.OpenFileForWriting(filePath))
                {
                    dataStream.Truncate();
                }

                // TODO: поглядеть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveFileFrom, fileToRemove.DiskBlockIndex, folderToRemoveFileFrom.FileReferencesStreamDefinition);

                _freeBlockManager.MarkBlockAsFree(fileToRemove.DiskBlockIndex);
                _freeBlockManager.MarkBlockAsFree(fileToRemove.FileContentsStreamDefinition.ContentsBlockIndex);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
            }
            catch (CannotResolvePathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(filePath));
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(filePath));
            }
        }
        /// <summary>
        /// Возвращает сведения о всех подпапках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>).
        /// </summary>
        /// <param name="folderToGetSubfoldersOf">Папка, поддиректории которой надо вернуть.</param>
        /// <returns>Сведения о всех папках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>)</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        public ReadOnlyCollection <FolderInfo> GetAllFoldersFrom(string folderToGetSubfoldersOf)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderToGetSubfoldersOf, "folderToGetSubfoldersOf");

            try
            {
                NodeWithSurroundingsResolvingResult <FolderNode> nodeResolvingResult = this.ResolveFolderNodeByPath(folderToGetSubfoldersOf);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                return(this.GetAllFoldersFrom(parentFolder)
                       .Select(folderNode => new FolderInfo(folderNode, _pathBuilder.CombinePaths(folderToGetSubfoldersOf, folderNode.Name)))
                       .ToList()
                       .AsReadOnly());
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderToGetSubfoldersOf));
            }
        }
Пример #15
0
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="NoFreeBlocksException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFileSizeReachedException"></exception>
        private FileNode CreateFile(FolderNode parentFolder, string fileName)
        {
            MethodArgumentValidator.ThrowIfNull(parentFolder, "parentFolder");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fileName, "fileName");

            var filesInTheFolder = _nodeResolver.GetAllFilesFrom(parentFolder);

            var fileWithSameName = filesInTheFolder.FirstOrDefault(file => _namesComparer.Equals(file.Name, fileName));

            if (fileWithSameName != null)
            {
                throw new FileAlreadyExistsException("Файл с именем \"{0}\" уже существует в папке \"{1}\"".FormatWith(fileName, parentFolder.Name));
            }

            var freeBlocks = _freeBlockManager.AcquireFreeBlocks(2);

            int blockToStoreDefinitionIn = freeBlocks[0];
            int blockToStoreFileNodeIn   = freeBlocks[1];

            var fileContentsStreamDefinition = new DataStreamDefinition(blockToStoreDefinitionIn, 0);

            try
            {
                // Note: это добавление ссылки может стать последней каплей для заполненного диска, тогда блоки придется отпустить
                _blockReferenceListsEditor.AddBlockReference(blockToStoreFileNodeIn, parentFolder.FileReferencesStreamDefinition, parentFolder);
            }
            catch (Exception)
            {
                _freeBlockManager.MarkBlocksAsFree(freeBlocks);

                throw;
            }

            var creationTime = DateTime.UtcNow;

            var fileNode = new FileNode(fileName, Guid.NewGuid(), blockToStoreFileNodeIn, fileContentsStreamDefinition, creationTime, creationTime, Guid.NewGuid());

            _fileSystemNodeStorage.WriteNode(fileNode);

            return(fileNode);
        }
        /// <summary>
        /// Note: case sensitive
        /// </summary>
        /// <param name="stringToCheck"></param>
        /// <param name="characters"></param>
        /// <param name="characterFound"></param>
        /// <returns></returns>
        public static bool ContainsAny(this string stringToCheck, IEnumerable <char> characters, out Nullable <char> characterFound)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(stringToCheck, "stringToCheck");
            MethodArgumentValidator.ThrowIfNull(characters, "characters");

            var charactersSeenSoFar  = new HashSet <char>();
            var charactersToCheckFor = new HashSet <char>(characters);

            foreach (char character in stringToCheck)
            {
                if (!charactersSeenSoFar.Contains(character) && charactersToCheckFor.Contains(character))
                {
                    characterFound = character;
                    return(true);
                }

                charactersSeenSoFar.Add(character);
            }

            characterFound = null;
            return(false);
        }
        internal PathBuilder(
            char directorySeparator,
            IPathValidator pathValidator,
            string rootPath,
            IEqualityComparer <string> nameComparer)
        {
            if (pathValidator == null)
            {
                throw new ArgumentNullException("pathValidator");
            }
            if (nameComparer == null)
            {
                throw new ArgumentNullException("nameComparer");
            }

            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(rootPath, "rootPath");

            _directorySeparator = directorySeparator;
            _pathValidator      = pathValidator;
            _rootPath           = rootPath;
            _nameComparer       = nameComparer;
        }
        /// <summary>
        /// Переименовывает папку.
        /// </summary>
        /// <param name="fullPathForFolder">Путь, указывающий папку, которую следует переименовать.</param>
        /// <param name="newFolderName">Новое имя папки (только имя - без пути)</param>
        /// <exception cref="FolderAlreadyExistsException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="FolderLockedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="InvalidNameException"></exception>
        public void RenameFolder(string fullPathForFolder, string newFolderName)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFolder, "fullPathForFolder");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newFolderName, "newFolderName");

            if (_pathBuilder.PointsToRoot(fullPathForFolder))
            {
                throw new InvalidPathException("Папка не была переименована: имя папки не может указывать на корень файловой системы");
            }

            _nameValidator.Validate(newFolderName);

            try
            {
                string folderName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(fullPathForFolder,
                                                                                              out folderName);

                string lastPartOfFullPath = _pathBuilder.GetFileOrFolderName(newFolderName);

                if (_namesComparer.Equals(folderName, lastPartOfFullPath))
                {
                    return;
                }

                FolderNode parentFolderNode = parentFolderResolvingResult.ResolvedNode;

                ReadOnlyCollection <FolderNode> folders = _nodeResolver.GetAllFoldersFrom(parentFolderNode);

                FolderNode folderNode = folders.FirstOrDefault(node => _namesComparer.Equals(node.Name, folderName));

                if (folderNode == null)
                {
                    throw new FolderNotFoundException("Не найдена папка для переименования (\"{0}\")".FormatWith(fullPathForFolder));
                }

                if (_lockingManager.IsNodeLockedForRenamesAndMoves(folderNode))
                {
                    throw new FolderLockedException("Не удалось переименовать папку. В ней (или в одной из ее поддиректорий) есть файлы, которые сейчас открыты.");
                }

                if (folders.Any(node => _namesComparer.Equals(newFolderName, node.Name)))
                {
                    throw new FolderAlreadyExistsException("Не удалось переименовать папку: папка с именем \"{0}\" уже существует в директории, где вы производите переименование".FormatWith(newFolderName));
                }

                var idsOfFolderUnderGivenOne = _nodeResolver.GetIdsOfAllFoldersUnderGivenOne(fullPathForFolder);

                folderNode.Name = newFolderName;

                _fileSystemNodeStorage.WriteNode(folderNode);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(idsOfFolderUnderGivenOne);
            }
            catch (CannotResolvePathException)
            {
                throw new FileNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(fullPathForFolder));
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(fullPathForFolder));
            }
        }
Пример #19
0
        /// <summary>
        /// Перемещает файл в указанную папку.
        /// </summary>
        /// <param name="currentPathForFile">Полный путь (от корня) к файлу, который следует переместить.</param>
        /// <param name="pathToFolderThatMustContainTheFile">Полный путь к папке, в которую нужно переместить указанный файл (<paramref name="currentPathForFile"/>).</param>
        /// <returns>Описание перемещенного файла, взятое с учетом его нового местоположения.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="MaximumFileCountReachedException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        public FileInfo MoveFile(string currentPathForFile, string pathToFolderThatMustContainTheFile)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(currentPathForFile, "currentPathForFile");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(pathToFolderThatMustContainTheFile, "pathToFolderThatMustContainTheFile");

            try
            {
                var newParentNodeResolvingResult = _nodeResolver.ResolveFolderNodeByPath(pathToFolderThatMustContainTheFile);

                FolderNode filesNewHome = newParentNodeResolvingResult.ResolvedNode;

                string fileName;

                var currentParentFolder = _nodeResolver.ResolveParentFolderNodeByPath(currentPathForFile, out fileName);

                ReadOnlyCollection <FileNode> allFilesInTheFolder;
                FolderNode folderToRemoveFileFrom = currentParentFolder.ResolvedNode;
                FileNode   fileToMove             = this.ResolveFileNodeThrowingUserFriendlyErrors(currentPathForFile, currentParentFolder, fileName, "переместить", out allFilesInTheFolder);

                var allFilesInDestinationFolder = _nodeResolver.GetAllFilesFrom(filesNewHome);

                // перемещение в то место, где файл и так уже находится.
                if (newParentNodeResolvingResult.ResolvedNode.Id.Equals(currentParentFolder.ResolvedNode.Id))
                {
                    return(new FileInfo(allFilesInDestinationFolder.First(fileNode => _namesComparer.Equals(fileNode.Name, fileName)), currentPathForFile));
                }

                if (allFilesInDestinationFolder.Any(fileNode => _namesComparer.Equals(fileNode.Name, fileName)))
                {
                    throw new FileAlreadyExistsException("Перемещение файла невозможно: в папке \"{0}\" уже существует файл с именем \"{1}\"".FormatWith(pathToFolderThatMustContainTheFile, fileName));
                }

                // сначала добавляем ссылку в новую папку, потом удаляем ссылку из старой (на добавление может не хватить места, удалить же можно всегда).
                _blockReferenceListsEditor.AddBlockReference(fileToMove.DiskBlockIndex, filesNewHome.FileReferencesStreamDefinition, filesNewHome);
                // TODO: поглядеть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveFileFrom, fileToMove.DiskBlockIndex, folderToRemoveFileFrom.FileReferencesStreamDefinition);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(newParentNodeResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(newParentNodeResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(currentParentFolder.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(currentParentFolder.ResolvedNode.Id);

                allFilesInDestinationFolder = _nodeResolver.GetAllFilesFrom(filesNewHome);

                return(new FileInfo(
                           allFilesInDestinationFolder.Single(fileNode => _namesComparer.Equals(fileNode.Name, fileName)),
                           _pathBuilder.CombinePaths(pathToFolderThatMustContainTheFile, fileName)));
            }
            catch (InsufficientSpaceException)
            {
                throw new InsufficientSpaceException("Не удалось переместить файл из \"{0}\" в \"{1}\" - не хватает места на диске для проведения операции.".FormatWith(currentPathForFile, pathToFolderThatMustContainTheFile));
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFileCountReachedException("Не удалось переместить файл \"{0}\". Папка \"{1}\" не может вместить больше файлов, чем уже вмещает".FormatWith(currentPathForFile, pathToFolderThatMustContainTheFile));
            }
            catch (CannotResolvePathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
        }
Пример #20
0
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFolderCountReachedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        internal ReadOnlyCollection <FileSystemTaskResult> CopyFolder(string fullPathForFolderToCopy, string destinationPathForFolderAndItsContents, IFileSystemCancellableTaskToken taskToken)
        {
            if (taskToken == null)
            {
                throw new ArgumentNullException("taskToken");
            }
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFolderToCopy, "fullPathForFolderToCopy");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(destinationPathForFolderAndItsContents, "destinationPathForFolderAndItsContents");

            // TODO: выделить общее у копированиея папок и импорта - там много.

            var allFilesToBeCopied = new List <FileInfo>();

            CreateFoldersNeededToCopy(fullPathForFolderToCopy, destinationPathForFolderAndItsContents, allFilesToBeCopied);

            var copyTaskResults = new List <FileSystemTaskResult>();
            int filesCopied     = 0;
            int percentage      = 0;

            foreach (FileInfo fileInfo in allFilesToBeCopied)
            {
                try
                {
                    if (taskToken.HasBeenCancelled)
                    {
                        copyTaskResults.Add(new FileTaskResult(fileInfo.ToFileAddressable(), null, "Задача снята."));
                    }
                    else
                    {
                        string relativePathToFile = _pathBuilder.GetRelativePath(fullPathForFolderToCopy, fileInfo.FullPath);
                        string destinationPath    = this.PathBuilder.CombinePaths(destinationPathForFolderAndItsContents, relativePathToFile);

                        var tokenWrapper   = new TaskTokenPartialWrapper(taskToken);
                        var copiedFileInfo = this.CopyFile(fileInfo.FullPath, destinationPath, tokenWrapper);
                        copyTaskResults.Add(new FileTaskResult(fileInfo.ToFileAddressable(), copiedFileInfo.ToFileAddressable(), String.Empty));
                    }
                }
                catch (TaskCancelledException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (FileNotFoundException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (FileLockedException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (ObjectDisposedException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (InvalidPathException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (FolderNotFoundException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (FileAlreadyExistsException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (InsufficientSpaceException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                catch (MaximumFileCountReachedException exception)
                {
                    copyTaskResults.Add(CreateCopyTaskFailureFromException(fileInfo, exception));
                }
                finally
                {
                    // Note: дурацкая часть по высчету прогресса везде общая. Надо выносить.

                    filesCopied++;

                    int newPercentage = (filesCopied * 100) / allFilesToBeCopied.Count;

                    if (newPercentage != percentage)
                    {
                        percentage = newPercentage;
                        taskToken.ReportProgressChange(newPercentage);
                    }
                }
            }

            return(copyTaskResults.AsReadOnly());
        }
        /// <summary>
        /// Перемещает папку в указанную директорию.
        /// </summary>
        /// <param name="currentPathForFolder">Полный путь (от корня) к папке, которую следует переместить.</param>
        /// <param name="pathToFolderThatWillContainTheFolderMoved">Полный путь к папке, в которую нужно переместить указанную директорию (<paramref name="currentPathForFolder"/>).</param>
        /// <returns>Описание перемещенной папки, взятое с учетом ее нового местоположения.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderLockedException"></exception>
        /// <exception cref="FolderAlreadyExistsException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="MaximumFolderCountReachedException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="InvalidOperationException">Если пытаетесь переместить папку в одну из ее собственных поддиректорий.</exception>
        public FolderInfo MoveFolder(string currentPathForFolder, string pathToFolderThatWillContainTheFolderMoved)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(currentPathForFolder, "cucurrentPathForFolderrrentPathForFile");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(pathToFolderThatWillContainTheFolderMoved, "pathToFolderThatWillContainTheFolderMoved");

            try
            {
                var newParentNodeResolvingResult =
                    _nodeResolver.ResolveFolderNodeByPath(pathToFolderThatWillContainTheFolderMoved);

                FolderNode foldersNewHome = newParentNodeResolvingResult.ResolvedNode;

                string folderName;

                var currentParentFolder = _nodeResolver.ResolveParentFolderNodeByPath(currentPathForFolder, out folderName);

                FolderNode folderToRemoveDirectoryFrom = currentParentFolder.ResolvedNode;

                var directoriesInFolder = _nodeResolver.GetAllFoldersFrom(folderToRemoveDirectoryFrom);

                FolderNode folderToMove =
                    directoriesInFolder.FirstOrDefault(fileNode => _namesComparer.Equals(fileNode.Name, folderName));

                if (folderToMove == null)
                {
                    throw new FolderNotFoundException("Не найдена папка для перемещения (\"{0}\")".FormatWith(currentPathForFolder));
                }

                if (newParentNodeResolvingResult.FoldersPassedWhileResolving.Any(folderNode => folderNode.Id.Equals(folderToMove.Id)))
                {
                    throw new InvalidOperationException("Операция перемещения папки \"{0}\" в \"{1}\" отменена: невозможно переместить папку в одну из ее же поддиректорий.".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved));
                }

                if (_lockingManager.IsNodeLockedForRenamesAndMoves(folderToMove))
                {
                    throw new FolderLockedException("Не удалось переместить папку (\"{0}\"): она или любая из ее поддиректорий содержит файлы открытые сейчас для чтения или записи.".FormatWith(currentPathForFolder));
                }

                var allSubfoldersOfDestinationFolder = _nodeResolver.GetAllFoldersFrom(foldersNewHome);

                var idsOfAllSubfolders = _nodeResolver.GetIdsOfAllFoldersUnderGivenOne(currentPathForFolder);

                // перемещение в то место, где файл и так уже находится.)
                if (newParentNodeResolvingResult.ResolvedNode.Id.Equals(currentParentFolder.ResolvedNode.Id))
                {
                    return(new FolderInfo(allSubfoldersOfDestinationFolder.First(fileNode => _namesComparer.Equals(fileNode.Name, folderName)), currentPathForFolder));
                }

                if (allSubfoldersOfDestinationFolder.Any(fileNode => _namesComparer.Equals(fileNode.Name, folderName)))
                {
                    throw new FolderAlreadyExistsException("Перемещение папки невозможно: в директории \"{0}\" уже существует папка с именем \"{1}\"".FormatWith(pathToFolderThatWillContainTheFolderMoved, folderName));
                }

                // сначала добавляем ссылку в новую папку, потом удаляем ссылку из старой (на добавление может не хватить места, удалить же можно всегда).
                _blockReferenceListsEditor.AddBlockReference(folderToMove.DiskBlockIndex, foldersNewHome.FolderReferencesStreamDefinition, foldersNewHome);
                // TODO: поглядеть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveDirectoryFrom, folderToMove.DiskBlockIndex, folderToRemoveDirectoryFrom.FolderReferencesStreamDefinition);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(newParentNodeResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(newParentNodeResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(currentParentFolder.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(currentParentFolder.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(idsOfAllSubfolders);

                allSubfoldersOfDestinationFolder = _nodeResolver.GetAllFoldersFrom(foldersNewHome);

                return(new FolderInfo(
                           allSubfoldersOfDestinationFolder.Single(folderNode => _namesComparer.Equals(folderNode.Name, folderName)),
                           _pathBuilder.CombinePaths(pathToFolderThatWillContainTheFolderMoved, folderName)));
            }
            catch (InsufficientSpaceException)
            {
                throw new InsufficientSpaceException("Не удалось переместить папку из \"{0}\" в \"{1}\" - не хватает места на диске для проведения операции.".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved));
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFolderCountReachedException("Не удалось переместить папку \"{0}\". Папка \"{1}\" не может вместить больше файлов, чем уже вмещает".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved));
            }
            catch (CannotResolvePathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message));
            }
        }