diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..22d5376407
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,13 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+# especially
+# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#enabling-dependabot-version-updates-for-actions
+
+version: 2
+updates:
+ - package-ecosystem: "github-actions" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index a30be08797..2dc811ea47 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -17,17 +17,17 @@ jobs:
steps:
- name: Checkout source
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
path: src
- name: Install .NET SDK
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: 5.0.201
- name: Add MSBuild to PATH
- uses: microsoft/setup-msbuild@v1.0.2
+ uses: microsoft/setup-msbuild@v2.0.0
- name: Build VFS for Git
shell: cmd
@@ -42,25 +42,25 @@ jobs:
run: src\scripts\CreateBuildArtifacts.bat ${{ matrix.configuration }} artifacts
- name: Upload functional tests drop
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: FunctionalTests_${{ matrix.configuration }}
path: artifacts\GVFS.FunctionalTests
- name: Upload FastFetch drop
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: FastFetch_${{ matrix.configuration }}
path: artifacts\FastFetch
- name: Upload installers
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Installers_${{ matrix.configuration }}
path: artifacts\GVFS.Installers
- name: Upload NuGet packages
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: NuGetPackages_${{ matrix.configuration }}
path: artifacts\NuGetPackages
@@ -76,13 +76,13 @@ jobs:
steps:
- name: Download installers
- uses: actions/download-artifact@v2
+ uses: actions/download-artifact@v4
with:
name: Installers_${{ matrix.configuration }}
path: install
- name: Download functional tests drop
- uses: actions/download-artifact@v2
+ uses: actions/download-artifact@v4
with:
name: FunctionalTests_${{ matrix.configuration }}
path: ft
@@ -101,7 +101,7 @@ jobs:
- name: Upload installation logs
if: always()
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: InstallationLogs_${{ matrix.configuration }}
path: install\logs
@@ -115,14 +115,14 @@ jobs:
- name: Upload functional test results
if: always()
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: FunctionalTests_Results_${{ matrix.configuration }}
path: TestResult.xml
- name: Upload Git trace2 output
if: always()
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: GitTrace2_${{ matrix.configuration }}
path: C:\temp\git-trace2.log
diff --git a/GVFS/FastFetch/FastFetch.csproj b/GVFS/FastFetch/FastFetch.csproj
index 52bb94654f..1a2bdaae99 100644
--- a/GVFS/FastFetch/FastFetch.csproj
+++ b/GVFS/FastFetch/FastFetch.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/GVFS/GVFS.Common/GVFS.Common.csproj b/GVFS/GVFS.Common/GVFS.Common.csproj
index e96c88ba78..e19e8ee2ec 100644
--- a/GVFS/GVFS.Common/GVFS.Common.csproj
+++ b/GVFS/GVFS.Common/GVFS.Common.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/GVFS/GVFS.Common/Http/HttpRequestor.cs b/GVFS/GVFS.Common/Http/HttpRequestor.cs
index 1f5271d679..ca850c9fb5 100644
--- a/GVFS/GVFS.Common/Http/HttpRequestor.cs
+++ b/GVFS/GVFS.Common/Http/HttpRequestor.cs
@@ -134,6 +134,14 @@ protected GitEndPointResponseData SendRequest(
{
response = this.client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).GetAwaiter().GetResult();
}
+ catch (HttpRequestException httpRequestException) when (TryGetResponseMessageFromHttpRequestException(httpRequestException, request, out response))
+ {
+ /* HttpClientHandler will automatically resubmit in certain circumstances, such as a 401 unauthorized response when UseDefaultCredentials
+ * is true but another credential was provided. This resubmit can throw (instead of returning a proper status code) in some case cases, such
+ * as when there is an exception loading the default credentials.
+ * If we can extract the original response message from the exception, we can continue and process the original failed status code. */
+ Tracer.RelatedWarning(responseMetadata, $"An exception occurred while resubmitting the request, but the original response is available.");
+ }
finally
{
responseWaitTime = requestStopwatch.Elapsed;
@@ -278,5 +286,48 @@ private static string GetSingleHeaderOrEmpty(HttpHeaders headers, string headerN
return string.Empty;
}
+
+ ///
+ /// This method is based on a private method System.Net.Http.HttpClientHandler.CreateResponseMessage
+ ///
+ private static bool TryGetResponseMessageFromHttpRequestException(HttpRequestException httpRequestException, HttpRequestMessage request, out HttpResponseMessage httpResponseMessage)
+ {
+ var webResponse = (httpRequestException?.InnerException as WebException)?.Response as HttpWebResponse;
+ if (webResponse == null)
+ {
+ httpResponseMessage = null;
+ return false;
+ }
+
+ httpResponseMessage = new HttpResponseMessage(webResponse.StatusCode);
+ httpResponseMessage.ReasonPhrase = webResponse.StatusDescription;
+ httpResponseMessage.Version = webResponse.ProtocolVersion;
+ httpResponseMessage.RequestMessage = request;
+ httpResponseMessage.Content = new StreamContent(webResponse.GetResponseStream());
+ request.RequestUri = webResponse.ResponseUri;
+ WebHeaderCollection rawHeaders = webResponse.Headers;
+ HttpContentHeaders responseContentHeaders = httpResponseMessage.Content.Headers;
+ HttpResponseHeaders responseHeaders = httpResponseMessage.Headers;
+ if (webResponse.ContentLength >= 0)
+ {
+ responseContentHeaders.ContentLength = webResponse.ContentLength;
+ }
+
+ for (int i = 0; i < rawHeaders.Count; i++)
+ {
+ string key = rawHeaders.GetKey(i);
+ if (string.Compare(key, "Content-Length", StringComparison.OrdinalIgnoreCase) != 0)
+ {
+ string[] values = rawHeaders.GetValues(i);
+ if (!responseHeaders.TryAddWithoutValidation(key, values))
+ {
+ bool flag = responseContentHeaders.TryAddWithoutValidation(key, values);
+ }
+ }
+ }
+
+ return true;
+
+ }
}
}
diff --git a/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj b/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj
index 9a1615fbf3..290a12b469 100644
--- a/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj
+++ b/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/GVFS/GVFS.Installers/GVFS.Installers.csproj b/GVFS/GVFS.Installers/GVFS.Installers.csproj
index 1f5b692d1c..44c166d565 100644
--- a/GVFS/GVFS.Installers/GVFS.Installers.csproj
+++ b/GVFS/GVFS.Installers/GVFS.Installers.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/GVFS/GVFS.Installers/Setup.iss b/GVFS/GVFS.Installers/Setup.iss
index ca93ac9142..109f4f45bc 100644
--- a/GVFS/GVFS.Installers/Setup.iss
+++ b/GVFS/GVFS.Installers/Setup.iss
@@ -221,8 +221,12 @@ begin
WizardForm.StatusLabel.Caption := 'Installing GVFS.Service.';
WizardForm.ProgressGauge.Style := npbstMarquee;
+ // Spaces after the equal signs are REQUIRED.
+ // https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create#remarks
try
- if Exec(ExpandConstant('{sys}\SC.EXE'), ExpandConstant('create GVFS.Service binPath="{app}\GVFS.Service.exe" start=auto'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0) then
+ // We must add additional quotes to the binPath to ensure that they survive argument parsing.
+ // Without quotes, sc.exe will try to start a file located at C:\Program if it exists.
+ if Exec(ExpandConstant('{sys}\SC.EXE'), ExpandConstant('create GVFS.Service binPath= "\"{app}\GVFS.Service.exe\"" start= auto'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0) then
begin
if Exec(ExpandConstant('{sys}\SC.EXE'), 'failure GVFS.Service reset= 30 actions= restart/10/restart/5000//1', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
diff --git a/GVFS/GVFS.Mount/GVFS.Mount.csproj b/GVFS/GVFS.Mount/GVFS.Mount.csproj
index b770e6f99c..6e41c00081 100644
--- a/GVFS/GVFS.Mount/GVFS.Mount.csproj
+++ b/GVFS/GVFS.Mount/GVFS.Mount.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/GVFS/GVFS/GVFS.csproj b/GVFS/GVFS/GVFS.csproj
index 8c143ebbc7..6d9d579f9c 100644
--- a/GVFS/GVFS/GVFS.csproj
+++ b/GVFS/GVFS/GVFS.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/Version.props b/Version.props
index 6ee26e84bc..1547245cec 100644
--- a/Version.props
+++ b/Version.props
@@ -18,7 +18,7 @@
including taking version numbers 2.X.Y from upstream and updating .W if we have any
hotfixes to microsoft/git.
-->
- 2.20211115.1
+ 2.20220414.4
v2.31.0.vfs.0.1