diff --git a/.azure-pipelines/release.yml b/.azure-pipelines/release.yml
index d098c5a70..f754ce9d1 100644
--- a/.azure-pipelines/release.yml
+++ b/.azure-pipelines/release.yml
@@ -28,7 +28,7 @@ jobs:
displayName: Install .NET SDK
inputs:
packageType: sdk
- version: 5.0.201
+ version: 8.0.413
- task: CmdLine@2
displayName: Build VFS for Git
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 2dc811ea4..79a4e4cc8 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -5,11 +5,38 @@ on:
branches: [ master, releases/shipped ]
push:
branches: [ master, releases/shipped ]
+ workflow_dispatch:
+ inputs:
+ git_version:
+ description: 'Microsoft Git version tag to include in the build (leave empty for default)'
+ required: false
+ type: string
+
+env:
+ GIT_VERSION: ${{ github.event.inputs.git_version || 'v2.50.1.vfs.0.1' }}
jobs:
+ validate:
+ runs-on: windows-2025
+ name: Validation
+ steps:
+ - name: Checkout source
+ uses: actions/checkout@v4
+
+ - name: Validate Microsoft Git version
+ shell: pwsh
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ & "$env:GITHUB_WORKSPACE\.github\workflows\scripts\validate_release.ps1" `
+ -Repository microsoft/git `
+ -Tag $env:GIT_VERSION && `
+ Write-Host ::notice title=Validation::Using microsoft/git version $env:GIT_VERSION
+
build:
- runs-on: windows-2019
+ runs-on: windows-2025
name: Build and Unit Test
+ needs: validate
strategy:
matrix:
@@ -24,7 +51,7 @@ jobs:
- name: Install .NET SDK
uses: actions/setup-dotnet@v4
with:
- dotnet-version: 5.0.201
+ dotnet-version: 8.0.413
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2.0.0
@@ -41,6 +68,13 @@ jobs:
shell: cmd
run: src\scripts\CreateBuildArtifacts.bat ${{ matrix.configuration }} artifacts
+ - name: Download microsoft/git installers
+ shell: cmd
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release download %GIT_VERSION% --repo microsoft/git --pattern "Git*.exe" --dir artifacts\GVFS.Installers
+
- name: Upload functional tests drop
uses: actions/upload-artifact@v4
with:
@@ -59,20 +93,15 @@ jobs:
name: Installers_${{ matrix.configuration }}
path: artifacts\GVFS.Installers
- - name: Upload NuGet packages
- uses: actions/upload-artifact@v4
- with:
- name: NuGetPackages_${{ matrix.configuration }}
- path: artifacts\NuGetPackages
-
functional_test:
- runs-on: windows-2019
+ runs-on: ${{ matrix.architecture == 'arm64' && 'windows-11-arm' || 'windows-2025' }}
name: Functional Tests
needs: build
strategy:
matrix:
configuration: [ Debug, Release ]
+ architecture: [ x86_64, arm64 ]
steps:
- name: Download installers
@@ -103,7 +132,7 @@ jobs:
if: always()
uses: actions/upload-artifact@v4
with:
- name: InstallationLogs_${{ matrix.configuration }}
+ name: InstallationLogs_${{ matrix.configuration }}_${{ matrix.architecture }}
path: install\logs
- name: Run functional tests
@@ -117,14 +146,14 @@ jobs:
if: always()
uses: actions/upload-artifact@v4
with:
- name: FunctionalTests_Results_${{ matrix.configuration }}
+ name: FunctionalTests_Results_${{ matrix.configuration }}_${{ matrix.architecture }}
path: TestResult.xml
- name: Upload Git trace2 output
if: always()
uses: actions/upload-artifact@v4
with:
- name: GitTrace2_${{ matrix.configuration }}
+ name: GitTrace2_${{ matrix.configuration }}_${{ matrix.architecture }}
path: C:\temp\git-trace2.log
- name: ProjFS details (post-test)
diff --git a/.github/workflows/scripts/validate_release.ps1 b/.github/workflows/scripts/validate_release.ps1
new file mode 100644
index 000000000..b9ee8c04d
--- /dev/null
+++ b/.github/workflows/scripts/validate_release.ps1
@@ -0,0 +1,124 @@
+param(
+ [Parameter(Mandatory=$true)]
+ [string]$Tag,
+
+ [Parameter(Mandatory=$true)]
+ [string]$Repository
+)
+
+function Write-GitHubActionsCommand {
+ param(
+ [Parameter(Mandatory=$true)]
+ [string]$Command,
+
+ [Parameter(Mandatory=$true)]
+ [string]$Message,
+
+ [Parameter(Mandatory=$true)]
+ [string]$Title
+ )
+
+ Write-Host "::$Command title=$Title::$Message"
+}
+
+
+function Write-GitHubActionsWarning {
+ param(
+ [Parameter(Mandatory=$true)]
+ [string]$Message,
+
+ [Parameter(Mandatory=$false)]
+ [string]$Title = "Warning"
+ )
+
+ if ($env:GITHUB_ACTIONS -eq "true") {
+ Write-GitHubActionsCommand -Command "warning" -Message $Message -Title $Title
+ } else {
+ Write-Host "! Warning: $Message" -ForegroundColor Yellow
+ }
+}
+
+function Write-GitHubActionsError {
+ param(
+ [Parameter(Mandatory=$true)]
+ [string]$Message,
+
+ [Parameter(Mandatory=$false)]
+ [string]$Title = "Error"
+ )
+
+ if ($env:GITHUB_ACTIONS -eq "true") {
+ Write-GitHubActionsCommand -Command "error" -Message $Message -Title $Title
+ } else {
+ Write-Host "x Error: $Message" -ForegroundColor Red
+ }
+}
+
+if ([string]::IsNullOrWhiteSpace($Tag)) {
+ Write-GitHubActionsError -Message "Tag parameter is required"
+ exit 1
+}
+
+if ([string]::IsNullOrWhiteSpace($Repository)) {
+ Write-GitHubActionsError -Message "Repository parameter is required"
+ exit 1
+}
+
+Write-Host "Validating $Repository release '$Tag'..."
+
+# Prepare headers for GitHub API
+$headers = @{
+ 'Accept' = 'application/vnd.github.v3+json'
+ 'User-Agent' = 'VFSForGit-Build'
+}
+
+if ($env:GITHUB_TOKEN) {
+ $headers['Authorization'] = "Bearer $env:GITHUB_TOKEN"
+}
+
+# Check if the tag exists in microsoft/git repository
+try {
+ $releaseResponse = Invoke-RestMethod `
+ -Uri "https://api.github.com/repos/$Repository/releases/tags/$Tag" `
+ -Headers $headers
+
+ Write-Host "✓ Tag '$Tag' found in $Repository" -ForegroundColor Green
+ Write-Host " Release : $($releaseResponse.name)"
+ Write-Host " Published : $($releaseResponse.published_at.ToString('u'))"
+
+ # Check if this a pre-release
+ if ($releaseResponse.prerelease -eq $true) {
+ Write-GitHubActionsWarning `
+ -Message "Using a pre-released version of $Repository" `
+ -Title "Pre-release $Repository version"
+ }
+
+ # Get the latest release for comparison
+ try {
+ $latestResponse = Invoke-RestMethod `
+ -Uri "https://api.github.com/repos/$Repository/releases/latest" `
+ -Headers $headers
+ $latestTag = $latestResponse.tag_name
+
+ # Check if this is the latest release
+ if ($Tag -eq $latestTag) {
+ Write-Host "✓ Using the latest release" -ForegroundColor Green
+ exit 0
+ }
+
+ # Not the latest!
+ $warningTitle = "Outdated $Repository release"
+ $warningMsg = "Not using latest release of $Repository (latest: $latestTag)"
+ Write-GitHubActionsWarning -Message $warningMsg -Title $warningTitle
+ } catch {
+ Write-GitHubActionsWarning -Message "Could not check latest release info for ${Repository}: $($_.Exception.Message)"
+ }
+} catch {
+ if ($_.Exception.Response.StatusCode -eq 404) {
+ Write-GitHubActionsError -Message "Tag '$Tag' does not exist in $Repository"
+ exit 1
+ } else {
+ Write-GitHubActionsError -Message "Error validating release '$Tag': $($_.Exception.Message)"
+ exit 1
+ }
+}
diff --git a/.vsconfig b/.vsconfig
index e91f31e69..095606afa 100644
--- a/.vsconfig
+++ b/.vsconfig
@@ -2,12 +2,13 @@
"version": "1.0",
"components": [
"Microsoft.Component.MSBuild",
- "Microsoft.VisualStudio.Workload.NativeDesktop"
+ "Microsoft.Net.Component.4.7.1.TargetingPack",
+ "Microsoft.Net.Component.4.7.1.SDK",
+ "Microsoft.Net.Core.Component.SDK.8.0",
+ "Microsoft.VisualStudio.Component.VC.v143.x86.x64",
+ "Microsoft.VisualStudio.Component.Windows11SDK.26100",
+ "Microsoft.VisualStudio.Workload.NativeDesktop",
"Microsoft.VisualStudio.Workload.ManagedDesktop",
- "Microsoft.VisualStudio.Workload.NetCoreTools",
- "Microsoft.Net.Core.Component.SDK.2.1",
- "Microsoft.VisualStudio.Component.VC.v141.x86.x64",
- "Microsoft.Net.Component.4.6.1.TargetingPack",
- "Microsoft.Net.Component.4.6.1.SDK",
+ "Microsoft.VisualStudio.Workload.NetCoreTools"
]
}
\ No newline at end of file
diff --git a/GVFS/FastFetch/FastFetch.csproj b/GVFS/FastFetch/FastFetch.csproj
index 1a2bdaae9..df25afb5b 100644
--- a/GVFS/FastFetch/FastFetch.csproj
+++ b/GVFS/FastFetch/FastFetch.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
x64
true
diff --git a/GVFS/GVFS.Common/Enlistment.cs b/GVFS/GVFS.Common/Enlistment.cs
index 3f061257f..090a81c9e 100644
--- a/GVFS/GVFS.Common/Enlistment.cs
+++ b/GVFS/GVFS.Common/Enlistment.cs
@@ -109,5 +109,18 @@ public virtual GitProcess CreateGitProcess()
{
return new GitProcess(this);
}
+
+ public bool GetTrustPackIndexesConfig()
+ {
+ var gitProcess = this.CreateGitProcess();
+ bool trustPackIndexes = true;
+ if (gitProcess.TryGetFromConfig(GVFSConstants.GitConfig.TrustPackIndexes, forceOutsideEnlistment: false, out var valueString)
+ && bool.TryParse(valueString, out var trustPackIndexesConfig))
+ {
+ trustPackIndexes = trustPackIndexesConfig;
+ }
+
+ return trustPackIndexes;
+ }
}
}
diff --git a/GVFS/GVFS.Common/GVFS.Common.csproj b/GVFS/GVFS.Common/GVFS.Common.csproj
index e19e8ee2e..daacd2ca2 100644
--- a/GVFS/GVFS.Common/GVFS.Common.csproj
+++ b/GVFS/GVFS.Common/GVFS.Common.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
true
@@ -13,6 +13,7 @@
+
diff --git a/GVFS/GVFS.Common/Git/GitObjects.cs b/GVFS/GVFS.Common/Git/GitObjects.cs
index 6614bd573..e21d4a1d1 100644
--- a/GVFS/GVFS.Common/Git/GitObjects.cs
+++ b/GVFS/GVFS.Common/Git/GitObjects.cs
@@ -135,12 +135,7 @@ public virtual bool TryDownloadPrefetchPacks(GitProcess gitProcess, long latestT
* pack file and an index file that do not match.
* Eventually we will make this the default, but it has a high performance cost for the first prefetch after
* cloning a large repository, so it must be explicitly enabled for now. */
- bool trustPackIndexes = true;
- if (gitProcess.TryGetFromConfig(GVFSConstants.GitConfig.TrustPackIndexes, forceOutsideEnlistment: false, out var valueString)
- && bool.TryParse(valueString, out var trustPackIndexesConfig))
- {
- trustPackIndexes = trustPackIndexesConfig;
- }
+ bool trustPackIndexes = this.Enlistment.GetTrustPackIndexesConfig();
metadata.Add("trustPackIndexes", trustPackIndexes);
long requestId = HttpRequestor.GetNewRequestId();
diff --git a/GVFS/GVFS.Common/Git/GitRepo.cs b/GVFS/GVFS.Common/Git/GitRepo.cs
index 4aa4b945a..ee9d8b96d 100644
--- a/GVFS/GVFS.Common/Git/GitRepo.cs
+++ b/GVFS/GVFS.Common/Git/GitRepo.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
+using static GVFS.Common.Git.LibGit2Repo;
namespace GVFS.Common.Git
{
@@ -60,9 +61,9 @@ public void OpenRepo()
this.libgit2RepoInvoker?.InitializeSharedRepo();
}
- public bool TryGetIsBlob(string sha, out bool isBlob)
+ public bool TryGetObjectType(string sha, out Native.ObjectTypes? objectType)
{
- return this.libgit2RepoInvoker.TryInvoke(repo => repo.IsBlob(sha), out isBlob);
+ return this.libgit2RepoInvoker.TryInvoke(repo => repo.GetObjectType(sha), out objectType);
}
public virtual bool TryCopyBlobContentStream(string blobSha, Action writeAction)
@@ -86,10 +87,12 @@ public virtual bool TryCopyBlobContentStream(string blobSha, Action repo.CommitAndRootTreeExists(commitSha), out output);
+ string treeShaLocal = null;
+ this.libgit2RepoInvoker.TryInvoke(repo => repo.CommitAndRootTreeExists(commitSha, out treeShaLocal), out output);
+ rootTreeSha = treeShaLocal;
return output;
}
diff --git a/GVFS/GVFS.Common/Git/GitVersion.cs b/GVFS/GVFS.Common/Git/GitVersion.cs
index aecd02465..a3c6461a7 100644
--- a/GVFS/GVFS.Common/Git/GitVersion.cs
+++ b/GVFS/GVFS.Common/Git/GitVersion.cs
@@ -1,15 +1,18 @@
using System;
-using System.Text;
namespace GVFS.Common.Git
{
public class GitVersion
{
public GitVersion(int major, int minor, int build, string platform = null, int revision = 0, int minorRevision = 0)
+ : this(major, minor, build, null, platform, revision, minorRevision) { }
+
+ public GitVersion(int major, int minor, int build, int? releaseCandidate = null, string platform = null, int revision = 0, int minorRevision = 0)
{
this.Major = major;
this.Minor = minor;
this.Build = build;
+ this.ReleaseCandidate = releaseCandidate;
this.Platform = platform;
this.Revision = revision;
this.MinorRevision = minorRevision;
@@ -18,6 +21,7 @@ public GitVersion(int major, int minor, int build, string platform = null, int r
public int Major { get; private set; }
public int Minor { get; private set; }
public int Build { get; private set; }
+ public int? ReleaseCandidate { get; private set; }
public string Platform { get; private set; }
public int Revision { get; private set; }
public int MinorRevision { get; private set; }
@@ -37,31 +41,12 @@ public static bool TryParseGitVersionCommandResult(string input, out GitVersion
return TryParseVersion(input, out version);
}
- public static bool TryParseInstallerName(string input, string installerExtension, out GitVersion version)
- {
- // Installer name is of the form
- // Git-2.14.1.gvfs.1.1.gb16030b-64-bit.exe
-
- version = null;
-
- if (!input.StartsWith("Git-", StringComparison.InvariantCultureIgnoreCase))
- {
- return false;
- }
-
- if (!input.EndsWith("-64-bit" + installerExtension, StringComparison.InvariantCultureIgnoreCase))
- {
- return false;
- }
-
- return TryParseVersion(input.Substring(4, input.Length - 15), out version);
- }
-
public static bool TryParseVersion(string input, out GitVersion version)
{
version = null;
int major, minor, build, revision = 0, minorRevision = 0;
+ int? releaseCandidate = null;
string platform = null;
if (string.IsNullOrWhiteSpace(input))
@@ -73,10 +58,10 @@ public static bool TryParseVersion(string input, out GitVersion version)
int numComponents = parsedComponents.Length;
// We minimally accept the official Git version number format which
- // consists of three components: "major.minor.build".
+ // consists of three components: "major.minor.build[.rcN]".
//
// The other supported formats are the Git for Windows and Microsoft Git
- // formats which look like: "major.minor.build.platform.revision.minorRevision"
+ // formats which look like: "major.minor.build[.rcN].platform.revision.minorRevision"
// 0 1 2 3 4 5
// len 1 2 3 4 5 6
//
@@ -103,25 +88,54 @@ public static bool TryParseVersion(string input, out GitVersion version)
return false;
}
- // Take the platform component verbatim
+ // Release candidate and/or platform
+ // Both of these are optional, but the release candidate is expected to be of the format 'rcN'
+ // where N is a number, helping us distinguish it from a platform string.
+ int platformIdx = 3;
if (numComponents >= 4)
{
- platform = parsedComponents[3];
+ string tag = parsedComponents[3];
+
+ // Release candidate 'rcN'
+ if (tag.StartsWith("rc", StringComparison.OrdinalIgnoreCase) &&
+ tag.Length > 2 && int.TryParse(tag.Substring(2), out int rc) && rc >= 0)
+ {
+ releaseCandidate = rc;
+
+ // The next component will now be the (optional) platform.
+ // Subsequent components will be revision and minor revision so we need to adjust
+ // the platform index to account for the release candidate.
+ platformIdx = 4;
+ if (numComponents >= 5)
+ {
+ platform = parsedComponents[4];
+ }
+ }
+ else // Platform string only
+ {
+ platform = tag;
+ }
}
// Platform revision
- if (numComponents < 5 || !TryParseComponent(parsedComponents[4], out revision))
+ if (numComponents > platformIdx + 1)
{
- revision = 0;
+ if (!TryParseComponent(parsedComponents[platformIdx + 1], out revision))
+ {
+ revision = 0;
+ }
}
// Minor platform revision
- if (numComponents < 6 || !TryParseComponent(parsedComponents[5], out minorRevision))
+ if (numComponents > platformIdx + 2)
{
- minorRevision = 0;
+ if (!TryParseComponent(parsedComponents[platformIdx + 2], out minorRevision))
+ {
+ minorRevision = 0;
+ }
}
- version = new GitVersion(major, minor, build, platform, revision, minorRevision);
+ version = new GitVersion(major, minor, build, releaseCandidate, platform, revision, minorRevision);
return true;
}
@@ -142,7 +156,12 @@ public bool IsLessThan(GitVersion other)
public override string ToString()
{
- return string.Format("{0}.{1}.{2}.{3}.{4}.{5}", this.Major, this.Minor, this.Build, this.Platform, this.Revision, this.MinorRevision);
+ if (ReleaseCandidate is null)
+ {
+ return $"{Major}.{Minor}.{Build}.{Platform}.{Revision}.{MinorRevision}";
+ }
+
+ return $"{Major}.{Minor}.{Build}.rc{ReleaseCandidate}.{Platform}.{Revision}.{MinorRevision}";
}
private static bool TryParseComponent(string component, out int parsedComponent)
@@ -182,6 +201,18 @@ private int CompareVersionNumbers(GitVersion other)
return this.Build.CompareTo(other.Build);
}
+ if (this.ReleaseCandidate != other.ReleaseCandidate)
+ {
+ if (this.ReleaseCandidate.HasValue && other.ReleaseCandidate.HasValue)
+ {
+ return this.ReleaseCandidate.Value.CompareTo(other.ReleaseCandidate.Value);
+ }
+
+ // If one version has a release candidate and the other does not,
+ // the one without a release candidate is considered "greater than" the one with.
+ return other.ReleaseCandidate.HasValue ? 1 : -1;
+ }
+
if (this.Revision != other.Revision)
{
return this.Revision.CompareTo(other.Revision);
diff --git a/GVFS/GVFS.Common/Git/LibGit2Repo.cs b/GVFS/GVFS.Common/Git/LibGit2Repo.cs
index c1056def3..0849dd6b7 100644
--- a/GVFS/GVFS.Common/Git/LibGit2Repo.cs
+++ b/GVFS/GVFS.Common/Git/LibGit2Repo.cs
@@ -41,24 +41,17 @@ protected LibGit2Repo()
protected ITracer Tracer { get; }
protected IntPtr RepoHandle { get; private set; }
- public bool IsBlob(string sha)
+ public Native.ObjectTypes? GetObjectType(string sha)
{
IntPtr objHandle;
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.SuccessCode)
{
- return false;
+ return null;
}
try
{
- switch (Native.Object.GetType(objHandle))
- {
- case Native.ObjectTypes.Blob:
- return true;
-
- default:
- return false;
- }
+ return Native.Object.GetType(objHandle);
}
finally
{
@@ -91,9 +84,9 @@ public virtual string GetTreeSha(string commitish)
return null;
}
- public virtual bool CommitAndRootTreeExists(string commitish)
+ public virtual bool CommitAndRootTreeExists(string commitish, out string treeSha)
{
- string treeSha = this.GetTreeSha(commitish);
+ treeSha = this.GetTreeSha(commitish);
if (treeSha == null)
{
return false;
diff --git a/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj b/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj
index 290a12b46..bb03a4171 100644
--- a/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj
+++ b/GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
Exe
diff --git a/GVFS/GVFS.FunctionalTests/GVFS.FunctionalTests.csproj b/GVFS/GVFS.FunctionalTests/GVFS.FunctionalTests.csproj
index 0a64e7440..f170451f4 100644
--- a/GVFS/GVFS.FunctionalTests/GVFS.FunctionalTests.csproj
+++ b/GVFS/GVFS.FunctionalTests/GVFS.FunctionalTests.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
Exe
diff --git a/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs b/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs
index 8aacac84a..76a77eb64 100644
--- a/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs
+++ b/GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs
@@ -63,19 +63,55 @@ public static ProcessResult InvokeGitAgainstGVFSRepo(
string command,
Dictionary environmentVariables = null,
bool removeWaitingMessages = true,
- bool removeUpgradeMessages = true)
+ bool removeUpgradeMessages = true,
+ bool removePartialHydrationMessages = true,
+ bool removeFSMonitorMessages = true)
{
ProcessResult result = GitProcess.InvokeProcess(gvfsRepoRoot, command, environmentVariables);
- string errors = result.Errors;
+ string output = FilterMessages(result.Output, false, false, false, removePartialHydrationMessages, removeFSMonitorMessages);
+ string errors = FilterMessages(result.Errors, true, removeWaitingMessages, removeUpgradeMessages, removePartialHydrationMessages, removeFSMonitorMessages);
- if (!string.IsNullOrEmpty(errors) && (removeWaitingMessages || removeUpgradeMessages))
+ return new ProcessResult(
+ output,
+ errors,
+ result.ExitCode);
+ }
+
+ private static IEnumerable SplitLinesKeepingNewlines(string input)
+ {
+ for (int start = 0; start < input.Length; )
{
- IEnumerable errorLines = errors.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
- IEnumerable filteredErrorLines = errorLines.Where(line =>
+ int nextLine = input.IndexOf('\n', start) + 1;
+
+ if (nextLine == 0)
{
- if (string.IsNullOrWhiteSpace(line) ||
+ // No more newlines, yield the rest
+ nextLine = input.Length;
+ }
+
+ yield return input.Substring(start, nextLine - start);
+ start = nextLine;
+ }
+ }
+
+ private static string FilterMessages(
+ string input,
+ bool removeEmptyLines,
+ bool removeWaitingMessages,
+ bool removeUpgradeMessages,
+ bool removePartialHydrationMessages,
+ bool removeFSMonitorMessages)
+ {
+ if (!string.IsNullOrEmpty(input) && (removeWaitingMessages || removeUpgradeMessages || removePartialHydrationMessages || removeFSMonitorMessages))
+ {
+ IEnumerable lines = SplitLinesKeepingNewlines(input);
+ IEnumerable filteredLines = lines.Where(line =>
+ {
+ if ((removeEmptyLines && string.IsNullOrWhiteSpace(line)) ||
(removeUpgradeMessages && line.StartsWith("A new version of VFS for Git is available.")) ||
- (removeWaitingMessages && line.StartsWith("Waiting for ")))
+ (removeWaitingMessages && line.StartsWith("Waiting for ")) ||
+ (removePartialHydrationMessages && line.StartsWith("You are in a partially-hydrated checkout with ")) ||
+ (removeFSMonitorMessages && line.TrimEnd().EndsWith(" is incompatible with fsmonitor")))
{
return false;
}
@@ -85,13 +121,10 @@ public static ProcessResult InvokeGitAgainstGVFSRepo(
}
});
- errors = filteredErrorLines.Any() ? string.Join(Environment.NewLine, filteredErrorLines) : string.Empty;
+ return filteredLines.Any() ? string.Join("", filteredLines) : string.Empty;
}
- return new ProcessResult(
- result.Output,
- errors,
- result.ExitCode);
+ return input;
}
public static void ValidateGitCommand(
diff --git a/GVFS/GVFS.GVFlt/GVFS.GVFlt.csproj b/GVFS/GVFS.GVFlt/GVFS.GVFlt.csproj
index a436520f9..97e2973e3 100644
--- a/GVFS/GVFS.GVFlt/GVFS.GVFlt.csproj
+++ b/GVFS/GVFS.GVFlt/GVFS.GVFlt.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
diff --git a/GVFS/GVFS.Hooks/GVFS.Hooks.csproj b/GVFS/GVFS.Hooks/GVFS.Hooks.csproj
index efe7842a7..23dd6ea97 100644
--- a/GVFS/GVFS.Hooks/GVFS.Hooks.csproj
+++ b/GVFS/GVFS.Hooks/GVFS.Hooks.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
diff --git a/GVFS/GVFS.Installers/GVFS.Installers.csproj b/GVFS/GVFS.Installers/GVFS.Installers.csproj
index bf0c5ec7f..4470aeaba 100644
--- a/GVFS/GVFS.Installers/GVFS.Installers.csproj
+++ b/GVFS/GVFS.Installers/GVFS.Installers.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
false
$(RepoOutPath)GVFS.Payload\bin\$(Configuration)\win-x64\
@@ -13,8 +13,6 @@
-
-
@@ -24,13 +22,8 @@
-
-
-
@@ -44,10 +37,6 @@
-
-
-
-
diff --git a/GVFS/GVFS.Installers/GVFS.Installers.template.nuspec b/GVFS/GVFS.Installers/GVFS.Installers.template.nuspec
deleted file mode 100644
index 8991bd81e..000000000
--- a/GVFS/GVFS.Installers/GVFS.Installers.template.nuspec
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- GVFS.Installers
- $version$
- Microsoft
- false
- GVFS and G4W installers
-
-
-
-
-
-
-
diff --git a/GVFS/GVFS.Installers/info.bat b/GVFS/GVFS.Installers/info.bat
index b068f9c69..ba61fbc7a 100644
--- a/GVFS/GVFS.Installers/info.bat
+++ b/GVFS/GVFS.Installers/info.bat
@@ -9,19 +9,31 @@ SET VFS_BUND_PROJFSLIB=C:\Program Files\VFS for Git\ProjFS\ProjectedFSLib.dll
SET VFS_EXEC=C:\Program Files\VFS for Git\GVFS.exe
SET GIT_EXEC=C:\Program Files\Git\cmd\git.exe
+REM Lookup the current Windows version
+FOR /F "tokens=*" %%i IN ('powershell -Command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"') DO SET OS_VER=%%i
+
+ECHO Print system information...
+ECHO OS version: %OS_VER%
+ECHO CPU architecture: %PROCESSOR_ARCHITECTURE%
+
+ECHO.
ECHO Checking ProjFS Windows feature...
powershell -Command "Get-WindowsOptionalFeature -Online -FeatureName Client-ProjFS"
+ECHO.
ECHO Checking ProjFS and GVFS services...
ECHO GVFS.Service:
sc query GVFS.Service
+ECHO.
ECHO Test.GVFS.Service:
sc query Test.GVFS.Service
+ECHO.
ECHO prjflt:
sc query prjflt
+ECHO.
ECHO Checking ProjFS files...
IF EXIST "%SYS_PRJFLT%" (
ECHO [ FOUND ] %SYS_PRJFLT%
diff --git a/GVFS/GVFS.Installers/install.bat b/GVFS/GVFS.Installers/install.bat
index c629c75bc..8375be193 100644
--- a/GVFS/GVFS.Installers/install.bat
+++ b/GVFS/GVFS.Installers/install.bat
@@ -1,8 +1,18 @@
@ECHO OFF
SETLOCAL
+REM Determine the correct architecture for the installer
+IF "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
+ SET GIT_ARCH=64-bit
+) ELSE IF "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
+ SET GIT_ARCH=arm64
+) ELSE (
+ ECHO Unknown architecture: %PROCESSOR_ARCHITECTURE%
+ exit 1
+)
+
REM Lookup full paths to Git and VFS for Git installers
-FOR /F "tokens=* USEBACKQ" %%F IN ( `where /R %~dp0 Git*.exe` ) DO SET GIT_INSTALLER=%%F
+FOR /F "tokens=* USEBACKQ" %%F IN ( `where /R %~dp0 Git*-%GIT_ARCH%.exe` ) DO SET GIT_INSTALLER=%%F
FOR /F "tokens=* USEBACKQ" %%F IN ( `where /R %~dp0 SetupGVFS*.exe` ) DO SET GVFS_INSTALLER=%%F
REM Create new empty directory for logs
@@ -12,7 +22,7 @@ IF EXIST %LOGDIR% (
)
mkdir %LOGDIR%
-ECHO Installing Git for Windows...
+ECHO Installing Git (%GIT_ARCH%)...
%GIT_INSTALLER% /LOG="%LOGDIR%\git.log" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /ALLOWDOWNGRADE=1
ECHO Installing VFS for Git...
diff --git a/GVFS/GVFS.Mount/GVFS.Mount.csproj b/GVFS/GVFS.Mount/GVFS.Mount.csproj
index 6e41c0008..83d89be63 100644
--- a/GVFS/GVFS.Mount/GVFS.Mount.csproj
+++ b/GVFS/GVFS.Mount/GVFS.Mount.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
diff --git a/GVFS/GVFS.Mount/InProcessMount.cs b/GVFS/GVFS.Mount/InProcessMount.cs
index a6f9710a8..a9dd95b70 100644
--- a/GVFS/GVFS.Mount/InProcessMount.cs
+++ b/GVFS/GVFS.Mount/InProcessMount.cs
@@ -14,8 +14,10 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
+using static GVFS.Common.Git.LibGit2Repo;
namespace GVFS.Mount
{
@@ -44,6 +46,9 @@ public class InProcessMount
private HeartbeatThread heartbeat;
private ManualResetEvent unmountEvent;
+ private readonly Dictionary treesWithDownloadedCommits = new Dictionary();
+ private DateTime lastCommitPackDownloadTime = DateTime.MinValue;
+
// True if InProcessMount is calling git reset as part of processing
// a folder dehydrate request
private volatile bool resetForDehydrateInProgress;
@@ -504,7 +509,21 @@ private void HandleDownloadObjectRequest(NamedPipeMessages.Message message, Name
else
{
Stopwatch downloadTime = Stopwatch.StartNew();
- if (this.gitObjects.TryDownloadAndSaveObject(objectSha, GVFSGitObjects.RequestSource.NamedPipeMessage) == GitObjects.DownloadAndSaveObjectResult.Success)
+
+ /* If this is the root tree for a commit that was was just downloaded, assume that more
+ * trees will be needed soon and download them as well by using the download commit API.
+ *
+ * Otherwise, or as a fallback if the commit download fails, download the object directly.
+ */
+ if (this.ShouldDownloadCommitPack(objectSha, out string commitSha)
+ && this.gitObjects.TryDownloadCommit(commitSha))
+ {
+ this.DownloadedCommitPack(objectSha: objectSha, commitSha: commitSha);
+ response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.SuccessResult);
+ // FUTURE: Should the stats be updated to reflect all the trees in the pack?
+ // FUTURE: Should we try to clean up duplicate trees or increase depth of the commit download?
+ }
+ else if (this.gitObjects.TryDownloadAndSaveObject(objectSha, GVFSGitObjects.RequestSource.NamedPipeMessage) == GitObjects.DownloadAndSaveObjectResult.Success)
{
response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.SuccessResult);
}
@@ -513,15 +532,59 @@ private void HandleDownloadObjectRequest(NamedPipeMessages.Message message, Name
response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.DownloadFailed);
}
- bool isBlob;
- this.context.Repository.TryGetIsBlob(objectSha, out isBlob);
- this.context.Repository.GVFSLock.Stats.RecordObjectDownload(isBlob, downloadTime.ElapsedMilliseconds);
+
+ Native.ObjectTypes? objectType;
+ this.context.Repository.TryGetObjectType(objectSha, out objectType);
+ this.context.Repository.GVFSLock.Stats.RecordObjectDownload(objectType == Native.ObjectTypes.Blob, downloadTime.ElapsedMilliseconds);
+
+ if (objectType == Native.ObjectTypes.Commit
+ && !this.PrefetchHasBeenDone()
+ && !this.context.Repository.CommitAndRootTreeExists(objectSha, out var treeSha)
+ && !string.IsNullOrEmpty(treeSha))
+ {
+ /* If a commit is downloaded, it wasn't prefetched.
+ * If any prefetch has been done, there is probably a commit in the prefetch packs that is close enough that
+ * loose object download of missing trees will be faster than downloading a pack of all the trees for the commit.
+ * Otherwise, the trees for the commit may be needed soon depending on the context.
+ * e.g. git log (without a pathspec) doesn't need trees, but git checkout does.
+ *
+ * Save the tree/commit so if the tree is requested soon we can download all the trees for the commit in a batch.
+ */
+ this.treesWithDownloadedCommits[treeSha] = objectSha;
+ }
}
}
connection.TrySendResponse(response.CreateMessage());
}
+ private bool PrefetchHasBeenDone()
+ {
+ var prefetchPacks = this.gitObjects.ReadPackFileNames(this.enlistment.GitPackRoot, GVFSConstants.PrefetchPackPrefix);
+ return prefetchPacks.Length > 0;
+ }
+
+ private bool ShouldDownloadCommitPack(string objectSha, out string commitSha)
+ {
+
+ if (!this.treesWithDownloadedCommits.TryGetValue(objectSha, out commitSha)
+ || this.PrefetchHasBeenDone())
+ {
+ return false;
+ }
+
+ /* This is a heuristic to prevent downloading multiple packs related to git history commands,
+ * since commits downloaded close together likely have similar trees. */
+ var timePassed = DateTime.UtcNow - this.lastCommitPackDownloadTime;
+ return (timePassed > TimeSpan.FromMinutes(5));
+ }
+
+ private void DownloadedCommitPack(string objectSha, string commitSha)
+ {
+ this.lastCommitPackDownloadTime = DateTime.UtcNow;
+ this.treesWithDownloadedCommits.Remove(objectSha);
+ }
+
private void HandlePostFetchJobRequest(NamedPipeMessages.Message message, NamedPipeServer.Connection connection)
{
NamedPipeMessages.RunPostFetchJob.Request request = new NamedPipeMessages.RunPostFetchJob.Request(message);
diff --git a/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj b/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj
index 87352d611..ae216cfae 100644
--- a/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj
+++ b/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj
@@ -17,19 +17,19 @@
{3771C555-B5C1-45E2-B8B7-2CEF1619CDC5}
Win32Proj
GVFSNativeTests
- 10.0.16299.0
+ 10.0
DynamicLibrary
true
- v142
+ v143
NotSet
DynamicLibrary
false
- v142
+ v143
true
NotSet
diff --git a/GVFS/GVFS.Payload/GVFS.Payload.csproj b/GVFS/GVFS.Payload/GVFS.Payload.csproj
index 1df5a3210..1311bc87d 100644
--- a/GVFS/GVFS.Payload/GVFS.Payload.csproj
+++ b/GVFS/GVFS.Payload/GVFS.Payload.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
false
diff --git a/GVFS/GVFS.Payload/layout.bat b/GVFS/GVFS.Payload/layout.bat
index de1c0df81..ebdae19c2 100644
--- a/GVFS/GVFS.Payload/layout.bat
+++ b/GVFS/GVFS.Payload/layout.bat
@@ -39,7 +39,7 @@ SET OUTPUT=%5
SET ROOT=%~dp0..\..
SET BUILD_OUT="%ROOT%\..\out"
-SET MANAGED_OUT_FRAGMENT=bin\%CONFIGURATION%\net461\win-x64
+SET MANAGED_OUT_FRAGMENT=bin\%CONFIGURATION%\net471\win-x64
SET NATIVE_OUT_FRAGMENT=bin\x64\%CONFIGURATION%
ECHO Copying files...
diff --git a/GVFS/GVFS.PerfProfiling/GVFS.PerfProfiling.csproj b/GVFS/GVFS.PerfProfiling/GVFS.PerfProfiling.csproj
index de092f981..bf3ce6850 100644
--- a/GVFS/GVFS.PerfProfiling/GVFS.PerfProfiling.csproj
+++ b/GVFS/GVFS.PerfProfiling/GVFS.PerfProfiling.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
diff --git a/GVFS/GVFS.Platform.Windows/GVFS.Platform.Windows.csproj b/GVFS/GVFS.Platform.Windows/GVFS.Platform.Windows.csproj
index 5cbd7e174..f8fb56597 100644
--- a/GVFS/GVFS.Platform.Windows/GVFS.Platform.Windows.csproj
+++ b/GVFS/GVFS.Platform.Windows/GVFS.Platform.Windows.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
diff --git a/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj b/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj
index 0537dfaf1..3808ff027 100644
--- a/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj
+++ b/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj
@@ -14,7 +14,7 @@
{24D161E9-D1F0-4299-BBD3-5D940BEDD535}
Win32Proj
GVFSPostIndexChangedHook
- 10.0.16299.0
+ 10.0
GVFS.PostIndexChangedHook
GVFS.PostIndexChangedHook
@@ -22,13 +22,13 @@
Application
true
- v142
+ v143
MultiByte
Application
false
- v142
+ v143
true
MultiByte
diff --git a/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj b/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj
index 613e9d9a7..09e9e6616 100644
--- a/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj
+++ b/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj
@@ -14,7 +14,7 @@
{5A6656D5-81C7-472C-9DC8-32D071CB2258}
Win32Proj
readobject
- 10.0.16299.0
+ 10.0
GVFS.ReadObjectHook
GVFS.ReadObjectHook
@@ -22,13 +22,13 @@
Application
true
- v142
+ v143
MultiByte
Application
false
- v142
+ v143
true
MultiByte
diff --git a/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj b/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj
index 90589d933..48e5c1605 100644
--- a/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj
+++ b/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
diff --git a/GVFS/GVFS.Service/GVFS.Service.csproj b/GVFS/GVFS.Service/GVFS.Service.csproj
index 821141326..c24eb6505 100644
--- a/GVFS/GVFS.Service/GVFS.Service.csproj
+++ b/GVFS/GVFS.Service/GVFS.Service.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
true
diff --git a/GVFS/GVFS.Tests/GVFS.Tests.csproj b/GVFS/GVFS.Tests/GVFS.Tests.csproj
index c02954c26..c8c173ebf 100644
--- a/GVFS/GVFS.Tests/GVFS.Tests.csproj
+++ b/GVFS/GVFS.Tests/GVFS.Tests.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
diff --git a/GVFS/GVFS.UnitTests/Common/GitVersionTests.cs b/GVFS/GVFS.UnitTests/Common/GitVersionTests.cs
index a69bd8f7e..3d349ad00 100644
--- a/GVFS/GVFS.UnitTests/Common/GitVersionTests.cs
+++ b/GVFS/GVFS.UnitTests/Common/GitVersionTests.cs
@@ -1,5 +1,4 @@
-using GVFS.Common;
-using GVFS.Common.Git;
+using GVFS.Common.Git;
using GVFS.Tests.Should;
using NUnit.Framework;
@@ -8,14 +7,6 @@ namespace GVFS.UnitTests.Common
[TestFixture]
public class GitVersionTests
{
- [TestCase]
- public void TryParseInstallerName()
- {
- this.ParseAndValidateInstallerVersion("Git-1.2.3.gvfs.4.5.gb16030b-64-bit" + GVFSPlatform.Instance.Constants.InstallerExtension);
- this.ParseAndValidateInstallerVersion("git-1.2.3.gvfs.4.5.gb16030b-64-bit" + GVFSPlatform.Instance.Constants.InstallerExtension);
- this.ParseAndValidateInstallerVersion("Git-1.2.3.gvfs.4.5.gb16030b-64-bit" + GVFSPlatform.Instance.Constants.InstallerExtension);
- }
-
[TestCase]
public void Version_Data_Null_Returns_False()
{
@@ -118,6 +109,46 @@ public void Compare_Version_Minor_Greater()
version1.IsEqualTo(version2).ShouldEqual(false);
}
+ [TestCase]
+ public void Compare_ReleaseCandidate_Less()
+ {
+ GitVersion version1 = new GitVersion(1, 2, 3, 1, "test", 4, 1);
+ GitVersion version2 = new GitVersion(1, 2, 3, 2, "test", 4, 1);
+
+ version1.IsLessThan(version2).ShouldEqual(true);
+ version1.IsEqualTo(version2).ShouldEqual(false);
+ }
+
+ [TestCase]
+ public void Compare_ReleaseCandidate_Greater()
+ {
+ GitVersion version1 = new GitVersion(1, 2, 3, 2, "test", 4, 1);
+ GitVersion version2 = new GitVersion(1, 2, 3, 1, "test", 4, 1);
+
+ version1.IsLessThan(version2).ShouldEqual(false);
+ version1.IsEqualTo(version2).ShouldEqual(false);
+ }
+
+ [TestCase]
+ public void Compare_ReleaseCandidate_NonRC_Less()
+ {
+ GitVersion version1 = new GitVersion(1, 2, 3, 0, "test", 4, 1);
+ GitVersion version2 = new GitVersion(1, 2, 3, null, "test", 4, 1);
+
+ version1.IsLessThan(version2).ShouldEqual(true);
+ version1.IsEqualTo(version2).ShouldEqual(false);
+ }
+
+ [TestCase]
+ public void Compare_ReleaseCandidate_NonRC_Greater()
+ {
+ GitVersion version1 = new GitVersion(1, 2, 3, null, "test", 4, 1);
+ GitVersion version2 = new GitVersion(1, 2, 3, 0, "test", 4, 1);
+
+ version1.IsLessThan(version2).ShouldEqual(false);
+ version1.IsEqualTo(version2).ShouldEqual(false);
+ }
+
[TestCase]
public void Compare_Version_Build_Less()
{
@@ -187,6 +218,7 @@ public void Allow_Blank_Minor_Revision()
version.Major.ShouldEqual(1);
version.Minor.ShouldEqual(2);
version.Build.ShouldEqual(3);
+ version.ReleaseCandidate.ShouldEqual(null);
version.Platform.ShouldEqual("test");
version.Revision.ShouldEqual(4);
version.MinorRevision.ShouldEqual(0);
@@ -201,21 +233,23 @@ public void Allow_Invalid_Minor_Revision()
version.Major.ShouldEqual(1);
version.Minor.ShouldEqual(2);
version.Build.ShouldEqual(3);
+ version.ReleaseCandidate.ShouldEqual(null);
version.Platform.ShouldEqual("test");
version.Revision.ShouldEqual(4);
version.MinorRevision.ShouldEqual(0);
}
- private void ParseAndValidateInstallerVersion(string installerName)
+ [TestCase]
+ public void Allow_ReleaseCandidates()
{
GitVersion version;
- bool success = GitVersion.TryParseInstallerName(installerName, GVFSPlatform.Instance.Constants.InstallerExtension, out version);
- success.ShouldBeTrue();
+ GitVersion.TryParseVersion("1.2.3.rc2.test.4.5", out version).ShouldEqual(true);
version.Major.ShouldEqual(1);
version.Minor.ShouldEqual(2);
version.Build.ShouldEqual(3);
- version.Platform.ShouldEqual("gvfs");
+ version.ReleaseCandidate.ShouldEqual(2);
+ version.Platform.ShouldEqual("test");
version.Revision.ShouldEqual(4);
version.MinorRevision.ShouldEqual(5);
}
diff --git a/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj b/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj
index fe7648aac..890714857 100644
--- a/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj
+++ b/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
Exe
true
@@ -21,6 +21,11 @@
+
+
+
+
+
diff --git a/GVFS/GVFS.UnitTests/Mock/Git/MockLibGit2Repo.cs b/GVFS/GVFS.UnitTests/Mock/Git/MockLibGit2Repo.cs
index c2494ba3f..990199561 100644
--- a/GVFS/GVFS.UnitTests/Mock/Git/MockLibGit2Repo.cs
+++ b/GVFS/GVFS.UnitTests/Mock/Git/MockLibGit2Repo.cs
@@ -12,8 +12,9 @@ public MockLibGit2Repo(ITracer tracer)
{
}
- public override bool CommitAndRootTreeExists(string commitish)
+ public override bool CommitAndRootTreeExists(string commitish, out string treeSha)
{
+ treeSha = string.Empty;
return false;
}
diff --git a/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj b/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj
index 8fb0cdb17..9390120db 100644
--- a/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj
+++ b/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj
@@ -14,7 +14,7 @@
{2D23AB54-541F-4ABC-8DCA-08C199E97ABB}
Win32Proj
GVFSVirtualFileSystemHook
- 10.0.16299.0
+ 10.0
GVFS.VirtualFileSystemHook
GVFS.VirtualFileSystemHook
@@ -22,13 +22,13 @@
Application
true
- v142
+ v143
MultiByte
Application
false
- v142
+ v143
true
MultiByte
diff --git a/GVFS/GVFS.Virtualization/GVFS.Virtualization.csproj b/GVFS/GVFS.Virtualization/GVFS.Virtualization.csproj
index bc5fa77f8..91772d269 100644
--- a/GVFS/GVFS.Virtualization/GVFS.Virtualization.csproj
+++ b/GVFS/GVFS.Virtualization/GVFS.Virtualization.csproj
@@ -1,7 +1,7 @@
- net461
+ net471
true
diff --git a/GVFS/GVFS/CommandLine/CloneVerb.cs b/GVFS/GVFS/CommandLine/CloneVerb.cs
index 47d7d3f97..e81030837 100644
--- a/GVFS/GVFS/CommandLine/CloneVerb.cs
+++ b/GVFS/GVFS/CommandLine/CloneVerb.cs
@@ -215,20 +215,40 @@ public override void Execute()
{
if (!this.NoPrefetch)
{
- ReturnCode result = this.Execute(
- enlistment,
- verb =>
+ bool trustPackIndexes = enlistment.GetTrustPackIndexesConfig();
+ /* If pack indexes are not trusted, the prefetch can take a long time.
+ * We will run the prefetch command in the background.
+ */
+ if (trustPackIndexes)
+ {
+ ReturnCode result = this.Execute(
+ enlistment,
+ verb =>
+ {
+ verb.Commits = true;
+ verb.SkipVersionCheck = true;
+ verb.ResolvedCacheServer = cacheServer;
+ verb.ServerGVFSConfig = serverGVFSConfig;
+ });
+
+ if (result != ReturnCode.Success)
{
- verb.Commits = true;
- verb.SkipVersionCheck = true;
- verb.ResolvedCacheServer = cacheServer;
- verb.ServerGVFSConfig = serverGVFSConfig;
- });
+ this.Output.WriteLine("\r\nError during prefetch @ {0}", fullEnlistmentRootPathParameter);
+ exitCode = (int)result;
+ }
+ }
- if (result != ReturnCode.Success)
+ else
{
- this.Output.WriteLine("\r\nError during prefetch @ {0}", fullEnlistmentRootPathParameter);
- exitCode = (int)result;
+ Process.Start(new ProcessStartInfo(
+ fileName: "gvfs",
+ arguments: "prefetch --commits")
+ {
+ UseShellExecute = true,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ WorkingDirectory = enlistment.EnlistmentRoot
+ });
+ this.Output.WriteLine("\r\nPrefetch of commit graph has been started as a background process. Git operations involving history may be slower until prefetch has completed.\r\n");
}
}
@@ -247,7 +267,7 @@ public override void Execute()
verb.SkipVersionCheck = true;
verb.ResolvedCacheServer = cacheServer;
verb.DownloadedGVFSConfig = serverGVFSConfig;
- });
+ });
}
}
else
diff --git a/GVFS/GVFS/CommandLine/GVFSVerb.cs b/GVFS/GVFS/CommandLine/GVFSVerb.cs
index cdf9e920e..a9fcb9587 100644
--- a/GVFS/GVFS/CommandLine/GVFSVerb.cs
+++ b/GVFS/GVFS/CommandLine/GVFSVerb.cs
@@ -663,7 +663,7 @@ protected bool TryDownloadCommit(
out string error,
bool checkLocalObjectCache = true)
{
- if (!checkLocalObjectCache || !repo.CommitAndRootTreeExists(commitId))
+ if (!checkLocalObjectCache || !repo.CommitAndRootTreeExists(commitId, out _))
{
if (!gitObjects.TryDownloadCommit(commitId))
{
diff --git a/GVFS/GVFS/GVFS.csproj b/GVFS/GVFS/GVFS.csproj
index 6d9d579f9..892bc1386 100644
--- a/GVFS/GVFS/GVFS.csproj
+++ b/GVFS/GVFS/GVFS.csproj
@@ -2,7 +2,7 @@
Exe
- net461
+ net471
diff --git a/GVFS/GitHooksLoader/GitHooksLoader.vcxproj b/GVFS/GitHooksLoader/GitHooksLoader.vcxproj
index 78a51bf7f..0c4d4fbdf 100644
--- a/GVFS/GitHooksLoader/GitHooksLoader.vcxproj
+++ b/GVFS/GitHooksLoader/GitHooksLoader.vcxproj
@@ -14,19 +14,19 @@
{798DE293-6EDA-4DC4-9395-BE7A71C563E3}
Win32Proj
GitHooksLoader
- 10.0.16299.0
+ 10.0
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
diff --git a/Readme.md b/Readme.md
index 2ee0517b9..e388634e5 100644
--- a/Readme.md
+++ b/Readme.md
@@ -42,15 +42,15 @@ will notify you when new versions are available.
## Building VFS for Git
If you'd like to build your own VFS for Git Windows installer:
-* Install Visual Studio 2017 Community Edition or higher (https://www.visualstudio.com/downloads/).
+* Install Visual Studio 2022 Community Edition or higher (https://www.visualstudio.com/downloads/).
* Include the following workloads:
* .NET desktop development
* Desktop development with C++
* .NET Core cross-platform development
* Include the following additional components:
* .NET Core runtime
- * Windows 10 SDK (10.0.10240.0)
-* Install the .NET Core 2.1 SDK (https://www.microsoft.com/net/download/dotnet-core/2.1)
+ * Windows 10 or 11 SDK (10.0+)
+* Install the .NET Core 8 SDK (https://www.microsoft.com/net/download/dotnet-core/8)
* Install [`nuget.exe`](https://www.nuget.org/downloads)
* Create a folder to clone into, e.g. `C:\Repos\VFSForGit`
* Clone this repo into the `src` subfolder, e.g. `C:\Repos\VFSForGit\src`
@@ -59,13 +59,7 @@ If you'd like to build your own VFS for Git Windows installer:
build will fail, and the second and subsequent builds will succeed. This is because the build requires a prebuild code generation step.
For details, see the build script in the previous step.
-You can also use Visual Studio 2019. There are a couple of options for getting all the dependencies.
-* You can install Visual Studio 2017 side by side with Visual Studio 2019, and make sure that you have all the dependencies from Visual Studio 2017 installed
-* Alternatively, if you only want to have Visual Studio 2019 installed, install the following extra dependencies:
- * MSVC v141 VS 2017 C++ build tools via the optional components in the Visual Studio 2019 installer. It is under the "Desktop Development with C++" heading.
- * Windows 10 SDK (10.0.10240.0) via the archived SDK page: https://developer.microsoft.com/en-us/windows/downloads/sdk-archive
-
-Visual Studio 2019 will [automatically prompt you to install these dependencies](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/) when you open the solution. The .vsconfig file that is present in the root of the repository specifies all required components _except_ the Windows 10 SDK (10.0.10240.0) as this component is no longer shipped with VS2019 - **you'll still need to install that separately**.
+Visual Studio 2022 will [automatically prompt you to install these dependencies](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/) when you open the solution. The .vsconfig file that is present in the root of the repository specifies all required components.
The installer can now be found at `C:\Repos\VFSForGit\BuildOutput\GVFS.Installer.Windows\bin\x64\[Debug|Release]\SetupGVFS..exe`
diff --git a/Version.props b/Version.props
index 1547245ce..d1f6f341b 100644
--- a/Version.props
+++ b/Version.props
@@ -5,10 +5,8 @@
0.2.173.2
- 2.20220414.4
v2.31.0.vfs.0.1
diff --git a/scripts/CreateBuildArtifacts.bat b/scripts/CreateBuildArtifacts.bat
index a7ba9795e..797ed0bf9 100644
--- a/scripts/CreateBuildArtifacts.bat
+++ b/scripts/CreateBuildArtifacts.bat
@@ -14,13 +14,6 @@ IF "%~2"=="" (
SET OUTROOT=%2
)
-REM Check NuGet is on the PATH
-where /q nuget.exe
-IF ERRORLEVEL 1 (
- ECHO ERROR: Could not find nuget.exe on the PATH
- EXIT /B 1
-)
-
IF EXIST %OUTROOT% (
rmdir /s /q %OUTROOT%
)
@@ -49,7 +42,7 @@ ECHO ^************************
ECHO Collecting FastFetch...
mkdir %OUTROOT%\FastFetch
xcopy /S /Y ^
- %VFS_OUTDIR%\FastFetch\bin\%CONFIGURATION%\net461\win-x64 ^
+ %VFS_OUTDIR%\FastFetch\bin\%CONFIGURATION%\net471\win-x64 ^
%OUTROOT%\FastFetch\ || GOTO ERROR
ECHO ^***********************************
@@ -57,22 +50,9 @@ ECHO ^* Collecting GVFS.FunctionalTests *
ECHO ^***********************************
mkdir %OUTROOT%\GVFS.FunctionalTests
xcopy /S /Y ^
- %VFS_OUTDIR%\GVFS.FunctionalTests\bin\%CONFIGURATION%\net461\win-x64 ^
+ %VFS_OUTDIR%\GVFS.FunctionalTests\bin\%CONFIGURATION%\net471\win-x64 ^
%OUTROOT%\GVFS.FunctionalTests\ || GOTO ERROR
-ECHO ^*************************************
-ECHO ^* Creating Installers NuGet Package *
-ECHO ^*************************************
-mkdir %OUTROOT%\NuGetPackages
-nuget.exe pack ^
- %VFS_OUTDIR%\GVFS.Installers\bin\%CONFIGURATION%\win-x64\GVFS.Installers.nuspec ^
- -BasePath %VFS_OUTDIR%\GVFS.Installers\bin\%CONFIGURATION%\win-x64 ^
- -OutputDirectory %OUTROOT%\NuGetPackages || GOTO ERROR
-
-REM Move the nuspec file to the NuGetPackages artifact directory
-move %OUTROOT%\GVFS.Installers\GVFS.Installers.nuspec ^
- %OUTROOT%\NuGetPackages
-
GOTO :EOF
:USAGE
diff --git a/scripts/RunFunctionalTests.bat b/scripts/RunFunctionalTests.bat
index 80ab7e1e4..ef86a74f8 100644
--- a/scripts/RunFunctionalTests.bat
+++ b/scripts/RunFunctionalTests.bat
@@ -27,7 +27,7 @@ IF NOT %ERRORLEVEL% == 0 (
ECHO error: unable to locate Git on the PATH (has it been installed?)
)
-%VFS_OUTDIR%\GVFS.FunctionalTests\bin\%CONFIGURATION%\net461\win-x64\GVFS.FunctionalTests.exe /result:TestResult.xml %2 %3 %4 %5
+%VFS_OUTDIR%\GVFS.FunctionalTests\bin\%CONFIGURATION%\net471\win-x64\GVFS.FunctionalTests.exe /result:TestResult.xml %2 %3 %4 %5
SET error=%ERRORLEVEL%
CALL %VFS_SCRIPTSDIR%\StopAllServices.bat
diff --git a/scripts/RunUnitTests.bat b/scripts/RunUnitTests.bat
index f9f684580..3424825ca 100644
--- a/scripts/RunUnitTests.bat
+++ b/scripts/RunUnitTests.bat
@@ -5,6 +5,6 @@ IF "%1"=="" (SET "CONFIGURATION=Debug") ELSE (SET "CONFIGURATION=%1")
SET RESULT=0
-%VFS_OUTDIR%\GVFS.UnitTests\bin\%CONFIGURATION%\net461\win-x64\GVFS.UnitTests.exe || SET RESULT=1
+%VFS_OUTDIR%\GVFS.UnitTests\bin\%CONFIGURATION%\net471\win-x64\GVFS.UnitTests.exe || SET RESULT=1
EXIT /b %RESULT%