mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-10-29 23:12:39 +01:00
parent
6dd85a5af9
commit
e791f4b743
@ -133,11 +133,16 @@ namespace NzbDrone.Common.Test
|
||||
|
||||
[TestCase(@"C:\test\", @"C:\Test\mydir")]
|
||||
[TestCase(@"C:\test", @"C:\Test\mydir\")]
|
||||
public void path_should_be_parent_on_windows_only(string parentPath, string childPath)
|
||||
public void windows_path_should_be_parent(string parentPath, string childPath)
|
||||
{
|
||||
var expectedResult = OsInfo.IsWindows;
|
||||
parentPath.IsParentPath(childPath).Should().Be(true);
|
||||
}
|
||||
|
||||
parentPath.IsParentPath(childPath).Should().Be(expectedResult);
|
||||
[TestCase("/test", "/test/mydir/")]
|
||||
[TestCase("/test/", "/test/mydir")]
|
||||
public void posix_path_should_be_parent(string parentPath, string childPath)
|
||||
{
|
||||
parentPath.IsParentPath(childPath).Should().Be(true);
|
||||
}
|
||||
|
||||
[TestCase(@"C:\Test\mydir", @"C:\Test")]
|
||||
@ -145,39 +150,57 @@ namespace NzbDrone.Common.Test
|
||||
[TestCase(@"C:\", null)]
|
||||
[TestCase(@"\\server\share", null)]
|
||||
[TestCase(@"\\server\share\test", @"\\server\share")]
|
||||
public void path_should_return_parent_windows(string path, string parentPath)
|
||||
public void windows_path_should_return_parent(string path, string parentPath)
|
||||
{
|
||||
WindowsOnly();
|
||||
path.GetParentPath().Should().Be(parentPath);
|
||||
}
|
||||
|
||||
[TestCase(@"/", null)]
|
||||
[TestCase(@"/test", "/")]
|
||||
public void path_should_return_parent_mono(string path, string parentPath)
|
||||
[TestCase(@"/test/tv", "/test")]
|
||||
public void unix_path_should_return_parent(string path, string parentPath)
|
||||
{
|
||||
PosixOnly();
|
||||
path.GetParentPath().Should().Be(parentPath);
|
||||
}
|
||||
|
||||
[TestCase(@"C:\Test\mydir", "Test")]
|
||||
[TestCase(@"C:\Test\", @"C:\")]
|
||||
[TestCase(@"C:\Test", @"C:\")]
|
||||
[TestCase(@"C:\", null)]
|
||||
[TestCase(@"\\server\share", null)]
|
||||
[TestCase(@"\\server\share\test", @"\\server\share")]
|
||||
public void path_should_return_parent_name_windows(string path, string parentPath)
|
||||
{
|
||||
WindowsOnly();
|
||||
path.GetParentName().Should().Be(parentPath);
|
||||
}
|
||||
|
||||
[TestCase(@"/", null)]
|
||||
[TestCase(@"/test", "/")]
|
||||
[TestCase(@"/test/tv", "test")]
|
||||
public void path_should_return_parent_name_mono(string path, string parentPath)
|
||||
{
|
||||
PosixOnly();
|
||||
path.GetParentName().Should().Be(parentPath);
|
||||
}
|
||||
|
||||
[TestCase(@"C:\Test\mydir", "mydir")]
|
||||
[TestCase(@"C:\Test\", "Test")]
|
||||
[TestCase(@"C:\Test", "Test")]
|
||||
[TestCase(@"C:\", "C:\\")]
|
||||
[TestCase(@"\\server\share", @"\\server\share")]
|
||||
[TestCase(@"\\server\share\test", "test")]
|
||||
public void path_should_return_directory_name_windows(string path, string parentPath)
|
||||
{
|
||||
path.GetDirectoryName().Should().Be(parentPath);
|
||||
}
|
||||
|
||||
[TestCase(@"/", "/")]
|
||||
[TestCase(@"/test", "test")]
|
||||
[TestCase(@"/test/tv", "tv")]
|
||||
public void path_should_return_directory_name_mono(string path, string parentPath)
|
||||
{
|
||||
path.GetDirectoryName().Should().Be(parentPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void path_should_return_parent_for_oversized_path()
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Common.Disk
|
||||
@ -9,6 +10,8 @@ namespace NzbDrone.Common.Disk
|
||||
private readonly string _path;
|
||||
private readonly OsPathKind _kind;
|
||||
|
||||
private static readonly Regex UncPathRegex = new Regex(@"(?<unc>^\\\\(?:\?\\UNC\\)?[^\\]+\\[^\\]+)(?:\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public OsPath(string path)
|
||||
{
|
||||
if (path == null)
|
||||
@ -96,6 +99,19 @@ namespace NzbDrone.Common.Disk
|
||||
return path;
|
||||
}
|
||||
|
||||
private static string TrimTrailingSlash(string path, OsPathKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case OsPathKind.Windows when !path.EndsWith(":\\"):
|
||||
return path.TrimEnd('\\');
|
||||
case OsPathKind.Unix when path != "/":
|
||||
return path.TrimEnd('/');
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public OsPathKind Kind => _kind;
|
||||
|
||||
public bool IsWindowsPath => _kind == OsPathKind.Windows;
|
||||
@ -130,7 +146,19 @@ namespace NzbDrone.Common.Disk
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
return new OsPath(null);
|
||||
return Null;
|
||||
}
|
||||
|
||||
var rootLength = GetRootLength();
|
||||
|
||||
if (rootLength == _path.Length)
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
if (rootLength > index + 1)
|
||||
{
|
||||
return new OsPath(_path.Substring(0, rootLength));
|
||||
}
|
||||
|
||||
return new OsPath(_path.Substring(0, index), _kind).AsDirectory();
|
||||
@ -139,6 +167,8 @@ namespace NzbDrone.Common.Disk
|
||||
|
||||
public string FullPath => _path;
|
||||
|
||||
public string PathWithoutTrailingSlash => TrimTrailingSlash(_path, _kind);
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
@ -161,6 +191,30 @@ namespace NzbDrone.Common.Disk
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
// Meant to behave similar to DirectoryInfo.Name
|
||||
|
||||
get
|
||||
{
|
||||
var index = GetFileNameIndex();
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
return PathWithoutTrailingSlash;
|
||||
}
|
||||
|
||||
var rootLength = GetRootLength();
|
||||
|
||||
if (rootLength > index + 1)
|
||||
{
|
||||
return _path.Substring(0, rootLength);
|
||||
}
|
||||
|
||||
return TrimTrailingSlash(_path.Substring(index).TrimStart('/', '\\'), _kind);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid => _path.IsPathValid(PathValidationType.CurrentOs);
|
||||
|
||||
private int GetFileNameIndex()
|
||||
@ -190,11 +244,50 @@ namespace NzbDrone.Common.Disk
|
||||
return index;
|
||||
}
|
||||
|
||||
private int GetRootLength()
|
||||
{
|
||||
if (!IsRooted)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_kind == OsPathKind.Unix)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (_kind == OsPathKind.Windows)
|
||||
{
|
||||
if (HasWindowsDriveLetter(_path))
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
var uncMatch = UncPathRegex.Match(_path);
|
||||
|
||||
// \\?\UNC\server\share\ or \\server\share
|
||||
if (uncMatch.Success)
|
||||
{
|
||||
return uncMatch.Groups["unc"].Length;
|
||||
}
|
||||
|
||||
// \\?\C:\
|
||||
if (_path.StartsWith(@"\\?\"))
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private string[] GetFragments()
|
||||
{
|
||||
return _path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public static OsPath Null => new (null);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _path;
|
||||
@ -267,6 +360,11 @@ namespace NzbDrone.Common.Disk
|
||||
}
|
||||
|
||||
public bool Equals(OsPath other)
|
||||
{
|
||||
return Equals(other, false);
|
||||
}
|
||||
|
||||
public bool Equals(OsPath other, bool ignoreTrailingSlash)
|
||||
{
|
||||
if (ReferenceEquals(other, null))
|
||||
{
|
||||
@ -278,8 +376,8 @@ namespace NzbDrone.Common.Disk
|
||||
return true;
|
||||
}
|
||||
|
||||
var left = _path;
|
||||
var right = other._path;
|
||||
var left = ignoreTrailingSlash ? PathWithoutTrailingSlash : _path;
|
||||
var right = ignoreTrailingSlash ? other.PathWithoutTrailingSlash : other._path;
|
||||
|
||||
if (Kind == OsPathKind.Windows || other.Kind == OsPathKind.Windows)
|
||||
{
|
||||
|
@ -92,26 +92,23 @@ namespace NzbDrone.Common.Extensions
|
||||
|
||||
public static string GetParentPath(this string childPath)
|
||||
{
|
||||
var cleanPath = childPath.GetCleanPath();
|
||||
var path = new OsPath(childPath).Directory;
|
||||
|
||||
if (cleanPath.IsNullOrWhiteSpace())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Directory.GetParent(cleanPath)?.FullName;
|
||||
return path == OsPath.Null ? null : path.PathWithoutTrailingSlash;
|
||||
}
|
||||
|
||||
public static string GetParentName(this string childPath)
|
||||
{
|
||||
var cleanPath = childPath.GetCleanPath();
|
||||
var path = new OsPath(childPath).Directory;
|
||||
|
||||
if (cleanPath.IsNullOrWhiteSpace())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return path == OsPath.Null ? null : path.Name;
|
||||
}
|
||||
|
||||
return Directory.GetParent(cleanPath)?.Name;
|
||||
public static string GetDirectoryName(this string childPath)
|
||||
{
|
||||
var path = new OsPath(childPath);
|
||||
|
||||
return path == OsPath.Null ? null : path.Name;
|
||||
}
|
||||
|
||||
public static string GetCleanPath(this string path)
|
||||
@ -125,27 +122,17 @@ namespace NzbDrone.Common.Extensions
|
||||
|
||||
public static bool IsParentPath(this string parentPath, string childPath)
|
||||
{
|
||||
if (parentPath != "/" && !parentPath.EndsWith(":\\"))
|
||||
{
|
||||
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
}
|
||||
var parent = new OsPath(parentPath);
|
||||
var child = new OsPath(childPath);
|
||||
|
||||
if (childPath != "/" && !parentPath.EndsWith(":\\"))
|
||||
while (child.Directory != OsPath.Null)
|
||||
{
|
||||
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
var parent = new DirectoryInfo(parentPath);
|
||||
var child = new DirectoryInfo(childPath);
|
||||
|
||||
while (child.Parent != null)
|
||||
{
|
||||
if (child.Parent.FullName.Equals(parent.FullName, DiskProviderBase.PathStringComparison))
|
||||
if (child.Directory.Equals(parent, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
child = child.Parent;
|
||||
child = child.Directory;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
@ -15,11 +16,13 @@ namespace NzbDrone.Core.Tv
|
||||
{
|
||||
private readonly IBuildFileNames _fileNameBuilder;
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SeriesPathBuilder(IBuildFileNames fileNameBuilder, IRootFolderService rootFolderService)
|
||||
public SeriesPathBuilder(IBuildFileNames fileNameBuilder, IRootFolderService rootFolderService, Logger logger)
|
||||
{
|
||||
_fileNameBuilder = fileNameBuilder;
|
||||
_rootFolderService = rootFolderService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string BuildPath(Series series, bool useExistingRelativeFolder)
|
||||
@ -42,7 +45,16 @@ namespace NzbDrone.Core.Tv
|
||||
{
|
||||
var rootFolderPath = _rootFolderService.GetBestRootFolderPath(series.Path);
|
||||
|
||||
return rootFolderPath.GetRelativePath(series.Path);
|
||||
if (rootFolderPath.IsParentPath(series.Path))
|
||||
{
|
||||
return rootFolderPath.GetRelativePath(series.Path);
|
||||
}
|
||||
|
||||
var directoryName = series.Path.GetDirectoryName();
|
||||
|
||||
_logger.Warn("Unable to get relative path for series path {0}, using series folder name {1}", series.Path, directoryName);
|
||||
|
||||
return directoryName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user