StreamCopyCommandHandler, Async rename
This commit is contained in:
9
src/Core/FileTime.Core/Command/CanHandleCommand.cs
Normal file
9
src/Core/FileTime.Core/Command/CanHandleCommand.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace FileTime.Core.Command
|
||||
{
|
||||
public enum CanHandleCommand
|
||||
{
|
||||
CanHandle,
|
||||
Fallback,
|
||||
CanNotHandle
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
using FileTime.Core.Timeline;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FileTime.Core.Command
|
||||
{
|
||||
public class CommandExecutor
|
||||
{
|
||||
private readonly List<ICommandHandler> _commandHandlers;
|
||||
private readonly ILogger<CommandExecutor> _logger;
|
||||
|
||||
public CommandExecutor(IEnumerable<ICommandHandler> commandHandlers)
|
||||
public CommandExecutor(
|
||||
IEnumerable<ICommandHandler> commandHandlers,
|
||||
ILogger<CommandExecutor> logger)
|
||||
{
|
||||
_commandHandlers = commandHandlers.ToList();
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task ExecuteCommandAsync(ICommand command, TimeRunner timeRunner)
|
||||
@@ -19,7 +24,15 @@ namespace FileTime.Core.Command
|
||||
}
|
||||
else
|
||||
{
|
||||
await _commandHandlers.Find(c => c.CanHandle(command))?.ExecuteAsync(command, timeRunner);
|
||||
var commandHandler = _commandHandlers.Find(c => c.CanHandle(command));
|
||||
if (commandHandler != null)
|
||||
{
|
||||
await commandHandler.ExecuteAsync(command, timeRunner);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("No command handler for command {Command}", command.GetType().Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
_copyOperation = (_, to, _, _) =>
|
||||
{
|
||||
var target = to.GetParentAsAbsolutePath().Resolve();
|
||||
var target = to.GetParent().ResolveAsync();
|
||||
newDiffs.Add(new Difference(
|
||||
target is IElement
|
||||
? DifferenceItemType.Element
|
||||
@@ -79,12 +79,12 @@ namespace FileTime.Core.Command
|
||||
var newContainerDiff = new Difference(
|
||||
DifferenceItemType.Container,
|
||||
DifferenceActionType.Create,
|
||||
AbsolutePath.FromParentAndChildName(target, name)
|
||||
AbsolutePath.FromParentAndChildName(target, name, AbsolutePathType.Container)
|
||||
);
|
||||
|
||||
newDiffs.Add(newContainerDiff);
|
||||
|
||||
return (IContainer)(await newContainerDiff.AbsolutePath.Resolve())!;
|
||||
return (IContainer)(await newContainerDiff.AbsolutePath.ResolveAsync())!;
|
||||
};
|
||||
|
||||
await TraverseTree(Sources, Target, TransportMode.Value);
|
||||
@@ -110,7 +110,7 @@ namespace FileTime.Core.Command
|
||||
await UpdateProgress();
|
||||
};
|
||||
|
||||
_createContainer = async (IContainer target, string name) => await target.CreateContainer(name);
|
||||
_createContainer = async (IContainer target, string name) => await target.CreateContainerAsync(name);
|
||||
_containerCopyDone = async (path) =>
|
||||
{
|
||||
foreach (var item in _operationStatuses[path])
|
||||
@@ -137,7 +137,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
_copyOperation = async (from, to, _, _) =>
|
||||
{
|
||||
var parentPath = to.GetParentAsAbsolutePath();
|
||||
var parentPath = to.GetParent();
|
||||
List<OperationProgress> operationsByFolder;
|
||||
if (operationStatuses.ContainsKey(parentPath))
|
||||
{
|
||||
@@ -145,7 +145,7 @@ namespace FileTime.Core.Command
|
||||
}
|
||||
else
|
||||
{
|
||||
var resolvedFrom = await from.Resolve();
|
||||
var resolvedFrom = await from.ResolveAsync();
|
||||
operationsByFolder = new List<OperationProgress>();
|
||||
operationStatuses.Add(parentPath, operationsByFolder);
|
||||
operationsByFolder.Add(new OperationProgress(from.Path, resolvedFrom is IElement element ? await element.GetElementSize() : 0L));
|
||||
@@ -166,7 +166,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
foreach (var source in sources)
|
||||
{
|
||||
var item = await source.Resolve();
|
||||
var item = await source.ResolveAsync();
|
||||
|
||||
if (item is IContainer container)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ namespace FileTime.Core.Command
|
||||
{
|
||||
var targetName = element.Name;
|
||||
|
||||
var targetNameExists = await target.IsExists(targetName);
|
||||
var targetNameExists = await target.IsExistsAsync(targetName);
|
||||
if (transportMode == Command.TransportMode.Merge)
|
||||
{
|
||||
for (var i = 0; targetNameExists; i++)
|
||||
@@ -197,7 +197,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
OperationProgress? operation = null;
|
||||
var targetFolderPath = new AbsolutePath(target);
|
||||
var targetElementPath = AbsolutePath.FromParentAndChildName(target, targetName);
|
||||
var targetElementPath = AbsolutePath.FromParentAndChildName(target, targetName, AbsolutePathType.Element);
|
||||
|
||||
foreach(var asd in _operationStatuses.Keys)
|
||||
{
|
||||
|
||||
@@ -26,10 +26,10 @@ namespace FileTime.Core.Command
|
||||
|
||||
public async Task Execute(TimeRunner timeRunner)
|
||||
{
|
||||
var possibleContainer = await Container.Resolve();
|
||||
var possibleContainer = await Container.ResolveAsync();
|
||||
if (possibleContainer is IContainer container)
|
||||
{
|
||||
await container.CreateContainer(NewContainerName);
|
||||
await container.CreateContainerAsync(NewContainerName);
|
||||
await timeRunner.RefreshContainer.InvokeAsync(this, new AbsolutePath(container));
|
||||
}
|
||||
//TODO: else
|
||||
@@ -39,18 +39,18 @@ namespace FileTime.Core.Command
|
||||
{
|
||||
var newDifferences = new List<Difference>()
|
||||
{
|
||||
new Difference(DifferenceItemType.Container, DifferenceActionType.Create, new AbsolutePath(Container.ContentProvider, Container.Path + Constants.SeparatorChar + NewContainerName, Container.VirtualContentProvider))
|
||||
new Difference(DifferenceItemType.Container, DifferenceActionType.Create, Container.GetChild(NewContainerName, AbsolutePathType.Container))
|
||||
};
|
||||
return Task.FromResult(startPoint.WithDifferences(newDifferences));
|
||||
}
|
||||
|
||||
public async Task<CanCommandRun> CanRun(PointInTime startPoint)
|
||||
{
|
||||
var resolvedContainer = await Container.Resolve();
|
||||
var resolvedContainer = await Container.ResolveAsync();
|
||||
if (resolvedContainer == null) return CanCommandRun.Forceable;
|
||||
|
||||
if (resolvedContainer is not IContainer container
|
||||
|| await container.IsExists(NewContainerName))
|
||||
|| await container.IsExistsAsync(NewContainerName))
|
||||
{
|
||||
return CanCommandRun.False;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ namespace FileTime.Core.Command
|
||||
|
||||
public async Task Execute(TimeRunner timeRunner)
|
||||
{
|
||||
var possibleContainer = await Container.Resolve();
|
||||
var possibleContainer = await Container.ResolveAsync();
|
||||
if (possibleContainer is IContainer container)
|
||||
{
|
||||
await container.CreateElement(NewElementName);
|
||||
await container.CreateElementAsync(NewElementName);
|
||||
await timeRunner.RefreshContainer.InvokeAsync(this, new AbsolutePath(container));
|
||||
}
|
||||
}
|
||||
@@ -36,18 +36,18 @@ namespace FileTime.Core.Command
|
||||
{
|
||||
var newDifferences = new List<Difference>()
|
||||
{
|
||||
new Difference(DifferenceItemType.Element, DifferenceActionType.Create, new AbsolutePath(Container.ContentProvider, Container.Path + Constants.SeparatorChar + NewElementName, Container.VirtualContentProvider))
|
||||
new Difference(DifferenceItemType.Element, DifferenceActionType.Create, Container.GetChild(NewElementName, AbsolutePathType.Element))
|
||||
};
|
||||
return Task.FromResult(startPoint.WithDifferences(newDifferences));
|
||||
}
|
||||
|
||||
public async Task<CanCommandRun> CanRun(PointInTime startPoint)
|
||||
{
|
||||
var resolvedContainer = Container.Resolve();
|
||||
var resolvedContainer = Container.ResolveAsync();
|
||||
if (resolvedContainer == null) return CanCommandRun.Forceable;
|
||||
|
||||
if (resolvedContainer is not IContainer container
|
||||
|| await container.IsExists(NewElementName))
|
||||
|| await container.IsExistsAsync(NewElementName))
|
||||
{
|
||||
return CanCommandRun.False;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
foreach (var item in ItemsToDelete)
|
||||
{
|
||||
await TraverseTree((await item.Resolve())!);
|
||||
await TraverseTree((await item.ResolveAsync())!);
|
||||
}
|
||||
|
||||
return startPoint.WithDifferences(newDifferences);
|
||||
@@ -64,7 +64,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
foreach (var item in ItemsToDelete)
|
||||
{
|
||||
await TraverseTree((await item.Resolve())!);
|
||||
await TraverseTree((await item.ResolveAsync())!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace FileTime.Core.Command
|
||||
var result = CanCommandRun.True;
|
||||
foreach (var itemPath in ItemsToDelete)
|
||||
{
|
||||
var resolvedItem = await itemPath.Resolve();
|
||||
var resolvedItem = await itemPath.ResolveAsync();
|
||||
if (resolvedItem != null
|
||||
&& (
|
||||
resolvedItem.CanDelete == SupportsDelete.False
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
public async Task Execute(TimeRunner timeRunner)
|
||||
{
|
||||
var itemToRename = await Source.Resolve();
|
||||
var itemToRename = await Source.ResolveAsync();
|
||||
if (itemToRename != null)
|
||||
{
|
||||
await itemToRename.Rename(Target);
|
||||
@@ -34,7 +34,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
public async Task<PointInTime> SimulateCommand(PointInTime startPoint)
|
||||
{
|
||||
var item = await Source.Resolve();
|
||||
var item = await Source.ResolveAsync();
|
||||
if (item == null) throw new FileNotFoundException();
|
||||
var newDifferences = new List<Difference>()
|
||||
{
|
||||
@@ -50,7 +50,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
public Task<CanCommandRun> CanRun(PointInTime startPoint)
|
||||
{
|
||||
return Task.FromResult(Source.Resolve() != null ? CanCommandRun.True : CanCommandRun.False);
|
||||
return Task.FromResult(Source.ResolveAsync() != null ? CanCommandRun.True : CanCommandRun.False);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using FileTime.Core.Command;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
namespace FileTime.Core.CommandHandlers
|
||||
{
|
||||
public class StreamCopyCommandHandler : ICommandHandler
|
||||
{
|
||||
public bool CanHandle(object command)
|
||||
{
|
||||
if (command is not CopyCommand copyCommand) return false;
|
||||
|
||||
return (copyCommand.Target?.Provider.SupportsContentStreams ?? false)
|
||||
&& copyCommand.Sources.All(p => p.ContentProvider.SupportsContentStreams);
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(object command, TimeRunner timeRunner)
|
||||
{
|
||||
if (command is not CopyCommand copyCommand) throw new ArgumentException($"Can not execute command of type '{command.GetType()}'.");
|
||||
|
||||
await copyCommand.Execute(CopyElement, timeRunner);
|
||||
}
|
||||
|
||||
public static async Task CopyElement(AbsolutePath sourcePath, AbsolutePath targetPath, OperationProgress? operationProgress, CopyCommandContext copyCommandContext)
|
||||
{
|
||||
var parent = (IContainer?)(await targetPath.GetParent().ResolveAsync())!;
|
||||
var elementName = targetPath.GetName();
|
||||
if (!await parent.IsExistsAsync(elementName))
|
||||
{
|
||||
await parent.CreateElementAsync(elementName);
|
||||
}
|
||||
|
||||
var source = (IElement?)(await sourcePath.ResolveAsync())!;
|
||||
var target = (IElement?)(await targetPath.ResolveAsync())!;
|
||||
|
||||
using var reader = await source.GetContentReaderAsync();
|
||||
using var writer = await target.GetContentWriterAsync();
|
||||
|
||||
byte[] dataRead;
|
||||
|
||||
do
|
||||
{
|
||||
dataRead = await reader.ReadBytesAsync(writer.PreferredBufferSize);
|
||||
await writer.WriteBytesAsync(dataRead);
|
||||
await writer.FlushAsync();
|
||||
if (operationProgress != null) operationProgress.Progress += dataRead.LongLength;
|
||||
await copyCommandContext.UpdateProgress();
|
||||
}
|
||||
while (dataRead.Length > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,19 +9,22 @@ namespace FileTime.Core.Models
|
||||
public IContentProvider? VirtualContentProvider { get; }
|
||||
|
||||
public string Path { get; }
|
||||
public AbsolutePathType Type { get; }
|
||||
|
||||
public AbsolutePath(AbsolutePath from)
|
||||
{
|
||||
ContentProvider = from.ContentProvider;
|
||||
Path = from.Path;
|
||||
VirtualContentProvider = from.VirtualContentProvider;
|
||||
Type = from.Type;
|
||||
}
|
||||
|
||||
public AbsolutePath(IContentProvider contentProvider, string path, IContentProvider? virtualContentProvider)
|
||||
public AbsolutePath(IContentProvider contentProvider, string path, AbsolutePathType type, IContentProvider? virtualContentProvider)
|
||||
{
|
||||
ContentProvider = contentProvider;
|
||||
Path = path;
|
||||
VirtualContentProvider = virtualContentProvider;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public AbsolutePath(IItem item)
|
||||
@@ -43,33 +46,39 @@ namespace FileTime.Core.Models
|
||||
ContentProvider = item.Provider;
|
||||
Path = item.FullName!;
|
||||
}
|
||||
|
||||
Type = item switch
|
||||
{
|
||||
IContainer => AbsolutePathType.Container,
|
||||
IElement => AbsolutePathType.Element,
|
||||
_ => AbsolutePathType.Unknown
|
||||
};
|
||||
}
|
||||
|
||||
public static AbsolutePath FromParentAndChildName(IContainer parent, string childName)
|
||||
public static AbsolutePath FromParentAndChildName(IContainer parent, string childName, AbsolutePathType childType)
|
||||
{
|
||||
IContentProvider? contentProvider;
|
||||
IContentProvider? virtualContentProvider;
|
||||
string? path;
|
||||
var contentProvider = parent.Provider;
|
||||
var path = parent.FullName! + Constants.SeparatorChar + childName;
|
||||
|
||||
if (parent is TimeContainer timeContainer)
|
||||
var virtualContentProvider = parent switch
|
||||
{
|
||||
contentProvider = timeContainer.Provider;
|
||||
virtualContentProvider = timeContainer.VirtualProvider;
|
||||
path = timeContainer.FullName! + Constants.SeparatorChar + childName;
|
||||
}
|
||||
else
|
||||
{
|
||||
contentProvider = parent.Provider;
|
||||
path = parent.FullName! + Constants.SeparatorChar + childName;
|
||||
virtualContentProvider = null;
|
||||
}
|
||||
TimeContainer timeContainer => timeContainer.VirtualProvider,
|
||||
_ => null
|
||||
};
|
||||
|
||||
return new AbsolutePath(contentProvider, path, virtualContentProvider);
|
||||
return new AbsolutePath(contentProvider, path, childType, virtualContentProvider);
|
||||
}
|
||||
|
||||
public async Task<IItem?> Resolve()
|
||||
public AbsolutePath GetChild(string childName, AbsolutePathType childType)
|
||||
{
|
||||
var result = VirtualContentProvider != null && (await VirtualContentProvider.IsExists(Path))
|
||||
var path = Path + Constants.SeparatorChar + childName;
|
||||
|
||||
return new AbsolutePath(ContentProvider, path, childType, VirtualContentProvider);
|
||||
}
|
||||
|
||||
public async Task<IItem?> ResolveAsync()
|
||||
{
|
||||
var result = VirtualContentProvider != null && (await VirtualContentProvider.IsExistsAsync(Path))
|
||||
? await VirtualContentProvider.GetByPath(Path)
|
||||
: null;
|
||||
|
||||
@@ -78,13 +87,13 @@ namespace FileTime.Core.Models
|
||||
return result;
|
||||
}
|
||||
|
||||
public string GetParent()
|
||||
public string GetParentPath()
|
||||
{
|
||||
var pathParts = Path.Split(Constants.SeparatorChar);
|
||||
return string.Join(Constants.SeparatorChar, pathParts[..^1]);
|
||||
}
|
||||
|
||||
public AbsolutePath GetParentAsAbsolutePath() => new(ContentProvider, GetParent(), VirtualContentProvider);
|
||||
public AbsolutePath GetParent() => new(ContentProvider, GetParentPath(), AbsolutePathType.Container, VirtualContentProvider);
|
||||
|
||||
public string GetName() => Path.Split(Constants.SeparatorChar).Last();
|
||||
|
||||
|
||||
9
src/Core/FileTime.Core/Models/AbsolutePathType.cs
Normal file
9
src/Core/FileTime.Core/Models/AbsolutePathType.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace FileTime.Core.Models
|
||||
{
|
||||
public enum AbsolutePathType
|
||||
{
|
||||
Unknown,
|
||||
Container,
|
||||
Element
|
||||
}
|
||||
}
|
||||
@@ -30,13 +30,13 @@ namespace FileTime.Core.Models
|
||||
return null;
|
||||
}
|
||||
|
||||
Task<IContainer> CreateContainer(string name);
|
||||
Task<IElement> CreateElement(string name);
|
||||
Task<IContainer> CreateContainerAsync(string name);
|
||||
Task<IElement> CreateElementAsync(string name);
|
||||
|
||||
Task<bool> IsExists(string name);
|
||||
Task<bool> IsExistsAsync(string name);
|
||||
|
||||
Task<IContainer> Clone();
|
||||
Task<bool> CanOpen();
|
||||
Task<IContainer> CloneAsync();
|
||||
Task<bool> CanOpenAsync();
|
||||
void Unload();
|
||||
|
||||
bool IsLoaded { get; }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using FileTime.Core.Providers;
|
||||
|
||||
namespace FileTime.Core.Models
|
||||
{
|
||||
public interface IElement : IItem
|
||||
@@ -6,5 +8,8 @@ namespace FileTime.Core.Models
|
||||
string GetPrimaryAttributeText();
|
||||
Task<string> GetContent(CancellationToken token = default);
|
||||
Task<long> GetElementSize(CancellationToken token = default);
|
||||
|
||||
Task<IContentReader> GetContentReaderAsync();
|
||||
Task<IContentWriter> GetContentWriterAsync();
|
||||
}
|
||||
}
|
||||
@@ -139,9 +139,9 @@ namespace FileTime.Core.Models
|
||||
: baseContainer;
|
||||
}
|
||||
|
||||
public async Task<IContainer> CreateContainer(string name) => await BaseContainer.CreateContainer(name);
|
||||
public async Task<IElement> CreateElement(string name) => await BaseContainer.CreateElement(name);
|
||||
public async Task<bool> IsExists(string name) => await BaseContainer.IsExists(name);
|
||||
public async Task<IContainer> CreateContainerAsync(string name) => await BaseContainer.CreateContainerAsync(name);
|
||||
public async Task<IElement> CreateElementAsync(string name) => await BaseContainer.CreateElementAsync(name);
|
||||
public async Task<bool> IsExistsAsync(string name) => await BaseContainer.IsExistsAsync(name);
|
||||
|
||||
public Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
||||
{
|
||||
@@ -157,10 +157,10 @@ namespace FileTime.Core.Models
|
||||
}
|
||||
|
||||
public async Task Delete(bool hardDelete = false) => await BaseContainer.Delete();
|
||||
public async Task<IContainer> Clone()
|
||||
public async Task<IContainer> CloneAsync()
|
||||
{
|
||||
return new VirtualContainer(
|
||||
await BaseContainer.Clone(),
|
||||
await BaseContainer.CloneAsync(),
|
||||
_containerTransformators,
|
||||
_elementTransformators,
|
||||
IsPermanent,
|
||||
@@ -170,7 +170,7 @@ namespace FileTime.Core.Models
|
||||
}
|
||||
|
||||
public async Task Rename(string newName) => await BaseContainer.Rename(newName);
|
||||
public async Task<bool> CanOpen() => await BaseContainer.CanOpen();
|
||||
public async Task<bool> CanOpenAsync() => await BaseContainer.CanOpenAsync();
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace FileTime.Core.Providers
|
||||
{
|
||||
public interface IContentProvider : IContainer
|
||||
{
|
||||
bool SupportsContentStreams { get; }
|
||||
|
||||
Task<IReadOnlyList<IContainer>> GetRootContainers(CancellationToken token = default);
|
||||
|
||||
bool CanHandlePath(string path);
|
||||
|
||||
9
src/Core/FileTime.Core/Providers/IContentReader.cs
Normal file
9
src/Core/FileTime.Core/Providers/IContentReader.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace FileTime.Core.Providers
|
||||
{
|
||||
public interface IContentReader : IDisposable
|
||||
{
|
||||
int PreferredBufferSize { get; }
|
||||
|
||||
Task<byte[]> ReadBytesAsync(int bufferSize);
|
||||
}
|
||||
}
|
||||
10
src/Core/FileTime.Core/Providers/IContentWriter.cs
Normal file
10
src/Core/FileTime.Core/Providers/IContentWriter.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace FileTime.Core.Providers
|
||||
{
|
||||
public interface IContentWriter : IDisposable
|
||||
{
|
||||
int PreferredBufferSize { get; }
|
||||
|
||||
Task WriteBytesAsync(byte[] data);
|
||||
Task FlushAsync();
|
||||
}
|
||||
}
|
||||
@@ -48,9 +48,9 @@ namespace FileTime.Core.Providers
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IContainer> CreateContainer(string name) => throw new NotImplementedException();
|
||||
public Task<IContainer> CreateContainerAsync(string name) => throw new NotImplementedException();
|
||||
|
||||
public Task<IElement> CreateElement(string name) => throw new NotImplementedException();
|
||||
public Task<IElement> CreateElementAsync(string name) => throw new NotImplementedException();
|
||||
|
||||
public Task Delete(bool hardDelete = false) => throw new NotImplementedException();
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace FileTime.Core.Providers
|
||||
|
||||
public IContainer? GetParent() => null;
|
||||
|
||||
public Task<bool> IsExists(string name) => throw new NotImplementedException();
|
||||
public Task<bool> IsExistsAsync(string name) => throw new NotImplementedException();
|
||||
|
||||
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||
|
||||
@@ -66,11 +66,11 @@ namespace FileTime.Core.Providers
|
||||
public Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default) => Task.FromResult(_containers);
|
||||
public Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default) => Task.FromResult(_elements);
|
||||
|
||||
public Task<IContainer> Clone() => Task.FromResult((IContainer)this);
|
||||
public Task<IContainer> CloneAsync() => Task.FromResult((IContainer)this);
|
||||
|
||||
public Task Rename(string newName) => throw new NotSupportedException();
|
||||
|
||||
public Task<bool> CanOpen() => Task.FromResult(true);
|
||||
public Task<bool> CanOpenAsync() => Task.FromResult(true);
|
||||
|
||||
public void Destroy() { }
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace FileTime.Core.Timeline
|
||||
return new Difference(
|
||||
Type,
|
||||
Action,
|
||||
new AbsolutePath(AbsolutePath.ContentProvider, AbsolutePath.Path, virtualContentProvider)
|
||||
new AbsolutePath(AbsolutePath.ContentProvider, AbsolutePath.Path, AbsolutePath.Type, virtualContentProvider)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,11 @@ namespace FileTime.Core.Timeline
|
||||
FullName = parent?.FullName == null ? Name : parent.FullName + Constants.SeparatorChar + Name;
|
||||
}
|
||||
|
||||
public async Task<IContainer> Clone() => new TimeContainer(Name, await _parent!.Clone(), Provider, VirtualProvider, _pointInTime);
|
||||
public async Task<IContainer> CloneAsync() => new TimeContainer(Name, await _parent!.CloneAsync(), Provider, VirtualProvider, _pointInTime);
|
||||
|
||||
public Task<IContainer> CreateContainer(string name) => Task.FromResult((IContainer)new TimeContainer(name, this, Provider, VirtualProvider, _pointInTime));
|
||||
public Task<IContainer> CreateContainerAsync(string name) => Task.FromResult((IContainer)new TimeContainer(name, this, Provider, VirtualProvider, _pointInTime));
|
||||
|
||||
public Task<IElement> CreateElement(string name) => Task.FromResult((IElement)new TimeElement(name, this, Provider, VirtualProvider));
|
||||
public Task<IElement> CreateElementAsync(string name) => Task.FromResult((IElement)new TimeElement(name, this, Provider, VirtualProvider));
|
||||
|
||||
public Task Delete(bool hardDelete = false) => Task.CompletedTask;
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public IContainer? GetParent() => _parent;
|
||||
|
||||
public async Task<bool> IsExists(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
||||
public async Task<bool> IsExistsAsync(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
||||
|
||||
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace FileTime.Core.Timeline
|
||||
if (elementDiff.Type != DifferenceItemType.Container) throw new ArgumentException($"{elementDiff}'s {nameof(Difference.Type)} property is not {DifferenceItemType.Element}.");
|
||||
return new TimeElement(elementDiff.Name, this, Provider, elementDiff.AbsolutePath.VirtualContentProvider ?? elementDiff.AbsolutePath.ContentProvider);
|
||||
}
|
||||
public Task<bool> CanOpen() => Task.FromResult(true);
|
||||
public Task<bool> CanOpenAsync() => Task.FromResult(true);
|
||||
|
||||
public void Destroy() => IsDestroyed = true;
|
||||
public void Unload() { }
|
||||
|
||||
@@ -48,5 +48,9 @@ namespace FileTime.Core.Timeline
|
||||
public Task<long> GetElementSize(CancellationToken token = default) => Task.FromResult(-1L);
|
||||
|
||||
public void Destroy() => IsDestroyed = true;
|
||||
|
||||
public Task<IContentReader> GetContentReaderAsync() => throw new NotSupportedException();
|
||||
|
||||
public Task<IContentWriter> GetContentWriterAsync() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ namespace FileTime.Core.Timeline
|
||||
public bool SupportsDirectoryLevelSoftDelete => false;
|
||||
|
||||
public bool IsDestroyed => false;
|
||||
public bool SupportsContentStreams => false;
|
||||
|
||||
public TimeProvider(PointInTime pointInTime)
|
||||
{
|
||||
@@ -41,14 +42,14 @@ namespace FileTime.Core.Timeline
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IContainer> Clone() => Task.FromResult((IContainer)this);
|
||||
public Task<IContainer> CloneAsync() => Task.FromResult((IContainer)this);
|
||||
|
||||
public Task<IContainer> CreateContainer(string name)
|
||||
public Task<IContainer> CreateContainerAsync(string name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IElement> CreateElement(string name)
|
||||
public Task<IElement> CreateElementAsync(string name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -82,7 +83,7 @@ namespace FileTime.Core.Timeline
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> IsExists(string name)
|
||||
public Task<bool> IsExistsAsync(string name)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -92,10 +93,20 @@ namespace FileTime.Core.Timeline
|
||||
public Task Rename(string newName) => throw new NotSupportedException();
|
||||
|
||||
public void SetParent(IContainer container) { }
|
||||
public Task<bool> CanOpen() => Task.FromResult(true);
|
||||
public Task<bool> CanOpenAsync() => Task.FromResult(true);
|
||||
|
||||
public void Destroy() { }
|
||||
|
||||
public void Unload() { }
|
||||
|
||||
public Task<IContentReader> GetContentReaderAsync(IElement element)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public Task<IContentWriter> GetContentWriterAsync(IElement element)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,10 @@ namespace FileTime.Core.Timeline
|
||||
_commandExecutor.ExecuteCommandAsync(commandToRun.Command, this).Wait();
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Error while running command: {CommandType} ({Command}).", commandToRun?.Command.GetType().Name, commandToRun?.Command.DisplayLabel);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DisposeCommandThread(Thread.CurrentThread, commandToRun).Wait();
|
||||
@@ -151,11 +155,11 @@ namespace FileTime.Core.Timeline
|
||||
{
|
||||
if (command != null)
|
||||
{
|
||||
_logger.LogDebug("Command finished running: {0}", command.Command.DisplayLabel);
|
||||
_logger.LogDebug("Command finished running: {Command}", command.Command.DisplayLabel);
|
||||
_commandsToRun[0].Remove(command);
|
||||
if (_commandsToRun[0].Commands.Count == 0)
|
||||
{
|
||||
_logger.LogDebug("Removing empty command array. {0} batch left.", _commandsToRun.Count - 1);
|
||||
_logger.LogDebug("Removing empty command array. {RemainingBatchNumber} batch left.", _commandsToRun.Count - 1);
|
||||
_commandsToRun.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user