Skip to content

Commit b58e509

Browse files
committed
Retarget all managed projects to .NET 10 (net10.0-windows10.0.17763.0)
Phase 3 of the .NET 10 migration: TFM retarget, API migrations, and build/CI updates consolidated into a single PR. Foundation: - Pin .NET 10 SDK in global.json (10.0.100 with latestFeature rollback) - Centralize TargetFramework in Directory.Build.props - Bump default dev version to 0.3.0.1 (official builds use 2.0.x.x) - Update MSBuild SDK versions (Traversal 4.1.0, NoTargets 3.7.0) - Update CI to .NET 10 SDK and windows-2025 runner Package updates: - Microsoft.Data.Sqlite 2.2.4 -> 9.0.4 - Microsoft.Build.* 16.0.461 -> 17.12.6 - Microsoft.Windows.ProjFS 1.1.19156.1 -> 2.1.0 - System.ServiceProcess.ServiceController 4.5.0 -> 9.0.4 - Add System.Diagnostics.EventLog, System.Management, System.IO.Pipes.AccessControl - Remove GVFS.ProjFS package (ProjFS is now a Windows OS feature) - Replace CommandLineParser and Newtonsoft.Json stale references API migrations: - HttpUtility.UrlEncode -> WebUtility.UrlEncode (OrgInfoApiClient) - Assembly.Location -> Environment.ProcessPath (ProcessHelper, HooksInstaller) - NamedPipeServerStream ctor -> NamedPipeServerStreamAcl.Create (WindowsPlatform) - Directory.Get/SetAccessControl -> DirectoryInfo extensions (WindowsFileSystem, GVFSService) - Directory.CreateDirectory(path, security) -> DirectorySecurity.CreateDirectory(path) - Remove HttpRequestor machine.config lock and ServicePointManager usage - Remove UseDefaultCredentials from HttpClientHandler - Remove all .NET Framework assembly references (System.Web, System.Net.Http, etc.) Scripts and installer: - Update output paths from net471 to net10.0-windows10.0.17763.0\win-x64 - Remove ProjFS native DLL bundling from layout.bat (OS feature now) - Update installer MinVersion to 10.0.17763 Test fixes: - Add missing IVirtualizationInstance members to MockVirtualizationInstance - Remove stale GVFS.Service.UI project reference from UnitTests All 803 unit tests pass (792 passed, 11 pre-existing skips). Assisted-by: Claude Opus 4.6 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
1 parent d397062 commit b58e509

46 files changed

Lines changed: 190 additions & 235 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ jobs:
198198
if: steps.skip.outputs.result != 'true'
199199
uses: actions/setup-dotnet@v5
200200
with:
201-
dotnet-version: 8.0.413
201+
global-json-file: src/global.json
202202

203203
- name: Add MSBuild to PATH
204204
if: steps.skip.outputs.result != 'true'

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
<!-- Managed project properties -->
2424
<PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.csproj'">
25+
<TargetFramework>net10.0-windows10.0.17763.0</TargetFramework>
2526
<LangVersion>latest</LangVersion>
2627
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
2728
<PlatformTarget>x64</PlatformTarget>

Directory.Packages.props

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
<PropertyGroup>
44
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5+
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
56
</PropertyGroup>
67

78
<ItemGroup>
8-
<!-- Serialization -->
9-
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
10-
119
<!-- Storage -->
12-
<PackageVersion Include="Microsoft.Data.Sqlite" Version="2.2.4" />
10+
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.4" />
1311

1412
<!-- Compression -->
1513
<PackageVersion Include="SharpZipLib" Version="1.3.3" />
@@ -18,30 +16,27 @@
1816
<PackageVersion Include="LibGit2Sharp.NativeBinaries" Version="2.0.322" />
1917

2018
<!-- ProjFS -->
21-
<PackageVersion Include="GVFS.ProjFS" Version="2019.411.1" />
22-
<PackageVersion Include="Microsoft.Windows.ProjFS" Version="1.1.19156.1" />
19+
<PackageVersion Include="Microsoft.Windows.ProjFS" Version="2.1.0" />
2320

2421
<!-- Windows -->
25-
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="4.5.0" />
22+
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.4" />
23+
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.4" />
24+
<PackageVersion Include="System.Management" Version="9.0.4" />
2625

2726
<!-- Build / packaging -->
2827
<PackageVersion Include="GVFS.VCRuntime" Version="0.2.0-build" />
2928
<PackageVersion Include="MicroBuild.Core" Version="0.2.0" />
30-
<PackageVersion Include="Microsoft.Build.Framework" Version="16.0.461" />
31-
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="16.0.461" />
29+
<PackageVersion Include="Microsoft.Build.Framework" Version="17.12.6" />
30+
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
3231
<PackageVersion Include="Tools.InnoSetup" Version="6.4.3" />
3332

