diff --git a/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesRow.js b/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesRow.js
index 89a2d8260..7777c768f 100644
--- a/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesRow.js
+++ b/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesRow.js
@@ -10,6 +10,7 @@ import styles from './ImportSeriesRow.css';
function ImportSeriesRow(props) {
const {
id,
+ relativePath,
monitor,
qualityProfileId,
seasonFolder,
@@ -32,7 +33,7 @@ function ImportSeriesRow(props) {
/>
- {id}
+ {relativePath}
@@ -84,6 +85,7 @@ function ImportSeriesRow(props) {
ImportSeriesRow.propTypes = {
id: PropTypes.string.isRequired,
+ relativePath: PropTypes.string.isRequired,
monitor: PropTypes.string.isRequired,
qualityProfileId: PropTypes.number.isRequired,
seriesType: PropTypes.string.isRequired,
diff --git a/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTable.js b/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTable.js
index 45e23a1b7..aa78925f2 100644
--- a/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTable.js
+++ b/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTable.js
@@ -32,7 +32,7 @@ class ImportSeriesTable extends Component {
unmappedFolders.forEach((unmappedFolder) => {
const id = unmappedFolder.name;
- onSeriesLookup(id, unmappedFolder.path);
+ onSeriesLookup(id, unmappedFolder.path, unmappedFolder.relativePath);
onSetImportSeriesValue({
id,
diff --git a/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTableConnector.js b/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTableConnector.js
index 09dfae097..8a26fbe79 100644
--- a/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTableConnector.js
+++ b/frontend/src/AddSeries/ImportSeries/Import/ImportSeriesTableConnector.js
@@ -26,10 +26,11 @@ function createMapStateToProps() {
function createMapDispatchToProps(dispatch, props) {
return {
- onSeriesLookup(name, path) {
+ onSeriesLookup(name, path, relativePath) {
dispatch(queueLookupSeries({
name,
path,
+ relativePath,
term: name
}));
},
diff --git a/frontend/src/Store/Actions/importSeriesActions.js b/frontend/src/Store/Actions/importSeriesActions.js
index 46cbb5add..75ec76591 100644
--- a/frontend/src/Store/Actions/importSeriesActions.js
+++ b/frontend/src/Store/Actions/importSeriesActions.js
@@ -67,6 +67,7 @@ export const actionHandlers = handleThunks({
const {
name,
path,
+ relativePath,
term,
topOfQueue = false
} = payload;
@@ -76,6 +77,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 0e3906652..2e283f31c 100644
--- a/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs
+++ b/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs
@@ -7,6 +7,7 @@ using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
+using NzbDrone.Core.Organizer;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
@@ -17,9 +18,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);
@@ -31,6 +36,10 @@ namespace NzbDrone.Core.Test.RootFolderTests
Mocker.GetMock()
.Setup(s => s.All())
.Returns(new List());
+
+ Mocker.GetMock()
+ .Setup(c => c.GetConfig())
+ .Returns(_namingConfig);
}
private void WithNonExistingFolder()
@@ -140,5 +149,47 @@ namespace NzbDrone.Core.Test.RootFolderTests
unmappedFolders.Count.Should().BeGreaterThan(0);
unmappedFolders.Should().NotContain(u => u.Name == subFolder);
}
+
+ [Test]
+ public void should_get_unmapped_folders_inside_letter_subfolder()
+ {
+ _namingConfig.SeriesFolderFormat = "{Series TitleFirstCharacter}\\{Series Title}";
+
+ var rootFolderPath = @"C:\Test\TV".AsOsAgnostic();
+ var rootFolder = Builder.CreateNew()
+ .With(r => r.Path = rootFolderPath)
+ .Build();
+
+ var subFolderPath = Path.Combine(rootFolderPath, "S");
+
+ var subFolders = new[]
+ {
+ "Series1",
+ "Series2",
+ "Series3",
+ };
+
+ 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.AllSeriesPaths())
+ .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 441099da3..23b75631c 100644
--- a/src/NzbDrone.Core/RootFolders/RootFolderService.cs
+++ b/src/NzbDrone.Core/RootFolders/RootFolderService.cs
@@ -7,6 +7,7 @@ using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
+using NzbDrone.Core.Organizer;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.RootFolders
@@ -26,6 +27,7 @@ namespace NzbDrone.Core.RootFolders
private readonly IRootFolderRepository _rootFolderRepository;
private readonly IDiskProvider _diskProvider;
private readonly ISeriesRepository _seriesRepository;
+ private readonly INamingConfigService _namingConfigService;
private readonly Logger _logger;
private static readonly HashSet SpecialFolders = new HashSet
@@ -44,11 +46,13 @@ namespace NzbDrone.Core.RootFolders
public RootFolderService(IRootFolderRepository rootFolderRepository,
IDiskProvider diskProvider,
ISeriesRepository seriesRepository,
+ INamingConfigService namingConfigService,
Logger logger)
{
_rootFolderRepository = rootFolderRepository;
_diskProvider = diskProvider;
_seriesRepository = seriesRepository;
+ _namingConfigService = namingConfigService;
_logger = logger;
}
@@ -139,13 +143,28 @@ namespace NzbDrone.Core.RootFolders
return results;
}
+ var subFolderDepth = _namingConfigService.GetConfig().SeriesFolderFormat.Count(f => f == Path.DirectorySeparatorChar);
var possibleSeriesFolders = _diskProvider.GetDirectories(path).ToList();
+
+ if (subFolderDepth > 0)
+ {
+ for (int i = 0; i < subFolderDepth; i++)
+ {
+ possibleSeriesFolders = possibleSeriesFolders.SelectMany(_diskProvider.GetDirectories).ToList();
+ }
+ }
+
var unmappedFolders = possibleSeriesFolders.Except(seriesPaths.Select(s => s.Value), PathEqualityComparer.Instance).ToList();
- foreach (string unmappedFolder in unmappedFolders)
+ foreach (var unmappedFolder in unmappedFolders)
{
var di = new DirectoryInfo(unmappedFolder.Normalize());
- results.Add(new UnmappedFolder { Name = di.Name, Path = di.FullName });
+ results.Add(new UnmappedFolder
+ {
+ Name = di.Name,
+ Path = di.FullName,
+ RelativePath = path.GetRelativePath(di.FullName)
+ });
}
var setToRemove = SpecialFolders;
@@ -181,8 +200,8 @@ namespace NzbDrone.Core.RootFolders
private void GetDetails(RootFolder rootFolder, Dictionary seriesPaths, bool timeout)
{
- Task.Run(() =>
- {
+ // Task.Run(() =>
+ // {
if (_diskProvider.FolderExists(rootFolder.Path))
{
rootFolder.Accessible = true;
@@ -190,7 +209,8 @@ namespace NzbDrone.Core.RootFolders
rootFolder.TotalSpace = _diskProvider.GetTotalSize(rootFolder.Path);
rootFolder.UnmappedFolders = GetUnmappedFolders(rootFolder.Path, seriesPaths);
}
- }).Wait(timeout ? 5000 : -1);
+
+ // }).Wait(timeout ? 5000 : -1);
}
}
}
diff --git a/src/NzbDrone.Core/RootFolders/UnmappedFolder.cs b/src/NzbDrone.Core/RootFolders/UnmappedFolder.cs
index 3a8a919de..095edc7b2 100644
--- a/src/NzbDrone.Core/RootFolders/UnmappedFolder.cs
+++ b/src/NzbDrone.Core/RootFolders/UnmappedFolder.cs
@@ -1,8 +1,9 @@
-namespace NzbDrone.Core.RootFolders
+namespace NzbDrone.Core.RootFolders
{
public class UnmappedFolder
{
public string Name { get; set; }
public string Path { get; set; }
+ public string RelativePath { get; set; }
}
}