aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs5
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs41
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs5
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs6
-rw-r--r--MediaBrowser.Controller/Persistence/IPeopleRepository.cs6
9 files changed, 59 insertions, 24 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index c25694aba5..1e2d94d2a4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -173,10 +173,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index 65669e6804..23b3341dbc 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -80,10 +80,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 28f40cb7fa..d030c8f420 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -48,6 +48,10 @@ namespace MediaBrowser.Controller.Entities
public const string ThemeSongFileName = "theme";
+ // Well below the 255 byte limit of the common Linux filesystems and the 255 character limit
+ // of Windows, so the files inside the folder still fit within MAX_PATH.
+ private const int MaxItemByNameFolderNameBytes = 128;
+
/// <summary>
/// The supported image extensions.
/// </summary>
@@ -942,6 +946,43 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
+ /// Turns an item-by-name entity's name into a folder name every supported filesystem accepts.
+ /// </summary>
+ /// <param name="name">The entity's name.</param>
+ /// <returns>The folder name.</returns>
+ public static string GetItemByNameFolderName(string name)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = FileSystem.GetValidFilename(name).Trim().TrimEnd('.');
+
+ // Most Linux filesystems cap a path component at 255 bytes, so a name past that cannot be
+ // turned into a folder at all - and an entity with no folder can never be created, which
+ // leaves the credit behind it stuck: not refreshable, not deletable, retried on every scan.
+ // Only broken provider data gets this long, but it still has to resolve to something, so
+ // keep a readable prefix and let a hash of the whole name tell two of them apart.
+ if (Encoding.UTF8.GetByteCount(validName) <= MaxItemByNameFolderNameBytes)
+ {
+ return validName;
+ }
+
+ var suffix = "-" + validName.GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ var budget = MaxItemByNameFolderNameBytes - suffix.Length;
+ var length = Math.Min(validName.Length, budget);
+ while (length > 0 && Encoding.UTF8.GetByteCount(validName.AsSpan(0, length)) > budget)
+ {
+ length--;
+ }
+
+ // Never cut a surrogate pair in half, the lone half is not a valid file name character.
+ if (length > 0 && char.IsHighSurrogate(validName[length - 1]))
+ {
+ length--;
+ }
+
+ return string.Concat(validName.AsSpan(0, length).TrimEnd().TrimEnd('.'), suffix);
+ }
+
+ /// <summary>
/// Cleans a raw name into its sortable form by applying the configured sort rules.
/// </summary>
/// <param name="name">The raw name to clean.</param>
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index 6ec78a270e..ef8acaef92 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -83,10 +83,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index 14325d971a..bba5005eed 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -98,10 +98,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validFilename = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validFilename = normalizeName ? GetItemByNameFolderName(name) : name;
string subFolderPrefix = null;
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 9103b09a95..a944b356c8 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -78,10 +78,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index 37820296cc..03fb2156d3 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -85,10 +85,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.YearPath, validName);
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index ca686fbd9d..2a6ea214b8 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -606,6 +606,12 @@ namespace MediaBrowser.Controller.Library
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery query);
/// <summary>
+ /// Deletes every credit that no item maps to any more.
+ /// </summary>
+ /// <returns>The number of credits that were deleted.</returns>
+ int DeleteOrphanedCredits();
+
+ /// <summary>
/// Gets the distinct people names per item for multiple items.
/// </summary>
/// <param name="itemIds">The item IDs.</param>
diff --git a/MediaBrowser.Controller/Persistence/IPeopleRepository.cs b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs
index 9811241d31..15183a8806 100644
--- a/MediaBrowser.Controller/Persistence/IPeopleRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs
@@ -34,6 +34,12 @@ public interface IPeopleRepository
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter);
/// <summary>
+ /// Deletes every credit that no item maps to any more.
+ /// </summary>
+ /// <returns>The number of credits that were deleted.</returns>
+ int DeleteOrphanedCredits();
+
+ /// <summary>
/// Gets the distinct people names per item for multiple items efficiently by querying from the mapping table.
/// </summary>
/// <param name="itemIds">The item IDs to get people for.</param>