From ccd680230506fe5e814f85ae1b92175c39e9a88b Mon Sep 17 00:00:00 2001 From: Marius Thesing Date: Sat, 24 Feb 2024 11:32:53 +0100 Subject: [PATCH 1/2] enable nullable on BaseClient and SftpClient --- src/Renci.SshNet/BaseClient.cs | 25 ++++++++--------- src/Renci.SshNet/IBaseClient.cs | 3 +- src/Renci.SshNet/ISftpClient.cs | 25 +++++++++-------- src/Renci.SshNet/SftpClient.cs | 49 +++++++++++++++++++-------------- 4 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs index 9d60d84ea..1751bd3cb 100644 --- a/src/Renci.SshNet/BaseClient.cs +++ b/src/Renci.SshNet/BaseClient.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -22,7 +23,7 @@ public abstract class BaseClient : IBaseClient private readonly IServiceFactory _serviceFactory; private readonly object _keepAliveLock = new object(); private TimeSpan _keepAliveInterval; - private Timer _keepAliveTimer; + private Timer? _keepAliveTimer; private ConnectionInfo _connectionInfo; private bool _isDisposed; @@ -32,7 +33,7 @@ public abstract class BaseClient : IBaseClient /// /// The current session. /// - internal ISession Session { get; private set; } + internal ISession? Session { get; private set; } /// /// Gets the factory for creating new services. @@ -142,17 +143,17 @@ public TimeSpan KeepAliveInterval /// /// Occurs when an error occurred. /// - public event EventHandler ErrorOccurred; + public event EventHandler? ErrorOccurred; /// /// Occurs when host key received. /// - public event EventHandler HostKeyReceived; + public event EventHandler? HostKeyReceived; /// /// Occurs when server identification received. /// - public event EventHandler ServerIdentificationReceived; + public event EventHandler? ServerIdentificationReceived; /// /// Initializes a new instance of the class. @@ -193,7 +194,7 @@ private protected BaseClient(ConnectionInfo connectionInfo, bool ownsConnectionI throw new ArgumentNullException(nameof(serviceFactory)); } - ConnectionInfo = connectionInfo; + _connectionInfo = connectionInfo; _ownsConnectionInfo = ownsConnectionInfo; _serviceFactory = serviceFactory; _keepAliveInterval = SshNet.Session.InfiniteTimeSpan; @@ -381,17 +382,17 @@ protected virtual void OnDisconnected() { } - private void Session_ErrorOccured(object sender, ExceptionEventArgs e) + private void Session_ErrorOccured(object? sender, ExceptionEventArgs e) { ErrorOccurred?.Invoke(this, e); } - private void Session_HostKeyReceived(object sender, HostKeyEventArgs e) + private void Session_HostKeyReceived(object? sender, HostKeyEventArgs e) { HostKeyReceived?.Invoke(this, e); } - private void Session_ServerIdentificationReceived(object sender, SshIdentificationEventArgs e) + private void Session_ServerIdentificationReceived(object? sender, SshIdentificationEventArgs e) { ServerIdentificationReceived?.Invoke(this, e); } @@ -422,14 +423,12 @@ protected virtual void Dispose(bool disposing) Disconnect(); - if (_ownsConnectionInfo && _connectionInfo is not null) + if (_ownsConnectionInfo) { if (_connectionInfo is IDisposable connectionInfoDisposable) { connectionInfoDisposable.Dispose(); } - - _connectionInfo = null; } _isDisposed = true; diff --git a/src/Renci.SshNet/IBaseClient.cs b/src/Renci.SshNet/IBaseClient.cs index c42df3426..9feab44cc 100644 --- a/src/Renci.SshNet/IBaseClient.cs +++ b/src/Renci.SshNet/IBaseClient.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs index efbce934a..a47233014 100644 --- a/src/Renci.SshNet/ISftpClient.cs +++ b/src/Renci.SshNet/ISftpClient.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -192,7 +193,7 @@ public interface ISftpClient : IBaseClient /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback); + IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback? asyncCallback); /// /// Begins an asynchronous file downloading into the stream. @@ -211,7 +212,7 @@ public interface ISftpClient : IBaseClient /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback, object state, Action downloadCallback = null); + IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback? asyncCallback, object? state, Action? downloadCallback = null); /// /// Begins an asynchronous operation of retrieving list of files in remote directory. @@ -224,7 +225,7 @@ public interface ISftpClient : IBaseClient /// An that references the asynchronous operation. /// /// The method was called after the client was disposed. - IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state, Action listCallback = null); + IAsyncResult BeginListDirectory(string path, AsyncCallback? asyncCallback, object? state, Action? listCallback = null); /// /// Begins the synchronize directories. @@ -240,7 +241,7 @@ public interface ISftpClient : IBaseClient /// is . /// is or contains only whitespace. /// If a problem occurs while copying the file. - IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state); + IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback? asyncCallback, object? state); /// /// Begins an asynchronous uploading the stream into remote file. @@ -289,7 +290,7 @@ public interface ISftpClient : IBaseClient /// If the remote file already exists, it is overwritten and truncated. /// /// - IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback); + IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback? asyncCallback); /// /// Begins an asynchronous uploading the stream into remote file. @@ -316,7 +317,7 @@ public interface ISftpClient : IBaseClient /// If the remote file already exists, it is overwritten and truncated. /// /// - IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state, Action uploadCallback = null); + IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback? asyncCallback, object? state, Action? uploadCallback = null); /// /// Begins an asynchronous uploading the stream into remote file. @@ -343,7 +344,7 @@ public interface ISftpClient : IBaseClient /// . /// /// - IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback asyncCallback, object state, Action uploadCallback = null); + IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback? asyncCallback, object? state, Action? uploadCallback = null); /// /// Changes remote directory to path. @@ -522,7 +523,7 @@ public interface ISftpClient : IBaseClient /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - void DownloadFile(string path, Stream output, Action downloadCallback = null); + void DownloadFile(string path, Stream output, Action? downloadCallback = null); /// /// Ends an asynchronous file downloading into the stream. @@ -700,7 +701,7 @@ public interface ISftpClient : IBaseClient /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. - IEnumerable ListDirectory(string path, Action listCallback = null); + IEnumerable ListDirectory(string path, Action? listCallback = null); /// /// Asynchronously enumerates the files in remote directory. @@ -1006,7 +1007,7 @@ public interface ISftpClient : IBaseClient /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - void UploadFile(Stream input, string path, Action uploadCallback = null); + void UploadFile(Stream input, string path, Action? uploadCallback = null); /// /// Uploads stream into remote file. @@ -1024,7 +1025,7 @@ public interface ISftpClient : IBaseClient /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - void UploadFile(Stream input, string path, bool canOverride, Action uploadCallback = null); + void UploadFile(Stream input, string path, bool canOverride, Action? uploadCallback = null); /// /// Writes the specified byte array to the specified file, and closes the file. diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs index 7d2c62165..40557d53c 100644 --- a/src/Renci.SshNet/SftpClient.cs +++ b/src/Renci.SshNet/SftpClient.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -26,7 +27,7 @@ public class SftpClient : BaseClient, ISftpClient /// Holds the instance that is used to communicate to the /// SFTP server. /// - private ISftpSession _sftpSession; + private ISftpSession? _sftpSession; /// /// Holds the operation timeout. @@ -154,7 +155,7 @@ public int ProtocolVersion /// /// The current SFTP session. /// - internal ISftpSession SftpSession + internal ISftpSession? SftpSession { get { return _sftpSession; } } @@ -573,7 +574,7 @@ public void SymbolicLink(string path, string linkPath) /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. - public IEnumerable ListDirectory(string path, Action listCallback = null) + public IEnumerable ListDirectory(string path, Action? listCallback = null) { CheckDisposed(); @@ -650,7 +651,7 @@ public async IAsyncEnumerable ListDirectoryAsync(string path, [Enumer /// An that references the asynchronous operation. /// /// The method was called after the client was disposed. - public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state, Action listCallback = null) + public IAsyncResult BeginListDirectory(string path, AsyncCallback? asyncCallback, object? state, Action? listCallback = null) { CheckDisposed(); @@ -798,7 +799,7 @@ public bool Exists(string path) /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - public void DownloadFile(string path, Stream output, Action downloadCallback = null) + public void DownloadFile(string path, Stream output, Action? downloadCallback = null) { CheckDisposed(); @@ -845,7 +846,7 @@ public IAsyncResult BeginDownloadFile(string path, Stream output) /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback) + public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback? asyncCallback) { return BeginDownloadFile(path, output, asyncCallback, state: null); } @@ -867,7 +868,7 @@ public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback, object state, Action downloadCallback = null) + public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback? asyncCallback, object? state, Action? downloadCallback = null) { CheckDisposed(); @@ -935,7 +936,7 @@ public void EndDownloadFile(IAsyncResult asyncResult) /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - public void UploadFile(Stream input, string path, Action uploadCallback = null) + public void UploadFile(Stream input, string path, Action? uploadCallback = null) { UploadFile(input, path, canOverride: true, uploadCallback); } @@ -956,7 +957,7 @@ public void UploadFile(Stream input, string path, Action uploadCallback = /// /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream. /// - public void UploadFile(Stream input, string path, bool canOverride, Action uploadCallback = null) + public void UploadFile(Stream input, string path, bool canOverride, Action? uploadCallback = null) { CheckDisposed(); @@ -1024,7 +1025,7 @@ public IAsyncResult BeginUploadFile(Stream input, string path) /// If the remote file already exists, it is overwritten and truncated. /// /// - public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback) + public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback? asyncCallback) { return BeginUploadFile(input, path, canOverride: true, asyncCallback, state: null); } @@ -1054,7 +1055,7 @@ public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asy /// If the remote file already exists, it is overwritten and truncated. /// /// - public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state, Action uploadCallback = null) + public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback? asyncCallback, object? state, Action? uploadCallback = null) { return BeginUploadFile(input, path, canOverride: true, asyncCallback, state, uploadCallback); } @@ -1084,7 +1085,7 @@ public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asy /// . /// /// - public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback asyncCallback, object state, Action uploadCallback = null) + public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback? asyncCallback, object? state, Action? uploadCallback = null) { CheckDisposed(); @@ -1702,9 +1703,10 @@ public string[] ReadAllLines(string path, Encoding encoding) using (var stream = new StreamReader(OpenRead(path), encoding)) { - while (!stream.EndOfStream) + string? line; + while ((line = stream.ReadLine()) != null) { - lines.Add(stream.ReadLine()); + lines.Add(line); } } @@ -2106,10 +2108,10 @@ public IEnumerable SynchronizeDirectories(string sourcePath, string de /// /// An that represents the asynchronous directory synchronization. /// - /// is . + /// or is . /// is or contains only whitespace. /// If a problem occurs while copying the file. - public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state) + public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback? asyncCallback, object? state) { if (sourcePath is null) { @@ -2121,6 +2123,11 @@ public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destin throw new ArgumentException("destDir"); } + if (searchPattern is null) + { + throw new ArgumentNullException(nameof(searchPattern)); + } + var asyncResult = new SftpSynchronizeDirectoriesAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(() => @@ -2160,7 +2167,7 @@ public IEnumerable EndSynchronizeDirectories(IAsyncResult asyncResult) return ar.EndInvoke(); } - private List InternalSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, SftpSynchronizeDirectoriesAsyncResult asynchResult) + private List InternalSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, SftpSynchronizeDirectoriesAsyncResult? asynchResult) { if (!Directory.Exists(sourcePath)) { @@ -2255,7 +2262,7 @@ private List InternalSynchronizeDirectories(string sourcePath, string /// /// is . /// Client not connected. - private List InternalListDirectory(string path, SftpListDirectoryAsyncResult asyncResult, Action listCallback) + private List InternalListDirectory(string path, SftpListDirectoryAsyncResult? asyncResult, Action? listCallback) { if (path is null) { @@ -2322,7 +2329,7 @@ private List InternalListDirectory(string path, SftpListDirectoryAsyn /// is . /// is or contains whitespace. /// Client not connected. - private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncResult asyncResult, Action downloadCallback) + private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncResult? asyncResult, Action? downloadCallback) { if (output is null) { @@ -2388,7 +2395,7 @@ private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncR /// is . /// is or contains whitespace. /// Client not connected. - private void InternalUploadFile(Stream input, string path, Flags flags, SftpUploadAsyncResult asyncResult, Action uploadCallback) + private void InternalUploadFile(Stream input, string path, Flags flags, SftpUploadAsyncResult? asyncResult, Action? uploadCallback) { if (input is null) { From fd605c4de0eb233df9ce38306ab8bb18facb8b7d Mon Sep 17 00:00:00 2001 From: Marius Thesing Date: Tue, 5 Mar 2024 17:51:10 +0100 Subject: [PATCH 2/2] SftpClient: use nameof for ArgumentException --- src/Renci.SshNet/SftpClient.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs index 40557d53c..735312636 100644 --- a/src/Renci.SshNet/SftpClient.cs +++ b/src/Renci.SshNet/SftpClient.cs @@ -354,7 +354,7 @@ public void DeleteDirectory(string path) if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (_sftpSession is null) @@ -383,7 +383,7 @@ public void DeleteFile(string path) if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (_sftpSession is null) @@ -414,7 +414,7 @@ public async Task DeleteFileAsync(string path, CancellationToken cancellationTok if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (_sftpSession is null) @@ -541,12 +541,12 @@ public void SymbolicLink(string path, string linkPath) if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (string.IsNullOrWhiteSpace(linkPath)) { - throw new ArgumentException("linkPath"); + throw new ArgumentException(nameof(linkPath)); } if (_sftpSession is null) @@ -743,7 +743,7 @@ public bool Exists(string path) if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (_sftpSession is null) @@ -874,7 +874,7 @@ public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback? if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (output is null) @@ -1096,7 +1096,7 @@ public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } var flags = Flags.Write | Flags.Truncate; @@ -2091,7 +2091,7 @@ public IEnumerable SynchronizeDirectories(string sourcePath, string de if (string.IsNullOrWhiteSpace(destinationPath)) { - throw new ArgumentException("destinationPath"); + throw new ArgumentException(nameof(destinationPath)); } return InternalSynchronizeDirectories(sourcePath, destinationPath, searchPattern, asynchResult: null); @@ -2120,7 +2120,7 @@ public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destin if (string.IsNullOrWhiteSpace(destinationPath)) { - throw new ArgumentException("destDir"); + throw new ArgumentException(nameof(destinationPath)); } if (searchPattern is null) @@ -2338,7 +2338,7 @@ private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncR if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (_sftpSession is null) @@ -2404,7 +2404,7 @@ private void InternalUploadFile(Stream input, string path, Flags flags, SftpUplo if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentException("path"); + throw new ArgumentException(nameof(path)); } if (_sftpSession is null)