Skip to content

Commit 25967e7

Browse files
authored
Merge branch 'develop' into bcl-mlkem
2 parents 0cac766 + 89ea230 commit 25967e7

File tree

10 files changed

+136
-292
lines changed

10 files changed

+136
-292
lines changed

.gitattributes

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
*.cs text diff=csharp
44
*.xaml text
5-
*.sln eol=crlf
65
*.csproj eol=crlf
76
*.shproj eol=crlf
87
*.appxmanifest eol=crlf

.github/workflows/build.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-24.04
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@v5
13+
uses: actions/checkout@v6
1414
with:
1515
fetch-depth: 0 # needed for Nerdbank.GitVersioning
1616

@@ -57,15 +57,15 @@ jobs:
5757
runs-on: windows-2025
5858
steps:
5959
- name: Checkout
60-
uses: actions/checkout@v5
60+
uses: actions/checkout@v6
6161
with:
6262
fetch-depth: 0 # needed for Nerdbank.GitVersioning
6363

6464
- name: Setup .NET
6565
uses: actions/setup-dotnet@v5
6666

6767
- name: Build Solution
68-
run: dotnet build Renci.SshNet.sln
68+
run: dotnet build Renci.SshNet.slnx
6969

7070
- name: Publish AOT Compatibility Test App
7171
run: dotnet publish -r win-x64 /warnaserror test/Renci.SshNet.AotCompatibilityTestApp/
@@ -113,7 +113,7 @@ jobs:
113113
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
114114
115115
- name: Checkout
116-
uses: actions/checkout@v5
116+
uses: actions/checkout@v6
117117
with:
118118
fetch-depth: 0 # needed for Nerdbank.GitVersioning
119119

@@ -160,7 +160,7 @@ jobs:
160160
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
161161
162162
- name: Checkout
163-
uses: actions/checkout@v5
163+
uses: actions/checkout@v6
164164
with:
165165
fetch-depth: 0 # needed for Nerdbank.GitVersioning
166166

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
runs-on: ubuntu-latest
2323
steps:
2424
- name: Checkout repository
25-
uses: actions/checkout@v5
25+
uses: actions/checkout@v6
2626

2727
- name: Setup Pages
2828
uses: actions/configure-pages@v5

Directory.Packages.props

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,24 @@
44
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
55
</PropertyGroup>
66
<ItemGroup>
7-
<PackageVersion Include="BenchmarkDotNet" Version="0.15.3" />
7+
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
88
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.6.2" />
99
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
1010
<PackageVersion Include="coverlet.msbuild" Version="6.0.4" />
11-
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
12-
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.220" />
11+
<PackageVersion Include="GitHubActionsTestLogger" Version="3.0.1" />
12+
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.264" />
1313
<!-- Should stay on LTS .NET releases. -->
14-
<PackageVersion Include="Microsoft.Bcl.Cryptography" Version="10.0.0" />
14+
<PackageVersion Include="Microsoft.Bcl.Cryptography" Version="10.0.1" />
1515
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
16-
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
16+
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.1" />
1717
<PackageVersion Include="MSTest" Version="4.0.2" />
1818
<PackageVersion Include="Moq" Version="4.20.72" />
19-
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.7.115" />
19+
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.9.50" />
2020
<PackageVersion Include="PolySharp" Version="1.15.0" />
21-
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.15.0.120848" />
21+
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.17.0.131074" />
2222
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
2323
<!-- Should stay on LTS .NET releases. -->
24-
<PackageVersion Include="System.Formats.Asn1" Version="8.0.2" />
25-
<PackageVersion Include="Testcontainers" Version="4.7.0" />
24+
<PackageVersion Include="System.Formats.Asn1" Version="10.0.1" />
25+
<PackageVersion Include="Testcontainers" Version="4.9.0" />
2626
</ItemGroup>
2727
</Project>

Renci.SshNet.sln

Lines changed: 0 additions & 267 deletions
This file was deleted.

