Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ on:
permissions:
contents: read

env:
DOTNET_TARGET_FRAMEWORK: net11.0

jobs:
Linux:
runs-on: ubuntu-24.04
Expand All @@ -27,15 +30,15 @@ jobs:
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0

- name: Build Unit Tests .NET
run: dotnet build -f net10.0 test/Renci.SshNet.Tests/
run: dotnet build -f $DOTNET_TARGET_FRAMEWORK test/Renci.SshNet.Tests/

- name: Build IntegrationTests .NET
run: dotnet build -f net10.0 test/Renci.SshNet.IntegrationTests/
run: dotnet build -f $DOTNET_TARGET_FRAMEWORK test/Renci.SshNet.IntegrationTests/

- name: Run Unit Tests .NET
run: |
dotnet test \
-f net10.0 \
-f $DOTNET_TARGET_FRAMEWORK \
--no-build \
--logger "console;verbosity=normal" \
--logger GitHubActions \
Expand All @@ -47,7 +50,7 @@ jobs:
- name: Run Integration Tests .NET
run: |
dotnet test \
-f net10.0 \
-f $DOTNET_TARGET_FRAMEWORK \
--no-build \
--logger "console;verbosity=normal" \
--logger GitHubActions \
Expand Down Expand Up @@ -92,7 +95,7 @@ jobs:
- name: Run Unit Tests .NET
run: |
dotnet test `
-f net10.0 `
-f $DOTNET_TARGET_FRAMEWORK `
--no-build `
--logger "console;verbosity=normal" `
--logger GitHubActions `
Expand Down Expand Up @@ -145,17 +148,8 @@ jobs:
-f net48 `
--logger "console;verbosity=normal" `
--logger GitHubActions `
-p:CollectCoverage=true `
-p:CoverletOutputFormat=cobertura `
-p:CoverletOutput=..\..\coverlet\windows_integration_test_net_4_8_coverage.xml `
test\Renci.SshNet.IntegrationTests\

- name: Archive Coverlet Results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Coverlet Results Windows .NET Framework
path: coverlet

Windows-Integration-Tests-Net:
name: Windows Integration Tests .NET
runs-on: windows-2025
Expand Down Expand Up @@ -185,7 +179,7 @@ jobs:
- name: Run Integration Tests .NET
run:
dotnet test `
-f net10.0 `
-f $env:DOTNET_TARGET_FRAMEWORK `
--logger "console;verbosity=normal" `
--logger GitHubActions `
-p:CollectCoverage=true `
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<!--
Disable nullable warnings on old frameworks because of missing annotations.
-->
<PropertyGroup Condition=" !$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0')) ">
<PropertyGroup Condition=" !$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net10.0')) ">
<NoWarn>$(NoWarn);CS8602;CS8604;CS8777</NoWarn>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion docfx/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"outputFormat": "apiPage",
"output": "api",
"properties": {
"TargetFramework": "net8.0"
"TargetFramework": "net10.0"
}
}
],
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "10.0.201",
"version": "11.0.0-rc.1.26425.128",
"rollForward": "latestMinor"
}
}
2 changes: 1 addition & 1 deletion src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Net;
using System.Net.Sockets;
#if NET9_0_OR_GREATER
#if NET
using System.Threading;
#endif

Expand Down
2 changes: 1 addition & 1 deletion src/Renci.SshNet/Common/Lock.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if !NET9_0_OR_GREATER
#if !NET
using System.Threading;

namespace Renci.SshNet.Common
Expand Down
6 changes: 3 additions & 3 deletions src/Renci.SshNet/Common/SshDataStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public bool IsEndOfData
// to write directly into the underlying buffer without the need for any intermediate
// arrays (rented or otherwise).

#if NET9_0_OR_GREATER
#if NET
/// <inheritdoc/>
public override void Write(ReadOnlySpan<byte> buffer)
{
Expand All @@ -75,13 +75,13 @@ public override void Write(ReadOnlySpan<byte> buffer)
#endif

private delegate void WriteAction<in TArg>(Span<byte> span, TArg arg)
#if NET9_0_OR_GREATER
#if NET
where TArg : allows ref struct
#endif
;

private void Write<TArg>(TArg arg, int numBytesToWrite, WriteAction<TArg> writeAction)
#if NET9_0_OR_GREATER
#if NET
where TArg : allows ref struct
#endif
{
Expand Down
7 changes: 2 additions & 5 deletions src/Renci.SshNet/Connection/HttpConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,11 @@ internal sealed partial class HttpConnector : ProxyConnector
private const string HttpHeaderPattern = @"(?<fieldName>[^\[\]()<>@,;:\""/?={} \t]+):(?<fieldValue>.+)?";

