public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode, DiskTransferVerificationMode verificationMode) { Ensure.That(sourcePath, () => sourcePath).IsValidPath(); Ensure.That(targetPath, () => targetPath).IsValidPath(); if (mode == TransferMode.Move && !_diskProvider.FolderExists(targetPath)) { if (verificationMode == DiskTransferVerificationMode.TryTransactional || verificationMode == DiskTransferVerificationMode.VerifyOnly) { var sourceMount = _diskProvider.GetMount(sourcePath); var targetMount = _diskProvider.GetMount(targetPath); // If we're on the same mount, do a simple folder move. if (sourceMount != null && targetMount != null && sourceMount.RootDirectory == targetMount.RootDirectory) { _logger.Debug("Move Directory [{0}] > [{1}]", sourcePath, targetPath); _diskProvider.MoveFolder(sourcePath, targetPath); return(mode); } } } if (!_diskProvider.FolderExists(targetPath)) { _diskProvider.CreateFolder(targetPath); _diskProvider.CopyPermissions(sourcePath, targetPath); } var result = mode; foreach (var subDir in _diskProvider.GetDirectoryInfos(sourcePath)) { if (ShouldIgnore(subDir)) { continue; } result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode, verificationMode); } foreach (var sourceFile in _diskProvider.GetFileInfos(sourcePath)) { if (ShouldIgnore(sourceFile)) { continue; } var destFile = Path.Combine(targetPath, sourceFile.Name); result &= TransferFile(sourceFile.FullName, destFile, mode, true, verificationMode); } if (mode.HasFlag(TransferMode.Move)) { _diskProvider.DeleteFolder(sourcePath, true); } return(result); }
public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode, DiskTransferVerificationMode verificationMode) { Ensure.That(sourcePath, () => sourcePath).IsValidPath(); Ensure.That(targetPath, () => targetPath).IsValidPath(); if (!_diskProvider.FolderExists(targetPath)) { _diskProvider.CreateFolder(targetPath); } var result = mode; foreach (var subDir in _diskProvider.GetDirectoryInfos(sourcePath)) { result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode, verificationMode); } foreach (var sourceFile in _diskProvider.GetFileInfos(sourcePath)) { var destFile = Path.Combine(targetPath, sourceFile.Name); result &= TransferFile(sourceFile.FullName, destFile, mode, true, verificationMode); } if (mode.HasFlag(TransferMode.Move)) { _diskProvider.DeleteFolder(sourcePath, true); } return(result); }
public void Scan(Series series) { var rootFolder = _diskProvider.GetParentFolder(series.Path); if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Series' root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.GetDirectories(rootFolder).Empty()) { _logger.Warn("Series' root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.RootFolderIsEmpty)); return; } _logger.ProgressInfo("Scanning disk for {0}", series.Title); if (!_diskProvider.FolderExists(series.Path)) { if (_configService.CreateEmptySeriesFolders && _diskProvider.FolderExists(rootFolder)) { _logger.Debug("Creating missing series folder: {0}", series.Path); _diskProvider.CreateFolder(series.Path); SetPermissions(series.Path); } else { _logger.Debug("Series folder doesn't exist: {0}", series.Path); } _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.SeriesFolderDoesNotExist)); return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterFiles(series, GetVideoFiles(series.Path)).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting episode files for: {0} [{1}]", series, videoFilesStopwatch.Elapsed); _logger.Debug("{0} Cleaning up media files in DB", series); _mediaFileTableCleanupService.Clean(series, mediaFileList); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", series, decisionsStopwatch.Elapsed); _importApprovedEpisodes.Import(decisions, false); _logger.Info("Completed scanning disk for {0}", series.Title); _eventAggregator.PublishEvent(new SeriesScannedEvent(series)); }
private void MoveFile(EpisodeFile episodeFile, string destinationFilename) { if (!_diskProvider.FileExists(episodeFile.Path)) { throw new FileNotFoundException("Episode file path does not exist", episodeFile.Path); } if (episodeFile.Path.PathEquals(destinationFilename)) { throw new SameFilenameException("File not moved, source and destination are the same", episodeFile.Path); } _diskProvider.CreateFolder(new FileInfo(destinationFilename).DirectoryName); _logger.Debug("Moving [{0}] > [{1}]", episodeFile.Path, destinationFilename); _diskProvider.MoveFile(episodeFile.Path, destinationFilename); //Wrapped in Try/Catch to prevent this from causing issues with remote NAS boxes, the move worked, which is more important. try { _diskProvider.InheritFolderPermissions(destinationFilename); } catch (UnauthorizedAccessException ex) { _logger.Debug("Unable to apply folder permissions to: ", destinationFilename); _logger.TraceException(ex.Message, ex); } }
public void Backup() { _logger.Info("Backing up appdata (database/config)"); var backupFolderAppData = _appFolderInfo.GetUpdateBackUpAppDataFolder(); if (_diskProvider.FolderExists(backupFolderAppData)) { _diskProvider.EmptyFolder(backupFolderAppData); } else { _diskProvider.CreateFolder(backupFolderAppData); } try { _diskTransferService.TransferFile(_appFolderInfo.GetConfigPath(), _appFolderInfo.GetUpdateBackupConfigFile(), TransferMode.Copy); //Backup new db if exists, else try old then fail if (_diskProvider.FileExists(_appFolderInfo.GetDatabase())) { _diskTransferService.TransferFile(_appFolderInfo.GetDatabase(), _appFolderInfo.GetUpdateBackupDatabase(), TransferMode.Copy); } else { _diskTransferService.TransferFile(_appFolderInfo.GetV0Database(), _appFolderInfo.GetV0UpdateBackupDatabase(), TransferMode.Copy); } } catch (Exception e) { _logger.Error(e, "Couldn't create a data backup"); } }
public void DeleteFile(string path, string subfolder = "") { _logger.Debug("Attempting to send '{0}' to recycling bin", path); var recyclingBin = _configService.RecycleBin; if (string.IsNullOrWhiteSpace(recyclingBin)) { _logger.Info("Recycling Bin has not been configured, deleting permanently. {0}", path); if (OsInfo.IsWindows) { _logger.Debug(_diskProvider.GetFileAttributes(path)); } _diskProvider.DeleteFile(path); _logger.Debug("File has been permanently deleted: {0}", path); } else { var fileInfo = new FileInfo(path); var destinationFolder = Path.Combine(recyclingBin, subfolder); var destination = Path.Combine(destinationFolder, fileInfo.Name); _diskProvider.CreateFolder(destinationFolder); var index = 1; while (_diskProvider.FileExists(destination)) { index++; if (fileInfo.Extension.IsNullOrWhiteSpace()) { destination = Path.Combine(destinationFolder, fileInfo.Name + "_" + index); } else { destination = Path.Combine(destinationFolder, Path.GetFileNameWithoutExtension(fileInfo.Name) + "_" + index + fileInfo.Extension); } } try { _logger.Debug("Moving '{0}' to '{1}'", path, destination); _diskTransferService.TransferFile(path, destination, TransferMode.Move); } catch (IOException e) { _logger.Error(e, "Unable to move '{0}' to the recycling bin: '{1}'", path, destination); throw; } //TODO: Better fix than this for non-Windows? if (OsInfo.IsWindows) { _diskProvider.FileSetLastWriteTime(destination, DateTime.UtcNow); } _logger.Debug("File has been moved to the recycling bin: {0}", destination); } }
private void MoveSingleMovie(Movie movie, string sourcePath, string destinationPath, int?index = null, int?total = null) { if (!_diskProvider.FolderExists(sourcePath)) { _logger.Debug("Folder '{0}' for '{1}' does not exist, not moving.", sourcePath, movie.Title); return; } if (index != null && total != null) { _logger.ProgressInfo("Moving {0} from '{1}' to '{2}' ({3}/{4})", movie.Title, sourcePath, destinationPath, index + 1, total); } else { _logger.ProgressInfo("Moving {0} from '{1}' to '{2}'", movie.Title, sourcePath, destinationPath); } try { _diskProvider.CreateFolder(new DirectoryInfo(destinationPath).Parent.FullName); _diskTransferService.TransferFolder(sourcePath, destinationPath, TransferMode.Move); _logger.ProgressInfo("{0} moved successfully to {1}", movie.Title, movie.Path); _eventAggregator.PublishEvent(new MovieMovedEvent(movie, sourcePath, destinationPath)); } catch (IOException ex) { _logger.Error(ex, "Unable to move movie from '{0}' to '{1}'. Try moving files manually", sourcePath, destinationPath); RevertPath(movie.Id, sourcePath); } }
private void MoveSingleSeries(Series series, string sourcePath, string destinationPath, int?index = null, int?total = null) { if (!_diskProvider.FolderExists(sourcePath)) { _logger.Debug("Folder '{0}' for '{1}' does not exist, not moving.", sourcePath, series.Title); return; } if (index != null && total != null) { _logger.ProgressInfo("Moving {0} from '{1}' to '{2}' ({3}/{4})", series.Title, sourcePath, destinationPath, index + 1, total); } else { _logger.ProgressInfo("Moving {0} from '{1}' to '{2}'", series.Title, sourcePath, destinationPath); } try { // Ensure the parent of the series folder exists, this will often just be the root folder, but // in cases where people are using subfolders for first letter (etc) it may not yet exist. _diskProvider.CreateFolder(new DirectoryInfo(destinationPath).Parent.FullName); _diskTransferService.TransferFolder(sourcePath, destinationPath, TransferMode.Move); _logger.ProgressInfo("{0} moved successfully to {1}", series.Title, series.Path); _eventAggregator.PublishEvent(new SeriesMovedEvent(series, sourcePath, destinationPath)); } catch (IOException ex) { _logger.Error(ex, "Unable to move series from '{0}' to '{1}'. Try moving files manually", sourcePath, destinationPath); RevertPath(series.Id, sourcePath); } }
public void Backup() { _logger.Info("Backing up appdata (database/config)"); var backupFolderAppData = _appFolderInfo.GetUpdateBackUpAppDataFolder(); _diskProvider.CreateFolder(backupFolderAppData); _diskProvider.CopyFile(_appFolderInfo.GetConfigPath(), _appFolderInfo.GetUpdateBackupConfigFile(), true); _diskProvider.CopyFile(_appFolderInfo.GetNzbDroneDatabase(), _appFolderInfo.GetUpdateBackupDatabase(), true); }
public void Scan(Series series) { var rootFolder = _diskProvider.GetParentFolder(series.Path); if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Series' root folder ({0}) doesn't exist.", rootFolder); return; } if (_diskProvider.GetDirectories(rootFolder).Empty()) { _logger.Warn("Series' root folder ({0}) is empty.", rootFolder); return; } _logger.ProgressInfo("Scanning disk for {0}", series.Title); _commandExecutor.PublishCommand(new CleanMediaFileDb(series.Id)); if (!_diskProvider.FolderExists(series.Path)) { if (_configService.CreateEmptySeriesFolders && _diskProvider.FolderExists(rootFolder)) { _logger.Debug("Creating missing series folder: {0}", series.Path); _diskProvider.CreateFolder(series.Path); SetPermissions(series.Path); } else { _logger.Debug("Series folder doesn't exist: {0}", series.Path); } return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = GetVideoFiles(series.Path).Where(file => !ExcludedSubFoldersRegex.IsMatch(series.Path.GetRelativePath(file))).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting episode files for: {0} [{1}]", series, videoFilesStopwatch.Elapsed); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series, false); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", series, decisionsStopwatch.Elapsed); _importApprovedEpisodes.Import(decisions, false); _logger.Info("Completed scanning disk for {0}", series.Title); _eventAggregator.PublishEvent(new SeriesScannedEvent(series)); }
public void Backup() { _logger.Info("Backing up appdata (database/config)"); var backupFolderAppData = _appFolderInfo.GetUpdateBackUpAppDataFolder(); _diskProvider.CreateFolder(backupFolderAppData); try { _diskTransferService.TransferFile(_appFolderInfo.GetConfigPath(), _appFolderInfo.GetUpdateBackupConfigFile(), TransferMode.Copy); _diskTransferService.TransferFile(_appFolderInfo.GetNzbDroneDatabase(), _appFolderInfo.GetUpdateBackupDatabase(), TransferMode.Copy); } catch (Exception e) { _logger.Error(e, "Couldn't create a data backup"); } }
private void CreateFolder(string directoryName) { Ensure.That(directoryName, () => directoryName).IsNotNullOrWhiteSpace(); var parentFolder = new OsPath(directoryName).Directory.FullPath; if (!_diskProvider.FolderExists(parentFolder)) { CreateFolder(parentFolder); } try { _diskProvider.CreateFolder(directoryName); } catch (IOException ex) { _logger.Error(ex, "Unable to create directory: {0}", directoryName); } _mediaFileAttributeService.SetFolderPermissions(directoryName); }
public void Scan(Series series) { _logger.ProgressInfo("Scanning disk for {0}", series.Title); _commandExecutor.PublishCommand(new CleanMediaFileDb(series.Id)); if (!_diskProvider.FolderExists(series.Path)) { if (_configService.CreateEmptySeriesFolders && _diskProvider.FolderExists(_diskProvider.GetParentFolder(series.Path))) { _logger.Debug("Creating missing series folder: {0}", series.Path); _diskProvider.CreateFolder(series.Path); } else { _logger.Debug("Series folder doesn't exist: {0}", series.Path); } return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = GetVideoFiles(series.Path).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting episode files for: {0} [{1}]", series, videoFilesStopwatch.Elapsed); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series, false); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", series, decisionsStopwatch.Elapsed); _importApprovedEpisodes.Import(decisions); _logger.Info("Completed scanning disk for {0}", series.Title); _eventAggregator.PublishEvent(new SeriesScannedEvent(series)); }
public void Scan(Series series) { var rootFolder = _rootFolderService.GetBestRootFolderPath(series.Path); var seriesFolderExists = _diskProvider.FolderExists(series.Path); if (!seriesFolderExists) { if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Series' root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.FolderEmpty(rootFolder)) { _logger.Warn("Series' root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new SeriesScanSkippedEvent(series, SeriesScanSkippedReason.RootFolderIsEmpty)); return; } } _logger.ProgressInfo("Scanning {0}", series.Title); if (!seriesFolderExists) { if (_configService.CreateEmptySeriesFolders) { if (_configService.DeleteEmptyFolders) { _logger.Debug("Not creating missing series folder: {0} because delete empty series folders is enabled", series.Path); } else { _logger.Debug("Creating missing series folder: {0}", series.Path); _diskProvider.CreateFolder(series.Path); SetPermissions(series.Path); } } else { _logger.Debug("Series folder doesn't exist: {0}", series.Path); } CleanMediaFiles(series, new List <string>()); CompletedScanning(series); return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterPaths(series.Path, GetVideoFiles(series.Path)).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting episode files for: {0} [{1}]", series, videoFilesStopwatch.Elapsed); CleanMediaFiles(series, mediaFileList); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", series, decisionsStopwatch.Elapsed); _importApprovedEpisodes.Import(decisions, false); RemoveEmptySeriesFolder(series.Path); CompletedScanning(series); }
private void EnsureDefinitionsFolder() { var definitionFolder = Path.Combine(_appFolderInfo.AppDataFolder, "Definitions"); _diskProvider.CreateFolder(definitionFolder); }
public void Scan(Movie movie) { //Try renaming the movie path in case anything changed such as year, title or something else. _renameMovieFiles.RenameMoviePath(movie, true); var rootFolder = _diskProvider.GetParentFolder(movie.Path); if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Movies' root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.GetDirectories(rootFolder).Empty()) { _logger.Warn("Movies' root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderIsEmpty)); return; } _logger.ProgressInfo("Scanning disk for {0}", movie.Title); if (!_diskProvider.FolderExists(movie.Path)) { if (movie.MovieFileId != 0) { //Since there is no folder, there can't be any files right? _mediaFileTableCleanupService.Clean(movie, new List <string>()); _logger.Debug("Movies folder doesn't exist: {0}", movie.Path); } else if (_configService.CreateEmptySeriesFolders && _diskProvider.FolderExists(rootFolder)) { _logger.Debug("Creating missing movies folder: {0}", movie.Path); _diskProvider.CreateFolder(movie.Path); SetPermissions(movie.Path); } else { _logger.Debug("Movies folder doesn't exist: {0}", movie.Path); } _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.MovieFolderDoesNotExist)); return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterFiles(movie, GetVideoFiles(movie.Path)).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting movie files for: {0} [{1}]", movie, videoFilesStopwatch.Elapsed); _logger.Debug("{0} Cleaning up media files in DB", movie); _mediaFileTableCleanupService.Clean(movie, mediaFileList); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie, true); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed); _importApprovedMovies.Import(decisions, false); _logger.Info("Completed scanning disk for {0}", movie.Title); _eventAggregator.PublishEvent(new MovieScannedEvent(movie)); }
public void Scan(Movie movie) { var rootFolder = _rootFolderService.GetBestRootFolderPath(movie.Path); var movieFolderExists = _diskProvider.FolderExists(movie.Path); if (!movieFolderExists) { if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Movie's root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.FolderEmpty(rootFolder)) { _logger.Warn("Movie's root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderIsEmpty)); return; } } _logger.ProgressInfo("Scanning disk for {0}", movie.Title); if (!movieFolderExists) { if (_configService.CreateEmptyMovieFolders) { if (_configService.DeleteEmptyFolders) { _logger.Debug("Not creating missing movie folder: {0} because delete empty movie folders is enabled", movie.Path); } else { _logger.Debug("Creating missing movie folder: {0}", movie.Path); _diskProvider.CreateFolder(movie.Path); SetPermissions(movie.Path); } } else { _logger.Debug("Movie's folder doesn't exist: {0}", movie.Path); } CleanMediaFiles(movie, new List <string>()); CompletedScanning(movie); return; } var videoFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterPaths(movie.Path, GetVideoFiles(movie.Path)).ToList(); videoFilesStopwatch.Stop(); _logger.Trace("Finished getting movie files for: {0} [{1}]", movie, videoFilesStopwatch.Elapsed); CleanMediaFiles(movie, mediaFileList); var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id); var unmappedFiles = MediaFileService.FilterExistingFiles(mediaFileList, movieFiles, movie); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(unmappedFiles, movie, false); decisionsStopwatch.Stop(); _logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed); _importApprovedMovies.Import(decisions, false); // Update existing files that have a different file size var fileInfoStopwatch = Stopwatch.StartNew(); var filesToUpdate = new List <MovieFile>(); foreach (var file in movieFiles) { var path = Path.Combine(movie.Path, file.RelativePath); var fileSize = _diskProvider.GetFileSize(path); if (file.Size == fileSize) { continue; } file.Size = fileSize; if (!_updateMediaInfoService.Update(file, movie)) { filesToUpdate.Add(file); } } // Update any files that had a file size change, but didn't get media info updated. if (filesToUpdate.Any()) { _mediaFileService.Update(filesToUpdate); } fileInfoStopwatch.Stop(); _logger.Trace("Reprocessing existing files complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed); RemoveEmptyMovieFolder(movie.Path); CompletedScanning(movie); }
public void Scan(Artist artist, FilterFilesType filter = FilterFilesType.Known) { var rootFolder = _rootFolderService.GetBestRootFolderPath(artist.Path); if (!_diskProvider.FolderExists(rootFolder)) { _logger.Warn("Artist' root folder ({0}) doesn't exist.", rootFolder); _eventAggregator.PublishEvent(new ArtistScanSkippedEvent(artist, ArtistScanSkippedReason.RootFolderDoesNotExist)); return; } if (_diskProvider.GetDirectories(rootFolder).Empty()) { _logger.Warn("Artist' root folder ({0}) is empty.", rootFolder); _eventAggregator.PublishEvent(new ArtistScanSkippedEvent(artist, ArtistScanSkippedReason.RootFolderIsEmpty)); return; } _logger.ProgressInfo("Scanning {0}", artist.Name); if (!_diskProvider.FolderExists(artist.Path)) { if (_configService.CreateEmptyArtistFolders) { _logger.Debug("Creating missing artist folder: {0}", artist.Path); _diskProvider.CreateFolder(artist.Path); SetPermissions(artist.Path); } else { _logger.Debug("Artist folder doesn't exist: {0}", artist.Path); } CleanMediaFiles(artist, new List <string>()); CompletedScanning(artist); return; } var musicFilesStopwatch = Stopwatch.StartNew(); var mediaFileList = FilterFiles(artist.Path, GetAudioFiles(artist.Path)).ToList(); musicFilesStopwatch.Stop(); _logger.Trace("Finished getting track files for: {0} [{1}]", artist, musicFilesStopwatch.Elapsed); CleanMediaFiles(artist, mediaFileList.Select(x => x.FullName).ToList()); var decisionsStopwatch = Stopwatch.StartNew(); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, artist, filter, true); decisionsStopwatch.Stop(); _logger.Debug("Import decisions complete for: {0} [{1}]", artist, decisionsStopwatch.Elapsed); var importStopwatch = Stopwatch.StartNew(); _importApprovedTracks.Import(decisions, false); // decisions may have been filtered to just new files. Anything new and approved will have been inserted. // Now we need to make sure anything new but not approved gets inserted // Note that knownFiles will include anything imported just now var knownFiles = _mediaFileService.GetFilesWithBasePath(artist.Path); var newFiles = decisions .ExceptBy(x => x.Item.Path, knownFiles, x => x.Path, PathEqualityComparer.Instance) .Select(decision => new TrackFile { Path = decision.Item.Path, Size = decision.Item.Size, Modified = decision.Item.Modified, DateAdded = DateTime.UtcNow, Quality = decision.Item.Quality, MediaInfo = decision.Item.FileTrackInfo.MediaInfo }) .ToList(); _mediaFileService.AddMany(newFiles); _logger.Debug($"Inserted {newFiles.Count} new unmatched trackfiles"); // finally update info on size/modified for existing files var updatedFiles = knownFiles .Join(decisions, x => x.Path, x => x.Item.Path, (file, decision) => new { File = file, Item = decision.Item }, PathEqualityComparer.Instance) .Where(x => x.File.Size != x.Item.Size || Math.Abs((x.File.Modified - x.Item.Modified).TotalSeconds) > 1) .Select(x => { x.File.Size = x.Item.Size; x.File.Modified = x.Item.Modified; x.File.MediaInfo = x.Item.FileTrackInfo.MediaInfo; x.File.Quality = x.Item.Quality; return(x.File); }) .ToList(); _mediaFileService.Update(updatedFiles); _logger.Debug($"Updated info for {updatedFiles.Count} known files"); RemoveEmptyArtistFolder(artist.Path); CompletedScanning(artist); importStopwatch.Stop(); _logger.Debug("Track import complete for: {0} [{1}]", artist, importStopwatch.Elapsed); }
private EpisodeFile TransferFile(EpisodeFile episodeFile, Series series, List <Episode> episodes, String destinationFilename, Boolean copyOnly) { Ensure.That(episodeFile, () => episodeFile).IsNotNull(); Ensure.That(series, () => series).IsNotNull(); Ensure.That(destinationFilename, () => destinationFilename).IsValidPath(); var episodeFilePath = episodeFile.Path ?? Path.Combine(series.Path, episodeFile.RelativePath); if (!_diskProvider.FileExists(episodeFilePath)) { throw new FileNotFoundException("Episode file path does not exist", episodeFilePath); } if (episodeFilePath.PathEquals(destinationFilename)) { throw new SameFilenameException("File not moved, source and destination are the same", episodeFilePath); } var directoryName = new FileInfo(destinationFilename).DirectoryName; if (!_diskProvider.FolderExists(directoryName)) { try { _diskProvider.CreateFolder(directoryName); } catch (IOException ex) { _logger.ErrorException("Unable to create directory: " + directoryName, ex); } SetFolderPermissions(directoryName); if (!directoryName.PathEquals(series.Path)) { SetFolderPermissions(series.Path); } } if (copyOnly) { _logger.Debug("Copying [{0}] > [{1}]", episodeFilePath, destinationFilename); _diskProvider.CopyFile(episodeFilePath, destinationFilename); } else { _logger.Debug("Moving [{0}] > [{1}]", episodeFilePath, destinationFilename); _diskProvider.MoveFile(episodeFilePath, destinationFilename); } episodeFile.RelativePath = series.Path.GetRelativePath(destinationFilename); _updateEpisodeFileService.ChangeFileDateForFile(episodeFile, series, episodes); try { SetFolderLastWriteTime(series.Path, episodeFile.DateAdded); if (series.SeasonFolder) { var seasonFolder = Path.GetDirectoryName(destinationFilename); SetFolderLastWriteTime(seasonFolder, episodeFile.DateAdded); } } catch (Exception ex) { _logger.WarnException("Unable to set last write time", ex); } //We should only run this on Windows if (OsInfo.IsWindows) { //Wrapped in Try/Catch to prevent this from causing issues with remote NAS boxes, the move worked, which is more important. try { _diskProvider.InheritFolderPermissions(destinationFilename); } catch (Exception ex) { if (ex is UnauthorizedAccessException || ex is InvalidOperationException) { _logger.Debug("Unable to apply folder permissions to: ", destinationFilename); _logger.DebugException(ex.Message, ex); } else { throw; } } } else { SetPermissions(destinationFilename, _configService.FileChmod); } return(episodeFile); }
public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode) { Ensure.That(sourcePath, () => sourcePath).IsValidPath(); Ensure.That(targetPath, () => targetPath).IsValidPath(); sourcePath = ResolveRealParentPath(sourcePath); targetPath = ResolveRealParentPath(targetPath); _logger.Debug("{0} Directory [{1}] > [{2}]", mode, sourcePath, targetPath); if (sourcePath == targetPath) { throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath)); } if (mode == TransferMode.Move && sourcePath.PathEquals(targetPath, StringComparison.InvariantCultureIgnoreCase) && _diskProvider.FolderExists(targetPath)) { // Move folder out of the way to allow case-insensitive renames var tempPath = sourcePath + ".backup~"; _logger.Trace("Rename Intermediate Directory [{0}] > [{1}]", sourcePath, tempPath); _diskProvider.MoveFolder(sourcePath, tempPath); if (!_diskProvider.FolderExists(targetPath)) { _logger.Trace("Rename Intermediate Directory [{0}] > [{1}]", tempPath, targetPath); _logger.Debug("Rename Directory [{0}] > [{1}]", sourcePath, targetPath); _diskProvider.MoveFolder(tempPath, targetPath); return(mode); } // There were two separate folders, revert the intermediate rename and let the recursion deal with it _logger.Trace("Rename Intermediate Directory [{0}] > [{1}]", tempPath, sourcePath); _diskProvider.MoveFolder(tempPath, sourcePath); } if (mode == TransferMode.Move && !_diskProvider.FolderExists(targetPath)) { var sourceMount = _diskProvider.GetMount(sourcePath); var targetMount = _diskProvider.GetMount(targetPath); // If we're on the same mount, do a simple folder move. if (sourceMount != null && targetMount != null && sourceMount.RootDirectory == targetMount.RootDirectory) { _logger.Debug("Rename Directory [{0}] > [{1}]", sourcePath, targetPath); _diskProvider.MoveFolder(sourcePath, targetPath); return(mode); } } if (!_diskProvider.FolderExists(targetPath)) { _diskProvider.CreateFolder(targetPath); _diskProvider.CopyPermissions(sourcePath, targetPath); } var result = mode; foreach (var subDir in _diskProvider.GetDirectoryInfos(sourcePath)) { if (ShouldIgnore(subDir)) { continue; } result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode); } foreach (var sourceFile in _diskProvider.GetFileInfos(sourcePath)) { if (ShouldIgnore(sourceFile)) { continue; } var destFile = Path.Combine(targetPath, sourceFile.Name); result &= TransferFile(sourceFile.FullName, destFile, mode, true); } if (mode.HasFlag(TransferMode.Move)) { var totalSize = _diskProvider.GetFileInfos(sourcePath).Sum(v => v.Length); if (totalSize > (100 * 1024L * 1024L)) { throw new IOException($"Large files still exist in {sourcePath} after folder move, not deleting source folder"); } _diskProvider.DeleteFolder(sourcePath, true); } return(result); }
private EpisodeFile TransferFile(EpisodeFile episodeFile, Series series, List <Episode> episodes, string destinationFilename, TransferMode mode) { Ensure.That(episodeFile, () => episodeFile).IsNotNull(); Ensure.That(series, () => series).IsNotNull(); Ensure.That(destinationFilename, () => destinationFilename).IsValidPath(); var episodeFilePath = episodeFile.Path ?? Path.Combine(series.Path, episodeFile.RelativePath); if (!_diskProvider.FileExists(episodeFilePath)) { throw new FileNotFoundException("Episode file path does not exist", episodeFilePath); } if (episodeFilePath.PathEquals(destinationFilename)) { throw new SameFilenameException("File not moved, source and destination are the same", episodeFilePath); } var directoryName = new FileInfo(destinationFilename).DirectoryName; if (!_diskProvider.FolderExists(directoryName)) { try { _diskProvider.CreateFolder(directoryName); } catch (IOException ex) { _logger.ErrorException("Unable to create directory: " + directoryName, ex); } _mediaFileAttributeService.SetFolderPermissions(directoryName); if (!directoryName.PathEquals(series.Path)) { _mediaFileAttributeService.SetFolderPermissions(series.Path); } } _logger.Debug("{0} [{1}] > [{2}]", mode, episodeFilePath, destinationFilename); _diskProvider.TransferFile(episodeFilePath, destinationFilename, mode); episodeFile.RelativePath = series.Path.GetRelativePath(destinationFilename); _updateEpisodeFileService.ChangeFileDateForFile(episodeFile, series, episodes); try { _mediaFileAttributeService.SetFolderLastWriteTime(series.Path, episodeFile.DateAdded); if (series.SeasonFolder) { var seasonFolder = Path.GetDirectoryName(destinationFilename); _mediaFileAttributeService.SetFolderLastWriteTime(seasonFolder, episodeFile.DateAdded); } } catch (Exception ex) { _logger.WarnException("Unable to set last write time", ex); } _mediaFileAttributeService.SetFilePermissions(destinationFilename); return(episodeFile); }