mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-12-26 17:36:52 +00:00
Backport pull request #12025 from jellyfin/release-10.9.z
Fix empty image folder removal for legacy locations
Original-merge: 476dc01f4d
Merged-by: Bond-009 <bond.009@outlook.com>
Backported-by: Joshua M. Boniface <joshua@boniface.me>
This commit is contained in:
parent
ac114b27a9
commit
6734450d40
|
@ -389,7 +389,7 @@ namespace Emby.Server.Implementations.IO
|
|||
var info = new FileInfo(path);
|
||||
|
||||
if (info.Exists &&
|
||||
((info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) != isHidden)
|
||||
(info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden != isHidden)
|
||||
{
|
||||
if (isHidden)
|
||||
{
|
||||
|
@ -417,8 +417,8 @@ namespace Emby.Server.Implementations.IO
|
|||
return;
|
||||
}
|
||||
|
||||
if (((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) == readOnly
|
||||
&& ((info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) == isHidden)
|
||||
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly == readOnly
|
||||
&& (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden == isHidden)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1884,7 +1884,7 @@ namespace Emby.Server.Implementations.Library
|
|||
try
|
||||
{
|
||||
var index = item.GetImageIndex(img);
|
||||
image = await ConvertImageToLocal(item, img, index, removeOnFailure: true).ConfigureAwait(false);
|
||||
image = await ConvertImageToLocal(item, img, index, true).ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
@ -133,53 +134,14 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
DeleteFile(file.FullName);
|
||||
FileSystemHelper.DeleteFile(_fileSystem, file.FullName, _logger);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
DeleteEmptyFolders(directory);
|
||||
FileSystemHelper.DeleteEmptyFolders(_fileSystem, directory, _logger);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
private void DeleteEmptyFolders(string parent)
|
||||
{
|
||||
foreach (var directory in _fileSystem.GetDirectoryPaths(parent))
|
||||
{
|
||||
DeleteEmptyFolders(directory);
|
||||
if (!_fileSystem.GetFileSystemEntryPaths(directory).Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(directory, false);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting directory {Path}", directory);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting directory {Path}", directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileSystem.DeleteFile(path);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting file {Path}", path);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting file {Path}", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
@ -113,53 +113,14 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
DeleteFile(file.FullName);
|
||||
FileSystemHelper.DeleteFile(_fileSystem, file.FullName, _logger);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
DeleteEmptyFolders(directory);
|
||||
FileSystemHelper.DeleteEmptyFolders(_fileSystem, directory, _logger);
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
private void DeleteEmptyFolders(string parent)
|
||||
{
|
||||
foreach (var directory in _fileSystem.GetDirectoryPaths(parent))
|
||||
{
|
||||
DeleteEmptyFolders(directory);
|
||||
if (!_fileSystem.GetFileSystemEntryPaths(directory).Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(directory, false);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting directory {Path}", directory);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting directory {Path}", directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileSystem.DeleteFile(path);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting file {Path}", path);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting file {Path}", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1949,14 +1949,15 @@ namespace MediaBrowser.Controller.Entities
|
|||
return;
|
||||
}
|
||||
|
||||
// Remove it from the item
|
||||
RemoveImage(info);
|
||||
|
||||
// Remove from file system
|
||||
if (info.IsLocalFile)
|
||||
{
|
||||
FileSystem.DeleteFile(info.Path);
|
||||
}
|
||||
|
||||
// Remove from item
|
||||
RemoveImage(info);
|
||||
|
||||
await UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
64
MediaBrowser.Controller/IO/FileSystemHelper.cs
Normal file
64
MediaBrowser.Controller/IO/FileSystemHelper.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MediaBrowser.Controller.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for file system management.
|
||||
/// </summary>
|
||||
public static class FileSystemHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Deletes the file.
|
||||
/// </summary>
|
||||
/// <param name="fileSystem">The fileSystem.</param>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void DeleteFile(IFileSystem fileSystem, string path, ILogger logger)
|
||||
{
|
||||
try
|
||||
{
|
||||
fileSystem.DeleteFile(path);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
logger.LogError(ex, "Error deleting file {Path}", path);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.LogError(ex, "Error deleting file {Path}", path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursively delete empty folders.
|
||||
/// </summary>
|
||||
/// <param name="fileSystem">The fileSystem.</param>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public static void DeleteEmptyFolders(IFileSystem fileSystem, string path, ILogger logger)
|
||||
{
|
||||
foreach (var directory in fileSystem.GetDirectoryPaths(path))
|
||||
{
|
||||
DeleteEmptyFolders(fileSystem, directory, logger);
|
||||
if (!fileSystem.GetFileSystemEntryPaths(directory).Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(directory, false);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
logger.LogError(ex, "Error deleting directory {Path}", directory);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.LogError(ex, "Error deleting directory {Path}", directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Common.Configuration;
|
|||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
@ -188,11 +189,27 @@ namespace MediaBrowser.Providers.Manager
|
|||
{
|
||||
_fileSystem.DeleteFile(currentPath);
|
||||
|
||||
// Remove containing directory if empty
|
||||
var folder = Path.GetDirectoryName(currentPath);
|
||||
if (!_fileSystem.GetFiles(folder).Any())
|
||||
// Remove local episode metadata directory if it exists and is empty
|
||||
var directory = Path.GetDirectoryName(currentPath);
|
||||
if (item is Episode && directory.Equals("metadata", StringComparison.Ordinal))
|
||||
{
|
||||
Directory.Delete(folder);
|
||||
var parentDirectoryPath = Directory.GetParent(currentPath).FullName;
|
||||
if (_fileSystem.DirectoryExists(parentDirectoryPath) && !_fileSystem.GetFiles(parentDirectoryPath).Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Deleting empty local metadata folder {Folder}", parentDirectoryPath);
|
||||
Directory.Delete(parentDirectoryPath);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting directory {Path}", parentDirectoryPath);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error deleting directory {Path}", parentDirectoryPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
|
@ -96,7 +97,7 @@ namespace MediaBrowser.Providers.Manager
|
|||
public bool ValidateImages(BaseItem item, IEnumerable<IImageProvider> providers, ImageRefreshOptions refreshOptions)
|
||||
{
|
||||
var hasChanges = false;
|
||||
IDirectoryService directoryService = refreshOptions?.DirectoryService;
|
||||
var directoryService = refreshOptions?.DirectoryService;
|
||||
|
||||
if (item is not Photo)
|
||||
{
|
||||
|
@ -359,10 +360,8 @@ namespace MediaBrowser.Providers.Manager
|
|||
|
||||
private void PruneImages(BaseItem item, IReadOnlyList<ItemImageInfo> images)
|
||||
{
|
||||
for (var i = 0; i < images.Count; i++)
|
||||
foreach (var image in images)
|
||||
{
|
||||
var image = images[i];
|
||||
|
||||
if (image.IsLocalFile)
|
||||
{
|
||||
try
|
||||
|
@ -377,19 +376,20 @@ namespace MediaBrowser.Providers.Manager
|
|||
{
|
||||
_logger.LogWarning(ex, "Unable to delete {Image}", image.Path);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Always remove empty parent folder
|
||||
var folder = Path.GetDirectoryName(image.Path);
|
||||
if (Directory.Exists(folder) && !_fileSystem.GetFiles(folder).Any())
|
||||
{
|
||||
Directory.Delete(folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.RemoveImages(images);
|
||||
|
||||
// Cleanup old metadata directory for episodes if empty
|
||||
if (item is Episode)
|
||||
{
|
||||
var oldLocalMetadataDirectory = Path.Combine(item.ContainingFolderPath, "metadata");
|
||||
if (_fileSystem.DirectoryExists(oldLocalMetadataDirectory) && !_fileSystem.GetFiles(oldLocalMetadataDirectory).Any())
|
||||
{
|
||||
Directory.Delete(oldLocalMetadataDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -92,10 +92,6 @@ namespace MediaBrowser.Providers.Manager
|
|||
}
|
||||
}
|
||||
|
||||
var localImagesFailed = false;
|
||||
|
||||
var allImageProviders = ProviderManager.GetImageProviders(item, refreshOptions).ToList();
|
||||
|
||||
if (refreshOptions.RemoveOldMetadata && refreshOptions.ReplaceAllImages)
|
||||
{
|
||||
if (ImageProvider.RemoveImages(item))
|
||||
|
@ -105,6 +101,8 @@ namespace MediaBrowser.Providers.Manager
|
|||
}
|
||||
|
||||
// Start by validating images
|
||||
var localImagesFailed = false;
|
||||
var allImageProviders = ProviderManager.GetImageProviders(item, refreshOptions).ToList();
|
||||
try
|
||||
{
|
||||
// Always validate images and check for new locally stored ones.
|
||||
|
@ -813,19 +811,16 @@ namespace MediaBrowser.Providers.Manager
|
|||
{
|
||||
var refreshResult = new RefreshResult();
|
||||
|
||||
var tmpDataMerged = false;
|
||||
if (id is not null)
|
||||
{
|
||||
MergeNewData(temp.Item, id);
|
||||
}
|
||||
|
||||
foreach (var provider in providers)
|
||||
{
|
||||
var providerName = provider.GetType().Name;
|
||||
Logger.LogDebug("Running {Provider} for {Item}", providerName, logName);
|
||||
|
||||
if (id is not null && !tmpDataMerged)
|
||||
{
|
||||
MergeNewData(temp.Item, id);
|
||||
tmpDataMerged = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await provider.GetMetadata(id, cancellationToken).ConfigureAwait(false);
|
||||
|
|
Loading…
Reference in a new issue