33+
<!-- CLI -->
34+
<PackageVersion Include="System.CommandLine" Version="2.0.5" />
35+
3436
<!-- Testing -->
3537
<PackageVersion Include="Moq" Version="4.10.1" />
3638
<PackageVersion Include="NUnit3TestAdapter" Version="3.13.0" />
3739
<PackageVersion Include="NUnitLite" Version="3.12.0" />
38-
39-
<!--
40-
Future packages: pre-declared for Phase 2+ branches to avoid
41-
merge conflicts on this file. Not yet referenced by any project.
42-
-->
43-
<PackageVersion Include="System.CommandLine" Version="2.0.5" />
44-
<PackageVersion Include="System.IO.Pipes.AccessControl" Version="8.0.0" />
4540
</ItemGroup>
4641

4742
</Project>

GVFS/FastFetch/FastFetch.csproj

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

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net471</TargetFramework>
65
<PlatformTarget>x64</PlatformTarget>
76
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
87
</PropertyGroup>
@@ -28,3 +27,4 @@
2827
</ItemGroup>
2928

3029
</Project>
30+

GVFS/GVFS.Common/FileSystem/HooksInstaller.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static class HooksInstaller
2222

2323
static HooksInstaller()
2424
{
25-
ExecutingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
25+
ExecutingDirectory = Path.GetDirectoryName(Environment.ProcessPath);
2626
}
2727

2828
public static string MergeHooksData(string[] defaultHooksLines, string filename, string hookName)
Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net471</TargetFramework>
54
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
65
</PropertyGroup>
76

87
<ItemGroup>
98
<PackageReference Include="LibGit2Sharp.NativeBinaries" />
109
<PackageReference Include="Microsoft.Data.Sqlite" />
11-
<PackageReference Include="System.Text.Json" />
1210
<PackageReference Include="SharpZipLib" />
1311
</ItemGroup>
1412

15-
<ItemGroup>
16-
<Reference Include="System.Net.Http" />
17-
<Reference Include="System.Web" />
18-
</ItemGroup>
19-
2013
<Target Name="_GenerateConstantsFile" BeforeTargets="BeforeCompile">
2114
<!-- Generate GVFS constants file with the minimum Git version -->
2215
<GenerateGVFSConstants MinimumGitVersion="$(MinimumGitVersion)" LibGit2FileName="$(libgit2_filename)" OutputFile="$(IntermediateOutputPath)GVFSConstants.g.cs" />
@@ -28,3 +21,4 @@
2821
</Target>
2922

3023
</Project>
24+