#if NET
private static readonly Regex HttpResponseRegex = GetHttpResponseRegex();
private static readonly Regex HttpHeaderRegex = GetHttpHeaderRegex();

[GeneratedRegex(HttpResponsePattern)]
private static partial Regex GetHttpResponseRegex();
private static partial Regex HttpResponseRegex { get; }

[GeneratedRegex(HttpHeaderPattern)]
private static partial Regex GetHttpHeaderRegex();
private static partial Regex HttpHeaderRegex { get; }
#else
private static readonly Regex HttpResponseRegex = new Regex(HttpResponsePattern, RegexOptions.Compiled);
private static readonly Regex HttpHeaderRegex = new Regex(HttpHeaderPattern, RegexOptions.Compiled);
Expand Down
4 changes: 1 addition & 3 deletions src/Renci.SshNet/Connection/ProtocolVersionExchange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ internal sealed partial class ProtocolVersionExchange : IProtocolVersionExchange
private const int MaximumBannerLineLength = 8192;

#if NET
private static readonly Regex ServerVersionRegex = GetServerVersionRegex();

[GeneratedRegex(ServerVersionPattern, RegexOptions.ExplicitCapture)]
private static partial Regex GetServerVersionRegex();
private static partial Regex ServerVersionRegex { get; }
#else
private static readonly Regex ServerVersionRegex = new Regex(ServerVersionPattern, RegexOptions.Compiled | RegexOptions.ExplicitCapture);
#endif
Expand Down
7 changes: 2 additions & 5 deletions src/Renci.SshNet/Netconf/NetConfSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@ internal sealed partial class NetConfSession : SubsystemSession, INetConfSession
private int _messageId;

#if NET
private static readonly Regex LengthRegex = GetLengthRegex();
private static readonly Regex ReplyRegex = GetReplyRegex();

[GeneratedRegex(LengthPattern)]
private static partial Regex GetLengthRegex();
private static partial Regex LengthRegex { get; }

[GeneratedRegex(ReplyPattern)]
private static partial Regex GetReplyRegex();
private static partial Regex ReplyRegex { get; }
#else
private static readonly Regex LengthRegex = new Regex(LengthPattern, RegexOptions.Compiled);
private static readonly Regex ReplyRegex = new Regex(ReplyPattern, RegexOptions.Compiled);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if NET9_0_OR_GREATER
#if NET
#nullable enable
#pragma warning disable SA1649 // File name should match first type name

Expand Down Expand Up @@ -209,15 +209,7 @@ public bool TryAdd(TKey key, TValue value)

public bool TryAdd(TKey key, TValue value, out int index)
{
#if NET10_0_OR_GREATER
return _impl.TryAdd(key, value, out index);
#else
var success = _impl.TryAdd(key, value);

index = _impl.IndexOf(key);

return success;
#endif
}

public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
Expand All @@ -227,18 +219,7 @@ public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)

