diff --git a/frontend/src/Movie/MoveMovie/MoveMovieModal.js b/frontend/src/Movie/MoveMovie/MoveMovieModal.js
index 6fa01ec76..04bb45e37 100644
--- a/frontend/src/Movie/MoveMovie/MoveMovieModal.js
+++ b/frontend/src/Movie/MoveMovie/MoveMovieModal.js
@@ -49,6 +49,13 @@ function MoveMovieModal(props) {
`Would you like to move the movie folders to '${destinationRootFolder}'?` :
`Would you like to move the movie files from '${originalPath}' to '${destinationPath}'?`
}
+ {
+ destinationRootFolder ?
+
+ This will also rename the movie folder per the movie folder format in settings.
+
:
+ null
+ }
diff --git a/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs b/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs
index 534cda2d6..c62d239ce 100644
--- a/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs
+++ b/src/NzbDrone.Api/Config/MediaManagementConfigResource.cs
@@ -39,7 +39,6 @@ namespace NzbDrone.Api.Config
CreateEmptySeriesFolders = model.CreateEmptyMovieFolders,
FileDate = model.FileDate,
AutoRenameFolders = model.AutoRenameFolders,
- PathsDefaultStatic = model.PathsDefaultStatic,
SetPermissionsLinux = model.SetPermissionsLinux,
FileChmod = model.FileChmod,
diff --git a/src/NzbDrone.Api/Movies/MovieEditorModule.cs b/src/NzbDrone.Api/Movies/MovieEditorModule.cs
index 31c184a40..a97443385 100644
--- a/src/NzbDrone.Api/Movies/MovieEditorModule.cs
+++ b/src/NzbDrone.Api/Movies/MovieEditorModule.cs
@@ -25,7 +25,7 @@ namespace NzbDrone.Api.Movies
var movie = resources.Select(movieResource => movieResource.ToModel(_movieService.GetMovie(movieResource.Id))).ToList();
- return ResponseWithCode(_movieService.UpdateMovie(movie)
+ return ResponseWithCode(_movieService.UpdateMovie(movie, true)
.ToResource(),
HttpStatusCode.Accepted);
}
diff --git a/src/NzbDrone.Api/Movies/MovieResource.cs b/src/NzbDrone.Api/Movies/MovieResource.cs
index 7dc9f40b4..9d745b50d 100644
--- a/src/NzbDrone.Api/Movies/MovieResource.cs
+++ b/src/NzbDrone.Api/Movies/MovieResource.cs
@@ -43,7 +43,6 @@ namespace NzbDrone.Api.Movies
//View & Edit
public string Path { get; set; }
public int ProfileId { get; set; }
- public MoviePathState PathState { get; set; }
//Editing Only
public bool Monitored { get; set; }
@@ -144,7 +143,6 @@ namespace NzbDrone.Api.Movies
Path = model.Path,
ProfileId = model.ProfileId,
- PathState = model.PathState,
Monitored = model.Monitored,
MinimumAvailability = model.MinimumAvailability,
@@ -209,7 +207,6 @@ namespace NzbDrone.Api.Movies
Path = resource.Path,
ProfileId = resource.ProfileId,
- PathState = resource.PathState,
Monitored = resource.Monitored,
MinimumAvailability = resource.MinimumAvailability,
diff --git a/src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs b/src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs
index f6882efb8..e954bdfde 100644
--- a/src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs
+++ b/src/NzbDrone.Core.Test/Datastore/WhereBuilderFixture.cs
@@ -153,30 +153,30 @@ namespace NzbDrone.Core.Test.Datastore
[Test]
public void enum_as_int()
{
- _subject = Where(x => x.PathState == MoviePathState.Static);
+ _subject = Where(x => x.Status == MovieStatusType.Released);
var name = _subject.Parameters.ParameterNames.First();
- _subject.ToString().Should().Be($"(\"Movies\".\"PathState\" = @{name})");
+ _subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @{name})");
}
[Test]
public void enum_in_list()
{
- var allowed = new List { MoviePathState.Dynamic, MoviePathState.Static };
- _subject = Where(x => allowed.Contains(x.PathState));
+ var allowed = new List { MovieStatusType.InCinemas, MovieStatusType.Released };
+ _subject = Where(x => allowed.Contains(x.Status));
var name = _subject.Parameters.ParameterNames.First();
- _subject.ToString().Should().Be($"(\"Movies\".\"PathState\" IN @{name})");
+ _subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @{name})");
}
[Test]
public void enum_in_array()
{
- var allowed = new MoviePathState[] { MoviePathState.Dynamic, MoviePathState.Static };
- _subject = Where(x => allowed.Contains(x.PathState));
+ var allowed = new MovieStatusType[] { MovieStatusType.InCinemas, MovieStatusType.Released };
+ _subject = Where(x => allowed.Contains(x.Status));
var name = _subject.Parameters.ParameterNames.First();
- _subject.ToString().Should().Be($"(\"Movies\".\"PathState\" IN @{name})");
+ _subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @{name})");
}
}
}
diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieFolderPathBuilderFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieFolderPathBuilderFixture.cs
new file mode 100644
index 000000000..bcc2981c9
--- /dev/null
+++ b/src/NzbDrone.Core.Test/MovieTests/MovieFolderPathBuilderFixture.cs
@@ -0,0 +1,94 @@
+using System.IO;
+using FizzWare.NBuilder;
+using FluentAssertions;
+using Moq;
+using NUnit.Framework;
+using NzbDrone.Core.Movies;
+using NzbDrone.Core.Organizer;
+using NzbDrone.Core.RootFolders;
+using NzbDrone.Core.Test.Framework;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.MovieTests
+{
+ [TestFixture]
+ public class MovieFolderPathBuilderFixture : CoreTest
+ {
+ private Movie _movie;
+
+ [SetUp]
+ public void Setup()
+ {
+ _movie = Builder.CreateNew()
+ .With(s => s.Title = "Movie Title")
+ .With(s => s.Path = @"C:\Test\Movies\Movie.Title".AsOsAgnostic())
+ .With(s => s.RootFolderPath = null)
+ .Build();
+ }
+
+ public void GivenMovieFolderName(string name)
+ {
+ Mocker.GetMock()
+ .Setup(s => s.GetMovieFolder(_movie, null))
+ .Returns(name);
+ }
+
+ public void GivenExistingRootFolder(string rootFolder)
+ {
+ Mocker.GetMock()
+ .Setup(s => s.GetBestRootFolderPath(It.IsAny()))
+ .Returns(rootFolder);
+ }
+
+ [Test]
+ public void should_create_new_movie_path()
+ {
+ var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
+
+ GivenMovieFolderName(_movie.Title);
+ _movie.RootFolderPath = rootFolder;
+
+ Subject.BuildPath(_movie, false).Should().Be(Path.Combine(rootFolder, _movie.Title));
+ }
+
+ [Test]
+ public void should_reuse_existing_relative_folder_name()
+ {
+ var folderName = Path.GetFileName(_movie.Path);
+ var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
+
+ GivenExistingRootFolder(Path.GetDirectoryName(_movie.Path));
+ GivenMovieFolderName(_movie.Title);
+ _movie.RootFolderPath = rootFolder;
+
+ Subject.BuildPath(_movie, true).Should().Be(Path.Combine(rootFolder, folderName));
+ }
+
+ [Test]
+ public void should_reuse_existing_relative_folder_structure()
+ {
+ var existingRootFolder = @"C:\Test\Movies".AsOsAgnostic();
+ var existingRelativePath = @"M\Movie.Title";
+ var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
+
+ GivenExistingRootFolder(existingRootFolder);
+ GivenMovieFolderName(_movie.Title);
+ _movie.RootFolderPath = rootFolder;
+ _movie.Path = Path.Combine(existingRootFolder, existingRelativePath);
+
+ Subject.BuildPath(_movie, true).Should().Be(Path.Combine(rootFolder, existingRelativePath));
+ }
+
+ [Test]
+ public void should_use_built_path_for_new_movie()
+ {
+ var rootFolder = @"C:\Test\Movies2".AsOsAgnostic();
+
+ GivenMovieFolderName(_movie.Title);
+ _movie.RootFolderPath = rootFolder;
+ _movie.Path = null;
+
+ Subject.BuildPath(_movie, true).Should().Be(Path.Combine(rootFolder, _movie.Title));
+ }
+ }
+}
diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs
index e5606c670..0f518244f 100644
--- a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs
+++ b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs
@@ -1,10 +1,12 @@
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Movies;
+using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
@@ -30,7 +32,7 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
[Test]
public void should_call_repo_updateMany()
{
- Subject.UpdateMovie(_movies);
+ Subject.UpdateMovie(_movies, false);
Mocker.GetMock().Verify(v => v.UpdateMany(_movies), Times.Once());
}
@@ -41,13 +43,17 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
var newRoot = @"C:\Test\TV2".AsOsAgnostic();
_movies.ForEach(s => s.RootFolderPath = newRoot);
- Subject.UpdateMovie(_movies).ForEach(s => s.Path.Should().StartWith(newRoot));
+ Mocker.GetMock()
+ .Setup(s => s.BuildPath(It.IsAny(), false))
+ .Returns((s, u) => Path.Combine(s.RootFolderPath, s.Title));
+
+ Subject.UpdateMovie(_movies, false).ForEach(s => s.Path.Should().StartWith(newRoot));
}
[Test]
public void should_not_update_path_when_rootFolderPath_is_empty()
{
- Subject.UpdateMovie(_movies).ForEach(s =>
+ Subject.UpdateMovie(_movies, false).ForEach(s =>
{
var expectedPath = _movies.Single(ser => ser.Id == s.Id).Path;
s.Path.Should().Be(expectedPath);
@@ -66,7 +72,11 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
var newRoot = @"C:\Test\Movies2".AsOsAgnostic();
movies.ForEach(s => s.RootFolderPath = newRoot);
- Subject.UpdateMovie(movies);
+ Mocker.GetMock()
+ .Setup(s => s.GetMovieFolder(It.IsAny(), (NamingConfig)null))
+ .Returns((s, n) => s.Title);
+
+ Subject.UpdateMovie(movies, false);
}
}
}
diff --git a/src/NzbDrone.Core.Test/NetImport/NetImportSearchServiceFixture.cs b/src/NzbDrone.Core.Test/NetImport/NetImportSearchServiceFixture.cs
index 88e1cb3b9..ae605ac1d 100644
--- a/src/NzbDrone.Core.Test/NetImport/NetImportSearchServiceFixture.cs
+++ b/src/NzbDrone.Core.Test/NetImport/NetImportSearchServiceFixture.cs
@@ -116,7 +116,7 @@ namespace NzbDrone.Core.Test.NetImport
.Verify(v => v.GetAllMovies(), Times.Never());
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(new List()), Times.Once());
+ .Verify(v => v.UpdateMovie(new List(), true), Times.Once());
}
[Test]
@@ -139,7 +139,7 @@ namespace NzbDrone.Core.Test.NetImport
.Verify(v => v.DeleteMovie(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never());
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(new List()), Times.Once());
+ .Verify(v => v.UpdateMovie(new List(), true), Times.Once());
}
[Test]
@@ -162,7 +162,7 @@ namespace NzbDrone.Core.Test.NetImport
.Verify(v => v.DeleteMovie(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never());
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(It.Is>(s => s.Count == 3 && s.All(m => !m.Monitored))), Times.Once());
+ .Verify(v => v.UpdateMovie(It.Is>(s => s.Count == 3 && s.All(m => !m.Monitored)), true), Times.Once());
}
[Test]
@@ -181,7 +181,7 @@ namespace NzbDrone.Core.Test.NetImport
Subject.Execute(_command);
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(It.Is>(s => s.Count == 2 && s.All(m => !m.Monitored))), Times.Once());
+ .Verify(v => v.UpdateMovie(It.Is>(s => s.Count == 2 && s.All(m => !m.Monitored)), true), Times.Once());
}
[Test]
@@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.NetImport
Subject.Execute(_command);
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(It.Is>(s => s.Count == 2 && s.All(m => !m.Monitored))), Times.Once());
+ .Verify(v => v.UpdateMovie(It.Is>(s => s.Count == 2 && s.All(m => !m.Monitored)), true), Times.Once());
}
[Test]
@@ -227,7 +227,7 @@ namespace NzbDrone.Core.Test.NetImport
.Verify(v => v.DeleteMovie(It.IsAny(), true, It.IsAny()), Times.Never());
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(new List()), Times.Once());
+ .Verify(v => v.UpdateMovie(new List(), true), Times.Once());
}
[Test]
@@ -253,7 +253,7 @@ namespace NzbDrone.Core.Test.NetImport
.Verify(v => v.DeleteMovie(It.IsAny(), true, It.IsAny()), Times.Exactly(3));
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(new List()), Times.Once());
+ .Verify(v => v.UpdateMovie(new List(), true), Times.Once());
}
[Test]
@@ -267,7 +267,7 @@ namespace NzbDrone.Core.Test.NetImport
Subject.Execute(_command);
Mocker.GetMock()
- .Verify(v => v.UpdateMovie(new List()), Times.Never());
+ .Verify(v => v.UpdateMovie(new List(), true), Times.Never());
}
[Test]
diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs
index 664978595..303f83232 100644
--- a/src/NzbDrone.Core/Configuration/ConfigService.cs
+++ b/src/NzbDrone.Core/Configuration/ConfigService.cs
@@ -299,13 +299,6 @@ namespace NzbDrone.Core.Configuration
set { SetValue("AutoRenameFolders", value); }
}
- public bool PathsDefaultStatic
- {
- get { return GetValueBoolean("PathsDefaultStatic", true); }
-
- set { SetValue("PathsDefaultStatic", value); }
- }
-
public RescanAfterRefreshType RescanAfterRefresh
{
get { return GetValueEnum("RescanAfterRefresh", RescanAfterRefreshType.Always); }
diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs
index 8da36b895..1fd9d9992 100644
--- a/src/NzbDrone.Core/Configuration/IConfigService.cs
+++ b/src/NzbDrone.Core/Configuration/IConfigService.cs
@@ -40,7 +40,6 @@ namespace NzbDrone.Core.Configuration
string ExtraFileExtensions { get; set; }
RescanAfterRefreshType RescanAfterRefresh { get; set; }
bool AutoRenameFolders { get; set; }
- bool PathsDefaultStatic { get; set; }
//Permissions (Media Management)
bool SetPermissionsLinux { get; set; }
diff --git a/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs b/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs
new file mode 100644
index 000000000..a3f191b48
--- /dev/null
+++ b/src/NzbDrone.Core/Datastore/Migration/167_remove_movie_pathstate.cs
@@ -0,0 +1,21 @@
+using FluentMigrator;
+using NzbDrone.Core.Datastore.Migration.Framework;
+
+namespace NzbDrone.Core.Datastore.Migration
+{
+ [Migration(167)]
+ public class remove_movie_pathstate : NzbDroneMigrationBase
+ {
+ protected override void MainDbUpgrade()
+ {
+ Delete.Column("PathState").FromTable("Movies");
+
+ Execute.Sql("DELETE FROM Config WHERE [KEY] IN ('pathsdefaultstatic')");
+
+ Alter.Table("MovieFiles").AddColumn("OriginalFilePath").AsString().Nullable();
+
+ //This is Ignored in mapping, should not be in DB
+ Delete.Column("Path").FromTable("MovieFiles");
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs b/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs
index ed398f23f..0650700b1 100644
--- a/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs
+++ b/src/NzbDrone.Core/MediaFiles/RenameMovieFileService.cs
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
-using System.Data.SQLite;
using System.IO;
using System.Linq;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Instrumentation.Extensions;
-using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles.Commands;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Commands;
@@ -20,22 +18,18 @@ namespace NzbDrone.Core.MediaFiles
public interface IRenameMovieFileService
{
List GetRenamePreviews(int movieId);
- void RenameMoviePath(Movie movie, bool shouldRenameFiles);
}
public class RenameMovieFileService : IRenameMovieFileService,
IExecute,
- IExecute,
- IExecute
+ IExecute
{
private readonly IMovieService _movieService;
private readonly IMediaFileService _mediaFileService;
private readonly IMoveMovieFiles _movieFileMover;
private readonly IEventAggregator _eventAggregator;
private readonly IBuildFileNames _filenameBuilder;
- private readonly IConfigService _configService;
private readonly IDiskProvider _diskProvider;
- private readonly IRecycleBinProvider _recycleBinProvider;
private readonly Logger _logger;
public RenameMovieFileService(IMovieService movieService,
@@ -43,8 +37,6 @@ namespace NzbDrone.Core.MediaFiles
IMoveMovieFiles movieFileMover,
IEventAggregator eventAggregator,
IBuildFileNames filenameBuilder,
- IConfigService configService,
- IRecycleBinProvider recycleBinProvider,
IDiskProvider diskProvider,
Logger logger)
{
@@ -53,8 +45,6 @@ namespace NzbDrone.Core.MediaFiles
_movieFileMover = movieFileMover;
_eventAggregator = eventAggregator;
_filenameBuilder = filenameBuilder;
- _configService = configService;
- _recycleBinProvider = recycleBinProvider;
_diskProvider = diskProvider;
_logger = logger;
}
@@ -82,28 +72,21 @@ namespace NzbDrone.Core.MediaFiles
{
MovieId = movie.Id,
MovieFileId = file.Id,
- ExistingPath = movieFilePath,
+ ExistingPath = file.RelativePath,
- //NewPath = movie.Path.GetRelativePath(newPath)
- NewPath = newPath
+ NewPath = movie.Path.GetRelativePath(newPath)
};
}
}
}
- private void RenameFiles(List movieFiles, Movie movie, string oldMoviePath = null)
+ private void RenameFiles(List movieFiles, Movie movie)
{
var renamed = new List();
- if (oldMoviePath == null)
- {
- oldMoviePath = movie.Path;
- }
-
foreach (var movieFile in movieFiles)
{
- var oldMovieFilePath = Path.Combine(oldMoviePath, movieFile.RelativePath);
- movieFile.Path = oldMovieFilePath;
+ var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
try
{
@@ -116,7 +99,7 @@ namespace NzbDrone.Core.MediaFiles
_logger.Debug("Renamed movie file: {0}", movieFile);
- _eventAggregator.PublishEvent(new MovieFileRenamedEvent(movie, movieFile, oldMovieFilePath));
+ _eventAggregator.PublishEvent(new MovieFileRenamedEvent(movie, movieFile, movieFilePath));
}
catch (SameFilenameException ex)
{
@@ -124,52 +107,15 @@ namespace NzbDrone.Core.MediaFiles
}
catch (Exception ex)
{
- _logger.Error(ex, "Failed to rename file: {0}", oldMovieFilePath);
+ _logger.Error(ex, "Failed to rename file: {0}", movieFilePath);
}
}
if (renamed.Any())
{
- _eventAggregator.PublishEvent(new MovieRenamedEvent(movie));
- }
- }
-
- 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;
-
- _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);
- // }
- _movieService.UpdateMovie(movie);
-
- if (_diskProvider.GetFiles(oldFolder, SearchOption.AllDirectories).Count() == 0)
- {
- _recycleBinProvider.DeleteFolder(oldFolder);
- }
- }
+ _diskProvider.RemoveEmptySubfolders(movie.Path);
- if (movie.PathState == MoviePathState.StaticOnce)
- {
- movie.PathState = MoviePathState.Dynamic;
- _movieService.UpdateMovie(movie);
+ _eventAggregator.PublishEvent(new MovieRenamedEvent(movie));
}
}
@@ -196,25 +142,5 @@ namespace NzbDrone.Core.MediaFiles
_logger.ProgressInfo("All movie files renamed for {0}", movie.Title);
}
}
-
- public void Execute(RenameMovieFolderCommand message)
- {
- try
- {
- _logger.Debug("Renaming movie folder for selected movie if necessary");
- var moviesToRename = _movieService.GetMovies(message.MovieIds);
- foreach (var movie in moviesToRename)
- {
- var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
-
- //_logger.ProgressInfo("Renaming movie folder for {0}", movie.Title);
- RenameMoviePath(movie);
- }
- }
- catch (SQLiteException ex)
- {
- _logger.Warn(ex, "wtf: {0}, {1}", ex.ResultCode, ex.Data);
- }
- }
}
}
diff --git a/src/NzbDrone.Core/Movies/Commands/MoveMovieCommand.cs b/src/NzbDrone.Core/Movies/Commands/MoveMovieCommand.cs
index a742ff66a..d99ed2932 100644
--- a/src/NzbDrone.Core/Movies/Commands/MoveMovieCommand.cs
+++ b/src/NzbDrone.Core/Movies/Commands/MoveMovieCommand.cs
@@ -9,6 +9,7 @@ namespace NzbDrone.Core.Movies.Commands
public string DestinationPath { get; set; }
public string DestinationRootFolder { get; set; }
+ public override bool SendUpdatesToClient => true;
public override bool RequiresDiskAccess => true;
}
}
diff --git a/src/NzbDrone.Core/Movies/Movie.cs b/src/NzbDrone.Core/Movies/Movie.cs
index 4428db360..01d05706a 100644
--- a/src/NzbDrone.Core/Movies/Movie.cs
+++ b/src/NzbDrone.Core/Movies/Movie.cs
@@ -42,7 +42,6 @@ namespace NzbDrone.Core.Movies
public string Certification { get; set; }
public string RootFolderPath { get; set; }
- public MoviePathState PathState { get; set; }
public DateTime Added { get; set; }
public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; }
@@ -154,7 +153,6 @@ namespace NzbDrone.Core.Movies
Path = otherMovie.Path;
ProfileId = otherMovie.ProfileId;
- PathState = otherMovie.PathState;
Monitored = otherMovie.Monitored;
MinimumAvailability = otherMovie.MinimumAvailability;
@@ -164,11 +162,4 @@ namespace NzbDrone.Core.Movies
AddOptions = otherMovie.AddOptions;
}
}
-
- public enum MoviePathState
- {
- Dynamic,
- StaticOnce,
- Static,
- }
}
diff --git a/src/NzbDrone.Core/Movies/MoviePathBuilder.cs b/src/NzbDrone.Core/Movies/MoviePathBuilder.cs
new file mode 100644
index 000000000..8d9c520ee
--- /dev/null
+++ b/src/NzbDrone.Core/Movies/MoviePathBuilder.cs
@@ -0,0 +1,48 @@
+using System;
+using System.IO;
+using NzbDrone.Common.Extensions;
+using NzbDrone.Core.Organizer;
+using NzbDrone.Core.RootFolders;
+
+namespace NzbDrone.Core.Movies
+{
+ public interface IBuildMoviePaths
+ {
+ string BuildPath(Movie movie, bool useExistingRelativeFolder);
+ }
+
+ public class MoviePathBuilder : IBuildMoviePaths
+ {
+ private readonly IBuildFileNames _fileNameBuilder;
+ private readonly IRootFolderService _rootFolderService;
+
+ public MoviePathBuilder(IBuildFileNames fileNameBuilder, IRootFolderService rootFolderService)
+ {
+ _fileNameBuilder = fileNameBuilder;
+ _rootFolderService = rootFolderService;
+ }
+
+ public string BuildPath(Movie movie, bool useExistingRelativeFolder)
+ {
+ if (movie.RootFolderPath.IsNullOrWhiteSpace())
+ {
+ throw new ArgumentException("Root folder was not provided", nameof(movie));
+ }
+
+ if (useExistingRelativeFolder && movie.Path.IsNotNullOrWhiteSpace())
+ {
+ var relativePath = GetExistingRelativePath(movie);
+ return Path.Combine(movie.RootFolderPath, relativePath);
+ }
+
+ return Path.Combine(movie.RootFolderPath, _fileNameBuilder.GetMovieFolder(movie));
+ }
+
+ private string GetExistingRelativePath(Movie movie)
+ {
+ var rootFolderPath = _rootFolderService.GetBestRootFolderPath(movie.Path);
+
+ return rootFolderPath.GetRelativePath(movie.Path);
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/Movies/MovieService.cs b/src/NzbDrone.Core/Movies/MovieService.cs
index 3ad94ba11..0ab43ba3f 100644
--- a/src/NzbDrone.Core/Movies/MovieService.cs
+++ b/src/NzbDrone.Core/Movies/MovieService.cs
@@ -43,7 +43,7 @@ namespace NzbDrone.Core.Movies
List GetAllMovies();
List AllForTag(int tagId);
Movie UpdateMovie(Movie movie);
- List UpdateMovie(List movie);
+ List UpdateMovie(List movie, bool useExistingRelativeFolder);
List FilterExistingMovies(List movies);
bool MoviePathExists(string folder);
void RemoveAddOptions(Movie movie);
@@ -57,6 +57,7 @@ namespace NzbDrone.Core.Movies
private readonly IEventAggregator _eventAggregator;
private readonly IBuildFileNames _fileNameBuilder;
private readonly IImportExclusionsService _exclusionService;
+ private readonly IBuildMoviePaths _moviePathBuilder;
private readonly Logger _logger;
public MovieService(IMovieRepository movieRepository,
@@ -64,6 +65,7 @@ namespace NzbDrone.Core.Movies
IBuildFileNames fileNameBuilder,
IConfigService configService,
IImportExclusionsService exclusionService,
+ IBuildMoviePaths moviePathBuilder,
Logger logger)
{
_movieRepository = movieRepository;
@@ -71,6 +73,7 @@ namespace NzbDrone.Core.Movies
_fileNameBuilder = fileNameBuilder;
_configService = configService;
_exclusionService = exclusionService;
+ _moviePathBuilder = moviePathBuilder;
_logger = logger;
}
@@ -93,21 +96,10 @@ namespace NzbDrone.Core.Movies
{
Ensure.That(newMovie, () => newMovie).IsNotNull();
- MoviePathState defaultState = MoviePathState.Static;
- if (!_configService.PathsDefaultStatic)
- {
- defaultState = MoviePathState.Dynamic;
- }
-
if (string.IsNullOrWhiteSpace(newMovie.Path))
{
var folderName = _fileNameBuilder.GetMovieFolder(newMovie);
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
- newMovie.PathState = defaultState;
- }
- else
- {
- newMovie.PathState = defaultState == MoviePathState.Dynamic ? MoviePathState.StaticOnce : MoviePathState.Static;
}
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
@@ -128,21 +120,10 @@ namespace NzbDrone.Core.Movies
newMovies.ForEach(m =>
{
- MoviePathState defaultState = MoviePathState.Static;
- if (!_configService.PathsDefaultStatic)
- {
- defaultState = MoviePathState.Dynamic;
- }
-
if (string.IsNullOrWhiteSpace(m.Path))
{
var folderName = _fileNameBuilder.GetMovieFolder(m);
m.Path = Path.Combine(m.RootFolderPath, folderName);
- m.PathState = defaultState;
- }
- else
- {
- m.PathState = defaultState == MoviePathState.Dynamic ? MoviePathState.StaticOnce : MoviePathState.Static;
}
m.CleanTitle = m.Title.CleanSeriesTitle();
@@ -324,21 +305,22 @@ namespace NzbDrone.Core.Movies
return updatedMovie;
}
- public List UpdateMovie(List movie)
+ public List UpdateMovie(List movie, bool useExistingRelativeFolder)
{
_logger.Debug("Updating {0} movie", movie.Count);
- foreach (var s in movie)
+ foreach (var m in movie)
{
- _logger.Trace("Updating: {0}", s.Title);
- if (!s.RootFolderPath.IsNullOrWhiteSpace())
+ _logger.Trace("Updating: {0}", m.Title);
+
+ if (!m.RootFolderPath.IsNullOrWhiteSpace())
{
- var folderName = new DirectoryInfo(s.Path).Name;
- s.Path = Path.Combine(s.RootFolderPath, folderName);
- _logger.Trace("Changing path for {0} to {1}", s.Title, s.Path);
+ m.Path = _moviePathBuilder.BuildPath(m, useExistingRelativeFolder);
+
+ _logger.Trace("Changing path for {0} to {1}", m.Title, m.Path);
}
else
{
- _logger.Trace("Not changing path for: {0}", s.Title);
+ _logger.Trace("Not changing path for: {0}", m.Title);
}
}
diff --git a/src/NzbDrone.Core/Movies/RefreshMovieService.cs b/src/NzbDrone.Core/Movies/RefreshMovieService.cs
index 5b2e37e92..4a8327ac3 100644
--- a/src/NzbDrone.Core/Movies/RefreshMovieService.cs
+++ b/src/NzbDrone.Core/Movies/RefreshMovieService.cs
@@ -138,7 +138,7 @@ namespace NzbDrone.Core.Movies
_logger.Info(ex, "Unable to communicate with Mappings Server.");
}
- _movieService.UpdateMovie(new List { movie });
+ _movieService.UpdateMovie(new List { movie }, true);
_creditService.UpdateCredits(tuple.Item2, movie);
try
diff --git a/src/NzbDrone.Core/NetImport/NetImportSearchService.cs b/src/NzbDrone.Core/NetImport/NetImportSearchService.cs
index 4c22caa99..a4fcdf607 100644
--- a/src/NzbDrone.Core/NetImport/NetImportSearchService.cs
+++ b/src/NzbDrone.Core/NetImport/NetImportSearchService.cs
@@ -194,7 +194,7 @@ namespace NzbDrone.Core.NetImport
}
}
- _movieService.UpdateMovie(moviesToUpdate);
+ _movieService.UpdateMovie(moviesToUpdate, true);
}
}
}
diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
index 0c4b57f38..83c7fd50b 100644
--- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
+++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
@@ -18,7 +18,6 @@ namespace NzbDrone.Core.Organizer
{
string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null);
string BuildFilePath(Movie movie, string fileName, string extension);
- string BuildMoviePath(Movie movie, NamingConfig namingConfig = null);
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
}
@@ -110,57 +109,9 @@ namespace NzbDrone.Core.Organizer
{
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
- var path = "";
-
- if (movie.PathState > 0)
- {
- path = movie.Path;
- }
- else
- {
- path = BuildMoviePath(movie);
- }
-
- return Path.Combine(path, fileName + extension);
- }
-
- public string BuildMoviePath(Movie movie, NamingConfig namingConfig = null)
- {
- if (namingConfig == null)
- {
- namingConfig = _namingConfigService.GetConfig();
- }
-
var path = movie.Path;
- var directory = new DirectoryInfo(path).Name;
- var parentDirectoryPath = new DirectoryInfo(path).Parent.FullName;
-
- var movieFile = movie.MovieFile;
- var pattern = namingConfig.MovieFolderFormat;
- var tokenHandlers = new Dictionary>(FileNameBuilderTokenEqualityComparer.Instance);
-
- AddMovieTokens(tokenHandlers, movie);
- AddReleaseDateTokens(tokenHandlers, movie.Year);
- AddIdTokens(tokenHandlers, movie);
-
- if (movie.MovieFile != null)
- {
- AddQualityTokens(tokenHandlers, movie, movieFile);
- AddMediaInfoTokens(tokenHandlers, movieFile);
- AddMovieFileTokens(tokenHandlers, movieFile);
- AddTagsTokens(tokenHandlers, movieFile);
- }
- else
- {
- AddMovieFileTokens(tokenHandlers, new MovieFile { SceneName = $"{movie.Title} {movie.Year}", RelativePath = $"{movie.Title} {movie.Year}" });
- }
-
- var directoryName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
- directoryName = FileNameCleanupRegex.Replace(directoryName, match => match.Captures[0].Value[0].ToString());
- directoryName = TrimSeparatorsRegex.Replace(directoryName, string.Empty);
-
- return Path.Combine(parentDirectoryPath, directoryName);
+ return Path.Combine(path, fileName + extension);
}
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec)
diff --git a/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs b/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs
index 5880b889b..b25746e0b 100644
--- a/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs
+++ b/src/Radarr.Api.V3/Config/MediaManagementConfigResource.cs
@@ -46,7 +46,6 @@ namespace Radarr.Api.V3.Config
FileDate = model.FileDate,
RescanAfterRefresh = model.RescanAfterRefresh,
AutoRenameFolders = model.AutoRenameFolders,
- PathsDefaultStatic = model.PathsDefaultStatic,
SetPermissionsLinux = model.SetPermissionsLinux,
FileChmod = model.FileChmod,
diff --git a/src/Radarr.Api.V3/Movies/MovieEditorModule.cs b/src/Radarr.Api.V3/Movies/MovieEditorModule.cs
index 66f22257a..499d4a8e6 100644
--- a/src/Radarr.Api.V3/Movies/MovieEditorModule.cs
+++ b/src/Radarr.Api.V3/Movies/MovieEditorModule.cs
@@ -85,7 +85,7 @@ namespace Radarr.Api.V3.Movies
});
}
- return ResponseWithCode(_movieService.UpdateMovie(moviesToUpdate)
+ return ResponseWithCode(_movieService.UpdateMovie(moviesToUpdate, !resource.MoveFiles)
.ToResource(),
HttpStatusCode.Accepted);
}
diff --git a/src/Radarr.Api.V3/Movies/MovieModule.cs b/src/Radarr.Api.V3/Movies/MovieModule.cs
index a0312d738..1ae827006 100644
--- a/src/Radarr.Api.V3/Movies/MovieModule.cs
+++ b/src/Radarr.Api.V3/Movies/MovieModule.cs
@@ -7,8 +7,10 @@ using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events;
+using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies;
+using NzbDrone.Core.Movies.Commands;
using NzbDrone.Core.Movies.Events;
using NzbDrone.Core.Validation;
using NzbDrone.Core.Validation.Paths;
@@ -29,11 +31,13 @@ namespace Radarr.Api.V3.Movies
{
protected readonly IMovieService _moviesService;
private readonly IMapCoversToLocal _coverMapper;
+ private readonly IManageCommandQueue _commandQueueManager;
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
IMovieService moviesService,
IMapCoversToLocal coverMapper,
+ IManageCommandQueue commandQueueManager,
IUpgradableSpecification qualityUpgradableSpecification,
RootFolderValidator rootFolderValidator,
MoviePathValidator moviesPathValidator,
@@ -46,6 +50,7 @@ namespace Radarr.Api.V3.Movies
_moviesService = moviesService;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_coverMapper = coverMapper;
+ _commandQueueManager = commandQueueManager;
GetResourceAll = AllMovie;
GetResourceById = GetMovie;
@@ -114,7 +119,24 @@ namespace Radarr.Api.V3.Movies
private void UpdateMovie(MovieResource moviesResource)
{
- var model = moviesResource.ToModel(_moviesService.GetMovie(moviesResource.Id));
+ var moveFiles = Request.GetBooleanQueryParameter("moveFiles");
+ var movie = _moviesService.GetMovie(moviesResource.Id);
+
+ if (moveFiles)
+ {
+ var sourcePath = movie.Path;
+ var destinationPath = moviesResource.Path;
+
+ _commandQueueManager.Push(new MoveMovieCommand
+ {
+ MovieId = movie.Id,
+ SourcePath = sourcePath,
+ DestinationPath = destinationPath,
+ Trigger = CommandTrigger.Manual
+ });
+ }
+
+ var model = moviesResource.ToModel(movie);
_moviesService.UpdateMovie(model);
diff --git a/src/Radarr.Api.V3/Movies/MovieResource.cs b/src/Radarr.Api.V3/Movies/MovieResource.cs
index d04ca508d..66c1076cb 100644
--- a/src/Radarr.Api.V3/Movies/MovieResource.cs
+++ b/src/Radarr.Api.V3/Movies/MovieResource.cs
@@ -45,7 +45,6 @@ namespace Radarr.Api.V3.Movies
//View & Edit
public string Path { get; set; }
public int QualityProfileId { get; set; }
- public MoviePathState PathState { get; set; }
//Editing Only
public bool Monitored { get; set; }
@@ -105,7 +104,6 @@ namespace Radarr.Api.V3.Movies
Path = model.Path,
QualityProfileId = model.ProfileId,
- PathState = model.PathState,
Monitored = model.Monitored,
MinimumAvailability = model.MinimumAvailability,
@@ -166,7 +164,6 @@ namespace Radarr.Api.V3.Movies
Path = model.Path,
QualityProfileId = model.ProfileId,
- PathState = model.PathState,
Monitored = model.Monitored,
MinimumAvailability = model.MinimumAvailability,
@@ -221,7 +218,6 @@ namespace Radarr.Api.V3.Movies
Path = resource.Path,
ProfileId = resource.QualityProfileId,
- PathState = resource.PathState,
Monitored = resource.Monitored,
MinimumAvailability = resource.MinimumAvailability,