GVFS/GVFS.Common/Git/GitSsl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ private X509Certificate2 GetCertificateFromFile(ITracer tracer, EventMetadata me
161161
try
162162
{
163163
byte[] certificateContent = this.fileSystem.ReadAllBytes(this.certificatePathOrSubjectCommonName);
164-
X509Certificate2 cert = new X509Certificate2(certificateContent, certificatePassword);
164+
X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(certificateContent, certificatePassword);
165165
if (this.ShouldVerify && cert != null && !this.certificateVerifier.Verify(cert))
166166
{
167167
tracer.RelatedWarning(metadata, "Certficate was found, but is invalid.");

GVFS/GVFS.Common/Http/HttpRequestor.cs

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Net;
99
using System.Net.Http;
1010
using System.Net.Http.Headers;
11-
using System.Runtime.InteropServices;
1211
using System.Text;
1312
using System.Threading;
1413
using System.Threading.Tasks;
@@ -32,19 +31,10 @@ public abstract class HttpRequestor : IDisposable
3231

3332
static HttpRequestor()
3433
{
35-
/* If machine.config is locked, then initializing ServicePointManager will fail and be unrecoverable.
36-
* Machine.config locking is typically very brief (~1ms by the antivirus scanner) so we can attempt to lock
37-
* it ourselves (by opening it for read) *beforehand and briefly wait if it's locked */
38-
using (var machineConfigLock = GetMachineConfigLock())
39-
{
40-
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12;
41-
42-
// HTTP downloads are I/O-bound, not CPU-bound, so we default to
43-
// 2x ProcessorCount. Can be overridden via gvfs.max-http-connections.
44-
int connectionLimit = 2 * Environment.ProcessorCount;
45-
ServicePointManager.DefaultConnectionLimit = connectionLimit;
46-
availableConnections = new SemaphoreSlim(connectionLimit);
47-
}
34+
// HTTP downloads are I/O-bound, not CPU-bound, so we default to
35+
// 2x ProcessorCount. Can be overridden via gvfs.max-http-connections.
36+
int connectionLimit = 2 * Environment.ProcessorCount;
37+
availableConnections = new SemaphoreSlim(connectionLimit);
4838
}
4939

5040
protected HttpRequestor(ITracer tracer, RetryConfig retryConfig, Enlistment enlistment)
@@ -62,7 +52,7 @@ protected HttpRequestor(ITracer tracer, RetryConfig retryConfig, Enlistment enli
6252
TryApplyConnectionLimitFromConfig(tracer, enlistment);
6353
}
6454

65-
HttpClientHandler httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
55+
HttpClientHandler httpClientHandler = new HttpClientHandler();
6656

6757
this.authentication.ConfigureHttpClientHandlerSslIfNeeded(this.Tracer, httpClientHandler, enlistment.CreateGitProcess());
6858

@@ -180,8 +170,8 @@ protected GitEndPointResponseData SendRequest(
180170
}
181171
catch (HttpRequestException httpRequestException) when (TryGetResponseMessageFromHttpRequestException(httpRequestException, request, out response))
182172
{
183-
/* HttpClientHandler will automatically resubmit in certain circumstances, such as a 401 unauthorized response when UseDefaultCredentials
184-
* is true but another credential was provided. This resubmit can throw (instead of returning a proper status code) in some case cases, such
173+
/* HttpClientHandler may automatically resubmit in certain circumstances, such as a 401 unauthorized response.
174+
* This resubmit can throw (instead of returning a proper status code) in some cases, such
185175
* as when there is an exception loading the default credentials.
186176
* If we can extract the original response message from the exception, we can continue and process the original failed status code. */
187177
Tracer.RelatedWarning(responseMetadata, $"An exception occurred while resubmitting the request, but the original response is available.");
@@ -391,8 +381,7 @@ private static void TryApplyConnectionLimitFromConfig(ITracer tracer, Enlistment
391381

392382
if (configuredLimit > 0)
393383
{
394-
int currentLimit = ServicePointManager.DefaultConnectionLimit;
395-
ServicePointManager.DefaultConnectionLimit = configuredLimit;
384+
int currentLimit = availableConnections.CurrentCount;
396385

397386
// Adjust the existing semaphore rather than replacing it, so any
398387
// in-flight waiters release permits to the correct instance.
@@ -425,28 +414,5 @@ private static void TryApplyConnectionLimitFromConfig(ITracer tracer, Enlistment
425414
tracer.RelatedWarning(metadata, "HttpRequestor: Failed to read gvfs.max-http-connections config, using default");
426415
}
427416
}
428-
429-
private static FileStream GetMachineConfigLock()
430-
{
431-
var machineConfigLocation = RuntimeEnvironment.SystemConfigurationFile;
432-
var tries = 0;
433-
var maxTries = 3;
434-
while (tries++ < maxTries)
435-
{
436-
try
437-
{
438-
/* Opening with FileShare.Read will fail if another process (eg antivirus) has opened the file for write,
439-
but will still let ServicePointManager read the file.*/
440-
FileStream stream = File.Open(machineConfigLocation, FileMode.Open, FileAccess.Read, FileShare.Read);
441-
return stream;
442-
}
443-
catch (IOException e) when ((uint)e.HResult == 0x80070020) // SHARING_VIOLATION
444-
{
445-
Thread.Sleep(10);
446-
}
447-
}
448-
/* Couldn't get the lock - the process will likely fail. */
449-
return null;
450-
}
451417
}
452418
}

GVFS/GVFS.Common/OrgInfoApiClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Net;
45
using System.Net.Http;
56
using System.Text;
6-
using System.Web;
77

88
namespace GVFS.Common
99
{
@@ -69,7 +69,7 @@ private string ConstructRequest(string baseUrl, Dictionary<string, string> query
6969
}
7070

7171
isFirst = false;
72-
sb.Append($"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}");
72+
sb.Append($"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}");
7373
}
7474

7575
return sb.ToString();

GVFS/GVFS.Common/ProcessHelper.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ public static ProcessResult Run(string programName, string args, bool redirectOu
2626

2727
public static string GetCurrentProcessLocation()
2828
{
29-
Assembly assembly = Assembly.GetExecutingAssembly();
30-
return Path.GetDirectoryName(assembly.Location);
29+
return Path.GetDirectoryName(Environment.ProcessPath);
3130
}
3231

3332
public static string GetEntryClassName()
@@ -36,8 +35,8 @@ public static string GetEntryClassName()
3635
if (assembly == null)
3736
{
3837
// The PR build tests doesn't produce an entry assembly because it is run from unmanaged code,
39-
// so we'll fall back on using this assembly. This should never ever happen for a normal exe invocation.
40-
assembly = Assembly.GetExecutingAssembly();
38+
// so we'll fall back on using process path. This should never ever happen for a normal exe invocation.
39+
return Path.GetFileNameWithoutExtension(Environment.ProcessPath);
4140
}
4241

4342
return assembly.GetName().Name;
@@ -47,8 +46,7 @@ public static string GetCurrentProcessVersion()
4746
{
4847
if (currentProcessVersion == null)
4948
{
50-
Assembly assembly = Assembly.GetExecutingAssembly();
51-
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
49+
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(Environment.ProcessPath);
5250
currentProcessVersion = fileVersionInfo.ProductVersion;
5351
}
5452

0 commit comments

Comments
 (0)