aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
authortheguymadmax <171496228+theguymadmax@users.noreply.github.com>2025-11-17 14:09:09 -0500
committerBond_009 <bond.009@outlook.com>2025-11-17 14:09:09 -0500
commit5b3f29946b5628b975578c1ef4a15a3248cd650a (patch)
tree0f1a546340ac2772ef58776132d3032de17886ea /Emby.Server.Implementations
parentc869b5b884d608aa38d597fa14fcdf02423b2053 (diff)
Backport pull request #15501 from jellyfin/release-10.11.z
Fix .ignore handling for directories Original-merge: e8150428b62668e062a3432960f98684d3b352cb Merged-by: crobibero <cody@robibe.ro> Backported-by: Bond_009 <bond.009@outlook.com>
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/Library/DotIgnoreIgnoreRule.cs97
1 files changed, 39 insertions, 58 deletions
diff --git a/Emby.Server.Implementations/Library/DotIgnoreIgnoreRule.cs b/Emby.Server.Implementations/Library/DotIgnoreIgnoreRule.cs
index 46e60dbaa..473ff8e1d 100644
--- a/Emby.Server.Implementations/Library/DotIgnoreIgnoreRule.cs
+++ b/Emby.Server.Implementations/Library/DotIgnoreIgnoreRule.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Runtime.InteropServices;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Resolvers;
@@ -13,28 +12,24 @@ namespace Emby.Server.Implementations.Library;
/// </summary>
public class DotIgnoreIgnoreRule : IResolverIgnoreRule
{
+ private static readonly bool IsWindows = OperatingSystem.IsWindows();
+
private static FileInfo? FindIgnoreFile(DirectoryInfo directory)
{
- var ignoreFile = new FileInfo(Path.Join(directory.FullName, ".ignore"));
- if (ignoreFile.Exists)
- {
- return ignoreFile;
- }
-
- var parentDir = directory.Parent;
- if (parentDir is null)
+ for (var current = directory; current is not null; current = current.Parent)
{
- return null;
+ var ignorePath = Path.Join(current.FullName, ".ignore");
+ if (File.Exists(ignorePath))
+ {
+ return new FileInfo(ignorePath);
+ }
}
- return FindIgnoreFile(parentDir);
+ return null;
}
/// <inheritdoc />
- public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem? parent)
- {
- return IsIgnored(fileInfo, parent);
- }
+ public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem? parent) => IsIgnored(fileInfo, parent);
/// <summary>
/// Checks whether or not the file is ignored.
@@ -44,72 +39,58 @@ public class DotIgnoreIgnoreRule : IResolverIgnoreRule
/// <returns>True if the file should be ignored.</returns>
public static bool IsIgnored(FileSystemMetadata fileInfo, BaseItem? parent)
{
- if (fileInfo.IsDirectory)
- {
- var dirIgnoreFile = FindIgnoreFile(new DirectoryInfo(fileInfo.FullName));
- if (dirIgnoreFile is null)
- {
- return false;
- }
-
- // Fast path in case the ignore files isn't a symlink and is empty
- if (dirIgnoreFile.LinkTarget is null && dirIgnoreFile.Length == 0)
- {
- return true;
- }
-
- // ignore the directory only if the .ignore file is empty
- // evaluate individual files otherwise
- return string.IsNullOrWhiteSpace(GetFileContent(dirIgnoreFile));
- }
+ var searchDirectory = fileInfo.IsDirectory
+ ? new DirectoryInfo(fileInfo.FullName)
+ : new DirectoryInfo(Path.GetDirectoryName(fileInfo.FullName) ?? string.Empty);
- var parentDirPath = Path.GetDirectoryName(fileInfo.FullName);
- if (string.IsNullOrEmpty(parentDirPath))
+ if (string.IsNullOrEmpty(searchDirectory.FullName))
{
return false;
}
- var folder = new DirectoryInfo(parentDirPath);
- var ignoreFile = FindIgnoreFile(folder);
+ var ignoreFile = FindIgnoreFile(searchDirectory);
if (ignoreFile is null)
{
return false;
}
- string ignoreFileString = GetFileContent(ignoreFile);
-
- if (string.IsNullOrWhiteSpace(ignoreFileString))
+ // Fast path in case the ignore files isn't a symlink and is empty
+ if (ignoreFile.LinkTarget is null && ignoreFile.Length == 0)
{
// Ignore directory if we just have the file
return true;
}
+ var content = GetFileContent(ignoreFile);
+ return string.IsNullOrWhiteSpace(content)
+ || CheckIgnoreRules(fileInfo.FullName, content, fileInfo.IsDirectory);
+ }
+
+ private static bool CheckIgnoreRules(string path, string ignoreFileContent, bool isDirectory)
+ {
// If file has content, base ignoring off the content .gitignore-style rules
- var ignoreRules = ignoreFileString.Split('\n', StringSplitOptions.RemoveEmptyEntries);
+ var rules = ignoreFileContent.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
var ignore = new Ignore.Ignore();
- ignore.Add(ignoreRules);
+ ignore.Add(rules);
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ // Mitigate the problem of the Ignore library not handling Windows paths correctly.
+ // See https://github.com/jellyfin/jellyfin/issues/15484
+ var pathToCheck = IsWindows ? path.NormalizePath('/') : path;
+
+ // Add trailing slash for directories to match "folder/"
+ if (isDirectory)
{
- // Mitigate the problem of the Ignore library not handling Windows paths correctly.
- // See https://github.com/jellyfin/jellyfin/issues/15484
- return ignore.IsIgnored(fileInfo.FullName.NormalizePath('/'));
+ pathToCheck = string.Concat(pathToCheck.AsSpan().TrimEnd('/'), "/");
}
- return ignore.IsIgnored(fileInfo.FullName);
+ return ignore.IsIgnored(pathToCheck);
}
- private static string GetFileContent(FileInfo dirIgnoreFile)
+ private static string GetFileContent(FileInfo ignoreFile)
{
- dirIgnoreFile = FileSystemHelper.ResolveLinkTarget(dirIgnoreFile, returnFinalTarget: true) ?? dirIgnoreFile;
- if (!dirIgnoreFile.Exists)
- {
- return string.Empty;
- }
-
- using (var reader = dirIgnoreFile.OpenText())
- {
- return reader.ReadToEnd();
- }
+ ignoreFile = FileSystemHelper.ResolveLinkTarget(ignoreFile, returnFinalTarget: true) ?? ignoreFile;
+ return ignoreFile.Exists
+ ? File.ReadAllText(ignoreFile.FullName)
+ : string.Empty;
}
}