Fix RootDriveInfo not show every drive

This commit is contained in:
2023-09-06 09:29:29 +02:00
parent 0e6c0c5cd5
commit 67484ba56b
9 changed files with 82 additions and 70 deletions

View File

@@ -14,7 +14,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
private readonly ITimelessContentProvider _timelessContentProvider;
private readonly IContentProviderRegistry _contentProviderRegistry;
private readonly bool _isCaseInsensitive;
private readonly Lazy<ObservableCollection<RootDriveInfo>> _rootDriveInfos;
private readonly Lazy<IRootDriveInfoService> _rootDriveInfo;
public LocalContentProvider(
ITimelessContentProvider timelessContentProvider,
@@ -26,7 +26,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
_contentProviderRegistry = contentProviderRegistry;
_isCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
_rootDriveInfos = new Lazy<ObservableCollection<RootDriveInfo>>(() => serviceProvider.GetRequiredService<IRootDriveInfoService>().RootDriveInfos);
_rootDriveInfo = new Lazy<IRootDriveInfoService>(serviceProvider.GetRequiredService<IRootDriveInfoService>);
SupportsContentStreams = true;
@@ -68,12 +68,26 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
public override ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
{
var rootDriveInfos = _rootDriveInfos.Value;
var rootDriveInfo = rootDriveInfos.FirstOrDefault(d => path.Path.StartsWith(d.Path.Path));
var nativePath = GetNativePath(path);
var possibleRootDrives = _rootDriveInfo.Value.AllDrives.Where(d => nativePath.Path.StartsWith(d.RootDirectory.FullName)).ToArray();
var rootDrive = possibleRootDrives.Length == 0
? null
: possibleRootDrives.MaxBy(d => d.RootDirectory.FullName.Length);
return rootDrive is null
? ValueTask.FromResult<VolumeSizeInfo?>(null)
: ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDrive.TotalSize, rootDrive.AvailableFreeSpace));
/*var rootDriveInfos = _rootDriveInfo.Value;
var possibleRootDriveInfo = rootDriveInfos.RootDriveInfos.Where(d => path.Path.StartsWith(d.Path.Path)).ToArray();
var rootDriveInfo = possibleRootDriveInfo.Length == 0
? null
: possibleRootDriveInfo.MaxBy(d => d.FullName.Length);
if (rootDriveInfo is null) return ValueTask.FromResult<VolumeSizeInfo?>(null);
return ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free));
return ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free));*/
}
public override async Task<IItem> GetItemByNativePathAsync(NativePath nativePath,
@@ -103,7 +117,8 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
return FileToElement(new FileInfo(path), pointInTime);
}
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar)).ToArray();
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar))
.ToArray();
for (var i = pathParts.Length - 1; i > 0; i--)
{
@@ -116,7 +131,8 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
var subPath = string.Join(Constants.SeparatorChar, pathParts.Skip(i));
var resolvedItem = await subContentProvider.GetItemByFullNameAsync(element, new FullName(subPath), pointInTime, forceResolvePathType, itemInitializationSettings);
var resolvedItem = await subContentProvider.GetItemByFullNameAsync(element, new FullName(subPath),
pointInTime, forceResolvePathType, itemInitializationSettings);
if (resolvedItem is not null)
{
@@ -155,7 +171,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
AbsolutePathType.Container => CreateEmptyContainer(
nativePath,
pointInTime,
new List<Exception> {innerException}
new List<Exception> { innerException }
),
AbsolutePathType.Element => CreateEmptyElement(nativePath),
_ => throw new Exception(
@@ -167,8 +183,9 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath)
{
var path = nativePath.Path;
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar)).ToArray();
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar))
.ToArray();
for (var i = pathParts.Length - 1; i > 0; i--)
{
var possiblePath = string.Join(Path.DirectorySeparatorChar, pathParts.Take(i));
@@ -440,7 +457,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
var finalSize = size switch
{
> int.MaxValue => int.MaxValue,
_ => (int) size
_ => (int)size
};
var buffer = new byte[finalSize];
var realSize = await reader.ReadAsync(buffer.AsMemory(0, finalSize), cancellationToken);

View File

@@ -1,6 +1,7 @@
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using ObservableComputations;
namespace FileTime.Providers.Local;
@@ -8,66 +9,65 @@ namespace FileTime.Providers.Local;
public class RootDriveInfoService : IRootDriveInfoService
{
private readonly ILocalContentProvider _localContentProvider;
private readonly List<DriveInfo> _rootDrives = new();
private readonly ObservableCollection<DriveInfo> _rootDrives = new();
private readonly ObservableCollection<DriveInfo> _allDrives = new();
private readonly OcConsumer _rootDriveInfosConsumer = new();
public ObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
public ReadOnlyObservableCollection<DriveInfo> AllDrives { get; set; }
public ReadOnlyObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
public RootDriveInfoService(ILocalContentProvider localContentProvider)
{
_localContentProvider = localContentProvider;
InitRootDrives();
var (rootDrives, allDrives) = GetRootDrives();
var rootDriveInfos = localContentProvider.Items.Selecting<AbsolutePath, (AbsolutePath Path, DriveInfo? Drive)>(
i => MatchRootDrive(i)
)
.Filtering(t => IsNotNull(t.Drive))
.Selecting(t => Resolve(t))
.Filtering(t => t.Item is IContainer)
.Selecting(t => new RootDriveInfo(t.Drive, (IContainer) t.Item!))
.Ordering(d => d.Name);
rootDriveInfos.For(_rootDriveInfosConsumer);
RootDriveInfos = rootDriveInfos;
void InitRootDrives()
foreach (var driveInfo in rootDrives)
{
var drives = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.Fixed)
: DriveInfo.GetDrives().Where(d =>
d.DriveType == DriveType.Fixed
_rootDrives.Add(driveInfo);
}
foreach (var driveInfo in allDrives)
{
_allDrives.Add(driveInfo);
}
var rootDriveInfos = _rootDrives.Selecting(r => GetContainer(r))
.Filtering(t => t.Item != null)
.Selecting(t => new RootDriveInfo(t.Drive, t.Item!))
.Ordering(d => d.Name)
.For(_rootDriveInfosConsumer);
RootDriveInfos = new ReadOnlyObservableCollection<RootDriveInfo>(rootDriveInfos);
AllDrives = new ReadOnlyObservableCollection<DriveInfo>(_allDrives);
(DriveInfo[] RootDrives, DriveInfo[] AllDrives) GetRootDrives()
{
var allDrives = DriveInfo.GetDrives();
var drives = DriveInfo.GetDrives().Where(d => d.DriveType is not DriveType.Unknown and not DriveType.Ram);
drives = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? drives
: drives.Where(d =>
d.TotalSize != 0
&& d.DriveFormat != "pstorefs"
&& d.DriveFormat != "bpf_fs"
&& d.DriveFormat != "tracefs"
&& d.DriveFormat != "rpc_pipefs"
&& !d.RootDirectory.FullName.StartsWith("/snap/"));
_rootDrives.Clear();
_rootDrives.AddRange(drives);
return (drives.ToArray(), allDrives);
}
}
private static bool IsNotNull(object? obj) => obj is not null;
private static (IItem? Item, DriveInfo Drive) Resolve((AbsolutePath Path, DriveInfo? Drive) tuple)
private (DriveInfo Drive, IContainer? Item) GetContainer(DriveInfo rootDriveInfo)
{
var t = Task.Run(async () => await tuple.Path.ResolveAsyncSafe());
t.Wait();
return (Item: t.Result, Drive: tuple.Drive!);
}
var task = Task.Run(
async () => await _localContentProvider.GetItemByNativePathAsync(
new NativePath(rootDriveInfo.RootDirectory.FullName),
PointInTime.Present)
);
task.Wait();
private (AbsolutePath Path, DriveInfo? Drive) MatchRootDrive(AbsolutePath sourceItem)
{
var rootDrive = _rootDrives.FirstOrDefault(d =>
{
var containerPath = _localContentProvider.GetNativePath(sourceItem.Path).Path;
var drivePath = d.Name.TrimEnd(Path.DirectorySeparatorChar);
return containerPath == drivePath
|| (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && containerPath == "/" &&
d.Name == "/");
});
return (Path: sourceItem, Drive: rootDrive);
return (rootDriveInfo, task.Result as IContainer);
}
public Task ExitAsync(CancellationToken token = default)