@ -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 )
{