mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-19 13:10:13 -07:00
Fixed: Include extension when calculating maximum episode title length when renaming files
Fixed: Option to override max filename length with MAX_NAME environment variable (cherry picked from commit 6efee036a826027391433b7d0c954ebc1a75c679)
This commit is contained in:
parent
f4292be588
commit
c86d5980d3
8 changed files with 61 additions and 33 deletions
|
@ -7,6 +7,7 @@ using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.CustomFormats;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
@ -43,12 +44,8 @@ namespace NzbDrone.Core.Test.MediaFiles.TrackFileMovingServiceTests
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
Mocker.GetMock<IBuildFileNames>()
|
Mocker.GetMock<IBuildFileNames>()
|
||||||
.Setup(s => s.BuildTrackFileName(It.IsAny<List<Track>>(), It.IsAny<Artist>(), It.IsAny<Album>(), It.IsAny<TrackFile>(), null, null))
|
.Setup(s => s.BuildTrackFilePath(It.IsAny<List<Track>>(), It.IsAny<Artist>(), It.IsAny<Album>(), It.IsAny<TrackFile>(), It.IsAny<string>(), It.IsAny<NamingConfig>(), It.IsAny<List<CustomFormat>>()))
|
||||||
.Returns("Album\\File Name");
|
.Returns(@"C:\Test\Music\Artist\Album\File Name.mp3".AsOsAgnostic());
|
||||||
|
|
||||||
Mocker.GetMock<IBuildFileNames>()
|
|
||||||
.Setup(s => s.BuildTrackFilePath(It.IsAny<Artist>(), It.IsAny<string>(), It.IsAny<string>()))
|
|
||||||
.Returns(@"C:\Test\Music\Artist\Album\File Name.mp3".AsOsAgnostic());
|
|
||||||
|
|
||||||
var rootFolder = @"C:\Test\Music\".AsOsAgnostic();
|
var rootFolder = @"C:\Test\Music\".AsOsAgnostic();
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Music;
|
using NzbDrone.Core.Music;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
@ -9,7 +11,6 @@ using NzbDrone.Test.Common;
|
||||||
namespace NzbDrone.Core.Test.OrganizerTests
|
namespace NzbDrone.Core.Test.OrganizerTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
|
||||||
public class BuildFilePathFixture : CoreTest<FileNameBuilder>
|
public class BuildFilePathFixture : CoreTest<FileNameBuilder>
|
||||||
{
|
{
|
||||||
private NamingConfig _namingConfig;
|
private NamingConfig _namingConfig;
|
||||||
|
@ -29,12 +30,24 @@ namespace NzbDrone.Core.Test.OrganizerTests
|
||||||
var filename = @"02 - Track Title";
|
var filename = @"02 - Track Title";
|
||||||
var expectedPath = @"C:\Test\Fake- The Artist\02 - Track Title.flac";
|
var expectedPath = @"C:\Test\Fake- The Artist\02 - Track Title.flac";
|
||||||
|
|
||||||
|
var fakeTracks = Builder<Track>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(s => s.Title = "Episode Title")
|
||||||
|
.With(s => s.AbsoluteTrackNumber = 5)
|
||||||
|
.Build().ToList();
|
||||||
var fakeArtist = Builder<Artist>.CreateNew()
|
var fakeArtist = Builder<Artist>.CreateNew()
|
||||||
.With(s => s.Name = "Fake: The Artist")
|
.With(s => s.Name = "Fake: The Artist")
|
||||||
.With(s => s.Path = @"C:\Test\Fake- The Artist".AsOsAgnostic())
|
.With(s => s.Path = @"C:\Test\Fake- The Artist".AsOsAgnostic())
|
||||||
.Build();
|
.Build();
|
||||||
|
var fakeAlbum = Builder<Album>.CreateNew()
|
||||||
|
.With(e => e.ArtistId = fakeArtist.Id)
|
||||||
|
.Build();
|
||||||
|
var fakeTrackFile = Builder<TrackFile>.CreateNew()
|
||||||
|
.With(s => s.SceneName = filename)
|
||||||
|
.With(f => f.Artist = fakeArtist)
|
||||||
|
.Build();
|
||||||
|
|
||||||
Subject.BuildTrackFilePath(fakeArtist, filename, ".flac").Should().Be(expectedPath.AsOsAgnostic());
|
Subject.BuildTrackFilePath(fakeTracks, fakeArtist, fakeAlbum, fakeTrackFile, ".flac").Should().Be(expectedPath.AsOsAgnostic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ using NzbDrone.Core.Test.Framework;
|
||||||
namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
|
||||||
public class FileNameBuilderFixture : CoreTest<FileNameBuilder>
|
public class FileNameBuilderFixture : CoreTest<FileNameBuilder>
|
||||||
{
|
{
|
||||||
private Artist _artist;
|
private Artist _artist;
|
||||||
|
@ -511,6 +510,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
{
|
{
|
||||||
_namingConfig.RenameTracks = false;
|
_namingConfig.RenameTracks = false;
|
||||||
_trackFile.Path = "Linkin Park - 06 - Test";
|
_trackFile.Path = "Linkin Park - 06 - Test";
|
||||||
|
_trackFile.SceneName = null;
|
||||||
|
|
||||||
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
||||||
.Should().Be(Path.GetFileNameWithoutExtension(_trackFile.Path));
|
.Should().Be(Path.GetFileNameWithoutExtension(_trackFile.Path));
|
||||||
|
@ -520,11 +520,11 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
public void use_file_name_when_sceneName_is_not_null()
|
public void use_file_name_when_sceneName_is_not_null()
|
||||||
{
|
{
|
||||||
_namingConfig.RenameTracks = false;
|
_namingConfig.RenameTracks = false;
|
||||||
|
_trackFile.SceneName = "Linkin.Park.06.FLAC-LOL";
|
||||||
_trackFile.Path = "Linkin Park - 06 - Test";
|
_trackFile.Path = "Linkin Park - 06 - Test";
|
||||||
_trackFile.SceneName = "SceneName";
|
|
||||||
|
|
||||||
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
||||||
.Should().Be(Path.GetFileNameWithoutExtension(_trackFile.Path));
|
.Should().Be("Linkin.Park.06.FLAC-LOL");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -532,6 +532,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
{
|
{
|
||||||
_namingConfig.RenameTracks = false;
|
_namingConfig.RenameTracks = false;
|
||||||
_trackFile.Path = @"C:\Test\Unsorted\Artist - 01 - Test";
|
_trackFile.Path = @"C:\Test\Unsorted\Artist - 01 - Test";
|
||||||
|
_trackFile.SceneName = null;
|
||||||
|
|
||||||
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
Subject.BuildTrackFileName(new List<Track> { _track1 }, _artist, _album, _trackFile)
|
||||||
.Should().Be(Path.GetFileNameWithoutExtension(_trackFile.Path));
|
.Should().Be(Path.GetFileNameWithoutExtension(_trackFile.Path));
|
||||||
|
|
|
@ -109,6 +109,22 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
||||||
_trackFile.Quality.Revision.Version = 2;
|
_trackFile.Quality.Revision.Version = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_truncate_with_extension()
|
||||||
|
{
|
||||||
|
_artist.Name = "The Fantastic Life of Mr. Sisko";
|
||||||
|
|
||||||
|
_tracks[0].AbsoluteTrackNumber = 18;
|
||||||
|
_tracks[0].Title = "This title has to be 197 characters in length, combined with the series title, quality and episode number it becomes 254ish and the extension puts it above the 255 limit and triggers the truncation";
|
||||||
|
_trackFile.Quality.Quality = Quality.FLAC;
|
||||||
|
_tracks = _tracks.Take(1).ToList();
|
||||||
|
_namingConfig.StandardTrackFormat = "{Artist Name} - {Album Title} - {track:00} - {Track Title} [{Quality Title}]";
|
||||||
|
|
||||||
|
var result = Subject.BuildTrackFileName(_tracks, _artist, _album, _trackFile, ".flac");
|
||||||
|
result.Length.Should().BeLessOrEqualTo(255);
|
||||||
|
result.Should().Be("The Fantastic Life of Mr. Sisko - Hail to the King - 18 - This title has to be 197 characters in length, combined with the series title, quality and episode number it becomes 254ish and the extension puts it above the 255 limit and triggers... [FLAC].flac");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_truncate_with_ellipsis_between_first_and_last_episode_titles()
|
public void should_truncate_with_ellipsis_between_first_and_last_episode_titles()
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,9 +91,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
var album = _albumService.GetAlbum(tracksInFile.First().AlbumId);
|
var album = _albumService.GetAlbum(tracksInFile.First().AlbumId);
|
||||||
|
var newPath = _filenameBuilder.BuildTrackFilePath(tracksInFile, artist, album, file, Path.GetExtension(trackFilePath));
|
||||||
var newName = _filenameBuilder.BuildTrackFileName(tracksInFile, artist, album, file);
|
|
||||||
var newPath = _filenameBuilder.BuildTrackFilePath(artist, newName, Path.GetExtension(trackFilePath));
|
|
||||||
|
|
||||||
if (!trackFilePath.PathEquals(newPath, StringComparison.Ordinal))
|
if (!trackFilePath.PathEquals(newPath, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,8 +64,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
{
|
{
|
||||||
var tracks = _trackService.GetTracksByFileId(trackFile.Id);
|
var tracks = _trackService.GetTracksByFileId(trackFile.Id);
|
||||||
var album = _albumService.GetAlbum(trackFile.AlbumId);
|
var album = _albumService.GetAlbum(trackFile.AlbumId);
|
||||||
var newFileName = _buildFileNames.BuildTrackFileName(tracks, artist, album, trackFile);
|
var filePath = _buildFileNames.BuildTrackFilePath(tracks, artist, album, trackFile, Path.GetExtension(trackFile.Path));
|
||||||
var filePath = _buildFileNames.BuildTrackFilePath(artist, newFileName, Path.GetExtension(trackFile.Path));
|
|
||||||
|
|
||||||
EnsureTrackFolder(trackFile, artist, album, filePath);
|
EnsureTrackFolder(trackFile, artist, album, filePath);
|
||||||
|
|
||||||
|
@ -76,8 +75,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
||||||
public TrackFile MoveTrackFile(TrackFile trackFile, LocalTrack localTrack)
|
public TrackFile MoveTrackFile(TrackFile trackFile, LocalTrack localTrack)
|
||||||
{
|
{
|
||||||
var newFileName = _buildFileNames.BuildTrackFileName(localTrack.Tracks, localTrack.Artist, localTrack.Album, trackFile);
|
var filePath = _buildFileNames.BuildTrackFilePath(localTrack.Tracks, localTrack.Artist, localTrack.Album, trackFile, Path.GetExtension(trackFile.Path));
|
||||||
var filePath = _buildFileNames.BuildTrackFilePath(localTrack.Artist, newFileName, Path.GetExtension(localTrack.Path));
|
|
||||||
|
|
||||||
EnsureTrackFolder(trackFile, localTrack, filePath);
|
EnsureTrackFolder(trackFile, localTrack, filePath);
|
||||||
|
|
||||||
|
@ -88,8 +86,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
||||||
public TrackFile CopyTrackFile(TrackFile trackFile, LocalTrack localTrack)
|
public TrackFile CopyTrackFile(TrackFile trackFile, LocalTrack localTrack)
|
||||||
{
|
{
|
||||||
var newFileName = _buildFileNames.BuildTrackFileName(localTrack.Tracks, localTrack.Artist, localTrack.Album, trackFile);
|
var filePath = _buildFileNames.BuildTrackFilePath(localTrack.Tracks, localTrack.Artist, localTrack.Album, trackFile, Path.GetExtension(trackFile.Path));
|
||||||
var filePath = _buildFileNames.BuildTrackFilePath(localTrack.Artist, newFileName, Path.GetExtension(localTrack.Path));
|
|
||||||
|
|
||||||
EnsureTrackFolder(trackFile, localTrack, filePath);
|
EnsureTrackFolder(trackFile, localTrack, filePath);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ namespace NzbDrone.Core.Organizer
|
||||||
{
|
{
|
||||||
public interface IBuildFileNames
|
public interface IBuildFileNames
|
||||||
{
|
{
|
||||||
string BuildTrackFileName(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null);
|
string BuildTrackFileName(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, string extension = "", NamingConfig namingConfig = null, List<CustomFormat> customFormats = null);
|
||||||
string BuildTrackFilePath(Artist artist, string fileName, string extension);
|
string BuildTrackFilePath(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, string extension, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null);
|
||||||
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
||||||
string GetArtistFolder(Artist artist, NamingConfig namingConfig = null);
|
string GetArtistFolder(Artist artist, NamingConfig namingConfig = null);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildTrackFileName(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, int maxPath, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null)
|
private string BuildTrackFileName(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, string extension, int maxPath, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null)
|
||||||
{
|
{
|
||||||
if (namingConfig == null)
|
if (namingConfig == null)
|
||||||
{
|
{
|
||||||
|
@ -92,7 +92,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
|
|
||||||
if (!namingConfig.RenameTracks)
|
if (!namingConfig.RenameTracks)
|
||||||
{
|
{
|
||||||
return GetOriginalFileName(trackFile);
|
return GetOriginalTitle(trackFile) + extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namingConfig.StandardTrackFormat.IsNullOrWhiteSpace() || namingConfig.MultiDiscTrackFormat.IsNullOrWhiteSpace())
|
if (namingConfig.StandardTrackFormat.IsNullOrWhiteSpace() || namingConfig.MultiDiscTrackFormat.IsNullOrWhiteSpace())
|
||||||
|
@ -112,9 +112,9 @@ namespace NzbDrone.Core.Organizer
|
||||||
var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
|
var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
var components = new List<string>();
|
var components = new List<string>();
|
||||||
|
|
||||||
foreach (var s in splitPatterns)
|
for (var i = 0; i < splitPatterns.Length; i++)
|
||||||
{
|
{
|
||||||
var splitPattern = s;
|
var splitPattern = splitPatterns[i];
|
||||||
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
||||||
splitPattern = FormatTrackNumberTokens(splitPattern, "", tracks);
|
splitPattern = FormatTrackNumberTokens(splitPattern, "", tracks);
|
||||||
splitPattern = FormatMediumNumberTokens(splitPattern, "", tracks);
|
splitPattern = FormatMediumNumberTokens(splitPattern, "", tracks);
|
||||||
|
@ -131,6 +131,10 @@ namespace NzbDrone.Core.Organizer
|
||||||
|
|
||||||
var component = ReplaceTokens(splitPattern, tokenHandlers, namingConfig, true).Trim();
|
var component = ReplaceTokens(splitPattern, tokenHandlers, namingConfig, true).Trim();
|
||||||
var maxPathSegmentLength = Math.Min(LongPathSupport.MaxFileNameLength, maxPath);
|
var maxPathSegmentLength = Math.Min(LongPathSupport.MaxFileNameLength, maxPath);
|
||||||
|
if (i == splitPatterns.Length - 1)
|
||||||
|
{
|
||||||
|
maxPathSegmentLength -= extension.GetByteCount();
|
||||||
|
}
|
||||||
|
|
||||||
var maxTrackTitleLength = maxPathSegmentLength - GetLengthWithoutTrackTitle(component, namingConfig);
|
var maxTrackTitleLength = maxPathSegmentLength - GetLengthWithoutTrackTitle(component, namingConfig);
|
||||||
|
|
||||||
|
@ -147,21 +151,23 @@ namespace NzbDrone.Core.Organizer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Path.Combine(components.ToArray());
|
return string.Join(Path.DirectorySeparatorChar.ToString(), components) + extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BuildTrackFileName(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null)
|
public string BuildTrackFileName(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, string extension = "", NamingConfig namingConfig = null, List<CustomFormat> customFormats = null)
|
||||||
{
|
{
|
||||||
return BuildTrackFileName(tracks, artist, album, trackFile, LongPathSupport.MaxFilePathLength, namingConfig, customFormats);
|
return BuildTrackFileName(tracks, artist, album, trackFile, extension, LongPathSupport.MaxFilePathLength, namingConfig, customFormats);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BuildTrackFilePath(Artist artist, string fileName, string extension)
|
public string BuildTrackFilePath(List<Track> tracks, Artist artist, Album album, TrackFile trackFile, string extension, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null)
|
||||||
{
|
{
|
||||||
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
|
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
|
||||||
|
|
||||||
var path = artist.Path;
|
var artistPath = artist.Path;
|
||||||
|
var remainingPathLength = LongPathSupport.MaxFilePathLength - artistPath.GetByteCount() - 1;
|
||||||
|
var fileName = BuildTrackFileName(tracks, artist, album, trackFile, extension, remainingPathLength, namingConfig, customFormats);
|
||||||
|
|
||||||
return Path.Combine(path, fileName + extension);
|
return Path.Combine(artistPath, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec)
|
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec)
|
||||||
|
|
|
@ -177,7 +177,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _buildFileNames.BuildTrackFileName(tracks, artist, album, trackFile, nameSpec, _customFormats);
|
return _buildFileNames.BuildTrackFileName(tracks, artist, album, trackFile, "", nameSpec, _customFormats);
|
||||||
}
|
}
|
||||||
catch (NamingFormatException)
|
catch (NamingFormatException)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue