SFTP CreateDirectoryAsync is not idempotent
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 38/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- csharp
- Ambito
- networking
Direzione di ricerca
Parti da SftpClient.CreateDirectoryAsync e dalla relativa documentazione XML esistente, quindi confrontane il comportamento con ExistsAsync e con la risposta SFTP riportata quando la directory esiste già. Determina se il comportamento idempotente richiesto o un'eccezione più specifica è compatibile con il protocollo; il lavoro è completato quando i chiamanti possono distinguere una directory esistente dagli altri errori.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
My specifications:
OS: Ubuntu Desktop and Windows 11
Framework: .NET 9
Package version: 2025.1.0
This is my current code:
using SftpClient client = new SftpClient(host, port, username, password);
await client.ConnectAsync(cancellationToken);
try
{
await client.CreateDirectoryAsync(someDir, cancellationToken);
}
catch (SftpException ex)
{
// Only some logging code here.
}
When this directory already exists, all I get as an exception message is "failure".
Renci.SshNet.Common.SftpException: failure
at Renci.SshNet.SubsystemSession.<WaitOnHandleAsync> g__DoWaitAsync | 38_0[T](TaskCompletionSource`1 tcs, Int32 millisecondsTimeout, CancellationToken cancellationToken)
at Renci.SshNet.SftpClient.CreateDirectoryAsync(String path, CancellationToken cancellationToken)
Problems:
- I can't know for sure if the exception is about the directory already existing, or whether something else is wrong. Type SftpException with message "failure" is just not descriptive enough.
- CreateDirectoryAsync is not idempotent. Throwing an exception seems very counter-intuitive for a method like this.
- The SftpException is not described in the method documentation:
/// <summary>
/// Asynchronously requests to create a remote directory specified by path.
/// </summary>
/// <param name="path">Directory path to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous create directory operation.</returns>
/// <exception cref="ArgumentException"><paramref name="path"/> is <see langword="null"/> or contains only whitespace characters.</exception>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
/// <exception cref="SftpPermissionDeniedException">Permission to create the directory was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception>
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
If I would want to do this properly, I need quite a lot of code. This is the extension method I wrote:
internal static async ValueTask EnsureDirectoryExists(this SftpClient client, string directory, CancellationToken cancellationToken)
{
bool directoryExists = await client.ExistsAsync(directory, cancellationToken);
if (directoryExists) return;
try
{
await client.CreateDirectoryAsync(directory, cancellationToken);
}
catch (SftpException ex)
{
try
{
bool directoryAlreadyExisted= await client.ExistsAsync(directory, cancellationToken);
if (directoryAlreadyExisted)
{
// The directory already existed, so we can ignore the exception.
return;
}
else
{
// The directory does not exist.
throw;
}
}
catch (SftpException)
{
// Failed checking if the directory exists.
// Throwing the original exception as that illustrates what really is the problem here.
throw ex;
}
}
}
There are 2 ways this could be fixed:
- Add an EnsureDirectoryExists method. I'm sure this can be done much closer to the actual SFTP protocol than the extension method I created.
- Add an SftpDirectoryAlreadyExistsException that inherits from SftpException.
I'm very curious, is there a reason why something like EnsureDirectoryExists was never added to SSH.NET?
- Lingua principale
- C#
- Stelle
- 4.4k
- Fork
- 993
- Merge medio
- 9g 21h
- PR unite (30g)
- 1
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di sshnet/SSH.NET
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
-
Using SshClient on Linux under Wine throws System.Security.Cryptography.CryptographicException Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 67/100
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
Tutte le issue di sshnet/SSH.NET
Issue simili
-
CS0162 "Unreachable code detected" warning from a MSBuildTemp .tmp file in every game project Apertabug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
-
Type: enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
apache/arrow-adbc#4809 ·
-
type/automation type/tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
microsoft/vscode-azurefunctions#5197 · 1 commento ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
microsoft/microsoft-ui-reactor#1274 ·