Merge pull request #7028 from cvium/everything_went_wrong
This commit is contained in:
commit
00211ca056
|
@ -1,6 +1,7 @@
|
||||||
#pragma warning disable CA1819
|
#pragma warning disable CA1819
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Emby.Naming.Video;
|
using Emby.Naming.Video;
|
||||||
|
@ -475,6 +476,12 @@ namespace Emby.Naming.Common
|
||||||
"theme",
|
"theme",
|
||||||
MediaType.Audio),
|
MediaType.Audio),
|
||||||
|
|
||||||
|
new ExtraRule(
|
||||||
|
ExtraType.ThemeSong,
|
||||||
|
ExtraRuleType.DirectoryName,
|
||||||
|
"theme-music",
|
||||||
|
MediaType.Audio),
|
||||||
|
|
||||||
new ExtraRule(
|
new ExtraRule(
|
||||||
ExtraType.Scene,
|
ExtraType.Scene,
|
||||||
ExtraRuleType.Suffix,
|
ExtraRuleType.Suffix,
|
||||||
|
@ -569,7 +576,7 @@ namespace Emby.Naming.Common
|
||||||
ExtraType.Unknown,
|
ExtraType.Unknown,
|
||||||
ExtraRuleType.DirectoryName,
|
ExtraRuleType.DirectoryName,
|
||||||
"extras",
|
"extras",
|
||||||
MediaType.Video),
|
MediaType.Video)
|
||||||
};
|
};
|
||||||
|
|
||||||
Format3DRules = new[]
|
Format3DRules = new[]
|
||||||
|
@ -681,9 +688,29 @@ namespace Emby.Naming.Common
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
|
AllExtrasTypesFolderNames = new Dictionary<string, ExtraType>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["trailers"] = ExtraType.Trailer,
|
||||||
|
["theme-music"] = ExtraType.ThemeSong,
|
||||||
|
["backdrops"] = ExtraType.ThemeVideo,
|
||||||
|
["extras"] = ExtraType.Unknown,
|
||||||
|
["behind the scenes"] = ExtraType.BehindTheScenes,
|
||||||
|
["deleted scenes"] = ExtraType.DeletedScene,
|
||||||
|
["interviews"] = ExtraType.Interview,
|
||||||
|
["scenes"] = ExtraType.Scene,
|
||||||
|
["samples"] = ExtraType.Sample,
|
||||||
|
["shorts"] = ExtraType.Clip,
|
||||||
|
["featurettes"] = ExtraType.Clip
|
||||||
|
};
|
||||||
|
|
||||||
Compile();
|
Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the folder name to extra types mapping.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets list of audio file extensions.
|
/// Gets or sets list of audio file extensions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -16,18 +16,13 @@ namespace Emby.Naming.Video
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resolves alternative versions and extras from list of video files.
|
/// Resolves alternative versions and extras from list of video files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="files">List of related video files.</param>
|
/// <param name="videoInfos">List of related video files.</param>
|
||||||
/// <param name="namingOptions">The naming options.</param>
|
/// <param name="namingOptions">The naming options.</param>
|
||||||
/// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param>
|
/// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param>
|
||||||
/// <param name="parseName">Whether to parse the name or use the filename.</param>
|
/// <param name="parseName">Whether to parse the name or use the filename.</param>
|
||||||
/// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns>
|
/// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns>
|
||||||
public static IReadOnlyList<VideoInfo> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true)
|
public static IReadOnlyList<VideoInfo> Resolve(IReadOnlyList<VideoFileInfo> videoInfos, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true)
|
||||||
{
|
{
|
||||||
var videoInfos = files
|
|
||||||
.Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions, parseName))
|
|
||||||
.OfType<VideoFileInfo>()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Filter out all extras, otherwise they could cause stacks to not be resolved
|
// Filter out all extras, otherwise they could cause stacks to not be resolved
|
||||||
// See the unit test TestStackedWithTrailer
|
// See the unit test TestStackedWithTrailer
|
||||||
var nonExtras = videoInfos
|
var nonExtras = videoInfos
|
||||||
|
|
|
@ -54,20 +54,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
// Ignore trailer folders but allow it at the collection level
|
// Ignore extras folders but allow it at the collection level
|
||||||
if (string.Equals(filename, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase)
|
if (_namingOptions.AllExtrasTypesFolderNames.ContainsKey(filename)
|
||||||
&& !(parent is AggregateFolder)
|
&& parent is not AggregateFolder
|
||||||
&& !(parent is UserRootFolder))
|
&& parent is not UserRootFolder)
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,8 +531,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
return key.GetMD5();
|
return key.GetMD5();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null)
|
public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null, IDirectoryService directoryService = null)
|
||||||
=> ResolvePath(fileInfo, new DirectoryService(_fileSystem), null, parent);
|
=> ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent);
|
||||||
|
|
||||||
private BaseItem ResolvePath(
|
private BaseItem ResolvePath(
|
||||||
FileSystemMetadata fileInfo,
|
FileSystemMetadata fileInfo,
|
||||||
|
@ -652,7 +652,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
return !args.ContainsFileSystemEntryByName(".ignore");
|
return !args.ContainsFileSystemEntryByName(".ignore");
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType)
|
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType = null)
|
||||||
{
|
{
|
||||||
return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers);
|
return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers);
|
||||||
}
|
}
|
||||||
|
@ -2683,7 +2683,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren)
|
public IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions);
|
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions);
|
||||||
if (ownerVideoInfo == null)
|
if (ownerVideoInfo == null)
|
||||||
|
@ -2692,17 +2692,36 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = fileSystemChildren.Count;
|
var count = fileSystemChildren.Count;
|
||||||
var files = new List<FileSystemMetadata>();
|
var files = new List<VideoFileInfo>();
|
||||||
|
var nonVideoFiles = new List<FileSystemMetadata>();
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var current = fileSystemChildren[i];
|
var current = fileSystemChildren[i];
|
||||||
if (current.IsDirectory && BaseItem.AllExtrasTypesFolderNames.ContainsKey(current.Name))
|
if (current.IsDirectory && _namingOptions.AllExtrasTypesFolderNames.ContainsKey(current.Name))
|
||||||
{
|
{
|
||||||
files.AddRange(_fileSystem.GetFiles(current.FullName, _namingOptions.VideoFileExtensions, false, false));
|
var filesInSubFolder = _fileSystem.GetFiles(current.FullName, _namingOptions.VideoFileExtensions, false, false);
|
||||||
|
foreach (var file in filesInSubFolder)
|
||||||
|
{
|
||||||
|
var videoInfo = VideoResolver.Resolve(file.FullName, file.IsDirectory, _namingOptions);
|
||||||
|
if (videoInfo == null)
|
||||||
|
{
|
||||||
|
nonVideoFiles.Add(file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
files.Add(videoInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!current.IsDirectory)
|
else if (!current.IsDirectory)
|
||||||
{
|
{
|
||||||
files.Add(current);
|
var videoInfo = VideoResolver.Resolve(current.FullName, current.IsDirectory, _namingOptions);
|
||||||
|
if (videoInfo == null)
|
||||||
|
{
|
||||||
|
nonVideoFiles.Add(current);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
files.Add(videoInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2714,11 +2733,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
var videos = VideoListResolver.Resolve(files, _namingOptions);
|
var videos = VideoListResolver.Resolve(files, _namingOptions);
|
||||||
// owner video info cannot be null as that implies it has no path
|
// owner video info cannot be null as that implies it has no path
|
||||||
var extras = ExtraResolver.GetExtras(videos, ownerVideoInfo, _namingOptions.VideoFlagDelimiters);
|
var extras = ExtraResolver.GetExtras(videos, ownerVideoInfo, _namingOptions.VideoFlagDelimiters);
|
||||||
|
|
||||||
for (var i = 0; i < extras.Count; i++)
|
for (var i = 0; i < extras.Count; i++)
|
||||||
{
|
{
|
||||||
var currentExtra = extras[i];
|
var currentExtra = extras[i];
|
||||||
var resolved = ResolvePath(_fileSystem.GetFileInfo(currentExtra.Path));
|
var resolved = ResolvePath(_fileSystem.GetFileInfo(currentExtra.Path), null, directoryService);
|
||||||
if (resolved is not Video video)
|
if (resolved is not Video video)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -2735,6 +2753,35 @@ namespace Emby.Server.Implementations.Library
|
||||||
video.OwnerId = owner.Id;
|
video.OwnerId = owner.Id;
|
||||||
yield return video;
|
yield return video;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: theme songs must be handled "manually" (but should we?) since they aren't video files
|
||||||
|
for (var i = 0; i < nonVideoFiles.Count; i++)
|
||||||
|
{
|
||||||
|
var current = nonVideoFiles[i];
|
||||||
|
var extraInfo = ExtraResolver.GetExtraInfo(current.FullName, _namingOptions);
|
||||||
|
if (extraInfo.ExtraType != ExtraType.ThemeSong)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolved = ResolvePath(current, null, directoryService);
|
||||||
|
if (resolved is not Audio themeSong)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||||
|
if (GetItemById(themeSong.Id) is Audio dbItem)
|
||||||
|
{
|
||||||
|
themeSong = dbItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
themeSong.ExtraType = ExtraType.ThemeSong;
|
||||||
|
themeSong.OwnerId = owner.Id;
|
||||||
|
themeSong.ParentId = Guid.Empty;
|
||||||
|
|
||||||
|
yield return themeSong;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem)
|
public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem)
|
||||||
|
|
|
@ -261,7 +261,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolverResult = VideoListResolver.Resolve(files, NamingOptions, supportMultiEditions, parseName);
|
var videoInfos = files
|
||||||
|
.Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, NamingOptions, parseName))
|
||||||
|
.Where(f => f != null)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var resolverResult = VideoListResolver.Resolve(videoInfos, NamingOptions, supportMultiEditions, parseName);
|
||||||
|
|
||||||
var result = new MultiItemResolverResult
|
var result = new MultiItemResolverResult
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,6 @@ using System.Threading.Tasks;
|
||||||
using Diacritics.Extensions;
|
using Diacritics.Extensions;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
using Jellyfin.Data.Enums;
|
using Jellyfin.Data.Enums;
|
||||||
using Jellyfin.Extensions;
|
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Channels;
|
using MediaBrowser.Controller.Channels;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
@ -22,7 +21,6 @@ using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Configuration;
|
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
|
@ -42,11 +40,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
private BaseItemKind? _baseItemKind;
|
private BaseItemKind? _baseItemKind;
|
||||||
|
|
||||||
public const string TrailerFileName = "trailer";
|
|
||||||
public const string TrailersFolderName = "trailers";
|
|
||||||
public const string ThemeSongsFolderName = "theme-music";
|
|
||||||
public const string ThemeSongFileName = "theme";
|
public const string ThemeSongFileName = "theme";
|
||||||
public const string ThemeVideosFolderName = "backdrops";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported image extensions.
|
/// The supported image extensions.
|
||||||
|
@ -83,21 +77,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
Model.Entities.ExtraType.Scene
|
Model.Entities.ExtraType.Scene
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The supported extra folder names and types. See <see cref="Emby.Naming.Common.NamingOptions" />.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly Dictionary<string, ExtraType> AllExtrasTypesFolderNames = new Dictionary<string, ExtraType>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["extras"] = MediaBrowser.Model.Entities.ExtraType.Unknown,
|
|
||||||
["behind the scenes"] = MediaBrowser.Model.Entities.ExtraType.BehindTheScenes,
|
|
||||||
["deleted scenes"] = MediaBrowser.Model.Entities.ExtraType.DeletedScene,
|
|
||||||
["interviews"] = MediaBrowser.Model.Entities.ExtraType.Interview,
|
|
||||||
["scenes"] = MediaBrowser.Model.Entities.ExtraType.Scene,
|
|
||||||
["samples"] = MediaBrowser.Model.Entities.ExtraType.Sample,
|
|
||||||
["shorts"] = MediaBrowser.Model.Entities.ExtraType.Clip,
|
|
||||||
["featurettes"] = MediaBrowser.Model.Entities.ExtraType.Clip
|
|
||||||
};
|
|
||||||
|
|
||||||
private string _sortName;
|
private string _sortName;
|
||||||
|
|
||||||
private string _forcedSortName;
|
private string _forcedSortName;
|
||||||
|
@ -1275,74 +1254,6 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return string.Join('/', terms);
|
return string.Join('/', terms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Loads the theme songs.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>List{Audio.Audio}.</returns>
|
|
||||||
private static Audio.Audio[] LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
|
||||||
{
|
|
||||||
var files = fileSystemChildren.Where(i => i.IsDirectory)
|
|
||||||
.Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.SelectMany(i => FileSystem.GetFiles(i.FullName))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Support plex/xbmc convention
|
|
||||||
files.AddRange(fileSystemChildren
|
|
||||||
.Where(i => !i.IsDirectory && System.IO.Path.GetFileNameWithoutExtension(i.FullName.AsSpan()).Equals(ThemeSongFileName, StringComparison.OrdinalIgnoreCase)));
|
|
||||||
|
|
||||||
return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
|
|
||||||
.OfType<Audio.Audio>()
|
|
||||||
.Select(audio =>
|
|
||||||
{
|
|
||||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
|
||||||
if (LibraryManager.GetItemById(audio.Id) is Audio.Audio dbItem)
|
|
||||||
{
|
|
||||||
audio = dbItem;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// item is new
|
|
||||||
audio.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeSong;
|
|
||||||
}
|
|
||||||
|
|
||||||
return audio;
|
|
||||||
|
|
||||||
// Sort them so that the list can be easily compared for changes
|
|
||||||
}).OrderBy(i => i.Path).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Loads the video backdrops.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>List{Video}.</returns>
|
|
||||||
private static Video[] LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
|
|
||||||
{
|
|
||||||
var files = fileSystemChildren.Where(i => i.IsDirectory)
|
|
||||||
.Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
.SelectMany(i => FileSystem.GetFiles(i.FullName));
|
|
||||||
|
|
||||||
return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
|
|
||||||
.OfType<Video>()
|
|
||||||
.Select(item =>
|
|
||||||
{
|
|
||||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
|
||||||
|
|
||||||
if (LibraryManager.GetItemById(item.Id) is Video dbItem)
|
|
||||||
{
|
|
||||||
item = dbItem;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// item is new
|
|
||||||
item.ExtraType = Model.Entities.ExtraType.ThemeVideo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
|
|
||||||
// Sort them so that the list can be easily compared for changes
|
|
||||||
}).OrderBy(i => i.Path).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task RefreshMetadata(CancellationToken cancellationToken)
|
public Task RefreshMetadata(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken);
|
return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken);
|
||||||
|
@ -1453,7 +1364,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns>
|
/// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns>
|
||||||
protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder || this.GetType() == typeof(Folder))
|
if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1470,11 +1381,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var extras = LibraryManager.FindExtras(item, fileSystemChildren).ToArray();
|
var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
|
||||||
var newExtraIds = extras.Select(i => i.Id).ToArray();
|
var newExtraIds = extras.Select(i => i.Id).ToArray();
|
||||||
var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds);
|
var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds);
|
||||||
|
|
||||||
if (!extrasChanged)
|
if (!extrasChanged && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public interface IHasSpecialFeatures
|
public interface IHasSpecialFeatures
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the special feature ids.
|
/// Gets the special feature ids.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The special feature ids.</value>
|
/// <value>The special feature ids.</value>
|
||||||
IReadOnlyList<Guid> SpecialFeatureIds { get; set; }
|
IReadOnlyList<Guid> SpecialFeatureIds { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,24 +19,11 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
|
public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
|
||||||
{
|
{
|
||||||
private IReadOnlyList<Guid> _specialFeatureIds;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<Guid> SpecialFeatureIds
|
public IReadOnlyList<Guid> SpecialFeatureIds => GetExtras()
|
||||||
{
|
.Where(extra => extra.ExtraType != null && extra is Video)
|
||||||
get
|
.Select(extra => extra.Id)
|
||||||
{
|
|
||||||
return _specialFeatureIds ??= GetExtras()
|
|
||||||
.Where(extra => extra.ExtraType != Model.Entities.ExtraType.Trailer)
|
|
||||||
.Select(song => song.Id)
|
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_specialFeatureIds = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<BaseItem> LocalTrailers => GetExtras()
|
public IReadOnlyList<BaseItem> LocalTrailers => GetExtras()
|
||||||
|
|
|
@ -58,10 +58,12 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fileInfo">The file information.</param>
|
/// <param name="fileInfo">The file information.</param>
|
||||||
/// <param name="parent">The parent.</param>
|
/// <param name="parent">The parent.</param>
|
||||||
|
/// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param>
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem ResolvePath(
|
BaseItem ResolvePath(
|
||||||
FileSystemMetadata fileInfo,
|
FileSystemMetadata fileInfo,
|
||||||
Folder parent = null);
|
Folder parent = null,
|
||||||
|
IDirectoryService directoryService = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resolves a set of files into a list of BaseItem.
|
/// Resolves a set of files into a list of BaseItem.
|
||||||
|
@ -430,10 +432,9 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="owner">The owner.</param>
|
/// <param name="owner">The owner.</param>
|
||||||
/// <param name="fileSystemChildren">The file system children.</param>
|
/// <param name="fileSystemChildren">The file system children.</param>
|
||||||
/// <returns>IEnumerable<Video>.</returns>
|
/// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param>
|
||||||
IEnumerable<Video> FindExtras(
|
/// <returns>IEnumerable<BaseItem>.</returns>
|
||||||
BaseItem owner,
|
IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService);
|
||||||
List<FileSystemMetadata> fileSystemChildren);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the collection folders.
|
/// Gets the collection folders.
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Jellyfin.Extensions;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
|
@ -120,7 +121,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
return directoryService.GetFileSystemEntries(path)
|
return directoryService.GetFileSystemEntries(path)
|
||||||
.Where(i =>
|
.Where(i =>
|
||||||
(includeDirectories && i.IsDirectory)
|
(includeDirectories && i.IsDirectory)
|
||||||
|| Array.FindIndex(BaseItem.SupportedImageExtensions, ext => string.Equals(ext, i.Extension, StringComparison.OrdinalIgnoreCase)) != -1)
|
|| BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparison.OrdinalIgnoreCase))
|
||||||
.OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty));
|
.OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result.Where(v => v.ExtraType == null));
|
Assert.Single(result.Where(v => v.ExtraType == null));
|
||||||
|
@ -46,11 +42,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result.Where(v => v.ExtraType == null));
|
Assert.Single(result.Where(v => v.ExtraType == null));
|
||||||
|
@ -68,11 +60,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -94,11 +82,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(7, result.Count);
|
Assert.Equal(7, result.Count);
|
||||||
|
@ -121,11 +105,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -149,11 +129,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(9, result.Count);
|
Assert.Equal(9, result.Count);
|
||||||
|
@ -173,11 +149,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
|
@ -199,11 +171,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
|
@ -226,11 +194,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -256,11 +220,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -280,11 +240,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -305,11 +261,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(7, result.Count);
|
Assert.Equal(7, result.Count);
|
||||||
|
@ -331,11 +283,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
|
@ -352,11 +300,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -373,11 +317,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -394,11 +334,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -415,11 +351,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -428,7 +360,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TestEmptyList()
|
public void TestEmptyList()
|
||||||
{
|
{
|
||||||
var result = VideoListResolver.Resolve(new List<FileSystemMetadata>(), _namingOptions).ToList();
|
var result = VideoListResolver.Resolve(new List<VideoFileInfo>(), _namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Empty(result);
|
Assert.Empty(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(11, result.Count);
|
Assert.Equal(11, result.Count);
|
||||||
|
@ -80,11 +76,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -100,11 +92,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -122,11 +110,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -145,11 +129,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
|
@ -169,11 +149,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
|
@ -192,11 +168,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -218,11 +190,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(5, result.Count);
|
Assert.Equal(5, result.Count);
|
||||||
|
@ -238,11 +206,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = true,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -259,11 +223,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = true,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -281,11 +241,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(3, result.Count);
|
Assert.Equal(3, result.Count);
|
||||||
|
@ -306,11 +262,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(4, result.Count);
|
Assert.Equal(4, result.Count);
|
||||||
|
@ -332,11 +284,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -351,11 +299,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -370,11 +314,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -390,11 +330,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
|
@ -410,11 +346,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -430,11 +362,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -452,11 +380,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
@ -474,11 +398,7 @@ namespace Jellyfin.Naming.Tests.Video
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = VideoListResolver.Resolve(
|
var result = VideoListResolver.Resolve(
|
||||||
files.Select(i => new FileSystemMetadata
|
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
|
||||||
{
|
|
||||||
IsDirectory = false,
|
|
||||||
FullName = i
|
|
||||||
}).ToList(),
|
|
||||||
_namingOptions).ToList();
|
_namingOptions).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, result.Count);
|
Assert.Equal(2, result.Count);
|
||||||
|
|
|
@ -5,11 +5,13 @@ using AutoFixture;
|
||||||
using AutoFixture.AutoMoq;
|
using AutoFixture.AutoMoq;
|
||||||
using Emby.Naming.Common;
|
using Emby.Naming.Common;
|
||||||
using Emby.Server.Implementations.Library.Resolvers;
|
using Emby.Server.Implementations.Library.Resolvers;
|
||||||
|
using Emby.Server.Implementations.Library.Resolvers.Audio;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Controller.Resolvers;
|
using MediaBrowser.Controller.Resolvers;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -22,6 +24,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library.LibraryManager;
|
||||||
public class FindExtrasTests
|
public class FindExtrasTests
|
||||||
{
|
{
|
||||||
private readonly Emby.Server.Implementations.Library.LibraryManager _libraryManager;
|
private readonly Emby.Server.Implementations.Library.LibraryManager _libraryManager;
|
||||||
|
private readonly Mock<IFileSystem> _fileSystemMock;
|
||||||
|
|
||||||
public FindExtrasTests()
|
public FindExtrasTests()
|
||||||
{
|
{
|
||||||
|
@ -29,11 +32,11 @@ public class FindExtrasTests
|
||||||
fixture.Register(() => new NamingOptions());
|
fixture.Register(() => new NamingOptions());
|
||||||
var configMock = fixture.Freeze<Mock<IServerConfigurationManager>>();
|
var configMock = fixture.Freeze<Mock<IServerConfigurationManager>>();
|
||||||
configMock.Setup(c => c.ApplicationPaths.ProgramDataPath).Returns("/data");
|
configMock.Setup(c => c.ApplicationPaths.ProgramDataPath).Returns("/data");
|
||||||
var fileSystemMock = fixture.Freeze<Mock<IFileSystem>>();
|
_fileSystemMock = fixture.Freeze<Mock<IFileSystem>>();
|
||||||
fileSystemMock.Setup(f => f.GetFileInfo(It.IsAny<string>())).Returns<string>(path => new FileSystemMetadata { FullName = path });
|
_fileSystemMock.Setup(f => f.GetFileInfo(It.IsAny<string>())).Returns<string>(path => new FileSystemMetadata { FullName = path });
|
||||||
_libraryManager = fixture.Build<Emby.Server.Implementations.Library.LibraryManager>().Do(s => s.AddParts(
|
_libraryManager = fixture.Build<Emby.Server.Implementations.Library.LibraryManager>().Do(s => s.AddParts(
|
||||||
fixture.Create<IEnumerable<IResolverIgnoreRule>>(),
|
fixture.Create<IEnumerable<IResolverIgnoreRule>>(),
|
||||||
new List<IItemResolver> { new GenericVideoResolver<Video>(fixture.Create<NamingOptions>()) },
|
new List<IItemResolver> { new GenericVideoResolver<Video>(fixture.Create<NamingOptions>()), new AudioResolver(fixture.Create<NamingOptions>()) },
|
||||||
fixture.Create<IEnumerable<IIntroProvider>>(),
|
fixture.Create<IEnumerable<IIntroProvider>>(),
|
||||||
fixture.Create<IEnumerable<IBaseItemComparer>>(),
|
fixture.Create<IEnumerable<IBaseItemComparer>>(),
|
||||||
fixture.Create<IEnumerable<ILibraryPostScanTask>>()))
|
fixture.Create<IEnumerable<ILibraryPostScanTask>>()))
|
||||||
|
@ -62,7 +65,7 @@ public class FindExtrasTests
|
||||||
IsDirectory = false
|
IsDirectory = false
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList();
|
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, extras.Count);
|
Assert.Equal(2, extras.Count);
|
||||||
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
||||||
|
@ -77,26 +80,77 @@ public class FindExtrasTests
|
||||||
{
|
{
|
||||||
"/movies/Up/Up.mkv",
|
"/movies/Up/Up.mkv",
|
||||||
"/movies/Up/Up - trailer.mkv",
|
"/movies/Up/Up - trailer.mkv",
|
||||||
"/movies/Up/trailers/some trailer.mkv",
|
"/movies/Up/trailers",
|
||||||
"/movies/Up/behind the scenes/the making of Up.mkv",
|
"/movies/Up/theme-music",
|
||||||
|
"/movies/Up/theme.mp3",
|
||||||
|
"/movies/Up/not a theme.mp3",
|
||||||
|
"/movies/Up/behind the scenes",
|
||||||
"/movies/Up/behind the scenes.mkv",
|
"/movies/Up/behind the scenes.mkv",
|
||||||
"/movies/Up/Up - sample.mkv",
|
"/movies/Up/Up - sample.mkv",
|
||||||
"/movies/Up/Up something else.mkv"
|
"/movies/Up/Up something else.mkv"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_fileSystemMock.Setup(f => f.GetFiles(
|
||||||
|
"/movies/Up/trailers",
|
||||||
|
It.IsAny<string[]>(),
|
||||||
|
false,
|
||||||
|
false))
|
||||||
|
.Returns(new List<FileSystemMetadata>
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
FullName = "/movies/Up/trailers/some trailer.mkv",
|
||||||
|
Name = "some trailer.mkv",
|
||||||
|
IsDirectory = false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_fileSystemMock.Setup(f => f.GetFiles(
|
||||||
|
"/movies/Up/behind the scenes",
|
||||||
|
It.IsAny<string[]>(),
|
||||||
|
false,
|
||||||
|
false))
|
||||||
|
.Returns(new List<FileSystemMetadata>
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
FullName = "/movies/Up/behind the scenes/the making of Up.mkv",
|
||||||
|
Name = "the making of Up.mkv",
|
||||||
|
IsDirectory = false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_fileSystemMock.Setup(f => f.GetFiles(
|
||||||
|
"/movies/Up/theme-music",
|
||||||
|
It.IsAny<string[]>(),
|
||||||
|
false,
|
||||||
|
false))
|
||||||
|
.Returns(new List<FileSystemMetadata>
|
||||||
|
{
|
||||||
|
new ()
|
||||||
|
{
|
||||||
|
FullName = "/movies/Up/theme-music/theme2.mp3",
|
||||||
|
Name = "theme2.mp3",
|
||||||
|
IsDirectory = false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var files = paths.Select(p => new FileSystemMetadata
|
var files = paths.Select(p => new FileSystemMetadata
|
||||||
{
|
{
|
||||||
FullName = p,
|
FullName = p,
|
||||||
IsDirectory = false
|
Name = Path.GetFileName(p),
|
||||||
|
IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p))
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList();
|
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||||
|
|
||||||
Assert.Equal(4, extras.Count);
|
Assert.Equal(6, extras.Count);
|
||||||
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
||||||
Assert.Equal(ExtraType.Trailer, extras[1].ExtraType);
|
Assert.Equal(ExtraType.Trailer, extras[1].ExtraType);
|
||||||
Assert.Equal(ExtraType.BehindTheScenes, extras[2].ExtraType);
|
Assert.Equal(ExtraType.BehindTheScenes, extras[2].ExtraType);
|
||||||
Assert.Equal(ExtraType.Sample, extras[3].ExtraType);
|
Assert.Equal(ExtraType.Sample, extras[3].ExtraType);
|
||||||
|
Assert.Equal(ExtraType.ThemeSong, extras[4].ExtraType);
|
||||||
|
Assert.Equal(ExtraType.ThemeSong, extras[5].ExtraType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -116,7 +170,7 @@ public class FindExtrasTests
|
||||||
IsDirectory = false
|
IsDirectory = false
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList();
|
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||||
|
|
||||||
Assert.Single(extras);
|
Assert.Single(extras);
|
||||||
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
||||||
|
@ -142,7 +196,7 @@ public class FindExtrasTests
|
||||||
IsDirectory = false
|
IsDirectory = false
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList();
|
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||||
|
|
||||||
Assert.Single(extras);
|
Assert.Single(extras);
|
||||||
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
||||||
|
@ -167,7 +221,7 @@ public class FindExtrasTests
|
||||||
IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p))
|
IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p))
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList();
|
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||||
|
|
||||||
Assert.Equal(2, extras.Count);
|
Assert.Equal(2, extras.Count);
|
||||||
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user