public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value, out int index)
{
#if NET10_0_OR_GREATER
return _impl.TryGetValue(key, out value, out index);
#else
if (_impl.TryGetValue(key, out value))
{
index = _impl.IndexOf(key);
return true;
}

index = -1;
return false;
#endif
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Renci.SshNet/OrderedDictionary.netstandard.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if !NET9_0_OR_GREATER
#if !NET
#nullable enable
#pragma warning disable SA1649 // File name should match first type name

Expand Down
10 changes: 3 additions & 7 deletions src/Renci.SshNet/PrivateKeyFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,14 @@ public partial class PrivateKeyFile : IPrivateKeySource, IDisposable
private const string CertificatePattern = @"(?<type>[-\w]+@openssh\.com)\s(?<data>[a-zA-Z0-9\/+=]*)(\s+(?<comment>.*))?";

#if NET
private static readonly Regex PrivateKeyRegex = GetPrivateKeyRegex();
private static readonly Regex PuTTYPrivateKeyRegex = GetPrivateKeyPuTTYRegex();
private static readonly Regex CertificateRegex = GetCertificateRegex();

[GeneratedRegex(PrivateKeyPattern, RegexOptions.Multiline | RegexOptions.ExplicitCapture)]
private static partial Regex GetPrivateKeyRegex();
private static partial Regex PrivateKeyRegex { get; }

[GeneratedRegex(PuTTYPrivateKeyPattern, RegexOptions.Multiline | RegexOptions.ExplicitCapture)]
private static partial Regex GetPrivateKeyPuTTYRegex();
private static partial Regex PuTTYPrivateKeyRegex { get; }

[GeneratedRegex(CertificatePattern, RegexOptions.ExplicitCapture)]
private static partial Regex GetCertificateRegex();
private static partial Regex CertificateRegex { get; }
#else
private static readonly Regex PrivateKeyRegex = new Regex(PrivateKeyPattern, RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.ExplicitCapture);
private static readonly Regex PuTTYPrivateKeyRegex = new Regex(PuTTYPrivateKeyPattern, RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.ExplicitCapture);
Expand Down
9 changes: 6 additions & 3 deletions src/Renci.SshNet/Renci.SshNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<AssemblyName>Renci.SshNet</AssemblyName>
<Product>SSH.NET</Product>
<AssemblyTitle>SSH.NET</AssemblyTitle>
<TargetFrameworks>net462;netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>
<TargetFrameworks>net462;netstandard2.0;net10.0;net11.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -36,19 +36,22 @@
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>

<PropertyGroup Condition=" $([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0')) ">
<PropertyGroup Condition=" $([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net10.0')) ">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Nerdbank.GitVersioning" PrivateAssets="all" />
<PackageReference Include="PolySharp" PrivateAssets="all">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition=" !$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net11.0')) ">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net462' ">
<PackageReference Include="Microsoft.Bcl.Cryptography" />
</ItemGroup>
Expand Down
10 changes: 3 additions & 7 deletions src/Renci.SshNet/ScpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,14 @@ public partial class ScpClient : BaseClient
private const string TimestampPattern = @"T(?<mtime>\d+) 0 (?<atime>\d+) 0";

#if NET
private static readonly Regex FileInfoRegex = GetFileInfoRegex();
private static readonly Regex DirectoryInfoRegex = GetDirectoryInfoRegex();
private static readonly Regex TimestampRegex = GetTimestampRegex();

[GeneratedRegex(FileInfoPattern)]
private static partial Regex GetFileInfoRegex();
private static partial Regex FileInfoRegex { get; }

[GeneratedRegex(DirectoryInfoPattern)]
private static partial Regex GetDirectoryInfoRegex();
private static partial Regex DirectoryInfoRegex { get; }

[GeneratedRegex(TimestampPattern)]
private static partial Regex GetTimestampRegex();
private static partial Regex TimestampRegex { get; }
#else
private static readonly Regex FileInfoRegex = new Regex(FileInfoPattern, RegexOptions.Compiled);
private static readonly Regex DirectoryInfoRegex = new Regex(DirectoryInfoPattern, RegexOptions.Compiled);
Expand Down
2 changes: 1 addition & 1 deletion src/Renci.SshNet/SshMessageFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Globalization;
using System.Linq;

#if NET9_0_OR_GREATER
#if NET
using System.Threading;
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net11.0</TargetFramework>
<PublishAot>true</PublishAot>
<SelfContained>true</SelfContained>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net11.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework>net11.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net8.0;net9.0;net10.0</TargetFrameworks>
<TargetFrameworks>net48;net10.0;net11.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<IsTestProject>true</IsTestProject>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
Expand Down
2 changes: 1 addition & 1 deletion test/Renci.SshNet.Tests/Common/PacketDump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private static string AsHex(byte[] data, int length)

if (length < data.Length)
{
_ = hex.Append(new string(' ', (data.Length - length) * 3));
_ = hex.Append(' ', (data.Length - length) * 3);
}

return hex.ToString();
Expand Down
2 changes: 1 addition & 1 deletion test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net462;net8.0;net9.0;net10.0</TargetFrameworks>
<TargetFrameworks>net462;net10.0;net11.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down