diff --git a/src/System/IO/SystemFile.cs b/src/System/IO/SystemFile.cs
index 124bbf7..6f754b4 100644
--- a/src/System/IO/SystemFile.cs
+++ b/src/System/IO/SystemFile.cs
@@ -29,7 +29,6 @@ public SystemFile(string path)
if (!File.Exists(path))
throw new FileNotFoundException($"File not found at path {path}.");
- Id = path;
Path = path;
}
@@ -45,12 +44,48 @@ public SystemFile(FileInfo info)
_info = info;
_name = _info.Name;
- Id = _info.FullName;
+ Path = _info.FullName;
+ }
+
+ ///
+ /// Creates a new instance of
+ ///
+ ///
+ /// NOTE: This constructor does not verify whether the file
+ /// actually exists beforehand. Do not use outside of enumeration
+ /// or when it's known that the file exists.
+ ///
+ /// The path to the file.
+ ///
+ /// A required value for this overload. No functional difference between provided values.
+ ///
+ internal SystemFile(string path, bool noValidation)
+ {
+ Path = path;
+ }
+
+ ///
+ /// Creates a new instance of
+ ///
+ ///
+ /// NOTE: This constructor does not verify whether the file
+ /// actually exists beforehand. Do not use outside of enumeration
+ /// or when it's known that the file exists.
+ ///
+ /// The file info.
+ ///
+ /// A required value for this overload. No functional difference between provided values.
+ ///
+ internal SystemFile(FileInfo info, bool noValidation)
+ {
+ _info = info;
+
+ _name = _info.Name;
Path = _info.FullName;
}
///
- public string Id { get; }
+ public string Id => Path;
///
public string Name => _name ??= global::System.IO.Path.GetFileName(Path);
@@ -78,13 +113,13 @@ public Task OpenStreamAsync(FileAccess accessMode = FileAccess.Read, Can
public Task GetParentAsync(CancellationToken cancellationToken = default)
{
DirectoryInfo? parent = _info != null ? _info.Directory : Directory.GetParent(Path);
- return Task.FromResult(parent != null ? new SystemFolder(parent) : null);
+ return Task.FromResult(parent != null ? new SystemFolder(parent, noValidation: true) : null);
}
///
public Task GetRootAsync(CancellationToken cancellationToken = default)
{
DirectoryInfo root = _info?.Directory != null ? _info.Directory.Root : new DirectoryInfo(Path).Root;
- return Task.FromResult(new SystemFolder(root));
+ return Task.FromResult(new SystemFolder(root, noValidation: true));
}
}
diff --git a/src/System/IO/SystemFolder.cs b/src/System/IO/SystemFolder.cs
index 083bb19..41a2b2a 100644
--- a/src/System/IO/SystemFolder.cs
+++ b/src/System/IO/SystemFolder.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -15,6 +15,7 @@ namespace OwlCore.Storage.System.IO;
///
public class SystemFolder : IModifiableFolder, IChildFolder, ICreateCopyOf, IMoveFrom, IGetItem, IGetItemRecursive, IGetFirstByName, IGetRoot
{
+ private string? _name;
private DirectoryInfo? _info;
///
@@ -29,14 +30,11 @@ public SystemFolder(string path)
throw new FormatException($"Provided path contains invalid character '{c}'.");
}
- // For consistency, always remove the trailing directory separator.
- Path = path.TrimEnd(global::System.IO.Path.PathSeparator, global::System.IO.Path.DirectorySeparatorChar, global::System.IO.Path.AltDirectorySeparatorChar);
-
if (!Directory.Exists(path))
throw new FileNotFoundException($"Directory not found at path '{Path}'.");
- Id = Path;
- Name = global::System.IO.Path.GetFileName(Path) ?? throw new ArgumentException($"Could not determine directory name from path '{Path}'.");
+ // For consistency, always remove the trailing directory separator.
+ Path = path.TrimEnd(global::System.IO.Path.PathSeparator, global::System.IO.Path.DirectorySeparatorChar, global::System.IO.Path.AltDirectorySeparatorChar);
}
///
@@ -45,16 +43,54 @@ public SystemFolder(string path)
/// The directory to use.
public SystemFolder(DirectoryInfo info)
{
+ if (!info.Exists)
+ throw new FileNotFoundException($"Directory not found at path '{Path}'.");
+
_info = info;
// For consistency, always remove the trailing directory separator.
Path = info.FullName.TrimEnd(global::System.IO.Path.PathSeparator, global::System.IO.Path.DirectorySeparatorChar, global::System.IO.Path.AltDirectorySeparatorChar);
+ _name = info.Name;
+ }
- if (!info.Exists)
- throw new FileNotFoundException($"Directory not found at path '{Path}'.");
+ ///
+ /// Creates a new instance of
+ ///
+ ///
+ /// NOTE: This constructor does not verify whether the directory
+ /// actually exists beforehand. Do not use outside of enumeration
+ /// or when it's known that the folder exists.
+ ///
+ /// The path to the folder.
+ ///
+ /// A required value for this overload. No functional difference between provided values.
+ ///
+ internal SystemFolder(string path, bool noValidation)
+ {
+ // For consistency, always remove the trailing directory separator.
+ Path = path.TrimEnd(global::System.IO.Path.PathSeparator, global::System.IO.Path.DirectorySeparatorChar, global::System.IO.Path.AltDirectorySeparatorChar);
+ }
- Id = Path;
- Name = global::System.IO.Path.GetFileName(Path) ?? throw new ArgumentException($"Could not determine directory name from path '{Path}'.");
+
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ /// NOTE: This constructor does not verify whether the directory
+ /// actually exists beforehand. Do not use outside of enumeration
+ /// or when it's known that the folder exists.
+ ///
+ /// The directory to use.
+ ///
+ /// A required value for this overload. No functional difference between provided values.
+ ///
+ internal SystemFolder(DirectoryInfo info, bool noValidation)
+ {
+ _info = info;
+
+ // For consistency, always remove the trailing directory separator.
+ Path = info.FullName.TrimEnd(global::System.IO.Path.PathSeparator, global::System.IO.Path.DirectorySeparatorChar, global::System.IO.Path.AltDirectorySeparatorChar);
+ _name = info.Name;
}
///
@@ -63,10 +99,10 @@ public SystemFolder(DirectoryInfo info)
public DirectoryInfo Info => _info ??= new DirectoryInfo(Path);
///
- public string Id { get; }
+ public string Id => Path;
///
- public string Name { get; }
+ public string Name => _name ??= global::System.IO.Path.GetFileName(Path) ?? throw new ArgumentException($"Could not determine directory name from path '{Path}'.");
///
/// Gets the path of the folder on disk.
@@ -83,18 +119,17 @@ public async IAsyncEnumerable GetItemsAsync(StorableType type =
if (type.HasFlag(StorableType.All))
{
- foreach (var item in Directory.EnumerateFileSystemEntries(Path))
+ foreach (var item in Info.EnumerateFileSystemInfos())
{
cancellationToken.ThrowIfCancellationRequested();
if (item is null)
continue;
- if (IsFolder(item))
- yield return new SystemFolder(item);
-
- else if (IsFile(item))
- yield return new SystemFile(item);
+ if (item.Attributes.HasFlag(FileAttributes.Directory))
+ yield return new SystemFolder((DirectoryInfo)item, noValidation: true);
+ else
+ yield return new SystemFile((FileInfo)item, noValidation: true);
}
yield break;
@@ -109,7 +144,7 @@ public async IAsyncEnumerable GetItemsAsync(StorableType type =
if (file is null)
continue;
- yield return new SystemFile(file);
+ yield return new SystemFile(file, noValidation: true);
}
}
@@ -122,7 +157,7 @@ public async IAsyncEnumerable GetItemsAsync(StorableType type =
if (folder is null)
continue;
- yield return new SystemFolder(folder);
+ yield return new SystemFolder(folder, noValidation: true);
}
}
}
@@ -135,10 +170,10 @@ public Task GetItemRecursiveAsync(string id, CancellationToken c
// Since the path is used as the id, we can provide a fast method of getting a single item, without iterating.
if (IsFile(id))
- return Task.FromResult(new SystemFile(id));
+ return Task.FromResult(new SystemFile(id, noValidation: true));
if (IsFolder(id))
- return Task.FromResult(new SystemFolder(id));
+ return Task.FromResult(new SystemFolder(id, noValidation: true));
throw new ArgumentException($"Could not determine if the provided path is a file or folder. Path '{id}'.");
}
@@ -159,7 +194,7 @@ public Task GetItemAsync(string id, CancellationToken cancellati
if (!File.Exists(fullPath))
throw new FileNotFoundException($"The provided Id does not belong to an item in this folder.");
- return Task.FromResult(new SystemFile(fullPath));
+ return Task.FromResult(new SystemFile(fullPath, noValidation: true));
}
if (IsFolder(id))
@@ -168,16 +203,16 @@ public Task GetItemAsync(string id, CancellationToken cancellati
if (global::System.IO.Path.GetDirectoryName(id) != Path || !Directory.Exists(id))
throw new FileNotFoundException($"The provided Id does not belong to an item in this folder.");
- return Task.FromResult(new SystemFolder(id));
+ return Task.FromResult(new SystemFolder(id, noValidation: true));
}
throw new FileNotFoundException($"Could not determine if the provided path exists, or whether it's a file or folder. Id '{id}'.");
}
///
- public async Task GetFirstByNameAsync(string name, CancellationToken cancellationToken = default)
+ public Task GetFirstByNameAsync(string name, CancellationToken cancellationToken = default)
{
- return await GetItemAsync(global::System.IO.Path.Combine(Path, name), cancellationToken);
+ return GetItemAsync(global::System.IO.Path.Combine(Path, name), cancellationToken);
}
///
@@ -195,8 +230,7 @@ public Task DeleteAsync(IStorableChild item, CancellationToken cancellationToken
if (IsFolder(item.Id))
Directory.Delete(item.Id, recursive: true);
-
- if (IsFile(item.Id))
+ else if (IsFile(item.Id))
File.Delete(item.Id);
return Task.CompletedTask;
@@ -219,14 +253,14 @@ public async Task CreateCopyOfAsync(IFile fileToCopy, bool overwrite
if (File.Exists(newPath))
{
if (!overwrite)
- return new SystemFile(newPath);
+ return new SystemFile(newPath, noValidation: true);
File.Delete(newPath);
}
File.Copy(systemFile.Path, newPath, overwrite);
- return new SystemFile(newPath);
+ return new SystemFile(newPath, noValidation: true);
}
///
@@ -239,14 +273,14 @@ public async Task MoveFromAsync(IChildFile fileToMove, IModifiableFo
// Handle using System.IO
var newPath = global::System.IO.Path.Combine(Path, systemFile.Name);
if (File.Exists(newPath) && !overwrite)
- return new SystemFile(newPath);
+ return new SystemFile(newPath, noValidation: true);
if (overwrite)
File.Delete(newPath);
File.Move(systemFile.Path, newPath);
- return new SystemFile(newPath);
+ return new SystemFile(newPath, noValidation: true);
}
///
@@ -276,13 +310,13 @@ public Task CreateFileAsync(string name, bool overwrite = false, Can
if (overwrite || !File.Exists(newPath))
File.Create(newPath).Dispose();
- return Task.FromResult(new SystemFile(newPath));
+ return Task.FromResult(new SystemFile(newPath, noValidation: true));
}
///
public Task GetParentAsync(CancellationToken cancellationToken = default)
{
- return Task.FromResult(Directory.GetParent(Path) is { } di ? new SystemFolder(di) : null);
+ return Task.FromResult(Directory.GetParent(Path) is { } di ? new SystemFolder(di, noValidation: true) : null);
}
///
@@ -311,4 +345,4 @@ string GetParentDirectoryName(string relativePath)
return parentPath.Replace(parentParentPath, "").TrimEnd(global::System.IO.Path.DirectorySeparatorChar);
}
-}
\ No newline at end of file
+}
diff --git a/src/System/IO/SystemFolderWatcher.cs b/src/System/IO/SystemFolderWatcher.cs
index 1c4b03e..214a14d 100644
--- a/src/System/IO/SystemFolderWatcher.cs
+++ b/src/System/IO/SystemFolderWatcher.cs
@@ -108,7 +108,7 @@ private static IStorable CreateStorableFromPath(string path, bool minimalImpleme
if (minimalImplementation)
return new SimpleStorableItem(id: path, name: Path.GetDirectoryName(path) ?? throw new ArgumentException($"Could not determine directory name from path '{path}'."));
- return new SystemFolder(path);
+ return new SystemFolder(path, noValidation: true);
}
if (IsFile(path))
@@ -116,7 +116,7 @@ private static IStorable CreateStorableFromPath(string path, bool minimalImpleme
if (minimalImplementation)
return new SimpleStorableItem(id: path, name: Path.GetFileName(path));
- return new SystemFile(path);
+ return new SystemFile(path, noValidation: true);
}
// The item is most likely deleted. Return all available information through SimpleStorableItem