Renci.SshNet.slnx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<Solution>
2+
<Folder Name="/Solution Items/">
3+
<File Path=".editorconfig" />
4+
<File Path=".gitattributes" />
5+
<File Path=".gitignore" />
6+
<File Path="CODEOWNERS" />
7+
<File Path="CONTRIBUTING.md" />
8+
<File Path="Directory.Build.props" />
9+
<File Path="Directory.Packages.props" />
10+
<File Path="exclusion.dic" />
11+
<File Path="global.json" />
12+
<File Path="LICENSE" />
13+
<File Path="nuget.config" />
14+
<File Path="README.md" />
15+
<File Path="stylecop.json" />
16+
<File Path="THIRD-PARTY-NOTICES.TXT" />
17+
<File Path="version.json" />
18+
</Folder>
19+
<Folder Name="/Solution Items/.github/">
20+
<File Path=".github/dependabot.yml" />
21+
</Folder>
22+
<Folder Name="/Solution Items/.github/workflows/">
23+
<File Path=".github/workflows/build.yml" />
24+
<File Path=".github/workflows/docs.yml" />
25+
</Folder>
26+
<Folder Name="/Solution Items/images/" />
27+
<Folder Name="/Solution Items/images/logo/" />
28+
<Folder Name="/Solution Items/images/logo/ai/">
29+
<File Path="images/logo/ai/SS-NET-icon-white.ai" />
30+
<File Path="images/logo/ai/SS-NET-icon.ai" />
31+
<File Path="images/logo/ai/SS-NET-white.ai" />
32+
<File Path="images/logo/ai/SS-NET.ai" />
33+
</Folder>
34+
<Folder Name="/Solution Items/images/logo/png/">
35+
<File Path="images/logo/png/SS-NET-1280x640.png" />
36+
<File Path="images/logo/png/SS-NET-h50.png" />
37+
<File Path="images/logo/png/SS-NET-h500.png" />
38+
<File Path="images/logo/png/SS-NET-icon-h50.png" />
39+
<File Path="images/logo/png/SS-NET-icon-h500.png" />
40+
<File Path="images/logo/png/SS-NET-icon-white-h50.png" />
41+
<File Path="images/logo/png/SS-NET-icon-white-h500.png" />
42+
<File Path="images/logo/png/SS-NET-white-h50.png" />
43+
<File Path="images/logo/png/SS-NET-white-h500.png" />
44+
</Folder>
45+
<Folder Name="/Solution Items/images/logo/svg/">
46+
<File Path="images/logo/svg/SS-NET-icon-white.svg" />
47+
<File Path="images/logo/svg/SS-NET-icon.svg" />
48+
<File Path="images/logo/svg/SS-NET-white.svg" />
49+
<File Path="images/logo/svg/SS-NET.svg" />
50+
</Folder>
51+
<Folder Name="/Solution Items/src/" />
52+
<Folder Name="/Solution Items/src/References/">
53+
<File Path="src/References/How the SCP protocol works.pdf" />
54+
<File Path="src/References/X.690-0207.pdf" />
55+
<File Path="src/References/X.690-0207.txt" />
56+
</Folder>
57+
<Folder Name="/Solution Items/test/">
58+
<File Path="test/Directory.Build.props" />
59+
</Folder>
60+
<Project Path="src/Renci.SshNet/Renci.SshNet.csproj" />
61+
<Project Path="test/Renci.SshNet.AotCompatibilityTestApp/Renci.SshNet.AotCompatibilityTestApp.csproj" />
62+
<Project Path="test/Renci.SshNet.Benchmarks/Renci.SshNet.Benchmarks.csproj" />
63+
<Project Path="test/Renci.SshNet.IntegrationBenchmarks/Renci.SshNet.IntegrationBenchmarks.csproj" />
64+
<Project Path="test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj" />
65+
<Project Path="test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj" />
66+
<Project Path="test/Renci.SshNet.TestTools.OpenSSH/Renci.SshNet.TestTools.OpenSSH.csproj" />
67+
</Solution>

src/Renci.SshNet/ISftpClient.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,22 @@ public interface ISftpClient : IBaseClient
11331133
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
11341134
Task UploadFileAsync(Stream input, string path, CancellationToken cancellationToken = default);
11351135

1136+
/// <summary>
1137+
/// Asynchronously uploads a <see cref="Stream"/> to a remote file path.
1138+
/// </summary>
1139+
/// <param name="input">The <see cref="Stream"/> to write to the remote path.</param>
1140+
/// <param name="path">The remote file path to write to.</param>
1141+
/// <param name="canOverride">Whether the remote file can be overwritten if it already exists.</param>
1142+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
1143+
/// <returns>A <see cref="Task"/> that represents the asynchronous upload operation.</returns>
1144+
/// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="path"/> is <see langword="null"/>.</exception>
1145+
/// <exception cref="ArgumentException"><paramref name="path" /> is empty or contains only whitespace characters.</exception>
1146+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
1147+
/// <exception cref="SftpPermissionDeniedException">Permission to upload the file was denied by the remote host. <para>-or-</para> An SSH command was denied by the server.</exception>
1148+
/// <exception cref="SshException">An SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception>
1149+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
1150+
Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken = default);
1151+
11361152
/// <summary>
11371153
/// Writes the specified byte array to the specified file, and closes the file.
11381154
/// </summary>

