diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml
index 0cfcc93..06231f8 100644
--- a/.github/workflows/Build.yaml
+++ b/.github/workflows/Build.yaml
@@ -28,18 +28,18 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Java
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
- name: Set up .NET
- uses: actions/setup-dotnet@v3
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml
index 2bc0023..8fd76c4 100644
--- a/.github/workflows/Release.yaml
+++ b/.github/workflows/Release.yaml
@@ -18,12 +18,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up .NET
- uses: actions/setup-dotnet@v3
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
diff --git a/FileSystem.Adapters.AmazonS3/FileSystem.Adapters.AmazonS3.csproj b/FileSystem.Adapters.AmazonS3/FileSystem.Adapters.AmazonS3.csproj
index d5056a1..42901eb 100644
--- a/FileSystem.Adapters.AmazonS3/FileSystem.Adapters.AmazonS3.csproj
+++ b/FileSystem.Adapters.AmazonS3/FileSystem.Adapters.AmazonS3.csproj
@@ -13,11 +13,11 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/FileSystem.Adapters.AmazonS3/README.md b/FileSystem.Adapters.AmazonS3/README.md
new file mode 100644
index 0000000..37a8126
--- /dev/null
+++ b/FileSystem.Adapters.AmazonS3/README.md
@@ -0,0 +1,20 @@
+# SharpGrip FileSystem AmazonS3 adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AmazonS3)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.AmazonS3` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AmazonS3).
+
+## Usage
+
+```
+// Amazon connection.
+var amazonClient = new AmazonS3Client("awsAccessKeyId", "awsSecretAccessKey", RegionEndpoint.USEast2);
+
+var adapters = new List
+{
+ new AmazonS3Adapter("amazon1", "/Files", amazonClient, "bucketName1")
+ new AmazonS3Adapter("amazon2", "/Files", amazonClient, "bucketName2")
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.AmazonS3/src/AmazonS3Adapter.cs b/FileSystem.Adapters.AmazonS3/src/AmazonS3Adapter.cs
index 8c18873..4e95be8 100644
--- a/FileSystem.Adapters.AmazonS3/src/AmazonS3Adapter.cs
+++ b/FileSystem.Adapters.AmazonS3/src/AmazonS3Adapter.cs
@@ -31,9 +31,10 @@ public override void Dispose()
client.Dispose();
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
diff --git a/FileSystem.Adapters.AzureBlobStorage/FileSystem.Adapters.AzureBlobStorage.csproj b/FileSystem.Adapters.AzureBlobStorage/FileSystem.Adapters.AzureBlobStorage.csproj
index ca2ba34..ced6707 100644
--- a/FileSystem.Adapters.AzureBlobStorage/FileSystem.Adapters.AzureBlobStorage.csproj
+++ b/FileSystem.Adapters.AzureBlobStorage/FileSystem.Adapters.AzureBlobStorage.csproj
@@ -13,11 +13,11 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/FileSystem.Adapters.AzureBlobStorage/README.md b/FileSystem.Adapters.AzureBlobStorage/README.md
new file mode 100644
index 0000000..c2f3288
--- /dev/null
+++ b/FileSystem.Adapters.AzureBlobStorage/README.md
@@ -0,0 +1,21 @@
+# SharpGrip FileSystem AzureBlobStorage adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureBlobStorage)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.AzureBlobStorage` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureBlobStorage).
+
+## Usage
+
+```
+// Azure connection.
+var blobServiceClient = new BlobServiceClient("connectionString");
+var azureClient = blobServiceClient.GetBlobContainerClient("blobContainerName");
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new AzureBlobStorageAdapter("azure", "/Files", azureClient)
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.AzureBlobStorage/src/AzureBlobStorageAdapter.cs b/FileSystem.Adapters.AzureBlobStorage/src/AzureBlobStorageAdapter.cs
index 43d0dfe..6333eba 100644
--- a/FileSystem.Adapters.AzureBlobStorage/src/AzureBlobStorageAdapter.cs
+++ b/FileSystem.Adapters.AzureBlobStorage/src/AzureBlobStorageAdapter.cs
@@ -28,9 +28,10 @@ public override void Dispose()
{
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
diff --git a/FileSystem.Adapters.AzureFileStorage/FileSystem.Adapters.AzureFileStorage.csproj b/FileSystem.Adapters.AzureFileStorage/FileSystem.Adapters.AzureFileStorage.csproj
index 94c929f..3d374d6 100644
--- a/FileSystem.Adapters.AzureFileStorage/FileSystem.Adapters.AzureFileStorage.csproj
+++ b/FileSystem.Adapters.AzureFileStorage/FileSystem.Adapters.AzureFileStorage.csproj
@@ -13,11 +13,11 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/FileSystem.Adapters.AzureFileStorage/README.md b/FileSystem.Adapters.AzureFileStorage/README.md
new file mode 100644
index 0000000..e8012f0
--- /dev/null
+++ b/FileSystem.Adapters.AzureFileStorage/README.md
@@ -0,0 +1,20 @@
+# SharpGrip FileSystem AzureFileStorage adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureFileStorage)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.AzureFileStorage` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureFileStorage).
+
+## Usage
+
+```
+// Azure connection.
+var azureClient = new ShareClient("connectionString", "shareName");
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new AzureFileStorageAdapter("azure", "/Files", azureClient)
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.AzureFileStorage/src/AzureFileStorageAdapter.cs b/FileSystem.Adapters.AzureFileStorage/src/AzureFileStorageAdapter.cs
index 24a9876..19378dd 100644
--- a/FileSystem.Adapters.AzureFileStorage/src/AzureFileStorageAdapter.cs
+++ b/FileSystem.Adapters.AzureFileStorage/src/AzureFileStorageAdapter.cs
@@ -27,9 +27,10 @@ public override void Dispose()
{
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
diff --git a/FileSystem.Adapters.Dropbox/FileSystem.Adapters.Dropbox.csproj b/FileSystem.Adapters.Dropbox/FileSystem.Adapters.Dropbox.csproj
index cec4561..bb9f54e 100644
--- a/FileSystem.Adapters.Dropbox/FileSystem.Adapters.Dropbox.csproj
+++ b/FileSystem.Adapters.Dropbox/FileSystem.Adapters.Dropbox.csproj
@@ -13,11 +13,11 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/FileSystem.Adapters.Dropbox/README.md b/FileSystem.Adapters.Dropbox/README.md
new file mode 100644
index 0000000..db09f84
--- /dev/null
+++ b/FileSystem.Adapters.Dropbox/README.md
@@ -0,0 +1,20 @@
+# SharpGrip FileSystem Dropbox adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Dropbox)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.Dropbox` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Dropbox).
+
+## Usage
+
+```
+// Dropbox connection.
+var dropboxClient = new DropboxClient("oAuth2AccessToken");
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new DropboxAdapter("dropbox", "/Files", dropboxClient)
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.Dropbox/src/DropboxAdapter.cs b/FileSystem.Adapters.Dropbox/src/DropboxAdapter.cs
index 6ff9106..7f40622 100644
--- a/FileSystem.Adapters.Dropbox/src/DropboxAdapter.cs
+++ b/FileSystem.Adapters.Dropbox/src/DropboxAdapter.cs
@@ -29,9 +29,10 @@ public override void Dispose()
client.Dispose();
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
diff --git a/FileSystem.Adapters.Ftp/FileSystem.Adapters.Ftp.csproj b/FileSystem.Adapters.Ftp/FileSystem.Adapters.Ftp.csproj
new file mode 100644
index 0000000..83ede9d
--- /dev/null
+++ b/FileSystem.Adapters.Ftp/FileSystem.Adapters.Ftp.csproj
@@ -0,0 +1,31 @@
+
+
+
+ SharpGrip.FileSystem.Adapters.Ftp
+
+
+
+ SharpGrip.FileSystem.Adapters.Ftp
+ SharpGrip.FileSystem.Adapters.Ftp
+ SharpGrip FileSystem FTP adapter
+ The SharpGrip FileSystem FTP adapter.
+ sharpgrip;file-system;ftp
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/FileSystem.Adapters.Ftp/README.md b/FileSystem.Adapters.Ftp/README.md
new file mode 100644
index 0000000..b1efb26
--- /dev/null
+++ b/FileSystem.Adapters.Ftp/README.md
@@ -0,0 +1,20 @@
+# SharpGrip FileSystem Ftp adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Ftp)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.Ftp` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Ftp).
+
+## Usage
+
+```
+// FTP connection.
+var ftpClient = new AsyncFtpClient("hostname", "username", "password");
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new FtpAdapter("ftp", "/var/files", ftpClient)
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.Ftp/src/FtpAdapter.cs b/FileSystem.Adapters.Ftp/src/FtpAdapter.cs
new file mode 100644
index 0000000..d95e289
--- /dev/null
+++ b/FileSystem.Adapters.Ftp/src/FtpAdapter.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+using FluentFTP;
+using FluentFTP.Exceptions;
+using SharpGrip.FileSystem.Constants;
+using SharpGrip.FileSystem.Exceptions;
+using SharpGrip.FileSystem.Extensions;
+using SharpGrip.FileSystem.Models;
+using SharpGrip.FileSystem.Utilities;
+using DirectoryNotFoundException = SharpGrip.FileSystem.Exceptions.DirectoryNotFoundException;
+using FileNotFoundException = SharpGrip.FileSystem.Exceptions.FileNotFoundException;
+
+namespace SharpGrip.FileSystem.Adapters.Ftp
+{
+ public class FtpAdapter : Adapter
+ {
+ private readonly IAsyncFtpClient client;
+
+ public FtpAdapter(string prefix, string rootPath, IAsyncFtpClient client, Action? configuration = null) : base(prefix, rootPath, configuration)
+ {
+ this.client = client;
+ }
+
+ public override void Dispose()
+ {
+ client.Dispose();
+ }
+
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
+ {
+ if (client.IsConnected)
+ {
+ return;
+ }
+
+ try
+ {
+ Logger.LogStartConnectingAdapter(this);
+ await client.Connect(cancellationToken);
+ Logger.LogFinishedConnectingAdapter(this);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task GetFileAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ var path = GetPath(virtualPath);
+
+ try
+ {
+ var file = await client.GetObjectInfo(path, token: cancellationToken);
+
+ if (file == null || file.Type != FtpObjectType.File)
+ {
+ throw new FileNotFoundException(path, Prefix);
+ }
+
+ return ModelFactory.CreateFile(file, virtualPath);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ var path = GetPath(virtualPath);
+
+ try
+ {
+ var directory = await client.GetObjectInfo(path, token: cancellationToken);
+
+ if (directory == null || directory.Type != FtpObjectType.Directory)
+ {
+ throw new DirectoryNotFoundException(path, Prefix);
+ }
+
+ return ModelFactory.CreateDirectory(directory, virtualPath);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task> GetFilesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
+ {
+ await GetDirectoryAsync(virtualPath, cancellationToken);
+ var path = GetPath(virtualPath);
+
+ try
+ {
+ var ftpListItems = await client.GetListing(path, cancellationToken);
+
+ return ftpListItems.Where(file => file.Type == FtpObjectType.File).Select(file => ModelFactory.CreateFile(file, GetVirtualPath(file.FullName)));
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task> GetDirectoriesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
+ {
+ await GetDirectoryAsync(virtualPath, cancellationToken);
+ var path = GetPath(virtualPath);
+
+ try
+ {
+ var ftpListItems = await client.GetListing(path, cancellationToken);
+
+ return ftpListItems.Where(file => file.Type == FtpObjectType.Directory).Select(file => ModelFactory.CreateDirectory(file, GetVirtualPath(file.FullName)));
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task CreateDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ if (await DirectoryExistsAsync(virtualPath, cancellationToken))
+ {
+ throw new DirectoryExistsException(GetPath(virtualPath), Prefix);
+ }
+
+ try
+ {
+ await client.CreateDirectory(GetPath(virtualPath), cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task DeleteDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ await GetDirectoryAsync(virtualPath, cancellationToken);
+
+ try
+ {
+ await client.DeleteDirectory(GetPath(virtualPath), cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task DeleteFileAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ await GetFileAsync(virtualPath, cancellationToken);
+
+ try
+ {
+ await client.DeleteFile(GetPath(virtualPath), cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task ReadFileStreamAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ await GetFileAsync(virtualPath, cancellationToken);
+
+ try
+ {
+ var fileStream = await client.OpenRead(GetPath(virtualPath), token: cancellationToken);
+
+ return await StreamUtilities.CopyContentsToMemoryStreamAsync(fileStream, true, cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task WriteFileAsync(string virtualPath, Stream contents, bool overwrite = false, CancellationToken cancellationToken = default)
+ {
+ if (!overwrite && await FileExistsAsync(virtualPath, cancellationToken))
+ {
+ throw new FileExistsException(GetPath(virtualPath), Prefix);
+ }
+
+ try
+ {
+ contents.Seek(0, SeekOrigin.Begin);
+
+ using var writeStream = await client.OpenWrite(GetPath(virtualPath), token: cancellationToken);
+
+ await contents.CopyToAsync(writeStream, FileSystemConstants.Streaming.DefaultMemoryStreamBufferSize, cancellationToken);
+ await writeStream.FlushAsync(cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task AppendFileAsync(string virtualPath, Stream contents, CancellationToken cancellationToken = default)
+ {
+ await GetFileAsync(virtualPath, cancellationToken);
+
+ try
+ {
+ using var fileStream = await client.OpenAppend(GetPath(virtualPath), token: cancellationToken);
+
+ await contents.CopyToAsync(fileStream);
+ }
+ catch (Exception exception)
+ {
+ throw new AdapterRuntimeException(exception);
+ }
+ }
+
+ protected override Exception Exception(Exception exception)
+ {
+ if (exception is FileSystemException)
+ {
+ return exception;
+ }
+
+ if (exception is SocketException socketException)
+ {
+ return new ConnectionException(socketException);
+ }
+
+ if (exception is FtpAuthenticationException ftpAuthenticationException)
+ {
+ return new ConnectionException(ftpAuthenticationException);
+ }
+
+ if (exception is FtpSecurityNotAvailableException ftpSecurityNotAvailableException)
+ {
+ return new ConnectionException(ftpSecurityNotAvailableException);
+ }
+
+ return new AdapterRuntimeException(exception);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FileSystem.Adapters.Ftp/src/FtpAdapterConfiguration.cs b/FileSystem.Adapters.Ftp/src/FtpAdapterConfiguration.cs
new file mode 100644
index 0000000..6d5764c
--- /dev/null
+++ b/FileSystem.Adapters.Ftp/src/FtpAdapterConfiguration.cs
@@ -0,0 +1,8 @@
+using SharpGrip.FileSystem.Configuration;
+
+namespace SharpGrip.FileSystem.Adapters.Ftp
+{
+ public class FtpAdapterConfiguration : AdapterConfiguration
+ {
+ }
+}
\ No newline at end of file
diff --git a/FileSystem.Adapters.Ftp/src/ModelFactory.cs b/FileSystem.Adapters.Ftp/src/ModelFactory.cs
new file mode 100644
index 0000000..7bced46
--- /dev/null
+++ b/FileSystem.Adapters.Ftp/src/ModelFactory.cs
@@ -0,0 +1,33 @@
+using FluentFTP;
+using SharpGrip.FileSystem.Models;
+
+namespace SharpGrip.FileSystem.Adapters.Ftp
+{
+ public static class ModelFactory
+ {
+ public static IFile CreateFile(FtpListItem file, string virtualPath)
+ {
+ return new FileModel
+ {
+ Name = file.Name,
+ Path = file.FullName,
+ VirtualPath = virtualPath,
+ Length = file.Size,
+ LastModifiedDateTime = file.Modified,
+ CreatedDateTime = file.Created
+ };
+ }
+
+ public static DirectoryModel CreateDirectory(FtpListItem directory, string virtualPath)
+ {
+ return new DirectoryModel
+ {
+ Name = directory.Name,
+ Path = directory.FullName,
+ VirtualPath = virtualPath,
+ LastModifiedDateTime = directory.Modified,
+ CreatedDateTime = directory.Created
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleCloudStorage/FileSystem.Adapters.GoogleCloudStorage.csproj b/FileSystem.Adapters.GoogleCloudStorage/FileSystem.Adapters.GoogleCloudStorage.csproj
new file mode 100644
index 0000000..e6bef0d
--- /dev/null
+++ b/FileSystem.Adapters.GoogleCloudStorage/FileSystem.Adapters.GoogleCloudStorage.csproj
@@ -0,0 +1,27 @@
+
+
+
+ SharpGrip.FileSystem.Adapters.GoogleCloudStorage
+
+
+
+ SharpGrip.FileSystem.Adapters.GoogleCloudStorage
+ SharpGrip.FileSystem.Adapters.GoogleCloudStorage
+ SharpGrip FileSystem Google Cloud Storage adapter
+ The SharpGrip FileSystem Google Cloud Storage adapter.
+ sharpgrip;file-system;google-cloud-storage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleCloudStorage/README.md b/FileSystem.Adapters.GoogleCloudStorage/README.md
new file mode 100644
index 0000000..9d6e722
--- /dev/null
+++ b/FileSystem.Adapters.GoogleCloudStorage/README.md
@@ -0,0 +1,21 @@
+# SharpGrip FileSystem GoogleCloudStorage adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleCloudStorage)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.GoogleCloudStorage` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleCloudStorage).
+
+## Usage
+
+```
+// Google connection.
+var credential = GoogleCredential.FromFile("path/to/credential/file");
+var storageClient = await StorageClient.CreateAsync(credential);
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new GoogleCloudStorageAdapter(prefix, rootPath, storageClient, "bucketName", configuration);
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleCloudStorage/src/GoogleCloudStorageAdapter.cs b/FileSystem.Adapters.GoogleCloudStorage/src/GoogleCloudStorageAdapter.cs
new file mode 100644
index 0000000..f8f2d62
--- /dev/null
+++ b/FileSystem.Adapters.GoogleCloudStorage/src/GoogleCloudStorageAdapter.cs
@@ -0,0 +1,321 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+using Google;
+using Google.Cloud.Storage.V1;
+using SharpGrip.FileSystem.Exceptions;
+using SharpGrip.FileSystem.Extensions;
+using SharpGrip.FileSystem.Models;
+using SharpGrip.FileSystem.Utilities;
+using DirectoryNotFoundException = SharpGrip.FileSystem.Exceptions.DirectoryNotFoundException;
+using FileNotFoundException = SharpGrip.FileSystem.Exceptions.FileNotFoundException;
+using Object = Google.Apis.Storage.v1.Data.Object;
+
+namespace SharpGrip.FileSystem.Adapters.GoogleCloudStorage
+{
+ public class GoogleCloudStorageAdapter : Adapter
+ {
+ private readonly StorageClient client;
+ private readonly string bucketName;
+
+ public GoogleCloudStorageAdapter(string prefix, string rootPath, StorageClient client, string bucketName, Action? configuration = null)
+ : base(prefix, rootPath, configuration)
+ {
+ this.client = client;
+ this.bucketName = bucketName;
+ }
+
+ public override void Dispose()
+ {
+ client.Dispose();
+ }
+
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
+ {
+ Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
+ Logger.LogFinishedConnectingAdapter(this);
+ }
+
+ public override async Task GetFileAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().RemoveTrailingForwardSlash();
+
+ try
+ {
+ var file = await client.GetObjectAsync(bucketName, path, new GetObjectOptions(), cancellationToken);
+
+ if (file == null)
+ {
+ throw new FileNotFoundException(path, Prefix);
+ }
+
+ return ModelFactory.CreateFile(file, path, virtualPath);
+ }
+ catch (GoogleApiException googleApiException) when (googleApiException.HttpStatusCode == HttpStatusCode.NotFound)
+ {
+ throw new FileNotFoundException(path, Prefix);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().EnsureTrailingForwardSlash();
+ var parentPath = GetParentPathPart(path).EnsureTrailingForwardSlash();
+
+ try
+ {
+ if (path.IsNullOrEmpty() || path == "/")
+ {
+ return ModelFactory.CreateDirectory("/", path, virtualPath);
+ }
+
+ var request = client.Service.Objects.List(bucketName);
+
+ request.Prefix = parentPath == "/" ? null : parentPath;
+ request.Delimiter = "/";
+
+ do
+ {
+ var objects = await request.ExecuteAsync(cancellationToken: cancellationToken);
+
+ if (objects.Prefixes != null)
+ {
+ foreach (var directoryPath in objects.Prefixes)
+ {
+ if (directoryPath == path)
+ {
+ var directoryName = GetLastPathPart(directoryPath);
+
+ return ModelFactory.CreateDirectory(directoryName.RemoveTrailingForwardSlash(), directoryPath.EnsureTrailingForwardSlash(), GetVirtualPath(directoryPath));
+ }
+ }
+ }
+
+ request.PageToken = objects.NextPageToken;
+ } while (request.PageToken != null);
+
+ throw new DirectoryNotFoundException(path, Prefix);
+ }
+ catch (GoogleApiException googleApiException) when (googleApiException.HttpStatusCode == HttpStatusCode.NotFound)
+ {
+ throw new DirectoryNotFoundException(path, Prefix);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task> GetFilesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
+ {
+ await GetDirectoryAsync(virtualPath, cancellationToken);
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().EnsureTrailingForwardSlash();
+
+ try
+ {
+ var files = new List();
+
+ var request = client.Service.Objects.List(bucketName);
+
+ request.Prefix = path == "/" ? null : path;
+ request.Delimiter = "/";
+
+ do
+ {
+ var objects = await request.ExecuteAsync(cancellationToken: cancellationToken);
+
+ if (objects.Items != null)
+ {
+ foreach (var file in objects.Items.Where(item => item.ContentType != null))
+ {
+ files.Add(ModelFactory.CreateFile(file, file.Name.RemoveTrailingForwardSlash(), GetVirtualPath(file.Name)));
+ }
+ }
+
+ request.PageToken = objects.NextPageToken;
+ } while (request.PageToken != null);
+
+ return files;
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task> GetDirectoriesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
+ {
+ await GetDirectoryAsync(virtualPath, cancellationToken);
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().EnsureTrailingForwardSlash();
+
+ try
+ {
+ var directories = new List();
+
+ var request = client.Service.Objects.List(bucketName);
+
+ request.Prefix = path == "/" ? null : path;
+ request.Delimiter = "/";
+
+ do
+ {
+ var objects = await request.ExecuteAsync(cancellationToken: cancellationToken);
+
+ if (objects.Prefixes != null)
+ {
+ foreach (var directoryPath in objects.Prefixes)
+ {
+ var directoryName = GetLastPathPart(directoryPath);
+
+ directories.Add(ModelFactory.CreateDirectory(directoryName.RemoveTrailingForwardSlash(), directoryPath.EnsureTrailingForwardSlash(), GetVirtualPath(directoryPath)));
+ }
+ }
+
+ request.PageToken = objects.NextPageToken;
+ } while (request.PageToken != null);
+
+ return directories;
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task CreateDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ if (await DirectoryExistsAsync(virtualPath, cancellationToken))
+ {
+ throw new DirectoryExistsException(GetPath(virtualPath), Prefix);
+ }
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().EnsureTrailingForwardSlash();
+
+ try
+ {
+ await client.UploadObjectAsync(bucketName, path.EnsureTrailingForwardSlash(), null, Stream.Null, cancellationToken: cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task DeleteDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ await GetDirectoryAsync(virtualPath, cancellationToken);
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().EnsureTrailingForwardSlash();
+
+ try
+ {
+ var files = await GetFilesAsync(virtualPath, cancellationToken);
+
+ foreach (var file in files)
+ {
+ await DeleteFileAsync(file.VirtualPath, cancellationToken);
+ }
+
+ var subDirectories = await GetDirectoriesAsync(virtualPath, cancellationToken);
+
+ foreach (var subDirectory in subDirectories)
+ {
+ await DeleteDirectoryAsync(subDirectory.VirtualPath, cancellationToken);
+ }
+
+ await client.DeleteObjectAsync(bucketName, path, cancellationToken: cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task DeleteFileAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ await GetFileAsync(virtualPath, cancellationToken);
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().RemoveTrailingForwardSlash();
+
+ try
+ {
+ await client.DeleteObjectAsync(bucketName, path, cancellationToken: cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task ReadFileStreamAsync(string virtualPath, CancellationToken cancellationToken = default)
+ {
+ await GetFileAsync(virtualPath, cancellationToken);
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().RemoveTrailingForwardSlash();
+
+ try
+ {
+ var file = await client.GetObjectAsync(bucketName, path, new GetObjectOptions(), cancellationToken);
+
+ var memoryStream = new MemoryStream();
+
+ await client.DownloadObjectAsync(file, memoryStream, new DownloadObjectOptions(), cancellationToken);
+
+ memoryStream.Position = 0;
+
+ return memoryStream;
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ public override async Task WriteFileAsync(string virtualPath, Stream contents, bool overwrite = false, CancellationToken cancellationToken = default)
+ {
+ if (!overwrite && await FileExistsAsync(virtualPath, cancellationToken))
+ {
+ throw new FileExistsException(GetPath(virtualPath), Prefix);
+ }
+
+ var path = GetPath(virtualPath).RemoveLeadingForwardSlash().RemoveTrailingForwardSlash();
+
+ try
+ {
+ var file = new Object
+ {
+ Bucket = bucketName,
+ Name = path,
+ ContentType = ContentTypeProvider.GetContentType(path)
+ };
+
+ await client.UploadObjectAsync(file, contents, new UploadObjectOptions(), cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw Exception(exception);
+ }
+ }
+
+ protected override Exception Exception(Exception exception)
+ {
+ if (exception is FileSystemException)
+ {
+ return exception;
+ }
+
+ return new AdapterRuntimeException(exception);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleCloudStorage/src/GoogleCloudStorageAdapterConfiguration.cs b/FileSystem.Adapters.GoogleCloudStorage/src/GoogleCloudStorageAdapterConfiguration.cs
new file mode 100644
index 0000000..dc83161
--- /dev/null
+++ b/FileSystem.Adapters.GoogleCloudStorage/src/GoogleCloudStorageAdapterConfiguration.cs
@@ -0,0 +1,8 @@
+using SharpGrip.FileSystem.Configuration;
+
+namespace SharpGrip.FileSystem.Adapters.GoogleCloudStorage
+{
+ public class GoogleCloudStorageAdapterConfiguration : AdapterConfiguration
+ {
+ }
+}
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleCloudStorage/src/ModelFactory.cs b/FileSystem.Adapters.GoogleCloudStorage/src/ModelFactory.cs
new file mode 100644
index 0000000..6a49dab
--- /dev/null
+++ b/FileSystem.Adapters.GoogleCloudStorage/src/ModelFactory.cs
@@ -0,0 +1,44 @@
+using Google.Apis.Storage.v1.Data;
+using SharpGrip.FileSystem.Models;
+using SharpGrip.FileSystem.Utilities;
+
+namespace SharpGrip.FileSystem.Adapters.GoogleCloudStorage
+{
+ public static class ModelFactory
+ {
+ public static FileModel CreateFile(Object file, string path, string virtualPath)
+ {
+ return new FileModel
+ {
+ Name = PathUtilities.GetLastPathPart(file.Name),
+ Path = path,
+ VirtualPath = virtualPath,
+ Length = (long?) file.Size,
+ LastModifiedDateTime = file.UpdatedDateTimeOffset?.DateTime,
+ CreatedDateTime = file.TimeCreatedDateTimeOffset?.DateTime
+ };
+ }
+
+ public static DirectoryModel CreateDirectory(string name, string path, string virtualPath)
+ {
+ return new DirectoryModel
+ {
+ Name = name,
+ Path = path,
+ VirtualPath = virtualPath
+ };
+ }
+
+ public static DirectoryModel CreateDirectory(Object directory, string path, string virtualPath)
+ {
+ return new DirectoryModel
+ {
+ Name = directory.Name,
+ Path = path,
+ VirtualPath = virtualPath,
+ LastModifiedDateTime = directory.UpdatedDateTimeOffset?.DateTime,
+ CreatedDateTime = directory.TimeCreatedDateTimeOffset?.DateTime
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleDrive/FileSystem.Adapters.GoogleDrive.csproj b/FileSystem.Adapters.GoogleDrive/FileSystem.Adapters.GoogleDrive.csproj
index 10a6000..e75cb58 100644
--- a/FileSystem.Adapters.GoogleDrive/FileSystem.Adapters.GoogleDrive.csproj
+++ b/FileSystem.Adapters.GoogleDrive/FileSystem.Adapters.GoogleDrive.csproj
@@ -13,11 +13,11 @@
-
+
-
+
diff --git a/FileSystem.Adapters.GoogleDrive/README.md b/FileSystem.Adapters.GoogleDrive/README.md
new file mode 100644
index 0000000..054cd83
--- /dev/null
+++ b/FileSystem.Adapters.GoogleDrive/README.md
@@ -0,0 +1,33 @@
+# SharpGrip FileSystem GoogleDrive adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleDrive)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.GoogleDrive` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleDrive).
+
+## Usage
+
+```
+// Google connection.
+await using var stream = new FileStream("path/to/credentials.json", FileMode.Open, FileAccess.Read);
+const string tokenPath = "path/to/token/directory";
+var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
+ (await GoogleClientSecrets.FromStreamAsync(stream)).Secrets,
+ new[] {DriveService.Scope.Drive},
+ "user",
+ CancellationToken.None,
+ new FileDataStore(tokenPath, true));
+
+var googleDriveClient = new DriveService(new BaseClientService.Initializer
+{
+ HttpClientInitializer = credential,
+ ApplicationName = "Test"
+});
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new GoogleDriveAdapter("google-drive", "/Files", googleDriveClient)
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.GoogleDrive/src/GoogleDriveAdapter.cs b/FileSystem.Adapters.GoogleDrive/src/GoogleDriveAdapter.cs
index c0f7f28..0b26edc 100644
--- a/FileSystem.Adapters.GoogleDrive/src/GoogleDriveAdapter.cs
+++ b/FileSystem.Adapters.GoogleDrive/src/GoogleDriveAdapter.cs
@@ -40,9 +40,10 @@ public override void Dispose()
client.Dispose();
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
diff --git a/FileSystem.Adapters.MicrosoftOneDrive/FileSystem.Adapters.MicrosoftOneDrive.csproj b/FileSystem.Adapters.MicrosoftOneDrive/FileSystem.Adapters.MicrosoftOneDrive.csproj
index 442c9e5..422edf7 100644
--- a/FileSystem.Adapters.MicrosoftOneDrive/FileSystem.Adapters.MicrosoftOneDrive.csproj
+++ b/FileSystem.Adapters.MicrosoftOneDrive/FileSystem.Adapters.MicrosoftOneDrive.csproj
@@ -13,12 +13,12 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/FileSystem.Adapters.MicrosoftOneDrive/README.md b/FileSystem.Adapters.MicrosoftOneDrive/README.md
new file mode 100644
index 0000000..8e803c7
--- /dev/null
+++ b/FileSystem.Adapters.MicrosoftOneDrive/README.md
@@ -0,0 +1,32 @@
+# SharpGrip FileSystem MicrosoftOneDrive adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.MicrosoftOneDrive)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.MicrosoftOneDrive` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.MicrosoftOneDrive).
+
+## Usage
+
+```
+// Microsoft connection.
+var scopes = new[] {"https://graph.microsoft.com/.default"};
+var tenantId = "tenantId";
+var confidentialClient = ConfidentialClientApplicationBuilder
+ .Create("clientId")
+ .WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
+ .WithClientSecret("clientSecret")
+ .Build();
+var oneDriveClient = new GraphServiceClient(new DelegateAuthenticationProvider(async requestMessage =>
+ {
+ var authResult = await confidentialClient.AcquireTokenForClient(scopes).ExecuteAsync();
+ requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
+ })
+);
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new MicrosoftOneDriveAdapter("onedrive", "/Files", oneDriveClient, "driveId")
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.MicrosoftOneDrive/src/MicrosoftOneDriveAdapter.cs b/FileSystem.Adapters.MicrosoftOneDrive/src/MicrosoftOneDriveAdapter.cs
index 60d0ff5..15adbed 100644
--- a/FileSystem.Adapters.MicrosoftOneDrive/src/MicrosoftOneDriveAdapter.cs
+++ b/FileSystem.Adapters.MicrosoftOneDrive/src/MicrosoftOneDriveAdapter.cs
@@ -29,9 +29,10 @@ public override void Dispose()
{
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
diff --git a/FileSystem.Adapters.Sftp/FileSystem.Adapters.Sftp.csproj b/FileSystem.Adapters.Sftp/FileSystem.Adapters.Sftp.csproj
index a8c6114..ac19ad0 100644
--- a/FileSystem.Adapters.Sftp/FileSystem.Adapters.Sftp.csproj
+++ b/FileSystem.Adapters.Sftp/FileSystem.Adapters.Sftp.csproj
@@ -13,7 +13,7 @@
-
+
@@ -21,7 +21,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/FileSystem.Adapters.Sftp/README.md b/FileSystem.Adapters.Sftp/README.md
new file mode 100644
index 0000000..bed4ff0
--- /dev/null
+++ b/FileSystem.Adapters.Sftp/README.md
@@ -0,0 +1,23 @@
+# SharpGrip FileSystem Sftp adapter [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Sftp)
+
+## Installation
+
+Reference NuGet package `SharpGrip.FileSystem.Adapters.Sftp` (https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Sftp).
+
+## Usage
+
+```
+// SFTP connection.
+var privateKeyFile = new PrivateKeyFile("/home/userName/.ssh/id_rsa");
+var privateKeyAuthenticationMethod = new PrivateKeyAuthenticationMethod("userName", privateKeyFile);
+var sftpConnectionInfo = new ConnectionInfo("hostName", "userName", privateKeyAuthenticationMethod);
+var sftpClient = new SftpClient(sftpConnectionInfo);
+
+var adapters = new List
+{
+ new LocalAdapter("local", "/var/files"),
+ new SftpAdapter("sftp", "/var/files", sftpClient)
+};
+
+var fileSystem = new FileSystem(adapters);
+```
\ No newline at end of file
diff --git a/FileSystem.Adapters.Sftp/src/SftpAdapter.cs b/FileSystem.Adapters.Sftp/src/SftpAdapter.cs
index 8c0aad4..071332a 100644
--- a/FileSystem.Adapters.Sftp/src/SftpAdapter.cs
+++ b/FileSystem.Adapters.Sftp/src/SftpAdapter.cs
@@ -32,10 +32,10 @@ public SftpAdapter(string prefix, string rootPath, ISftpClient client, ActionSharpGrip.FileSystem
SharpGrip FileSystem
SharpGrip FileSystem is a file system abstraction supporting multiple adapters.
- sharpgrip;file-system;amazon-s3;azure-blob-storage;azure-file-storage;dropbox;microsoft-onedrive;sftp
+ sharpgrip;file-system;amazon-s3;azure-blob-storage;azure-file-storage;dropbox;ftp;google-cloud-storage;google-drive;microsoft-onedrive;sftp
diff --git a/FileSystem/src/Adapters/Adapter.cs b/FileSystem/src/Adapters/Adapter.cs
index aa39db7..265445f 100644
--- a/FileSystem/src/Adapters/Adapter.cs
+++ b/FileSystem/src/Adapters/Adapter.cs
@@ -20,7 +20,7 @@ namespace SharpGrip.FileSystem.Adapters
{
public string Prefix { get; }
public string RootPath { get; }
- public string Name => GetType().FullName!;
+ public string Name { get; }
public IAdapterConfiguration AdapterConfiguration => Configuration;
protected TAdapterConfiguration Configuration { get; }
protected ILogger Logger { get; } = NullLogger>.Instance;
@@ -32,6 +32,7 @@ protected Adapter(string prefix, string rootPath, Action?
var adapterConfiguration = new TAdapterConfiguration();
configuration?.Invoke(adapterConfiguration);
+ Name = GetType().FullName!;
Configuration = adapterConfiguration;
if (Configuration.EnableLogging)
@@ -96,7 +97,7 @@ public virtual async Task AppendFileAsync(string virtualPath, Stream contents, C
using var memoryStream = await StreamUtilities.CopyContentsToMemoryStreamAsync(fileContents, false, cancellationToken);
- await contents.CopyToAsync(memoryStream, AdapterConstants.DefaultMemoryStreamBufferSize, cancellationToken);
+ await contents.CopyToAsync(memoryStream, FileSystemConstants.Streaming.DefaultMemoryStreamBufferSize, cancellationToken);
memoryStream.Seek(0, SeekOrigin.Begin);
await DeleteFileAsync(virtualPath, cancellationToken);
@@ -116,7 +117,7 @@ public virtual async Task AppendFileAsync(string virtualPath, Stream contents, C
}
public abstract void Dispose();
- public abstract void Connect();
+ public abstract Task ConnectAsync(CancellationToken cancellationToken = default);
public abstract Task GetFileAsync(string virtualPath, CancellationToken cancellationToken = default);
public abstract Task GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default);
public abstract Task> GetFilesAsync(string virtualPath = "", CancellationToken cancellationToken = default);
@@ -128,9 +129,9 @@ public virtual async Task AppendFileAsync(string virtualPath, Stream contents, C
public abstract Task WriteFileAsync(string virtualPath, Stream contents, bool overwrite = false, CancellationToken cancellationToken = default);
protected abstract Exception Exception(Exception exception);
- protected string GetPath(string path)
+ protected string GetPath(string virtualPath)
{
- return PathUtilities.GetPath(path, RootPath);
+ return PathUtilities.GetPath(virtualPath, RootPath);
}
protected string GetVirtualPath(string path)
diff --git a/FileSystem/src/Adapters/IAdapter.cs b/FileSystem/src/Adapters/IAdapter.cs
index 3839204..496959f 100644
--- a/FileSystem/src/Adapters/IAdapter.cs
+++ b/FileSystem/src/Adapters/IAdapter.cs
@@ -14,7 +14,7 @@ public interface IAdapter : IDisposable
public string RootPath { get; }
public string Name { get; }
public IAdapterConfiguration AdapterConfiguration { get; }
- public void Connect();
+ public Task ConnectAsync(CancellationToken cancellationToken = default);
public void ClearCache();
public Task GetFileAsync(string virtualPath, CancellationToken cancellationToken = default);
public Task GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default);
diff --git a/FileSystem/src/Adapters/LocalAdapter.cs b/FileSystem/src/Adapters/LocalAdapter.cs
index 1837a92..3a52558 100644
--- a/FileSystem/src/Adapters/LocalAdapter.cs
+++ b/FileSystem/src/Adapters/LocalAdapter.cs
@@ -22,9 +22,10 @@ public override void Dispose()
{
}
- public override void Connect()
+ public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
+ await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}
@@ -196,7 +197,7 @@ public override async Task WriteFileAsync(string virtualPath, Stream contents, b
using var fileStream = new FileStream(GetPath(virtualPath), FileMode.Create);
contents.Seek(0, SeekOrigin.Begin);
- await contents.CopyToAsync(fileStream, AdapterConstants.DefaultMemoryStreamBufferSize, cancellationToken);
+ await contents.CopyToAsync(fileStream, FileSystemConstants.Streaming.DefaultMemoryStreamBufferSize, cancellationToken);
}
catch (Exception exception)
{
@@ -213,7 +214,7 @@ public override async Task AppendFileAsync(string virtualPath, Stream contents,
using var fileStream = new FileStream(GetPath(virtualPath), FileMode.Append);
contents.Seek(0, SeekOrigin.Begin);
- await contents.CopyToAsync(fileStream, AdapterConstants.DefaultMemoryStreamBufferSize, cancellationToken);
+ await contents.CopyToAsync(fileStream, FileSystemConstants.Streaming.DefaultMemoryStreamBufferSize, cancellationToken);
}
catch (Exception exception)
{
diff --git a/FileSystem/src/Constants/AdapterConstants.cs b/FileSystem/src/Constants/AdapterConstants.cs
deleted file mode 100644
index 6b18777..0000000
--- a/FileSystem/src/Constants/AdapterConstants.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace SharpGrip.FileSystem.Constants
-{
- public static class AdapterConstants
- {
- public const int DefaultMemoryStreamBufferSize = 81920;
- }
-}
\ No newline at end of file
diff --git a/FileSystem/src/Constants/FileSystemConstants.cs b/FileSystem/src/Constants/FileSystemConstants.cs
new file mode 100644
index 0000000..2c14b4c
--- /dev/null
+++ b/FileSystem/src/Constants/FileSystemConstants.cs
@@ -0,0 +1,10 @@
+namespace SharpGrip.FileSystem.Constants
+{
+ public static class FileSystemConstants
+ {
+ public static class Streaming
+ {
+ public const int DefaultMemoryStreamBufferSize = 81920;
+ }
+ }
+}
\ No newline at end of file
diff --git a/FileSystem/src/Exceptions/InvalidVirtualPathException.cs b/FileSystem/src/Exceptions/InvalidVirtualPathException.cs
new file mode 100644
index 0000000..71d26b5
--- /dev/null
+++ b/FileSystem/src/Exceptions/InvalidVirtualPathException.cs
@@ -0,0 +1,17 @@
+namespace SharpGrip.FileSystem.Exceptions
+{
+ public class InvalidVirtualPathException : FileSystemException
+ {
+ public string VirtualPath { get; }
+
+ public InvalidVirtualPathException(string virtualPath) : base(GetMessage(virtualPath))
+ {
+ VirtualPath = virtualPath;
+ }
+
+ private static string GetMessage(string virtualPath)
+ {
+ return $"Invalid virtual path '{virtualPath}'.";
+ }
+ }
+}
\ No newline at end of file
diff --git a/FileSystem/src/FileSystem.cs b/FileSystem/src/FileSystem.cs
index 983b7c2..72c4336 100644
--- a/FileSystem/src/FileSystem.cs
+++ b/FileSystem/src/FileSystem.cs
@@ -154,23 +154,25 @@ public IFile GetFile(string virtualPath)
/// Thrown when an adapter could not be found via the provided prefix.
/// Thrown when a prefix in the provided path could not be found.
/// Thrown if the file does not exists at the given path.
- public Task GetFileAsync(string virtualPath, CancellationToken cancellationToken = default)
+ public async Task GetFileAsync(string virtualPath, CancellationToken cancellationToken = default)
{
try
{
Logger.LogStartExecutingMethod(nameof(GetFileAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
adapter.ClearCache();
}
- return adapter.GetFileAsync(virtualPath, cancellationToken);
+ return await adapter.GetFileAsync(virtualPath, cancellationToken);
}
catch (FileSystemException fileSystemException)
{
@@ -213,23 +215,25 @@ public IDirectory GetDirectory(string virtualPath)
/// Thrown when an adapter could not be found via the provided prefix.
/// Thrown when a prefix in the provided path could not be found.
/// Thrown if the directory does not exists at the given path.
- public Task GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
+ public async Task GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
{
try
{
Logger.LogStartExecutingMethod(nameof(GetDirectoryAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
adapter.ClearCache();
}
- return adapter.GetDirectoryAsync(virtualPath, cancellationToken);
+ return await adapter.GetDirectoryAsync(virtualPath, cancellationToken);
}
catch (FileSystemException fileSystemException)
{
@@ -272,23 +276,25 @@ public IEnumerable GetFiles(string virtualPath = "")
/// Thrown when an adapter could not be found via the provided prefix.
/// Thrown when a prefix in the provided path could not be found.
/// Thrown if the directory does not exists at the given path.
- public Task> GetFilesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
+ public async Task> GetFilesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
{
try
{
Logger.LogStartExecutingMethod(nameof(GetFilesAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
adapter.ClearCache();
}
- return adapter.GetFilesAsync(virtualPath, cancellationToken);
+ return await adapter.GetFilesAsync(virtualPath, cancellationToken);
}
catch (FileSystemException fileSystemException)
{
@@ -331,23 +337,25 @@ public IEnumerable GetDirectories(string virtualPath = "")
/// Thrown when an adapter could not be found via the provided prefix.
/// Thrown when a prefix in the provided path could not be found.
/// Thrown if the directory does not exists at the given path.
- public Task> GetDirectoriesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
+ public async Task> GetDirectoriesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
{
try
{
Logger.LogStartExecutingMethod(nameof(GetDirectoriesAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
adapter.ClearCache();
}
- return adapter.GetDirectoriesAsync(virtualPath, cancellationToken);
+ return await adapter.GetDirectoriesAsync(virtualPath, cancellationToken);
}
catch (FileSystemException fileSystemException)
{
@@ -394,10 +402,12 @@ public async Task FileExistsAsync(string virtualPath, CancellationToken ca
{
Logger.LogStartExecutingMethod(nameof(FileExistsAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -451,10 +461,12 @@ public async Task DirectoryExistsAsync(string virtualPath, CancellationTok
{
Logger.LogStartExecutingMethod(nameof(DirectoryExistsAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -508,10 +520,12 @@ public async Task CreateDirectoryAsync(string virtualPath, CancellationToken can
{
Logger.LogStartExecutingMethod(nameof(CreateDirectoryAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -565,10 +579,12 @@ public async Task DeleteFileAsync(string virtualPath, CancellationToken cancella
{
Logger.LogStartExecutingMethod(nameof(DeleteFileAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -622,10 +638,12 @@ public async Task DeleteDirectoryAsync(string virtualPath, CancellationToken can
{
Logger.LogStartExecutingMethod(nameof(DeleteDirectoryAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -663,10 +681,12 @@ public async Task ReadFileStreamAsync(string virtualPath, CancellationTo
{
Logger.LogStartExecutingMethod(nameof(ReadFileStreamAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -722,6 +742,8 @@ public async Task ReadFileAsync(string virtualPath, CancellationToken ca
{
Logger.LogStartExecutingMethod(nameof(ReadFileAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var stream = await ReadFileStreamAsync(virtualPath, cancellationToken);
using var memoryStream = await StreamUtilities.CopyContentsToMemoryStreamAsync(stream, true, cancellationToken);
@@ -774,6 +796,8 @@ public async Task ReadTextFileAsync(string virtualPath, CancellationToke
{
Logger.LogStartExecutingMethod(nameof(ReadTextFileAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
using var stream = await ReadFileStreamAsync(virtualPath, cancellationToken);
using var streamReader = new StreamReader(stream);
@@ -830,20 +854,23 @@ public async Task CopyFileAsync(string virtualSourcePath, string virtualDestinat
{
Logger.LogStartExecutingMethod(nameof(CopyFileAsync));
+ virtualSourcePath = PathUtilities.NormalizeVirtualPath(virtualSourcePath);
+ virtualDestinationPath = PathUtilities.NormalizeVirtualPath(virtualDestinationPath);
+
var sourcePrefix = PathUtilities.GetPrefix(virtualSourcePath);
var sourceAdapter = GetAdapter(sourcePrefix);
var destinationPrefix = PathUtilities.GetPrefix(virtualDestinationPath);
var destinationAdapter = GetAdapter(destinationPrefix);
- sourceAdapter.Connect();
+ await sourceAdapter.ConnectAsync(cancellationToken);
if (!sourceAdapter.AdapterConfiguration.EnableCache)
{
sourceAdapter.ClearCache();
}
- destinationAdapter.Connect();
+ await destinationAdapter.ConnectAsync(cancellationToken);
if (!destinationAdapter.AdapterConfiguration.EnableCache)
{
@@ -904,27 +931,30 @@ public async Task MoveFileAsync(string virtualSourcePath, string virtualDestinat
{
Logger.LogStartExecutingMethod(nameof(MoveFileAsync));
+ virtualSourcePath = PathUtilities.NormalizeVirtualPath(virtualSourcePath);
+ virtualDestinationPath = PathUtilities.NormalizeVirtualPath(virtualDestinationPath);
+
var sourcePrefix = PathUtilities.GetPrefix(virtualSourcePath);
var sourceAdapter = GetAdapter(sourcePrefix);
var destinationPrefix = PathUtilities.GetPrefix(virtualDestinationPath);
var destinationAdapter = GetAdapter(destinationPrefix);
- sourceAdapter.Connect();
+ await sourceAdapter.ConnectAsync(cancellationToken);
if (!sourceAdapter.AdapterConfiguration.EnableCache)
{
sourceAdapter.ClearCache();
}
- destinationAdapter.Connect();
+ await destinationAdapter.ConnectAsync(cancellationToken);
if (!destinationAdapter.AdapterConfiguration.EnableCache)
{
destinationAdapter.ClearCache();
}
- using var fileStream = await sourceAdapter.ReadFileStreamAsync(virtualSourcePath, cancellationToken);
+ var fileStream = await sourceAdapter.ReadFileStreamAsync(virtualSourcePath, cancellationToken);
await destinationAdapter.WriteFileAsync(virtualDestinationPath, fileStream, overwrite, cancellationToken);
fileStream.Dispose();
@@ -961,10 +991,12 @@ public async Task WriteFileAsync(string virtualPath, Stream contents, bool overw
{
Logger.LogStartExecutingMethod(nameof(WriteFileAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
@@ -1078,10 +1110,12 @@ public async Task AppendFileAsync(string virtualPath, Stream contents, Cancellat
{
Logger.LogStartExecutingMethod(nameof(AppendFileAsync));
+ virtualPath = PathUtilities.NormalizeVirtualPath(virtualPath);
+
var prefix = PathUtilities.GetPrefix(virtualPath);
var adapter = GetAdapter(prefix);
- adapter.Connect();
+ await adapter.ConnectAsync(cancellationToken);
if (!adapter.AdapterConfiguration.EnableCache)
{
diff --git a/FileSystem/src/Utilities/PathUtilities.cs b/FileSystem/src/Utilities/PathUtilities.cs
index 2077fb8..61a008e 100644
--- a/FileSystem/src/Utilities/PathUtilities.cs
+++ b/FileSystem/src/Utilities/PathUtilities.cs
@@ -36,6 +36,28 @@ public static string NormalizeRootPath(string rootPath)
return rootPath.Replace(InvalidPathSeparator, PathSeparator).RemoveTrailingForwardSlash();
}
+ ///
+ /// Normalizes a virtual path.
+ ///
+ /// The virtual path.
+ /// The normalized virtual path.
+ public static string NormalizeVirtualPath(string virtualPath)
+ {
+ if (!virtualPath.Contains(AdapterPrefixSeparator))
+ {
+ throw new InvalidVirtualPathException(virtualPath);
+ }
+
+ var prefixAndPath = ResolvePrefixAndPath(virtualPath);
+
+ if (prefixAndPath.Length == 1)
+ {
+ return virtualPath;
+ }
+
+ return prefixAndPath[0] + AdapterPrefixSeparator + prefixAndPath[1].RemoveLeadingForwardSlash();
+ }
+
///
/// Returns the path from a prefixed path.
///
diff --git a/FileSystem/src/Utilities/StreamUtilities.cs b/FileSystem/src/Utilities/StreamUtilities.cs
index 4462951..aba6178 100644
--- a/FileSystem/src/Utilities/StreamUtilities.cs
+++ b/FileSystem/src/Utilities/StreamUtilities.cs
@@ -10,7 +10,7 @@ public static class StreamUtilities
public static async Task CopyContentsToMemoryStreamAsync(Stream sourceStream, bool setPositionToStart, CancellationToken cancellationToken = default)
{
var memoryStream = new MemoryStream();
- await sourceStream.CopyToAsync(memoryStream, AdapterConstants.DefaultMemoryStreamBufferSize, cancellationToken);
+ await sourceStream.CopyToAsync(memoryStream, FileSystemConstants.Streaming.DefaultMemoryStreamBufferSize, cancellationToken);
if (setPositionToStart)
{
diff --git a/README.md b/README.md
index 4e2d720..d34b409 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,10 @@
## Introduction
-SharpGrip FileSystem is a .NET file system abstraction supporting multiple adapters.
+SharpGrip FileSystem is a versatile .NET file system abstraction that supports multiple storage adapters.
+It empowers developers to manage various file systems and services through a unified and easily comprehensible API.
+By coding against the abstractions provided by this library, developers can sidestep vendor-specific APIs, effectively avoiding vendor lock-ins.
+This flexibility enhances the portability and maintainability of the codebase, allowing for smoother transitions between different file systems.
## Installation
@@ -22,16 +25,18 @@ For adapters other than the local file system (included in the `SharpGrip.FileSy
## Supported adapters
-| Adapter | Package | NuGet |
-|:------------------------------------------------|:--------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Local adapter](#local-adapter) | `SharpGrip.FileSystem` | [](https://www.nuget.org/packages/SharpGrip.FileSystem) [](https://www.nuget.org/packages/SharpGrip.FileSystem) |
-| [AmazonS3](#amazons3-adapter) | `SharpGrip.FileSystem.Adapters.AmazonS3` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AmazonS3) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AmazonS3) |
-| [AzureBlobStorage](#azureblobstorage-adapter) | `SharpGrip.FileSystem.Adapters.AzureBlobStorage` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureBlobStorage) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureBlobStorage) |
-| [AzureFileStorage](#azurefilestorage-adapter) | `SharpGrip.FileSystem.Adapters.AzureFileStorage` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureFileStorage) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureFileStorage) |
-| [Dropbox](#dropbox-adapter) | `SharpGrip.FileSystem.Adapters.Dropbox` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Dropbox) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Dropbox) |
-| [GoogleDrive](#googledrive-adapter) | `SharpGrip.FileSystem.Adapters.GoogleDrive` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleDrive) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleDrive) |
-| [MicrosoftOneDrive](#microsoftonedrive-adapter) | `SharpGrip.FileSystem.Adapters.MicrosoftOneDrive` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.MicrosoftOneDrive) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.MicrosoftOneDrive) |
-| [SFTP](#sftp-adapter) | `SharpGrip.FileSystem.Adapters.Sftp` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Sftp) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Sftp) |
+| Adapter | Package | NuGet |
+|:-----------------------------------------------------------------------|:---------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Local adapter](#local-adapter) | `SharpGrip.FileSystem` | [](https://www.nuget.org/packages/SharpGrip.FileSystem) [](https://www.nuget.org/packages/SharpGrip.FileSystem) |
+| [AmazonS3](FileSystem.Adapters.AmazonS3/README.md) | `SharpGrip.FileSystem.Adapters.AmazonS3` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AmazonS3) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AmazonS3) |
+| [AzureBlobStorage](FileSystem.Adapters.AzureBlobStorage/README.md) | `SharpGrip.FileSystem.Adapters.AzureBlobStorage` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureBlobStorage) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureBlobStorage) |
+| [AzureFileStorage](FileSystem.Adapters.AzureFileStorage/README.md) | `SharpGrip.FileSystem.Adapters.AzureFileStorage` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureFileStorage) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.AzureFileStorage) |
+| [Dropbox](FileSystem.Adapters.Dropbox/README.md) | `SharpGrip.FileSystem.Adapters.Dropbox` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Dropbox) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Dropbox) |
+| [FTP](FileSystem.Adapters.Ftp/README.md) | `SharpGrip.FileSystem.Adapters.Ftp` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Ftp) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Ftp) |
+| [GoogleCloudStorage](FileSystem.Adapters.GoogleCloudStorage/README.md) | `SharpGrip.FileSystem.Adapters.GoogleCloudStorage` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleCloudStorage) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleCloudStorage) |
+| [GoogleDrive](FileSystem.Adapters.GoogleDrive/README.md) | `SharpGrip.FileSystem.Adapters.GoogleDrive` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleDrive) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.GoogleDrive) |
+| [MicrosoftOneDrive](FileSystem.Adapters.MicrosoftOneDrive/README.md) | `SharpGrip.FileSystem.Adapters.MicrosoftOneDrive` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.MicrosoftOneDrive) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.MicrosoftOneDrive) |
+| [SFTP](FileSystem.Adapters.Sftp/README.md) | `SharpGrip.FileSystem.Adapters.Sftp` | [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Sftp) [](https://www.nuget.org/packages/SharpGrip.FileSystem.Adapters.Sftp) |
## Supported operations
@@ -67,140 +72,6 @@ var adapters = new List
var fileSystem = new FileSystem(adapters);
```
-### AmazonS3 adapter
-
-```
-// Amazon connection.
-var amazonClient = new AmazonS3Client("awsAccessKeyId", "awsSecretAccessKey", RegionEndpoint.USEast2);
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new AmazonS3Adapter("amazon", "/Files", amazonClient, "bucketName")
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
-### AzureBlobStorage adapter
-
-```
-// Azure connection.
-var blobServiceClient = new BlobServiceClient("connectionString");
-var azureClient = blobServiceClient.GetBlobContainerClient("blobContainerName");
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new AzureBlobStorageAdapter("azure", "/Files", azureClient)
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
-### AzureFileStorage adapter
-
-```
-// Azure connection.
-var azureClient = new ShareClient("connectionString", "shareName");
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new AzureFileStorageAdapter("azure", "/Files", azureClient)
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
-### Dropbox adapter
-
-```
-// Dropbox connection.
-var dropboxClient = new DropboxClient("oAuth2AccessToken");
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new DropboxAdapter("dropbox", "/Files", dropboxClient)
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
-### GoogleDrive adapter
-
-```
-// Google connection.
-await using var stream = new FileStream("path/to/credentials.json", FileMode.Open, FileAccess.Read);
-const string tokenPath = "path/to/token/directory";
-var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
- (await GoogleClientSecrets.FromStreamAsync(stream)).Secrets,
- new[] {DriveService.Scope.Drive},
- "user",
- CancellationToken.None,
- new FileDataStore(tokenPath, true));
-
-var googleDriveClient = new DriveService(new BaseClientService.Initializer
-{
- HttpClientInitializer = credential,
- ApplicationName = "Test"
-});
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new GoogleDriveAdapter("google-drive", "/Files", googleDriveClient)
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
-### MicrosoftOneDrive adapter
-
-```
-// Microsoft connection.
-var scopes = new[] {"https://graph.microsoft.com/.default"};
-var tenantId = "tenantId";
-var confidentialClient = ConfidentialClientApplicationBuilder
- .Create("clientId")
- .WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
- .WithClientSecret("clientSecret")
- .Build();
-var oneDriveClient = new GraphServiceClient(new DelegateAuthenticationProvider(async requestMessage =>
- {
- var authResult = await confidentialClient.AcquireTokenForClient(scopes).ExecuteAsync();
- requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
- })
-);
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new MicrosoftOneDriveAdapter("onedrive", "/Files", oneDriveClient, "driveId")
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
-### SFTP adapter
-
-```
-// SFTP connection.
-var privateKeyFile = new PrivateKeyFile("/home/userName/.ssh/id_rsa");
-var privateKeyAuthenticationMethod = new PrivateKeyAuthenticationMethod("userName", privateKeyFile);
-var sftpConnectionInfo = new ConnectionInfo("hostName", "userName", privateKeyAuthenticationMethod);
-var sftpClient = new SftpClient(sftpConnectionInfo);
-
-var adapters = new List
-{
- new LocalAdapter("local", "/var/files"),
- new SftpAdapter("sftp", "/var/files", sftpClient)
-};
-
-var fileSystem = new FileSystem(adapters);
-```
-
### Example operations
```
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 3f7b907..4c1f556 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -8,26 +8,26 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Tests/src/FileSystem.Adapters.AmazonS3/AmazonS3AdapterTest.cs b/Tests/src/FileSystem.Adapters.AmazonS3/AmazonS3AdapterTest.cs
index 0342332..45f1a59 100644
--- a/Tests/src/FileSystem.Adapters.AmazonS3/AmazonS3AdapterTest.cs
+++ b/Tests/src/FileSystem.Adapters.AmazonS3/AmazonS3AdapterTest.cs
@@ -36,14 +36,12 @@ public void Test_Instantiation()
}
[Fact]
- public Task Test_Connect()
+ public async Task Test_Connect()
{
var amazonS3Client = Substitute.For();
var amazonS3Adapter = new AmazonS3Adapter("prefix", "/root-path", amazonS3Client, "bucket");
- amazonS3Adapter.Connect();
-
- return Task.CompletedTask;
+ await amazonS3Adapter.ConnectAsync();
}
[Fact]
diff --git a/Tests/src/FileSystem.Adapters.AzureBlobStorage/AzureBlobStorageAdapterTest.cs b/Tests/src/FileSystem.Adapters.AzureBlobStorage/AzureBlobStorageAdapterTest.cs
index 38e18a5..b57bc9a 100644
--- a/Tests/src/FileSystem.Adapters.AzureBlobStorage/AzureBlobStorageAdapterTest.cs
+++ b/Tests/src/FileSystem.Adapters.AzureBlobStorage/AzureBlobStorageAdapterTest.cs
@@ -19,14 +19,12 @@ public void Test_Instantiation()
}
[Fact]
- public Task Test_Connect()
+ public async Task Test_Connect()
{
var blobContainerClient = Substitute.For();
var azureBlobStorageAdapter = new AzureBlobStorageAdapter("prefix", "/root-path", blobContainerClient);
- azureBlobStorageAdapter.Connect();
-
- return Task.CompletedTask;
+ await azureBlobStorageAdapter.ConnectAsync();
}
[Fact]
diff --git a/Tests/src/FileSystem.Adapters.AzureFileStorage/AzureFileStorageAdapterTest.cs b/Tests/src/FileSystem.Adapters.AzureFileStorage/AzureFileStorageAdapterTest.cs
index 3dedba0..9ada96b 100644
--- a/Tests/src/FileSystem.Adapters.AzureFileStorage/AzureFileStorageAdapterTest.cs
+++ b/Tests/src/FileSystem.Adapters.AzureFileStorage/AzureFileStorageAdapterTest.cs
@@ -19,14 +19,12 @@ public void Test_Instantiation()
}
[Fact]
- public Task Test_Connect()
+ public async Task Test_Connect()
{
var shareClient = Substitute.For();
var azureFileStorageAdapter = new AzureFileStorageAdapter("prefix", "/root-path", shareClient);
- azureFileStorageAdapter.Connect();
-
- return Task.CompletedTask;
+ await azureFileStorageAdapter.ConnectAsync();
}
[Fact]
diff --git a/Tests/src/FileSystem.Adapters.GoogleDrive/GoogleDriveAdapterTest.cs b/Tests/src/FileSystem.Adapters.GoogleDrive/GoogleDriveAdapterTest.cs
index c19ea3a..ed76597 100644
--- a/Tests/src/FileSystem.Adapters.GoogleDrive/GoogleDriveAdapterTest.cs
+++ b/Tests/src/FileSystem.Adapters.GoogleDrive/GoogleDriveAdapterTest.cs
@@ -19,14 +19,12 @@ public void Test_Instantiation()
}
[Fact]
- public Task Test_Connect()
+ public async Task Test_Connect()
{
var googleDriveClient = Substitute.For();
var googleDriveAdapter = new GoogleDriveAdapter("prefix", "/root-path", googleDriveClient);
- googleDriveAdapter.Connect();
-
- return Task.CompletedTask;
+ await googleDriveAdapter.ConnectAsync();
}
[Fact]
diff --git a/Tests/src/FileSystem.Adapters.MicrosoftOneDrive/MicrosoftOneDriveAdapterTest.cs b/Tests/src/FileSystem.Adapters.MicrosoftOneDrive/MicrosoftOneDriveAdapterTest.cs
index e6cc23d..78072aa 100644
--- a/Tests/src/FileSystem.Adapters.MicrosoftOneDrive/MicrosoftOneDriveAdapterTest.cs
+++ b/Tests/src/FileSystem.Adapters.MicrosoftOneDrive/MicrosoftOneDriveAdapterTest.cs
@@ -21,15 +21,13 @@ public void Test_Instantiation()
}
[Fact]
- public Task Test_Connect()
+ public async Task Test_Connect()
{
var delegateAuthenticationProvider = new DelegateAuthenticationProvider(message => Task.FromResult(message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "12345")));
var graphServiceClient = Substitute.For(delegateAuthenticationProvider, null);
var microsoftOneDriveAdapter = new MicrosoftOneDriveAdapter("prefix", "/root-path", graphServiceClient, "driveId");
- microsoftOneDriveAdapter.Connect();
-
- return Task.CompletedTask;
+ await microsoftOneDriveAdapter.ConnectAsync();
}
[Fact]
diff --git a/Tests/src/FileSystem.Adapters.Sftp/SftpAdapterTest.cs b/Tests/src/FileSystem.Adapters.Sftp/SftpAdapterTest.cs
index d410219..df4b1a4 100644
--- a/Tests/src/FileSystem.Adapters.Sftp/SftpAdapterTest.cs
+++ b/Tests/src/FileSystem.Adapters.Sftp/SftpAdapterTest.cs
@@ -31,14 +31,12 @@ public void Test_Instantiation()
}
[Fact]
- public Task Test_Connect()
+ public async Task Test_Connect()
{
var sftpClient = Substitute.For();
var sftpAdapter = new SftpAdapter("prefix", "/root-path", sftpClient);
- sftpAdapter.Connect();
-
- return Task.CompletedTask;
+ await sftpAdapter.ConnectAsync();
}
[Fact]