From b1f76082b202f5f33acc4f818bf518b0602d9e9d Mon Sep 17 00:00:00 2001 From: Leonardo Galli Date: Fri, 2 Feb 2018 13:23:29 +0100 Subject: [PATCH] Added: Dynamic paths cleanup old folders now! Old folder is now only left behind if extra files are also present in new dir and cannot be overwritten. Generally Dynamic Paths should be more stable now. Fixes #2048 --- .../.idea.NzbDrone/.idea/contentModel.xml | 3480 +++++++++++++++++ .../.idea.NzbDrone/.idea/indexLayout.xml | 7 + src/.idea/.idea.NzbDrone/riderModule.iml | 100 +- src/NzbDrone.Common/Disk/DiskProviderBase.cs | 33 + src/NzbDrone.Common/Disk/IDiskProvider.cs | 1 + .../MediaFiles/MovieFileMovingService.cs | 38 +- .../MediaFiles/RenameMovieFileService.cs | 22 +- src/NzbDrone.sln.DotSettings | 9 + 8 files changed, 3574 insertions(+), 116 deletions(-) create mode 100644 src/.idea/.idea.NzbDrone/.idea/indexLayout.xml diff --git a/src/.idea/.idea.NzbDrone/.idea/contentModel.xml b/src/.idea/.idea.NzbDrone/.idea/contentModel.xml index 02cf7ea47..bced20297 100644 --- a/src/.idea/.idea.NzbDrone/.idea/contentModel.xml +++ b/src/.idea/.idea.NzbDrone/.idea/contentModel.xml @@ -1,5 +1,3485 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/.idea/.idea.NzbDrone/.idea/indexLayout.xml b/src/.idea/.idea.NzbDrone/.idea/indexLayout.xml new file mode 100644 index 000000000..f1feadf0e --- /dev/null +++ b/src/.idea/.idea.NzbDrone/.idea/indexLayout.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/.idea/.idea.NzbDrone/riderModule.iml b/src/.idea/.idea.NzbDrone/riderModule.iml index c84a9c732..c8b2ee068 100644 --- a/src/.idea/.idea.NzbDrone/riderModule.iml +++ b/src/.idea/.idea.NzbDrone/riderModule.iml @@ -1,103 +1,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + \ No newline at end of file diff --git a/src/NzbDrone.Common/Disk/DiskProviderBase.cs b/src/NzbDrone.Common/Disk/DiskProviderBase.cs index cedd0f348..5ba2021cc 100644 --- a/src/NzbDrone.Common/Disk/DiskProviderBase.cs +++ b/src/NzbDrone.Common/Disk/DiskProviderBase.cs @@ -245,6 +245,25 @@ public void MoveFile(string source, string destination, bool overwrite = false) File.Move(source, destination); } + public void MoveFolder(string source, string destination, bool overwrite = false) + { + Ensure.That(source, () => source).IsValidPath(); + Ensure.That(destination, () => destination).IsValidPath(); + + if (source.PathEquals(destination)) + { + throw new IOException(string.Format("Source and destination can't be the same {0}", source)); + } + + if (FolderExists(destination) && overwrite) + { + DeleteFolder(destination, true); + } + + RemoveReadOnlyFolder(source); + Directory.Move(source, destination); + } + public abstract bool TryCreateHardLink(string source, string destination); public void DeleteFolder(string path, bool recursive) @@ -371,6 +390,20 @@ private static void RemoveReadOnly(string path) } } + private static void RemoveReadOnlyFolder(string path) + { + if (Directory.Exists(path)) + { + var dirInfo = new DirectoryInfo(path); + + if (dirInfo.Attributes.HasFlag(FileAttributes.ReadOnly)) + { + var newAttributes = dirInfo.Attributes & ~(FileAttributes.ReadOnly); + dirInfo.Attributes = newAttributes; + } + } + } + public FileAttributes GetFileAttributes(string path) { return File.GetAttributes(path); diff --git a/src/NzbDrone.Common/Disk/IDiskProvider.cs b/src/NzbDrone.Common/Disk/IDiskProvider.cs index 3976219d2..33e8d0228 100644 --- a/src/NzbDrone.Common/Disk/IDiskProvider.cs +++ b/src/NzbDrone.Common/Disk/IDiskProvider.cs @@ -30,6 +30,7 @@ public interface IDiskProvider void DeleteFile(string path); void CopyFile(string source, string destination, bool overwrite = false); void MoveFile(string source, string destination, bool overwrite = false); + void MoveFolder(string source, string destination, bool overwrite = false); bool TryCreateHardLink(string source, string destination); void DeleteFolder(string path, bool recursive); string ReadAllText(string filePath); diff --git a/src/NzbDrone.Core/MediaFiles/MovieFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/MovieFileMovingService.cs index 32679afe5..312fda380 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieFileMovingService.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieFileMovingService.cs @@ -66,7 +66,7 @@ public MovieFile MoveMovieFile(MovieFile movieFile, Movie movie) EnsureMovieFolder(movieFile, movie, filePath); _logger.Debug("Renaming movie file: {0} to {1}", movieFile, filePath); - + return TransferFile(movieFile, movie, filePath, TransferMode.Move); } @@ -78,7 +78,7 @@ public MovieFile MoveMovieFile(MovieFile movieFile, LocalMovie localMovie) EnsureMovieFolder(movieFile, localMovie, filePath); _logger.Debug("Moving movie file: {0} to {1}", movieFile.Path, filePath); - + return TransferFile(movieFile, localMovie.Movie, filePath, TransferMode.Move); } @@ -98,7 +98,7 @@ public MovieFile CopyMovieFile(MovieFile movieFile, LocalMovie localMovie) _logger.Debug("Copying movie file: {0} to {1}", movieFile.Path, filePath); return TransferFile(movieFile, localMovie.Movie, filePath, TransferMode.Copy); } - + private MovieFile TransferFile(MovieFile movieFile, Movie movie, string destinationFilePath, TransferMode mode) { Ensure.That(movieFile, () => movieFile).IsNotNull(); @@ -122,11 +122,8 @@ private MovieFile TransferFile(MovieFile movieFile, Movie movie, string destinat var oldMoviePath = movie.Path; var newMoviePath = new OsPath(destinationFilePath).Directory.FullPath.TrimEnd(Path.DirectorySeparatorChar); - movie.Path = newMoviePath; - if (oldMoviePath != newMoviePath) - { - _movieService.UpdateMovie(movie); - } + + movie.Path = newMoviePath; //We update it when everything went well! movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath); @@ -146,12 +143,35 @@ private MovieFile TransferFile(MovieFile movieFile, Movie movie, string destinat if(oldMoviePath != newMoviePath) { + //Let's move the old files before deleting the old folder. We could just do move folder, but the main file (movie file) is already moved, so eh. + var files = _diskProvider.GetFiles(oldMoviePath, SearchOption.AllDirectories); + + foreach (var file in files) + { + try + { + var destFile = Path.Combine(newMoviePath, oldMoviePath.GetRelativePath(file)); + _diskProvider.EnsureFolder(Path.GetDirectoryName(destFile)); + _diskProvider.MoveFile(file, destFile); + } + catch (Exception e) + { + _logger.Warn(e, "Error while trying to move extra file {0} to new folder. Maybe it already exists? (Manual cleanup necessary!).", oldMoviePath.GetRelativePath(file)); + } + } + if (_diskProvider.GetFiles(oldMoviePath, SearchOption.AllDirectories).Count() == 0) { _recycleBinProvider.DeleteFolder(oldMoviePath); } } + //Only update the movie path if we were successfull! + if (oldMoviePath != newMoviePath) + { + _movieService.UpdateMovie(movie); + } + return movieFile; } @@ -163,7 +183,7 @@ private void EnsureMovieFolder(MovieFile movieFile, LocalMovie localMovie, strin private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath) { var movieFolder = Path.GetDirectoryName(filePath); - movie.Path = movieFolder; + //movie.Path = movieFolder; var rootFolder = new OsPath(movieFolder).Directory.FullPath; var fileName = Path.GetFileName(filePath); diff --git a/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs b/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs index 626c8929f..ad402c789 100644 --- a/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs +++ b/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs @@ -38,7 +38,7 @@ public class RenameMovieFileService : IRenameMovieFileService, private readonly IDiskProvider _diskProvider; private readonly IRecycleBinProvider _recycleBinProvider; private readonly Logger _logger; - + public RenameMovieFileService(IMovieService movieService, IMediaFileService mediaFileService, IMoveMovieFiles movieFileMover, @@ -91,7 +91,7 @@ private IEnumerable GetPreviews(Movie movie, List movieFiles, Movie movie, string oldMoviePath = null) @@ -136,23 +136,25 @@ public void RenameMoviePath(Movie movie, bool shouldRenameFiles = true) var newFolder = _filenameBuilder.BuildMoviePath(movie); if (newFolder != movie.Path && movie.PathState == MoviePathState.Dynamic) { - + if (!_configService.AutoRenameFolders) { _logger.Info("{0}'s movie should be {1} according to your naming config.", movie, newFolder); return; } - + _logger.Info("{0}'s movie folder changed to: {1}", movie, newFolder); var oldFolder = movie.Path; movie.Path = newFolder; - if (shouldRenameFiles) + _diskProvider.MoveFolder(oldFolder, movie.Path); + + if (false) { var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id); _logger.ProgressInfo("Renaming movie files for {0}", movie.Title); RenameFiles(movieFiles, movie, oldFolder); - _logger.ProgressInfo("All movie files renamed for {0}", movie.Title); + _logger.ProgressInfo("All movie files renamed for {0}", movie.Title); } _movieService.UpdateMovie(movie); @@ -162,7 +164,7 @@ public void RenameMoviePath(Movie movie, bool shouldRenameFiles = true) _recycleBinProvider.DeleteFolder(oldFolder); } - + } if (movie.PathState == MoviePathState.StaticOnce) @@ -194,7 +196,7 @@ public void Execute(RenameMovieCommand message) RenameFiles(movieFiles, movie); _logger.ProgressInfo("All movie files renamed for {0}", movie.Title); } - + } public void Execute(RenameMovieFolderCommand message) @@ -206,7 +208,7 @@ public void Execute(RenameMovieFolderCommand message) foreach(var movie in moviesToRename) { var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id); - _logger.ProgressInfo("Renaming movie folder for {0}", movie.Title); + //_logger.ProgressInfo("Renaming movie folder for {0}", movie.Title); RenameMoviePath(movie); } } @@ -214,7 +216,7 @@ public void Execute(RenameMovieFolderCommand message) { _logger.Warn(ex, "wtf: {0}, {1}", ex.ResultCode, ex.Data); } - + } } } diff --git a/src/NzbDrone.sln.DotSettings b/src/NzbDrone.sln.DotSettings index 6eb81d19a..53d134aab 100644 --- a/src/NzbDrone.sln.DotSettings +++ b/src/NzbDrone.sln.DotSettings @@ -27,9 +27,13 @@ ALWAYS_ADD True True + NEVER + NEVER False + NEVER False False + ALWAYS ON_SINGLE_LINE False False @@ -66,7 +70,12 @@ True 2 False + True + True + True + True True + True True True True