diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js
index 4a78b05c2..7858b6633 100644
--- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js
+++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js
@@ -10,6 +10,7 @@ import styles from './ImportMovieRow.css';
function ImportMovieRow(props) {
const {
id,
+ relativePath,
monitor,
qualityProfileId,
minimumAvailability,
@@ -31,7 +32,7 @@ function ImportMovieRow(props) {
/>
- {id}
+ {relativePath}
@@ -73,6 +74,7 @@ function ImportMovieRow(props) {
ImportMovieRow.propTypes = {
id: PropTypes.string.isRequired,
+ relativePath: PropTypes.string.isRequired,
monitor: PropTypes.string.isRequired,
qualityProfileId: PropTypes.number.isRequired,
minimumAvailability: PropTypes.string.isRequired,
diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js
index c4fd8352d..29fd293e3 100644
--- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js
+++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js
@@ -30,7 +30,7 @@ class ImportMovieTable extends Component {
unmappedFolders.forEach((unmappedFolder) => {
const id = unmappedFolder.name;
- onMovieLookup(id, unmappedFolder.path);
+ onMovieLookup(id, unmappedFolder.path, unmappedFolder.relativePath);
onSetImportMovieValue({
id,
diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js
index 2717336c9..368f0a689 100644
--- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js
+++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js
@@ -25,10 +25,11 @@ function createMapStateToProps() {
function createMapDispatchToProps(dispatch, props) {
return {
- onMovieLookup(name, path) {
+ onMovieLookup(name, path, relativePath) {
dispatch(queueLookupMovie({
name,
path,
+ relativePath,
term: name
}));
},
diff --git a/frontend/src/Store/Actions/importMovieActions.js b/frontend/src/Store/Actions/importMovieActions.js
index a3aa59a86..4e13cd6d0 100644
--- a/frontend/src/Store/Actions/importMovieActions.js
+++ b/frontend/src/Store/Actions/importMovieActions.js
@@ -66,6 +66,7 @@ export const actionHandlers = handleThunks({
const {
name,
path,
+ relativePath,
term,
topOfQueue = false
} = payload;
@@ -75,6 +76,7 @@ export const actionHandlers = handleThunks({
id: name,
term,
path,
+ relativePath,
isFetching: false,
isPopulated: false,
error: null
diff --git a/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs b/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs
index 7ecfa4a60..c7b85c204 100644
--- a/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs
+++ b/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs
@@ -10,6 +10,7 @@
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Movies;
+using NzbDrone.Core.Organizer;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
@@ -19,9 +20,13 @@ namespace NzbDrone.Core.Test.RootFolderTests
[TestFixture]
public class RootFolderServiceFixture : CoreTest
{
+ private NamingConfig _namingConfig;
+
[SetUp]
public void Setup()
{
+ _namingConfig = NamingConfig.Default;
+
Mocker.GetMock()
.Setup(m => m.FolderExists(It.IsAny()))
.Returns(true);
@@ -33,6 +38,10 @@ public void Setup()
Mocker.GetMock()
.Setup(s => s.All())
.Returns(new List());
+
+ Mocker.GetMock()
+ .Setup(c => c.GetConfig())
+ .Returns(_namingConfig);
}
private void WithNonExistingFolder()
@@ -254,5 +263,47 @@ public void should_exclude_recycle_bin()
unmappedFolders.Count.Should().Be(3);
unmappedFolders.Should().NotContain(u => u.Name == "BIN");
}
+
+ [Test]
+ public void should_get_unmapped_folders_inside_letter_subfolder()
+ {
+ _namingConfig.MovieFolderFormat = "{Movie TitleFirstCharacter}\\{Movie Title}".AsOsAgnostic();
+
+ var rootFolderPath = @"C:\Test\Movies".AsOsAgnostic();
+ var rootFolder = Builder.CreateNew()
+ .With(r => r.Path = rootFolderPath)
+ .Build();
+
+ var subFolderPath = Path.Combine(rootFolderPath, "M");
+
+ var subFolders = new[]
+ {
+ "Movie1",
+ "Movie2",
+ "Movie3",
+ };
+
+ var folders = subFolders.Select(f => Path.Combine(subFolderPath, f)).ToArray();
+
+ Mocker.GetMock()
+ .Setup(s => s.Get(It.IsAny()))
+ .Returns(rootFolder);
+
+ Mocker.GetMock()
+ .Setup(s => s.AllMoviePaths())
+ .Returns(new Dictionary());
+
+ Mocker.GetMock()
+ .Setup(s => s.GetDirectories(rootFolder.Path))
+ .Returns(new[] { subFolderPath });
+
+ Mocker.GetMock()
+ .Setup(s => s.GetDirectories(subFolderPath))
+ .Returns(folders);
+
+ var unmappedFolders = Subject.Get(rootFolder.Id, false).UnmappedFolders;
+
+ unmappedFolders.Count.Should().Be(3);
+ }
}
}
diff --git a/src/NzbDrone.Core/RootFolders/RootFolder.cs b/src/NzbDrone.Core/RootFolders/RootFolder.cs
index 7e6c5444b..26fc1b3d0 100644
--- a/src/NzbDrone.Core/RootFolders/RootFolder.cs
+++ b/src/NzbDrone.Core/RootFolders/RootFolder.cs
@@ -6,7 +6,6 @@ namespace NzbDrone.Core.RootFolders
public class RootFolder : ModelBase
{
public string Path { get; set; }
-
public bool Accessible { get; set; }
public long? FreeSpace { get; set; }
public long? TotalSpace { get; set; }
diff --git a/src/NzbDrone.Core/RootFolders/RootFolderService.cs b/src/NzbDrone.Core/RootFolders/RootFolderService.cs
index 5d0a0d45f..52da032b7 100644
--- a/src/NzbDrone.Core/RootFolders/RootFolderService.cs
+++ b/src/NzbDrone.Core/RootFolders/RootFolderService.cs
@@ -9,6 +9,7 @@
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Movies;
+using NzbDrone.Core.Organizer;
namespace NzbDrone.Core.RootFolders
{
@@ -28,6 +29,7 @@ public class RootFolderService : IRootFolderService
private readonly IDiskProvider _diskProvider;
private readonly IMovieRepository _movieRepository;
private readonly IConfigService _configService;
+ private readonly INamingConfigService _namingConfigService;
private readonly Logger _logger;
private static readonly HashSet SpecialFolders = new HashSet
@@ -47,12 +49,14 @@ public RootFolderService(IRootFolderRepository rootFolderRepository,
IDiskProvider diskProvider,
IMovieRepository movieRepository,
IConfigService configService,
+ INamingConfigService namingConfigService,
Logger logger)
{
_rootFolderRepository = rootFolderRepository;
_diskProvider = diskProvider;
_movieRepository = movieRepository;
_configService = configService;
+ _namingConfigService = namingConfigService;
_logger = logger;
}
@@ -145,7 +149,17 @@ private List GetUnmappedFolders(string path, Dictionary f == Path.DirectorySeparatorChar);
var possibleMovieFolders = _diskProvider.GetDirectories(path).ToList();
+
+ if (subFolderDepth > 0)
+ {
+ for (var i = 0; i < subFolderDepth; i++)
+ {
+ possibleMovieFolders = possibleMovieFolders.SelectMany(_diskProvider.GetDirectories).ToList();
+ }
+ }
+
var unmappedFolders = possibleMovieFolders.Except(moviePaths.Select(s => s.Value), PathEqualityComparer.Instance).ToList();
var recycleBinPath = _configService.RecycleBin;
@@ -158,7 +172,12 @@ private List GetUnmappedFolders(string path, Dictionary