src/Renci.SshNet/SftpClient.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,15 +1077,32 @@ public void UploadFile(Stream input, string path, bool canOverride, Action<ulong
10771077

10781078
/// <inheritdoc />
10791079
public Task UploadFileAsync(Stream input, string path, CancellationToken cancellationToken = default)
1080+
{
1081+
return UploadFileAsync(input, path, canOverride: true, cancellationToken);
1082+
}
1083+
1084+
/// <inheritdoc />
1085+
public Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken = default)
10801086
{
10811087
ArgumentNullException.ThrowIfNull(input);
10821088
ArgumentException.ThrowIfNullOrWhiteSpace(path);
10831089
CheckDisposed();
10841090

1091+
var flags = Flags.Write | Flags.Truncate;
1092+
1093+
if (canOverride)
1094+
{
1095+
flags |= Flags.CreateNewOrOpen;
1096+
}
1097+
else
1098+
{
1099+
flags |= Flags.CreateNew;
1100+
}
1101+
10851102
return InternalUploadFile(
10861103
input,
10871104
path,
1088-
Flags.Write | Flags.Truncate | Flags.CreateNewOrOpen,
1105+
flags,
10891106
asyncResult: null,
10901107
uploadCallback: null,
10911108
isAsync: true,

test/Renci.SshNet.IntegrationTests/OldIntegrationTests/SftpClientTest.Upload.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ public async Task Test_Sftp_Upload_And_Download_Async_1MB_File()
7474
await sftp.UploadFileAsync(file, remoteFileName).ConfigureAwait(false);
7575
}
7676

77+
// uploading again should not throw because of the default canOverride = true
78+
using (var file = File.OpenRead(uploadedFileName))
79+
{
80+
await sftp.UploadFileAsync(file, remoteFileName).ConfigureAwait(false);
81+
}
82+
83+
// uploading with canOverride = false should throw because the file already exists
84+
using (var file = File.OpenRead(uploadedFileName))
85+
{
86+
await Assert.ThrowsAsync<SftpException>(async () => await sftp.UploadFileAsync(file, remoteFileName, canOverride: false).ConfigureAwait(false));
87+
}
88+
7789
var downloadedFileName = Path.GetTempFileName();
7890

7991
using (var file = File.OpenWrite(downloadedFileName))

test/Renci.SshNet.Tests/Classes/SessionTest_Connected.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,9 @@ public void ISession_WaitOnHandleShouldThrowArgumentNullExceptionWhenWaitHandleI
260260
public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnSuccessIfWaitHandleIsSignaled()
261261
{
262262
var session = (ISession)Session;
263-
var waitHandle = new ManualResetEvent(true);
263+
using var waitHandle = new ManualResetEvent(true);
264264

265-
var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0));
265+
var result = session.TryWait(waitHandle, TimeSpan.Zero);
266266

267267
Assert.AreEqual(WaitResult.Success, result);
268268
}
@@ -271,9 +271,9 @@ public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnSuccessIfWaitHandl
271271
public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnTimedOutIfWaitHandleIsNotSignaled()
272272
{
273273
var session = (ISession)Session;
274-
var waitHandle = new ManualResetEvent(false);
274+
using var waitHandle = new ManualResetEvent(false);
275275

276-
var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0));
276+
var result = session.TryWait(waitHandle, TimeSpan.Zero);
277277

278278
Assert.AreEqual(WaitResult.TimedOut, result);
279279
}
@@ -300,9 +300,9 @@ public void ISession_TryWait_WaitHandleAndTimeout_ShouldThrowArgumentNullExcepti
300300
public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnSuccessIfWaitHandleIsSignaled()
301301
{
302302
var session = (ISession)Session;
303-
var waitHandle = new ManualResetEvent(true);
303+
using var waitHandle = new ManualResetEvent(true);
304304

305-
var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0), out var exception);
305+
var result = session.TryWait(waitHandle, TimeSpan.Zero, out var exception);
306306

307307
Assert.AreEqual(WaitResult.Success, result);
308308
Assert.IsNull(exception);
@@ -312,9 +312,9 @@ public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnSucces
312312
public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnTimedOutIfWaitHandleIsNotSignaled()
313313
{
314314
var session = (ISession)Session;
315-
var waitHandle = new ManualResetEvent(false);
315+
using var waitHandle = new ManualResetEvent(false);
316316

317-
var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0), out var exception);
317+
var result = session.TryWait(waitHandle, TimeSpan.Zero, out var exception);
318318

319319
Assert.AreEqual(WaitResult.TimedOut, result);
320320
Assert.IsNull(exception);

0 commit comments

Comments
 (0)