├── .azure-pipelines └── release.yml ├── .editorconfig ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── build.yaml │ └── release-winget.yaml ├── .gitignore ├── .vsconfig ├── AuthoringTests.md ├── CONTRIBUTING.md ├── Directory.Build.props ├── Directory.Build.targets ├── Directory.Solution.props ├── GVFS.sln ├── GVFS ├── FastFetch │ ├── CheckoutPrefetcher.cs │ ├── CheckoutStage.cs │ ├── FastFetch.csproj │ ├── FastFetchLibGit2Repo.cs │ ├── FastFetchVerb.cs │ ├── GitEnlistment.cs │ ├── Index.cs │ ├── IndexLock.cs │ ├── NativeMethods.cs │ ├── Program.cs │ └── WorkingTree.cs ├── GVFS.Common │ ├── AzDevOpsOrgFromNuGetFeed.cs │ ├── ConcurrentHashSet.cs │ ├── ConsoleHelper.cs │ ├── Database │ │ ├── GVFSDatabase.cs │ │ ├── GVFSDatabaseException.cs │ │ ├── IDbCommandExtensions.cs │ │ ├── IDbConnectionFactory.cs │ │ ├── IGVFSConnectionPool.cs │ │ ├── IPlaceholderCollection.cs │ │ ├── IPlaceholderData.cs │ │ ├── ISparseCollection.cs │ │ ├── PlaceholderTable.cs │ │ ├── SparseTable.cs │ │ └── SqliteDatabase.cs │ ├── DiskLayoutUpgrades │ │ ├── DiskLayoutUpgrade.cs │ │ ├── DiskLayoutUpgrade_SqlitePlaceholders.cs │ │ └── DiskLayoutVersion.cs │ ├── Enlistment.cs │ ├── EpochConverter.cs │ ├── FileBasedCollection.cs │ ├── FileBasedCollectionException.cs │ ├── FileBasedDictionary.cs │ ├── FileBasedLock.cs │ ├── FileSystem │ │ ├── DirectoryItemInfo.cs │ │ ├── FileProperties.cs │ │ ├── FlushToDiskFileStream.cs │ │ ├── HooksInstaller.cs │ │ ├── IKernelDriver.cs │ │ ├── IPlatformFileSystem.cs │ │ └── PhysicalFileSystem.cs │ ├── GVFS.Common.csproj │ ├── GVFSConstants.cs │ ├── GVFSContext.cs │ ├── GVFSEnlistment.Shared.cs │ ├── GVFSEnlistment.cs │ ├── GVFSLock.Shared.cs │ ├── GVFSLock.cs │ ├── GVFSPlatform.cs │ ├── Git │ │ ├── DiffTreeResult.cs │ │ ├── EndianHelper.cs │ │ ├── GVFSGitObjects.cs │ │ ├── GitAuthentication.cs │ │ ├── GitConfigHelper.cs │ │ ├── GitConfigSetting.cs │ │ ├── GitIndexGenerator.cs │ │ ├── GitObjectContentType.cs │ │ ├── GitObjects.cs │ │ ├── GitOid.cs │ │ ├── GitPathConverter.cs │ │ ├── GitProcess.cs │ │ ├── GitRefs.cs │ │ ├── GitRepo.cs │ │ ├── GitSsl.cs │ │ ├── GitVersion.cs │ │ ├── HashingStream.cs │ │ ├── ICredentialStore.cs │ │ ├── IGitInstallation.cs │ │ ├── LibGit2Repo.cs │ │ ├── LibGit2RepoInvoker.cs │ │ ├── NoOpStream.cs │ │ ├── RefLogEntry.cs │ │ ├── Sha1Id.cs │ │ └── SideChannelStream.cs │ ├── GitCommandLineParser.cs │ ├── GitStatusCache.cs │ ├── GitStatusCacheConfig.cs │ ├── HealthCalculator │ │ ├── EnlistmentHealthCalculator.cs │ │ ├── EnlistmentHealthData.cs │ │ └── EnlistmentPathData.cs │ ├── HeartbeatThread.cs │ ├── Http │ │ ├── CacheServerInfo.cs │ │ ├── CacheServerResolver.cs │ │ ├── ConfigHttpRequestor.cs │ │ ├── GitEndPointResponseData.cs │ │ ├── GitObjectsHttpException.cs │ │ ├── GitObjectsHttpRequestor.cs │ │ └── HttpRequestor.cs │ ├── IDiskLayoutUpgradeData.cs │ ├── IHeartBeatMetadataProvider.cs │ ├── IProcessRunner.cs │ ├── InternalVerbParameters.cs │ ├── InternalsVisibleTo.cs │ ├── InvalidRepoException.cs │ ├── LegacyPlaceholderListDatabase.cs │ ├── LocalCacheResolver.cs │ ├── LocalGVFSConfig.cs │ ├── Maintenance │ │ ├── GitMaintenanceQueue.cs │ │ ├── GitMaintenanceScheduler.cs │ │ ├── GitMaintenanceStep.cs │ │ ├── GitProcessChecker.cs │ │ ├── LooseObjectsStep.cs │ │ ├── PackfileMaintenanceStep.cs │ │ ├── PostFetchStep.cs │ │ └── PrefetchStep.cs │ ├── ModifiedPathsDatabase.cs │ ├── NamedPipes │ │ ├── AllowAllLocksNamedPipeServer.cs │ │ ├── BrokenPipeException.cs │ │ ├── LockNamedPipeMessages.cs │ │ ├── NamedPipeClient.cs │ │ ├── NamedPipeMessages.cs │ │ ├── NamedPipeServer.cs │ │ ├── NamedPipeStreamReader.cs │ │ ├── NamedPipeStreamWriter.cs │ │ └── PipeNameLengthException.cs │ ├── NativeMethods.Shared.cs │ ├── NativeMethods.cs │ ├── NetworkStreams │ │ ├── BatchedLooseObjectDeserializer.cs │ │ ├── PrefetchPacksDeserializer.cs │ │ └── RestrictedStream.cs │ ├── OrgInfoApiClient.cs │ ├── Paths.Shared.cs │ ├── Prefetch │ │ ├── BlobPrefetcher.cs │ │ ├── Git │ │ │ ├── DiffHelper.cs │ │ │ ├── PathWithMode.cs │ │ │ └── PrefetchGitObjects.cs │ │ └── Pipeline │ │ │ ├── BatchObjectDownloadStage.cs │ │ │ ├── Data │ │ │ ├── BlobDownloadRequest.cs │ │ │ ├── IndexPackRequest.cs │ │ │ └── TreeSearchRequest.cs │ │ │ ├── FindBlobsStage.cs │ │ │ ├── HydrateFilesStage.cs │ │ │ ├── IndexPackStage.cs │ │ │ └── PrefetchPipelineStage.cs │ ├── ProcessHelper.cs │ ├── ProcessResult.cs │ ├── ProcessRunnerImpl.cs │ ├── RepoMetadata.cs │ ├── RetryBackoff.cs │ ├── RetryConfig.cs │ ├── RetryWrapper.cs │ ├── RetryableException.cs │ ├── ReturnCode.cs │ ├── SHA1Util.cs │ ├── ServerGVFSConfig.cs │ ├── StreamUtil.cs │ ├── Tracing │ │ ├── DiagnosticConsoleEventListener.cs │ │ ├── EventLevel.cs │ │ ├── EventListener.cs │ │ ├── EventMetadata.cs │ │ ├── EventOpcode.cs │ │ ├── IEventListenerEventSink.cs │ │ ├── IQueuedPipeStringWriterEventSink.cs │ │ ├── ITracer.cs │ │ ├── JsonTracer.cs │ │ ├── Keywords.cs │ │ ├── LogFileEventListener.cs │ │ ├── PrettyConsoleEventListener.cs │ │ ├── QueuedPipeStringWriter.cs │ │ ├── TelemetryDaemonEventListener.cs │ │ ├── TraceEventMessage.cs │ │ └── TracingConstants.cs │ ├── VersionResponse.cs │ └── X509Certificates │ │ ├── CertificateVerifier.cs │ │ └── SystemCertificateStore.cs ├── GVFS.FunctionalTests.LockHolder │ ├── AcquireGVFSLock.cs │ ├── GVFS.FunctionalTests.LockHolder.csproj │ └── Program.cs ├── GVFS.FunctionalTests │ ├── AssemblyAttributes.cs │ ├── Categories.cs │ ├── FileSystemRunners │ │ ├── BashRunner.cs │ │ ├── CmdRunner.cs │ │ ├── FileSystemRunner.cs │ │ ├── PowerShellRunner.cs │ │ ├── ShellRunner.cs │ │ └── SystemIORunner.cs │ ├── GVFS.FunctionalTests.csproj │ ├── GVFSTestConfig.cs │ ├── GlobalSetup.cs │ ├── Program.cs │ ├── Settings.cs │ ├── Should │ │ └── FileSystemShouldExtensions.cs │ ├── Tests │ │ ├── DiskLayoutVersionTests.cs │ │ ├── EnlistmentPerFixture │ │ │ ├── BasicFileSystemTests.cs │ │ │ ├── CacheServerTests.cs │ │ │ ├── CloneTests.cs │ │ │ ├── DehydrateTests.cs │ │ │ ├── DiagnoseTests.cs │ │ │ ├── GVFSLockTests.cs │ │ │ ├── GVFSUpgradeReminderTests.cs │ │ │ ├── GitBlockCommandsTests.cs │ │ │ ├── GitCorruptObjectTests.cs │ │ │ ├── GitFilesTests.cs │ │ │ ├── GitMoveRenameTests.cs │ │ │ ├── GitReadAndGitLockTests.cs │ │ │ ├── HealthTests.cs │ │ │ ├── MountTests.cs │ │ │ ├── MoveRenameFileTests.cs │ │ │ ├── MoveRenameFileTests_2.cs │ │ │ ├── MoveRenameFolderTests.cs │ │ │ ├── MultithreadedReadWriteTests.cs │ │ │ ├── ParallelHydrationTests.cs │ │ │ ├── PrefetchVerbTests.cs │ │ │ ├── PrefetchVerbWithoutSharedCacheTests.cs │ │ │ ├── SparseTests.cs │ │ │ ├── StatusVerbTests.cs │ │ │ ├── SymbolicLinkTests.cs │ │ │ ├── TestsWithEnlistmentPerFixture.cs │ │ │ ├── UnmountTests.cs │ │ │ ├── UpdatePlaceholderTests.cs │ │ │ └── WorkingDirectoryTests.cs │ │ ├── EnlistmentPerTestCase │ │ │ ├── DiskLayoutUpgradeTests.cs │ │ │ ├── LooseObjectStepTests.cs │ │ │ ├── ModifiedPathsTests.cs │ │ │ ├── PersistedWorkingDirectoryTests.cs │ │ │ ├── RepairTests.cs │ │ │ └── TestsWithEnlistmentPerTestCase.cs │ │ ├── FastFetchTests.cs │ │ ├── GVFSVerbTests.cs │ │ ├── GitCommands │ │ │ ├── AddStageTests.cs │ │ │ ├── CheckoutTests.cs │ │ │ ├── CherryPickConflictTests.cs │ │ │ ├── CreatePlaceholderTests.cs │ │ │ ├── DeleteEmptyFolderTests.cs │ │ │ ├── EnumerationMergeTest.cs │ │ │ ├── GitCommandsTests.cs │ │ │ ├── GitRepoTests.cs │ │ │ ├── HashObjectTests.cs │ │ │ ├── MergeConflictTests.cs │ │ │ ├── RebaseConflictTests.cs │ │ │ ├── RebaseTests.cs │ │ │ ├── ResetHardTests.cs │ │ │ ├── ResetMixedTests.cs │ │ │ ├── ResetSoftTests.cs │ │ │ ├── RmTests.cs │ │ │ ├── StatusTests.cs │ │ │ ├── UpdateIndexTests.cs │ │ │ └── UpdateRefTests.cs │ │ ├── MultiEnlistmentTests │ │ │ ├── ConfigVerbTests.cs │ │ │ ├── ServiceVerbTests.cs │ │ │ ├── SharedCacheTests.cs │ │ │ └── TestsWithMultiEnlistment.cs │ │ ├── PrintTestCaseStats.cs │ │ └── TestResultsHelper.cs │ ├── Tools │ │ ├── ControlGitRepo.cs │ │ ├── FileSystemHelpers.cs │ │ ├── GVFSFunctionalTestEnlistment.cs │ │ ├── GVFSHelpers.cs │ │ ├── GVFSProcess.cs │ │ ├── GVFSServiceProcess.cs │ │ ├── GitHelpers.cs │ │ ├── GitProcess.cs │ │ ├── NativeMethods.cs │ │ ├── ProcessHelper.cs │ │ ├── ProcessResult.cs │ │ ├── ProjFSFilterInstaller.cs │ │ ├── RepositoryHelpers.cs │ │ └── TestConstants.cs │ └── Windows │ │ ├── TestData │ │ └── BackgroundGitUpdates │ │ │ ├── PersistentDictionary.edb │ │ │ ├── PersistentDictionary.jfm │ │ │ ├── epc.chk │ │ │ ├── epcres00001.jrs │ │ │ └── epcres00002.jrs │ │ ├── Tests │ │ ├── JunctionAndSubstTests.cs │ │ ├── ServiceTests.cs │ │ ├── SharedCacheUpgradeTests.cs │ │ ├── WindowsDiskLayoutUpgradeTests.cs │ │ ├── WindowsFileSystemTests.cs │ │ ├── WindowsFolderUsnUpdate.cs │ │ ├── WindowsTombstoneTests.cs │ │ └── WindowsUpdatePlaceholderTests.cs │ │ └── Tools │ │ ├── ESENTDatabase.cs │ │ └── RegistryHelper.cs ├── GVFS.GVFlt │ ├── GVFS.GVFlt.csproj │ └── GVFltCallbacks.cs ├── GVFS.Hooks │ ├── GVFS.Hooks.csproj │ ├── HooksPlatform │ │ └── GVFSHooksPlatform.cs │ ├── KnownGitCommands.cs │ └── Program.cs ├── GVFS.Installers │ ├── GVFS.Installers.csproj │ ├── GVFS.Installers.template.nuspec │ ├── Setup.iss │ ├── info.bat │ └── install.bat ├── GVFS.MSBuild │ ├── CompileTemplatedFile.cs │ ├── GVFS.MSBuild.csproj │ ├── GVFS.targets │ ├── GVFS.tasks │ ├── GenerateGVFSConstants.cs │ ├── GenerateGVFSVersionHeader.cs │ └── GenerateWindowsAppManifest.cs ├── GVFS.Mount │ ├── GVFS.Mount.csproj │ ├── InProcessMount.cs │ ├── InProcessMountVerb.cs │ ├── MountAbortedException.cs │ └── Program.cs ├── GVFS.NativeHooks.Common │ ├── common.h │ └── common.windows.cpp ├── GVFS.NativeTests │ ├── FileUtils.cpp │ ├── FileUtils.h │ ├── GVFS.NativeTests.vcxproj │ ├── GVFS.NativeTests.vcxproj.filters │ ├── ReadMe.txt │ ├── include │ │ ├── NtFunctions.h │ │ ├── SafeHandle.h │ │ ├── SafeOverlapped.h │ │ ├── Should.h │ │ ├── TestException.h │ │ ├── TestHelpers.h │ │ ├── TestVerifiers.h │ │ ├── prjlib_internal.h │ │ ├── prjlibp.h │ │ ├── stdafx.h │ │ └── targetver.h │ ├── interface │ │ ├── NtQueryDirectoryFileTests.h │ │ ├── PlaceholderUtils.h │ │ ├── ProjFS_BugRegressionTest.h │ │ ├── ProjFS_DeleteFileTest.h │ │ ├── ProjFS_DeleteFolderTest.h │ │ ├── ProjFS_DirEnumTest.h │ │ ├── ProjFS_FileAttributeTest.h │ │ ├── ProjFS_FileEATest.h │ │ ├── ProjFS_FileOperationTest.h │ │ ├── ProjFS_MoveFileTest.h │ │ ├── ProjFS_MoveFolderTest.h │ │ ├── ProjFS_MultiThreadsTest.h │ │ ├── ProjFS_SetLinkTest.h │ │ ├── ReadAndWriteTests.h │ │ └── TrailingSlashTests.h │ ├── packages.config │ └── source │ │ ├── NtFunctions.cpp │ │ ├── NtQueryDirectoryFileTests.cpp │ │ ├── PlaceholderUtils.cpp │ │ ├── ProjFS_BugRegressionTest.cpp │ │ ├── ProjFS_DeleteFileTest.cpp │ │ ├── ProjFS_DeleteFolderTest.cpp │ │ ├── ProjFS_DirEnumTest.cpp │ │ ├── ProjFS_FileAttributeTest.cpp │ │ ├── ProjFS_FileEATest.cpp │ │ ├── ProjFS_FileOperationTest.cpp │ │ ├── ProjFS_MoveFileTest.cpp │ │ ├── ProjFS_MoveFolderTest.cpp │ │ ├── ProjFS_MultiThreadTest.cpp │ │ ├── ProjFS_SetLinkTest.cpp │ │ ├── ReadAndWriteTests.cpp │ │ ├── TrailingSlashTests.cpp │ │ ├── dllmain.cpp │ │ └── stdafx.cpp ├── GVFS.Payload │ ├── GVFS.Payload.csproj │ └── layout.bat ├── GVFS.PerfProfiling │ ├── GVFS.PerfProfiling.csproj │ ├── ProfilingEnvironment.cs │ └── Program.cs ├── GVFS.Platform.Windows │ ├── ActiveEnumeration.cs │ ├── CurrentUser.cs │ ├── DiskLayoutUpgrades │ │ ├── DiskLayout10to11Upgrade_NewOperationType.cs │ │ ├── DiskLayout11to12Upgrade_SharedLocalCache.cs │ │ ├── DiskLayout12_0To12_1Upgrade_StatusAheadBehind.cs │ │ ├── DiskLayout12to13Upgrade_FolderPlaceholder.cs │ │ ├── DiskLayout13to14Upgrade_BlobSizes.cs │ │ ├── DiskLayout14to15Upgrade_ModifiedPaths.cs │ │ ├── DiskLayout15to16Upgrade_GitStatusCache.cs │ │ ├── DiskLayout16to17Upgrade_FolderPlaceholderValues.cs │ │ ├── DiskLayout17to18Upgrade_TombstoneFolderPlaceholders.cs │ │ ├── DiskLayout18to19Upgrade_SqlitePlacholders.cs │ │ ├── DiskLayout7to8Upgrade_NewOperationType.cs │ │ ├── DiskLayout8to9Upgrade_RepoMetadataToJson.cs │ │ ├── DiskLayout9to10Upgrade_BackgroundAndPlaceholderListToFileBased.cs │ │ └── WindowsDiskLayoutUpgradeData.cs │ ├── GVFS.Platform.Windows.csproj │ ├── HResultExtensions.cs │ ├── PatternMatcher.cs │ ├── PlatformLoader.Windows.cs │ ├── ProjFSFilter.cs │ ├── Readme.md │ ├── WindowsFileBasedLock.cs │ ├── WindowsFileSystem.Shared.cs │ ├── WindowsFileSystem.cs │ ├── WindowsFileSystemVirtualizer.cs │ ├── WindowsGitHooksInstaller.cs │ ├── WindowsGitInstallation.cs │ ├── WindowsPhysicalDiskInfo.cs │ ├── WindowsPlatform.Shared.cs │ └── WindowsPlatform.cs ├── GVFS.PostIndexChangedHook │ ├── GVFS.PostIndexChangedHook.vcxproj │ ├── GVFS.PostIndexChangedHook.vcxproj.filters │ ├── Version.rc │ ├── main.cpp │ ├── resource.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── GVFS.ReadObjectHook │ ├── GVFS.ReadObjectHook.vcxproj │ ├── GVFS.ReadObjectHook.vcxproj.filters │ ├── Version.rc │ ├── main.cpp │ ├── packet.cpp │ ├── packet.h │ ├── resource.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── GVFS.Service.UI │ ├── Data │ │ ├── ActionItem.cs │ │ ├── ActionsData.cs │ │ ├── BindingData.cs │ │ ├── BindingItem.cs │ │ ├── ToastData.cs │ │ └── VisualData.cs │ ├── GVFS.Service.UI.csproj │ ├── GVFSServiceUI.cs │ ├── GVFSToastRequestHandler.cs │ ├── IToastNotifier.cs │ ├── Program.cs │ ├── WinToastNotifier.cs │ └── XmlList.cs ├── GVFS.Service │ ├── Configuration.cs │ ├── GVFS.Service.csproj │ ├── GVFSMountProcess.cs │ ├── GVFSService.Windows.cs │ ├── Handlers │ │ ├── EnableAndAttachProjFSHandler.cs │ │ ├── GetActiveRepoListHandler.cs │ │ ├── INotificationHandler.cs │ │ ├── MessageHandler.cs │ │ ├── NotificationHandler.cs │ │ ├── RegisterRepoHandler.cs │ │ ├── RequestHandler.Windows.cs │ │ ├── RequestHandler.cs │ │ └── UnregisterRepoHandler.cs │ ├── IRepoMounter.cs │ ├── IRepoRegistry.cs │ ├── Program.cs │ ├── RepoRegistration.cs │ └── RepoRegistry.cs ├── GVFS.Tests │ ├── DataSources.cs │ ├── GVFS.Tests.csproj │ ├── NUnitRunner.cs │ └── Should │ │ ├── EnumerableShouldExtensions.cs │ │ ├── StringExtensions.cs │ │ ├── StringShouldExtensions.cs │ │ └── ValueShouldExtensions.cs ├── GVFS.UnitTests │ ├── Category │ │ └── CategoryConstants.cs │ ├── CommandLine │ │ └── HooksInstallerTests.cs │ ├── Common │ │ ├── AzDevOpsOrgFromNuGetFeedTests.cs │ │ ├── BackgroundTaskQueueTests.cs │ │ ├── CacheServerResolverTests.cs │ │ ├── Database │ │ │ ├── GVFSDatabaseTests.cs │ │ │ ├── PlaceholderTableTests.cs │ │ │ ├── SparseTableTests.cs │ │ │ └── TableTests.cs │ │ ├── EpochConverterTests.cs │ │ ├── FileBasedDictionaryTests.cs │ │ ├── GVFSEnlistmentHealthTests.cs │ │ ├── GVFSEnlistmentTests.cs │ │ ├── GVFSLockTests.cs │ │ ├── Git │ │ │ ├── GitSslTests.cs │ │ │ └── Sha1IdTests.cs │ │ ├── GitCommandLineParserTests.cs │ │ ├── GitConfigHelperTests.cs │ │ ├── GitObjectsTests.cs │ │ ├── GitPathConverterTests.cs │ │ ├── GitStatusCacheTests.cs │ │ ├── GitVersionTests.cs │ │ ├── JsonTracerTests.cs │ │ ├── LegacyPlaceholderDatabaseTests.cs │ │ ├── LibGit2RepoInvokerTests.cs │ │ ├── ModifiedPathsDatabaseTests.cs │ │ ├── NamedPipeStreamReaderWriterTests.cs │ │ ├── NamedPipeTests.cs │ │ ├── OrgInfoApiClientTests.cs │ │ ├── PathsTests.cs │ │ ├── PhysicalFileSystemDeleteTests.cs │ │ ├── RefLogEntryTests.cs │ │ ├── RetryBackoffTests.cs │ │ ├── RetryConfigTests.cs │ │ ├── RetryWrapperTests.cs │ │ └── SHA1UtilTests.cs │ ├── Data │ │ ├── backward.txt │ │ ├── caseChange.txt │ │ ├── forward.txt │ │ └── index_v4 │ ├── GVFS.UnitTests.csproj │ ├── Git │ │ ├── GVFSGitObjectsTests.cs │ │ ├── GitAuthenticationTests.cs │ │ ├── GitObjectsTests.cs │ │ └── GitProcessTests.cs │ ├── Maintenance │ │ ├── GitMaintenanceQueueTests.cs │ │ ├── GitMaintenanceStepTests.cs │ │ ├── LooseObjectStepTests.cs │ │ ├── PackfileMaintenanceStepTests.cs │ │ └── PostFetchStepTests.cs │ ├── Mock │ │ ├── Common │ │ │ ├── MockFileBasedLock.cs │ │ │ ├── MockGVFSEnlistment.cs │ │ │ ├── MockGitStatusCache.cs │ │ │ ├── MockLocalGVFSConfig.cs │ │ │ ├── MockLocalGVFSConfigBuilder.cs │ │ │ ├── MockPhysicalGitObjects.cs │ │ │ ├── MockPlatform.cs │ │ │ ├── MockTracer.cs │ │ │ └── Tracing │ │ │ │ └── MockListener.cs │ │ ├── FileSystem │ │ │ ├── ConfigurableFileSystem.cs │ │ │ ├── MockDirectory.cs │ │ │ ├── MockFile.cs │ │ │ ├── MockFileSystem.cs │ │ │ ├── MockFileSystemCallbacks.cs │ │ │ ├── MockFileSystemWithCallbacks.cs │ │ │ └── MockPlatformFileSystem.cs │ │ ├── Git │ │ │ ├── MockBatchHttpGitObjects.cs │ │ │ ├── MockGVFSGitObjects.cs │ │ │ ├── MockGitInstallation.cs │ │ │ ├── MockGitProcess.cs │ │ │ ├── MockGitRepo.cs │ │ │ ├── MockHttpGitObjects.cs │ │ │ └── MockLibGit2Repo.cs │ │ ├── MockCacheServerInfo.cs │ │ ├── MockTextWriter.cs │ │ ├── ReusableMemoryStream.cs │ │ └── Virtualization │ │ │ ├── Background │ │ │ └── MockBackgroundTaskManager.cs │ │ │ ├── BlobSize │ │ │ └── MockBlobSizesDatabase.cs │ │ │ ├── FileSystem │ │ │ └── MockFileSystemVirtualizer.cs │ │ │ └── Projection │ │ │ └── MockGitIndexProjection.cs │ ├── Prefetch │ │ ├── BatchObjectDownloadStageTests.cs │ │ ├── BlobPrefetcherTests.cs │ │ ├── DiffHelperTests.cs │ │ ├── DiffTreeResultTests.cs │ │ ├── PrefetchPacksDeserializerTests.cs │ │ └── PrefetchTracingTests.cs │ ├── Program.cs │ ├── Readme.md │ ├── Service │ │ └── RepoRegistryTests.cs │ ├── Setup.cs │ ├── Tracing │ │ ├── EventListenerTests.cs │ │ ├── QueuedPipeStringWriterTests.cs │ │ └── TelemetryDaemonEventListenerTests.cs │ ├── Virtual │ │ ├── CommonRepoSetup.cs │ │ ├── FileSystemVirtualizerTester.cs │ │ └── TestsWithCommonRepo.cs │ ├── Virtualization │ │ ├── FileSystemCallbacksTests.cs │ │ └── Projection │ │ │ ├── GitIndexEntryTests.cs │ │ │ ├── LazyUTF8StringTests.cs │ │ │ ├── ObjectPoolTests.cs │ │ │ └── SortedFolderEntriesTests.cs │ └── Windows │ │ ├── CommandLine │ │ └── SparseVerbTests.cs │ │ ├── Mock │ │ ├── MockVirtualizationInstance.cs │ │ ├── MockWriteBuffer.cs │ │ └── WindowsFileSystemVirtualizerTester.cs │ │ ├── Platform │ │ └── ProjFSFilterTests.cs │ │ ├── ServiceUI │ │ └── GVFSToastRequestHandlerTests.cs │ │ ├── Virtualization │ │ ├── ActiveEnumerationTests.cs │ │ ├── PatternMatcherTests.cs │ │ └── WindowsFileSystemVirtualizerTests.cs │ │ └── WindowsFileBasedLockTests.cs ├── GVFS.VirtualFileSystemHook │ ├── GVFS.VirtualFileSystemHook.vcxproj │ ├── GVFS.VirtualFileSystemHook.vcxproj.filters │ ├── Version.rc │ ├── main.cpp │ ├── resource.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── GVFS.Virtualization │ ├── Background │ │ ├── BackgroundFileSystemTaskRunner.cs │ │ ├── FileSystemTask.cs │ │ ├── FileSystemTaskQueue.cs │ │ └── FileSystemTaskResult.cs │ ├── BlobSize │ │ ├── BlobSizes.cs │ │ └── BlobSizesException.cs │ ├── FileSystem │ │ ├── FSResult.cs │ │ ├── FileSystemResult.cs │ │ ├── FileSystemVirtualizer.cs │ │ ├── UpdateFailureReason.cs │ │ └── UpdatePlaceholderType.cs │ ├── FileSystemCallbacks.cs │ ├── GVFS.Virtualization.csproj │ ├── InternalsVisibleTo.cs │ └── Projection │ │ ├── GitIndexProjection.FileData.cs │ │ ├── GitIndexProjection.FileTypeAndMode.cs │ │ ├── GitIndexProjection.FolderData.cs │ │ ├── GitIndexProjection.FolderEntryData.cs │ │ ├── GitIndexProjection.GitIndexEntry.cs │ │ ├── GitIndexProjection.GitIndexParser.cs │ │ ├── GitIndexProjection.LazyUTF8String.cs │ │ ├── GitIndexProjection.ObjectPool.cs │ │ ├── GitIndexProjection.PoolAllocationMultipliers.cs │ │ ├── GitIndexProjection.SortedFolderEntries.cs │ │ ├── GitIndexProjection.SparseFolder.cs │ │ ├── GitIndexProjection.cs │ │ ├── IProfilerOnlyIndexProjection.cs │ │ ├── ProjectedFileInfo.cs │ │ ├── Readme.md │ │ └── SizesUnavailableException.cs ├── GVFS │ ├── CommandLine │ │ ├── CacheServerVerb.cs │ │ ├── CloneVerb.cs │ │ ├── ConfigVerb.cs │ │ ├── DehydrateVerb.cs │ │ ├── DiagnoseVerb.cs │ │ ├── GVFSVerb.cs │ │ ├── HealthVerb.cs │ │ ├── LogVerb.cs │ │ ├── MountVerb.cs │ │ ├── PrefetchVerb.cs │ │ ├── RepairVerb.cs │ │ ├── ServiceVerb.cs │ │ ├── SparseVerb.cs │ │ ├── StatusVerb.cs │ │ ├── UnmountVerb.cs │ │ └── UpgradeVerb.cs │ ├── GVFS.csproj │ ├── GitVirtualFileSystem.ico │ ├── InternalsVisibleTo.cs │ ├── Program.cs │ └── RepairJobs │ │ ├── BackgroundOperationDatabaseRepairJob.cs │ │ ├── BlobSizeDatabaseRepairJob.cs │ │ ├── GitConfigRepairJob.cs │ │ ├── GitHeadRepairJob.cs │ │ ├── GitIndexRepairJob.cs │ │ ├── RepairJob.cs │ │ ├── RepoMetadataDatabaseRepairJob.cs │ │ └── VFSForGitDatabaseRepairJob.cs └── GitHooksLoader │ ├── GitHooksLoader.cpp │ ├── GitHooksLoader.vcxproj │ ├── GitHooksLoader.vcxproj.filters │ ├── Version.rc │ ├── resource.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── GvFlt_EULA.md ├── License.md ├── Protocol.md ├── Readme.md ├── SECURITY.md ├── ThirdPartyNotices.txt ├── Version.props ├── docs ├── faq.md ├── getting-started.md ├── index.md └── troubleshooting.md ├── global.json ├── nuget.config └── scripts ├── Build.bat ├── CreateBuildArtifacts.bat ├── InitializeEnvironment.bat ├── RunFunctionalTests.bat ├── RunUnitTests.bat ├── StopAllServices.bat └── StopService.bat /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*.cs] 7 | trim_trailing_whitespace = true 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Do not normalize any line endings. 3 | ############################################################################### 4 | * -text 5 | *.cs diff=csharp 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | # especially 6 | # 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 7 | 8 | version: 2 9 | updates: 10 | - package-ecosystem: "github-actions" # See documentation for possible values 11 | directory: "/" # Location of package manifests 12 | schedule: 13 | interval: "weekly" 14 | -------------------------------------------------------------------------------- /.github/workflows/release-winget.yaml: -------------------------------------------------------------------------------- 1 | name: "release-winget" 2 | on: 3 | release: 4 | types: [released] 5 | 6 | jobs: 7 | release: 8 | runs-on: windows-latest 9 | steps: 10 | - name: Publish manifest with winget-create 11 | run: | 12 | # Get correct release asset 13 | $github = Get-Content '${{ github.event_path }}' | ConvertFrom-Json 14 | $asset = $github.release.assets | Where-Object -Property name -match 'SetupGVFS[\d\.]*.exe' 15 | 16 | # Remove 'v' from the version 17 | $version = $github.release.tag_name -replace ".v","" 18 | 19 | # Download and run wingetcreate 20 | Invoke-WebRequest https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe 21 | .\wingetcreate.exe update Microsoft.VFSforGit -u $asset.browser_download_url -v $version -o manifests -t "${{ secrets.WINGET_TOKEN }}" -s 22 | shell: powershell -------------------------------------------------------------------------------- /.vsconfig: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "components": [ 4 | "Microsoft.Component.MSBuild", 5 | "Microsoft.VisualStudio.Workload.NativeDesktop" 6 | "Microsoft.VisualStudio.Workload.ManagedDesktop", 7 | "Microsoft.VisualStudio.Workload.NetCoreTools", 8 | "Microsoft.Net.Core.Component.SDK.2.1", 9 | "Microsoft.VisualStudio.Component.VC.v141.x86.x64", 10 | "Microsoft.Net.Component.4.6.1.TargetingPack", 11 | "Microsoft.Net.Component.4.6.1.SDK", 12 | ] 13 | } -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | <Project> 2 | 3 | <!-- Import version props --> 4 | <Import Project="Version.props" /> 5 | 6 | <!-- Common project properties --> 7 | <PropertyGroup> 8 | <RepoPath>$(MSBuildThisFileDirectory)</RepoPath> 9 | <RepoSrcPath>$(RepoPath)</RepoSrcPath> 10 | <RepoOutPath>$(RepoPath)..\out\</RepoOutPath> 11 | <ProjectOutPath>$(RepoOutPath)$(MSBuildProjectName)\</ProjectOutPath> 12 | <BuildPackagesPath>$(RepoPath)..\packages\</BuildPackagesPath> 13 | 14 | <!-- 15 | Ensure `msbuild /t:restore` restores both PackageReference and 16 | package.config styles of NuGet package references. 17 | Native/C++ projects do not support the new PackageReference style, 18 | but our .NET projects do. 19 | --> 20 | <RestorePackagesConfig>true</RestorePackagesConfig> 21 | </PropertyGroup> 22 | 23 | <!-- Managed project properties --> 24 | <PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.csproj'"> 25 | <RuntimeIdentifier>win-x64</RuntimeIdentifier> 26 | <PlatformTarget>x64</PlatformTarget> 27 | <BaseOutputPath>$(ProjectOutPath)bin\</BaseOutputPath> 28 | <BaseIntermediateOutputPath>$(ProjectOutPath)obj\</BaseIntermediateOutputPath> 29 | </PropertyGroup> 30 | 31 | <!-- Native project properties --> 32 | <PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.vcxproj'"> 33 | <Platform>x64</Platform> 34 | <OutDir>$(ProjectOutPath)bin\$(Platform)\$(Configuration)\</OutDir> 35 | <IntDir>$(ProjectOutPath)intermediate\$(Platform)\$(Configuration)\</IntDir> 36 | <GeneratedIncludePath>$(IntDir)include\</GeneratedIncludePath> 37 | </PropertyGroup> 38 | 39 | </Project> 40 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | <Project> 2 | 3 | <!-- Define common properties that rely on SDK/props-defined properties --> 4 | <PropertyGroup> 5 | <Version>$(GVFSVersion)</Version> 6 | </PropertyGroup> 7 | 8 | <!-- Include custom MSBuild targets/tasks --> 9 | <Import Project="$(MSBuildThisFileDirectory)GVFS\GVFS.MSBuild\GVFS.targets" /> 10 | 11 | </Project> 12 | -------------------------------------------------------------------------------- /Directory.Solution.props: -------------------------------------------------------------------------------- 1 | <Project> 2 | 3 | <!-- Import common build props for solution builds --> 4 | <Import Project="Directory.Build.props" /> 5 | 6 | </Project> 7 | -------------------------------------------------------------------------------- /GVFS/FastFetch/FastFetch.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net461</TargetFramework> 6 | <PlatformTarget>x64</PlatformTarget> 7 | <AllowUnsafeBlocks>true</AllowUnsafeBlocks> 8 | </PropertyGroup> 9 | 10 | <ItemGroup> 11 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 12 | </ItemGroup> 13 | 14 | <ItemGroup> 15 | <PackageReference Include="CommandLineParser" Version="2.6.0" /> 16 | <PackageReference Include="MicroBuild.Core" Version="0.2.0" ExcludeAssets="none" /> 17 | </ItemGroup> 18 | 19 | <ItemGroup> 20 | <FilesToSign Include=" 21 | $(OutputPath)\FastFetch.exe; 22 | $(OutputPath)\GVFS.Common.dll; 23 | $(OutputPath)\GVFS.GVFlt.dll; 24 | $(OutputPath)\GVFS.Platform.Windows.dll; 25 | $(OutputPath)\GVFS.Virtualization.dll;"> 26 | <Authenticode>Microsoft400</Authenticode> 27 | <InProject>false</InProject> 28 | </FilesToSign> 29 | </ItemGroup> 30 | 31 | </Project> 32 | -------------------------------------------------------------------------------- /GVFS/FastFetch/GitEnlistment.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using System; 3 | using System.IO; 4 | 5 | namespace FastFetch 6 | { 7 | public class GitEnlistment : Enlistment 8 | { 9 | private GitEnlistment(string repoRoot, string gitBinPath) 10 | : base( 11 | repoRoot, 12 | repoRoot, 13 | repoRoot, 14 | null, 15 | gitBinPath, 16 | flushFileBuffersForPacks: false, 17 | authentication: null) 18 | { 19 | this.GitObjectsRoot = Path.Combine(repoRoot, GVFSConstants.DotGit.Objects.Root); 20 | this.LocalObjectsRoot = this.GitObjectsRoot; 21 | this.GitPackRoot = Path.Combine(this.GitObjectsRoot, GVFSConstants.DotGit.Objects.Pack.Name); 22 | } 23 | 24 | public override string GitObjectsRoot { get; protected set; } 25 | 26 | public override string LocalObjectsRoot { get; protected set; } 27 | 28 | public override string GitPackRoot { get; protected set; } 29 | 30 | public string FastFetchLogRoot 31 | { 32 | get { return Path.Combine(this.EnlistmentRoot, GVFSConstants.DotGit.Root, ".fastfetch"); } 33 | } 34 | 35 | public static GitEnlistment CreateFromCurrentDirectory(string gitBinPath) 36 | { 37 | string root = Paths.GetGitEnlistmentRoot(Environment.CurrentDirectory); 38 | if (root != null) 39 | { 40 | return new GitEnlistment(root, gitBinPath); 41 | } 42 | 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /GVFS/FastFetch/Program.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | using GVFS.PlatformLoader; 3 | 4 | namespace FastFetch 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | GVFSPlatformLoader.Initialize(); 11 | Parser.Default.ParseArguments<FastFetchVerb>(args) 12 | .WithParsed(fastFetch => fastFetch.Execute()); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/FastFetch/WorkingTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using GVFS.Common; 6 | 7 | namespace FastFetch 8 | { 9 | public static class WorkingTree 10 | { 11 | /// <summary> 12 | /// Enumerates all files in the working tree in a asynchronous parallel manner. 13 | /// Files found are sent to callback in chunks. 14 | /// Make no assumptions about ordering or how big chunks will be 15 | /// </summary> 16 | /// <param name="repoRoot"></param> 17 | /// <param name="asyncParallelCallback"></param> 18 | public static void ForAllFiles(string repoRoot, Action<string, FileInfo[]> asyncParallelCallback) 19 | { 20 | ForAllDirectories(new DirectoryInfo(repoRoot), asyncParallelCallback); 21 | } 22 | 23 | public static void ForAllDirectories(DirectoryInfo dir, Action<string, FileInfo[]> asyncParallelCallback) 24 | { 25 | asyncParallelCallback(dir.FullName, dir.GetFiles()); 26 | 27 | Parallel.ForEach( 28 | dir.EnumerateDirectories().Where(subdir => 29 | (!subdir.Name.Equals(GVFSConstants.DotGit.Root, GVFSPlatform.Instance.Constants.PathComparison) && 30 | !subdir.Attributes.HasFlag(FileAttributes.ReparsePoint))), 31 | subdir => { ForAllDirectories(subdir, asyncParallelCallback); }); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/ConcurrentHashSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | 5 | namespace GVFS.Common 6 | { 7 | public class ConcurrentHashSet<T> : IEnumerable<T> 8 | { 9 | private ConcurrentDictionary<T, bool> dictionary; 10 | 11 | public ConcurrentHashSet() 12 | { 13 | this.dictionary = new ConcurrentDictionary<T, bool>(); 14 | } 15 | 16 | public ConcurrentHashSet(IEqualityComparer<T> comparer) 17 | { 18 | this.dictionary = new ConcurrentDictionary<T, bool>(comparer); 19 | } 20 | 21 | public int Count 22 | { 23 | get { return this.dictionary.Count; } 24 | } 25 | 26 | public bool Add(T entry) 27 | { 28 | return this.dictionary.TryAdd(entry, true); 29 | } 30 | 31 | public bool Contains(T item) 32 | { 33 | return this.dictionary.ContainsKey(item); 34 | } 35 | 36 | public void Clear() 37 | { 38 | this.dictionary.Clear(); 39 | } 40 | 41 | public IEnumerator<T> GetEnumerator() 42 | { 43 | return this.dictionary.Keys.GetEnumerator(); 44 | } 45 | 46 | IEnumerator IEnumerable.GetEnumerator() 47 | { 48 | return this.GetEnumerator(); 49 | } 50 | 51 | public bool TryRemove(T key) 52 | { 53 | bool value; 54 | return this.dictionary.TryRemove(key, out value); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/GVFSDatabaseException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.Database 4 | { 5 | public class GVFSDatabaseException : Exception 6 | { 7 | public GVFSDatabaseException(string message, Exception innerException) 8 | : base(message, innerException) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/IDbCommandExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace GVFS.Common.Database 4 | { 5 | /// <summary> 6 | /// Extension methods for the IDbCommand interface 7 | /// </summary> 8 | public static class IDbCommandExtensions 9 | { 10 | public static IDbDataParameter AddParameter(this IDbCommand command, string name, DbType dbType, object value) 11 | { 12 | IDbDataParameter parameter = command.CreateParameter(); 13 | parameter.ParameterName = name; 14 | parameter.DbType = dbType; 15 | parameter.Value = value; 16 | command.Parameters.Add(parameter); 17 | return parameter; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/IDbConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace GVFS.Common.Database 4 | { 5 | /// <summary> 6 | /// Interface used to open a new connection to a database 7 | /// </summary> 8 | public interface IDbConnectionFactory 9 | { 10 | IDbConnection OpenNewConnection(string databasePath); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/IGVFSConnectionPool.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace GVFS.Common.Database 4 | { 5 | /// <summary> 6 | /// Interface for getting a pooled database connection 7 | /// </summary> 8 | public interface IGVFSConnectionPool 9 | { 10 | IDbConnection GetConnection(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/IPlaceholderCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GVFS.Common.Database 4 | { 5 | /// <summary> 6 | /// Interface for interacting with placeholders 7 | /// </summary> 8 | public interface IPlaceholderCollection 9 | { 10 | int GetCount(); 11 | void GetAllEntries(out List<IPlaceholderData> filePlaceholders, out List<IPlaceholderData> folderPlaceholders); 12 | int GetFilePlaceholdersCount(); 13 | int GetFolderPlaceholdersCount(); 14 | 15 | HashSet<string> GetAllFilePaths(); 16 | 17 | void AddPartialFolder(string path, string sha); 18 | void AddExpandedFolder(string path); 19 | void AddPossibleTombstoneFolder(string path); 20 | 21 | void AddFile(string path, string sha); 22 | 23 | void Remove(string path); 24 | List<IPlaceholderData> RemoveAllEntriesForFolder(string path); 25 | void AddPlaceholderData(IPlaceholderData data); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/IPlaceholderData.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Database 2 | { 3 | /// <summary> 4 | /// Interface for holding placeholder information 5 | /// </summary> 6 | public interface IPlaceholderData 7 | { 8 | string Path { get; } 9 | string Sha { get; set; } 10 | bool IsFolder { get; } 11 | bool IsExpandedFolder { get; } 12 | bool IsPossibleTombstoneFolder { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Database/ISparseCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace GVFS.Common.Database 6 | { 7 | public interface ISparseCollection 8 | { 9 | HashSet<string> GetAll(); 10 | 11 | void Add(string directory); 12 | void Remove(string directory); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/DiskLayoutUpgrades/DiskLayoutVersion.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common 2 | { 3 | public class DiskLayoutVersion 4 | { 5 | public DiskLayoutVersion(int currentMajorVersion, int currentMinorVersion, int minimumSupportedMajorVersion) 6 | { 7 | this.CurrentMajorVersion = currentMajorVersion; 8 | this.CurrentMinorVersion = currentMinorVersion; 9 | this.MinimumSupportedMajorVersion = minimumSupportedMajorVersion; 10 | } 11 | 12 | // The major version should be bumped whenever there is an on-disk format change that requires a one-way upgrade. 13 | // Increasing this version will make older versions of GVFS unable to mount a repo that has been mounted by a newer 14 | // version of GVFS. 15 | public int CurrentMajorVersion { get; } 16 | 17 | // The minor version should be bumped whenever there is an upgrade that can be safely ignored by older versions of GVFS. 18 | // For example, this allows an upgrade step that sets a default value for some new config setting. 19 | public int CurrentMinorVersion { get; } 20 | 21 | // This is the last time GVFS made a breaking change that required a reclone. This should not 22 | // be incremented on platforms that have released a v1.0 as all their format changes should be 23 | // supported with an upgrade step. 24 | public int MinimumSupportedMajorVersion { get; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/EpochConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common 4 | { 5 | public static class EpochConverter 6 | { 7 | private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 8 | 9 | public static long ToUnixEpochSeconds(DateTime datetime) 10 | { 11 | return Convert.ToInt64(Math.Truncate((datetime - UnixEpoch).TotalSeconds)); 12 | } 13 | 14 | public static DateTime FromUnixEpochSeconds(long secondsSinceEpoch) 15 | { 16 | return UnixEpoch.AddSeconds(secondsSinceEpoch); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileBasedCollectionException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common 4 | { 5 | public class FileBasedCollectionException : Exception 6 | { 7 | public FileBasedCollectionException(Exception innerException) 8 | : base(innerException.Message, innerException) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileBasedLock.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.FileSystem; 2 | using GVFS.Common.Tracing; 3 | using System; 4 | 5 | namespace GVFS.Common 6 | { 7 | public abstract class FileBasedLock : IDisposable 8 | { 9 | public FileBasedLock( 10 | PhysicalFileSystem fileSystem, 11 | ITracer tracer, 12 | string lockPath) 13 | { 14 | this.FileSystem = fileSystem; 15 | this.Tracer = tracer; 16 | this.LockPath = lockPath; 17 | } 18 | 19 | protected PhysicalFileSystem FileSystem { get; } 20 | protected string LockPath { get; } 21 | protected ITracer Tracer { get; } 22 | 23 | public abstract bool TryAcquireLock(); 24 | 25 | public abstract void Dispose(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileSystem/DirectoryItemInfo.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.FileSystem 2 | { 3 | public class DirectoryItemInfo 4 | { 5 | public string Name { get; set; } 6 | public string FullName { get; set; } 7 | public long Length { get; set; } 8 | public bool IsDirectory { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileSystem/FileProperties.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace GVFS.Common.FileSystem 5 | { 6 | public class FileProperties 7 | { 8 | public static readonly FileProperties DefaultFile = new FileProperties(FileAttributes.Normal, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, 0); 9 | public static readonly FileProperties DefaultDirectory = new FileProperties(FileAttributes.Directory, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, 0); 10 | 11 | public FileProperties(FileAttributes attributes, DateTime creationTimeUTC, DateTime lastAccessTimeUTC, DateTime lastWriteTimeUTC, long length) 12 | { 13 | this.FileAttributes = attributes; 14 | this.CreationTimeUTC = creationTimeUTC; 15 | this.LastAccessTimeUTC = lastAccessTimeUTC; 16 | this.LastWriteTimeUTC = lastWriteTimeUTC; 17 | this.Length = length; 18 | } 19 | 20 | public FileAttributes FileAttributes { get; private set; } 21 | public DateTime CreationTimeUTC { get; private set; } 22 | public DateTime LastAccessTimeUTC { get; private set; } 23 | public DateTime LastWriteTimeUTC { get; private set; } 24 | public long Length { get; private set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileSystem/FlushToDiskFileStream.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace GVFS.Common.FileSystem 4 | { 5 | public class FlushToDiskFileStream : FileStream 6 | { 7 | public FlushToDiskFileStream(string path, FileMode mode) 8 | : base(path, mode) 9 | { 10 | } 11 | 12 | public FlushToDiskFileStream(string path, FileMode mode, FileAccess access, FileShare share) 13 | : base(path, mode, access, share) 14 | { 15 | } 16 | 17 | public FlushToDiskFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) 18 | : base(path, mode, access, share, bufferSize, options) 19 | { 20 | } 21 | 22 | public override void Flush() 23 | { 24 | // Ensure that all buffered data in intermediate file buffers is written to disk 25 | // Passing in true below results in a call to FlushFileBuffers 26 | base.Flush(true); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileSystem/IKernelDriver.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using System; 3 | using System.IO; 4 | 5 | namespace GVFS.Common.FileSystem 6 | { 7 | public interface IKernelDriver 8 | { 9 | bool EnumerationExpandsDirectories { get; } 10 | 11 | /// <summary> 12 | /// Gets a value indicating whether file sizes required to write/update placeholders 13 | /// </summary> 14 | bool EmptyPlaceholdersRequireFileSize { get; } 15 | 16 | string LogsFolderPath { get; } 17 | bool IsSupported(string normalizedEnlistmentRootPath, out string warning, out string error); 18 | bool TryFlushLogs(out string errors); 19 | bool TryPrepareFolderForCallbacks(string folderPath, out string error, out Exception exception); 20 | bool IsReady(JsonTracer tracer, string enlistmentRoot, TextWriter output, out string error); 21 | bool IsGVFSUpgradeSupported(); 22 | bool RegisterForOfflineIO(); 23 | bool UnregisterForOfflineIO(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/FileSystem/IPlatformFileSystem.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using System; 3 | 4 | namespace GVFS.Common.FileSystem 5 | { 6 | public interface IPlatformFileSystem 7 | { 8 | bool SupportsFileMode { get; } 9 | void FlushFileBuffers(string path); 10 | void MoveAndOverwriteFile(string sourceFileName, string destinationFilename); 11 | bool TryGetNormalizedPath(string path, out string normalizedPath, out string errorMessage); 12 | void SetDirectoryLastWriteTime(string path, DateTime lastWriteTime, out bool directoryExists); 13 | void ChangeMode(string path, ushort mode); 14 | bool HydrateFile(string fileName, byte[] buffer); 15 | bool IsExecutable(string filePath); 16 | bool IsSocket(string filePath); 17 | bool TryCreateDirectoryAccessibleByAuthUsers(string directoryPath, out string error, ITracer tracer = null); 18 | bool TryCreateDirectoryWithAdminAndUserModifyPermissions(string directoryPath, out string error); 19 | bool TryCreateOrUpdateDirectoryToAdminModifyPermissions(ITracer tracer, string directoryPath, out string error); 20 | bool IsFileSystemSupported(string path, out string error); 21 | void EnsureDirectoryIsOwnedByCurrentUser(string workingDirectoryRoot); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/GVFS.Common.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net461</TargetFramework> 5 | <AllowUnsafeBlocks>true</AllowUnsafeBlocks> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <PackageReference Include="LibGit2Sharp.NativeBinaries" Version="2.0.322" /> 10 | <PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.4" /> 11 | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> 12 | <PackageReference Include="SharpZipLib" Version="1.3.3" /> 13 | </ItemGroup> 14 | 15 | <ItemGroup> 16 | <Reference Include="System.Web" /> 17 | </ItemGroup> 18 | 19 | <Target Name="_GenerateConstantsFile" BeforeTargets="BeforeCompile"> 20 | <!-- Generate GVFS constants file with the minimum Git version --> 21 | <GenerateGVFSConstants MinimumGitVersion="$(MinimumGitVersion)" LibGit2FileName="$(libgit2_filename)" OutputFile="$(IntermediateOutputPath)GVFSConstants.g.cs" /> 22 | <!-- Add the generated file to the list of file writes for MSBuild to keep track of for clean-up --> 23 | <ItemGroup> 24 | <Compile Include="$(IntermediateOutputPath)GVFSConstants.g.cs" /> 25 | <FileWrites Include="$(IntermediateOutputPath)GVFSConstants.g.cs" /> 26 | </ItemGroup> 27 | </Target> 28 | 29 | </Project> 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/GVFSContext.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.FileSystem; 2 | using GVFS.Common.Git; 3 | using GVFS.Common.Tracing; 4 | using System; 5 | 6 | namespace GVFS.Common 7 | { 8 | public class GVFSContext : IDisposable 9 | { 10 | private bool disposedValue = false; 11 | 12 | public GVFSContext(ITracer tracer, PhysicalFileSystem fileSystem, GitRepo repository, GVFSEnlistment enlistment) 13 | { 14 | this.Tracer = tracer; 15 | this.FileSystem = fileSystem; 16 | this.Enlistment = enlistment; 17 | this.Repository = repository; 18 | 19 | this.Unattended = GVFSEnlistment.IsUnattended(this.Tracer); 20 | } 21 | 22 | public ITracer Tracer { get; private set; } 23 | public PhysicalFileSystem FileSystem { get; private set; } 24 | public GitRepo Repository { get; private set; } 25 | public GVFSEnlistment Enlistment { get; private set; } 26 | public bool Unattended { get; private set; } 27 | 28 | public void Dispose() 29 | { 30 | this.Dispose(true); 31 | GC.SuppressFinalize(this); 32 | } 33 | 34 | protected virtual void Dispose(bool disposing) 35 | { 36 | if (!this.disposedValue) 37 | { 38 | if (disposing) 39 | { 40 | this.Repository.Dispose(); 41 | this.Tracer.Dispose(); 42 | this.Tracer = null; 43 | } 44 | 45 | this.disposedValue = true; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/GVFSEnlistment.Shared.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using System; 3 | using System.Security; 4 | 5 | namespace GVFS.Common 6 | { 7 | public partial class GVFSEnlistment 8 | { 9 | public static bool IsUnattended(ITracer tracer) 10 | { 11 | try 12 | { 13 | return Environment.GetEnvironmentVariable(GVFSConstants.UnattendedEnvironmentVariable) == "1"; 14 | } 15 | catch (SecurityException e) 16 | { 17 | if (tracer != null) 18 | { 19 | EventMetadata metadata = new EventMetadata(); 20 | metadata.Add("Area", nameof(GVFSEnlistment)); 21 | metadata.Add("Exception", e.ToString()); 22 | tracer.RelatedError(metadata, "Unable to read environment variable " + GVFSConstants.UnattendedEnvironmentVariable); 23 | } 24 | 25 | return false; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/EndianHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Git 2 | { 3 | public static class EndianHelper 4 | { 5 | public static short Swap(short source) 6 | { 7 | return (short)Swap((ushort)source); 8 | } 9 | 10 | public static int Swap(int source) 11 | { 12 | return (int)Swap((uint)source); 13 | } 14 | 15 | public static long Swap(long source) 16 | { 17 | return (long)((ulong)source); 18 | } 19 | 20 | public static ushort Swap(ushort source) 21 | { 22 | return (ushort)(((source & 0x000000FF) << 8) | 23 | ((source & 0x0000FF00) >> 8)); 24 | } 25 | 26 | public static uint Swap(uint source) 27 | { 28 | return 29 | ((source & 0x000000FF) << 24) | 30 | ((source & 0x0000FF00) << 8) | 31 | ((source & 0x00FF0000) >> 8) | 32 | ((source & 0xFF000000) >> 24); 33 | } 34 | 35 | public static ulong Swap(ulong source) 36 | { 37 | return 38 | ((source & 0x00000000000000FF) << 56) | 39 | ((source & 0x000000000000FF00) << 40) | 40 | ((source & 0x0000000000FF0000) << 24) | 41 | ((source & 0x00000000FF000000) << 8) | 42 | ((source & 0x000000FF00000000) >> 8) | 43 | ((source & 0x0000FF0000000000) >> 24) | 44 | ((source & 0x00FF000000000000) >> 40) | 45 | ((source & 0xFF00000000000000) >> 56); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/GitConfigSetting.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GVFS.Common.Git 4 | { 5 | public class GitConfigSetting 6 | { 7 | public const string CoreVirtualizeObjectsName = "core.virtualizeobjects"; 8 | public const string CoreVirtualFileSystemName = "core.virtualfilesystem"; 9 | public const string CredentialUseHttpPath = "credential.\"https://dev.azure.com\".useHttpPath"; 10 | 11 | public const string HttpSslCert = "http.sslcert"; 12 | public const string HttpSslVerify = "http.sslverify"; 13 | public const string HttpSslCertPasswordProtected = "http.sslcertpasswordprotected"; 14 | 15 | public GitConfigSetting(string name, params string[] values) 16 | { 17 | this.Name = name; 18 | this.Values = new HashSet<string>(values); 19 | } 20 | 21 | public string Name { get; } 22 | public HashSet<string> Values { get; } 23 | 24 | public bool HasValue(string value) 25 | { 26 | return this.Values.Contains(value); 27 | } 28 | 29 | public void Add(string value) 30 | { 31 | this.Values.Add(value); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/GitObjectContentType.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Git 2 | { 3 | public enum GitObjectContentType 4 | { 5 | None, 6 | LooseObject, 7 | BatchedLooseObjects, 8 | PackFile 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/GitOid.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace GVFS.Common.Git 4 | { 5 | [StructLayout(LayoutKind.Sequential)] 6 | public struct GitOid 7 | { 8 | // OIDs are 20 bytes long 9 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] 10 | public byte[] Id; 11 | 12 | public override string ToString() 13 | { 14 | return SHA1Util.HexStringFromBytes(this.Id); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/ICredentialStore.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | 3 | namespace GVFS.Common.Git 4 | { 5 | public interface ICredentialStore 6 | { 7 | bool TryGetCredential(ITracer tracer, string url, out string username, out string password, out string error); 8 | 9 | bool TryStoreCredential(ITracer tracer, string url, string username, string password, out string error); 10 | 11 | bool TryDeleteCredential(ITracer tracer, string url, string username, string password, out string error); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/IGitInstallation.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Git 2 | { 3 | public interface IGitInstallation 4 | { 5 | bool GitExists(string gitBinPath); 6 | string GetInstalledGitBinPath(); 7 | } 8 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/NoOpStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace GVFS.Common.Git 5 | { 6 | public class NoOpStream : Stream 7 | { 8 | public override bool CanRead => false; 9 | 10 | public override bool CanSeek => false; 11 | 12 | public override bool CanWrite => true; 13 | 14 | public override long Length => 0; 15 | 16 | public override long Position { get => 0; set => throw new NotImplementedException(); } 17 | 18 | public override void Flush() 19 | { 20 | } 21 | 22 | public override int Read(byte[] buffer, int offset, int count) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | 27 | public override long Seek(long offset, SeekOrigin origin) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public override void SetLength(long value) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | public override void Write(byte[] buffer, int offset, int count) 38 | { 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Git/RefLogEntry.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Git 2 | { 3 | public class RefLogEntry 4 | { 5 | public RefLogEntry(string sourceSha, string targetSha, string reason) 6 | { 7 | this.SourceSha = sourceSha; 8 | this.TargetSha = targetSha; 9 | this.Reason = reason; 10 | } 11 | 12 | public string SourceSha { get; } 13 | public string TargetSha { get; } 14 | public string Reason { get; } 15 | 16 | public static bool TryParse(string line, out RefLogEntry entry) 17 | { 18 | entry = null; 19 | if (string.IsNullOrEmpty(line)) 20 | { 21 | return false; 22 | } 23 | 24 | if (line.Length < GVFSConstants.ShaStringLength + 1 + GVFSConstants.ShaStringLength) 25 | { 26 | return false; 27 | } 28 | 29 | string sourceSha = line.Substring(0, GVFSConstants.ShaStringLength); 30 | string targetSha = line.Substring(GVFSConstants.ShaStringLength + 1, GVFSConstants.ShaStringLength); 31 | 32 | int reasonStart = line.LastIndexOf("\t"); 33 | if (reasonStart < 0) 34 | { 35 | return false; 36 | } 37 | 38 | string reason = line.Substring(reasonStart + 1); 39 | 40 | entry = new RefLogEntry(sourceSha, targetSha, reason); 41 | return true; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Http/GitObjectsHttpException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace GVFS.Common.Http 5 | { 6 | public class GitObjectsHttpException : Exception 7 | { 8 | public GitObjectsHttpException(HttpStatusCode statusCode, string ex) : base(ex) 9 | { 10 | this.StatusCode = statusCode; 11 | } 12 | 13 | public HttpStatusCode StatusCode { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/IDiskLayoutUpgradeData.cs: -------------------------------------------------------------------------------- 1 | using GVFS.DiskLayoutUpgrades; 2 | using System; 3 | 4 | namespace GVFS.Common 5 | { 6 | public interface IDiskLayoutUpgradeData 7 | { 8 | DiskLayoutUpgrade[] Upgrades { get; } 9 | DiskLayoutVersion Version { get; } 10 | bool TryParseLegacyDiskLayoutVersion(string dotGVFSPath, out int majorVersion); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/IHeartBeatMetadataProvider.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | 3 | namespace GVFS.Common 4 | { 5 | public interface IHeartBeatMetadataProvider 6 | { 7 | EventMetadata GetAndResetHeartBeatMetadata(out bool logToFile); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/IProcessRunner.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common 2 | { 3 | /// <summary> 4 | /// Interface around process helper methods. This is to enable 5 | /// testing of components that interact with the ProcessHelper 6 | /// static class. 7 | /// </summary> 8 | public interface IProcessRunner 9 | { 10 | ProcessResult Run(string programName, string args, bool redirectOutput); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/InternalVerbParameters.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace GVFS.Common 4 | { 5 | public class InternalVerbParameters 6 | { 7 | public InternalVerbParameters( 8 | string serviceName = null, 9 | bool startedByService = true, 10 | string maintenanceJob = null, 11 | string packfileMaintenanceBatchSize = null) 12 | { 13 | this.ServiceName = serviceName; 14 | this.StartedByService = startedByService; 15 | this.MaintenanceJob = maintenanceJob; 16 | this.PackfileMaintenanceBatchSize = packfileMaintenanceBatchSize; 17 | } 18 | 19 | public string ServiceName { get; private set; } 20 | public bool StartedByService { get; private set; } 21 | public string MaintenanceJob { get; private set; } 22 | public string PackfileMaintenanceBatchSize { get; private set; } 23 | 24 | public static InternalVerbParameters FromJson(string json) 25 | { 26 | return JsonConvert.DeserializeObject<InternalVerbParameters>(json); 27 | } 28 | 29 | public string ToJson() 30 | { 31 | return JsonConvert.SerializeObject(this); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GVFS.UnitTests")] 4 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/InvalidRepoException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common 4 | { 5 | public class InvalidRepoException : Exception 6 | { 7 | public InvalidRepoException(string message) 8 | : base(message) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Maintenance/GitProcessChecker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | 6 | namespace GVFS.Common.Maintenance 7 | { 8 | public class GitProcessChecker 9 | { 10 | public virtual IEnumerable<int> GetRunningGitProcessIds() 11 | { 12 | Process[] allProcesses = Process.GetProcesses(); 13 | return allProcesses 14 | .Where(x => x.ProcessName.Equals("git", GVFSPlatform.Instance.Constants.PathComparison)) 15 | .Select(x => x.Id); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/NamedPipes/BrokenPipeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace GVFS.Common.NamedPipes 5 | { 6 | public class BrokenPipeException : Exception 7 | { 8 | public BrokenPipeException(string message, IOException innerException) 9 | : base(message, innerException) 10 | { 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/NamedPipes/NamedPipeStreamWriter.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | 4 | namespace GVFS.Common.NamedPipes 5 | { 6 | public class NamedPipeStreamWriter 7 | { 8 | private const byte TerminatorByte = 0x3; 9 | private const string TerminatorByteString = "\x3"; 10 | private Stream stream; 11 | 12 | public NamedPipeStreamWriter(Stream stream) 13 | { 14 | this.stream = stream; 15 | } 16 | 17 | public void WriteMessage(string message) 18 | { 19 | byte[] byteBuffer = Encoding.UTF8.GetBytes(message + TerminatorByteString); 20 | this.stream.Write(byteBuffer, 0, byteBuffer.Length); 21 | this.stream.Flush(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/NamedPipes/PipeNameLengthException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.NamedPipes 4 | { 5 | public class PipeNameLengthException : Exception 6 | { 7 | public PipeNameLengthException(string message) 8 | : base(message) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Paths.Shared.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace GVFS.Common 6 | { 7 | public static class Paths 8 | { 9 | public static string GetGitEnlistmentRoot(string directory) 10 | { 11 | return GetRoot(directory, GVFSConstants.DotGit.Root); 12 | } 13 | 14 | public static string GetRoot(string startingDirectory, string rootName) 15 | { 16 | startingDirectory = startingDirectory.TrimEnd(Path.DirectorySeparatorChar); 17 | DirectoryInfo dirInfo; 18 | 19 | try 20 | { 21 | dirInfo = new DirectoryInfo(startingDirectory); 22 | } 23 | catch (Exception) 24 | { 25 | return null; 26 | } 27 | 28 | while (dirInfo != null) 29 | { 30 | if (dirInfo.Exists) 31 | { 32 | DirectoryInfo[] dotGVFSDirs = new DirectoryInfo[0]; 33 | 34 | try 35 | { 36 | dotGVFSDirs = dirInfo.GetDirectories(rootName); 37 | } 38 | catch (IOException) 39 | { 40 | } 41 | 42 | if (dotGVFSDirs.Count() == 1) 43 | { 44 | return dirInfo.FullName; 45 | } 46 | } 47 | 48 | dirInfo = dirInfo.Parent; 49 | } 50 | 51 | return null; 52 | } 53 | 54 | public static string ConvertPathToGitFormat(string path) 55 | { 56 | return path.Replace(Path.DirectorySeparatorChar, GVFSConstants.GitPathSeparator); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Prefetch/Git/PathWithMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.Prefetch.Git 4 | { 5 | public class PathWithMode 6 | { 7 | public PathWithMode(string path, ushort mode) 8 | { 9 | this.Path = path; 10 | this.Mode = mode; 11 | } 12 | 13 | public ushort Mode { get; } 14 | public string Path { get; } 15 | 16 | public override bool Equals(object obj) 17 | { 18 | PathWithMode x = obj as PathWithMode; 19 | 20 | if (x == null) 21 | { 22 | return false; 23 | } 24 | 25 | return x.Path.Equals(this.Path, GVFSPlatform.Instance.Constants.PathComparison); 26 | } 27 | 28 | public override int GetHashCode() 29 | { 30 | return GVFSPlatform.Instance.Constants.PathComparer.GetHashCode(this.Path); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Prefetch/Git/PrefetchGitObjects.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.FileSystem; 2 | using GVFS.Common.Git; 3 | using GVFS.Common.Http; 4 | using GVFS.Common.Tracing; 5 | 6 | namespace GVFS.Common.Prefetch.Git 7 | { 8 | public class PrefetchGitObjects : GitObjects 9 | { 10 | public PrefetchGitObjects(ITracer tracer, Enlistment enlistment, GitObjectsHttpRequestor objectRequestor, PhysicalFileSystem fileSystem = null) : base(tracer, enlistment, objectRequestor, fileSystem) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Prefetch/Pipeline/Data/BlobDownloadRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | 4 | namespace GVFS.Common.Prefetch.Pipeline.Data 5 | { 6 | public class BlobDownloadRequest 7 | { 8 | private static int requestCounter = 0; 9 | 10 | public BlobDownloadRequest(IReadOnlyList<string> objectIds) 11 | { 12 | this.ObjectIds = objectIds; 13 | this.RequestId = Interlocked.Increment(ref requestCounter); 14 | } 15 | 16 | public static int TotalRequests 17 | { 18 | get 19 | { 20 | return requestCounter; 21 | } 22 | } 23 | 24 | public IReadOnlyList<string> ObjectIds { get; } 25 | 26 | public int RequestId { get; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Prefetch/Pipeline/Data/IndexPackRequest.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Prefetch.Pipeline.Data 2 | { 3 | public class IndexPackRequest 4 | { 5 | public IndexPackRequest(string tempPackFile, BlobDownloadRequest downloadRequest) 6 | { 7 | this.TempPackFile = tempPackFile; 8 | this.DownloadRequest = downloadRequest; 9 | } 10 | 11 | public BlobDownloadRequest DownloadRequest { get; } 12 | 13 | public string TempPackFile { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Prefetch/Pipeline/Data/TreeSearchRequest.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Prefetch.Pipeline.Data 2 | { 3 | public class SearchTreeRequest 4 | { 5 | public SearchTreeRequest(string treeSha, string rootPath, bool shouldRecurse) 6 | { 7 | this.TreeSha = treeSha; 8 | this.RootPath = rootPath; 9 | this.ShouldRecurse = shouldRecurse; 10 | } 11 | 12 | public bool ShouldRecurse { get; } 13 | 14 | public string TreeSha { get; } 15 | 16 | public string RootPath { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Prefetch/Pipeline/PrefetchPipelineStage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace GVFS.Common.Prefetch.Pipeline 5 | { 6 | public abstract class PrefetchPipelineStage 7 | { 8 | private int maxParallel; 9 | private Thread[] workers; 10 | 11 | public PrefetchPipelineStage(int maxParallel) 12 | { 13 | this.maxParallel = maxParallel; 14 | } 15 | 16 | public bool HasFailures { get; protected set; } 17 | 18 | public void Start() 19 | { 20 | if (this.workers != null) 21 | { 22 | throw new InvalidOperationException("Cannot call start twice"); 23 | } 24 | 25 | this.DoBeforeWork(); 26 | 27 | this.workers = new Thread[this.maxParallel]; 28 | for (int i = 0; i < this.workers.Length; ++i) 29 | { 30 | this.workers[i] = new Thread(this.DoWork); 31 | this.workers[i].Start(); 32 | } 33 | } 34 | 35 | public void WaitForCompletion() 36 | { 37 | if (this.workers == null) 38 | { 39 | throw new InvalidOperationException("Cannot wait for completion before start is called"); 40 | } 41 | 42 | foreach (Thread t in this.workers) 43 | { 44 | t.Join(); 45 | } 46 | 47 | this.DoAfterWork(); 48 | this.workers = null; 49 | } 50 | 51 | protected virtual void DoBeforeWork() 52 | { 53 | } 54 | 55 | protected abstract void DoWork(); 56 | 57 | protected virtual void DoAfterWork() 58 | { 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/ProcessResult.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common 2 | { 3 | public class ProcessResult 4 | { 5 | public ProcessResult(string output, string errors, int exitCode) 6 | { 7 | this.Output = output; 8 | this.Errors = errors; 9 | this.ExitCode = exitCode; 10 | } 11 | 12 | public string Output { get; } 13 | public string Errors { get; } 14 | public int ExitCode { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/ProcessRunnerImpl.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common 2 | { 3 | /// <summary> 4 | /// Default product implementation of IProcessRunner 5 | /// interface. Delegates calls to static ProcessHelper class. This 6 | /// class can be used to enable testing of components that call 7 | /// into the ProcessHelper functionality. 8 | /// </summary> 9 | public class ProcessRunnerImpl : IProcessRunner 10 | { 11 | public ProcessResult Run(string programName, string args, bool redirectOutput) 12 | { 13 | return ProcessHelper.Run(programName, args, redirectOutput); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/RetryableException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common 4 | { 5 | public class RetryableException : Exception 6 | { 7 | public RetryableException(string message, Exception inner) : base(message, inner) 8 | { 9 | } 10 | 11 | public RetryableException(string message) : base(message) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/ReturnCode.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common 2 | { 3 | public enum ReturnCode 4 | { 5 | Success = 0, 6 | ParsingError = 1, 7 | RebootRequired = 2, 8 | GenericError = 3, 9 | FilterError = 4, 10 | NullRequestData = 5, 11 | UnableToRegisterForOfflineIO = 6, 12 | DehydrateFolderFailures = 7, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/ServerGVFSConfig.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace GVFS.Common 7 | { 8 | public class ServerGVFSConfig 9 | { 10 | public IEnumerable<VersionRange> AllowedGVFSClientVersions { get; set; } 11 | 12 | public IEnumerable<CacheServerInfo> CacheServers { get; set; } = Enumerable.Empty<CacheServerInfo>(); 13 | 14 | public class VersionRange 15 | { 16 | public Version Min { get; set; } 17 | public Version Max { get; set; } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/DiagnosticConsoleEventListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.Tracing 4 | { 5 | /// <summary> 6 | /// An event listener that will print all telemetry messages to the console with timestamps. 7 | /// The format of the message is designed for completeness and parsability, but not for beauty. 8 | /// </summary> 9 | public class DiagnosticConsoleEventListener : EventListener 10 | { 11 | public DiagnosticConsoleEventListener(EventLevel maxVerbosity, Keywords keywordFilter, IEventListenerEventSink eventSink) 12 | : base(maxVerbosity, keywordFilter, eventSink) 13 | { 14 | } 15 | 16 | protected override void RecordMessageInternal(TraceEventMessage message) 17 | { 18 | Console.WriteLine(this.GetLogString(message.EventName, message.Opcode, message.Payload)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/EventLevel.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Tracing 2 | { 3 | // The default EventLevel is Verbose, which does not go to log files by default. 4 | // If you want to log to a file, you need to raise EventLevel to at least Informational 5 | public enum EventLevel 6 | { 7 | LogAlways = 0, 8 | Critical = 1, 9 | Error = 2, 10 | Warning = 3, 11 | Informational = 4, 12 | Verbose = 5 13 | } 14 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/EventMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GVFS.Common.Tracing 4 | { 5 | // This is a convenience class to make code around event metadata look nicer. 6 | // It's more obvious to see EventMetadata than Dictionary<string, object> everywhere. 7 | public class EventMetadata : Dictionary<string, object> 8 | { 9 | public EventMetadata() 10 | { 11 | } 12 | 13 | public EventMetadata(Dictionary<string, object> metadata) 14 | : base(metadata) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/EventOpcode.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Tracing 2 | { 3 | // Copied from Microsoft.Diagnostics.Tracing.EventOpcode 4 | public enum EventOpcode 5 | { 6 | // Summary: 7 | // An informational event 8 | Info = 0, 9 | 10 | // Summary: 11 | // An activity start event 12 | Start = 1, 13 | 14 | // Summary: 15 | // An activity end event 16 | Stop = 2, 17 | } 18 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/IEventListenerEventSink.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Tracing 2 | { 3 | public interface IEventListenerEventSink 4 | { 5 | void OnListenerRecovery(EventListener listener); 6 | 7 | void OnListenerFailure(EventListener listener, string errorMessage); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/IQueuedPipeStringWriterEventSink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.Tracing 4 | { 5 | public interface IQueuedPipeStringWriterEventSink 6 | { 7 | void OnStateChanged(QueuedPipeStringWriter writer, QueuedPipeStringWriterState state, Exception exception); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/ITracer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.Tracing 4 | { 5 | public interface ITracer : IDisposable 6 | { 7 | ITracer StartActivity(string activityName, EventLevel level); 8 | 9 | ITracer StartActivity(string activityName, EventLevel level, EventMetadata metadata); 10 | ITracer StartActivity(string activityName, EventLevel level, Keywords startStopKeywords, EventMetadata metadata); 11 | 12 | void SetGitCommandSessionId(string sessionId); 13 | 14 | void RelatedEvent(EventLevel level, string eventName, EventMetadata metadata); 15 | 16 | void RelatedEvent(EventLevel level, string eventName, EventMetadata metadata, Keywords keywords); 17 | 18 | void RelatedInfo(string message); 19 | 20 | void RelatedInfo(string format, params object[] args); 21 | 22 | void RelatedInfo(EventMetadata metadata, string message); 23 | 24 | void RelatedWarning(EventMetadata metadata, string message); 25 | 26 | void RelatedWarning(EventMetadata metadata, string message, Keywords keywords); 27 | 28 | void RelatedWarning(string message); 29 | 30 | void RelatedWarning(string format, params object[] args); 31 | 32 | void RelatedError(EventMetadata metadata, string message); 33 | 34 | void RelatedError(EventMetadata metadata, string message, Keywords keywords); 35 | 36 | void RelatedError(string message); 37 | 38 | void RelatedError(string format, params object[] args); 39 | 40 | TimeSpan Stop(EventMetadata metadata); 41 | } 42 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/Keywords.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Tracing 2 | { 3 | public enum Keywords : long 4 | { 5 | None = 1 << 0, 6 | Network = 1 << 1, 7 | DEPRECATED = 1 << 2, 8 | Telemetry = 1 << 3, 9 | 10 | Any = ~0, 11 | } 12 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/LogFileEventListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace GVFS.Common.Tracing 5 | { 6 | public class LogFileEventListener : EventListener 7 | { 8 | private FileStream logFile; 9 | private TextWriter writer; 10 | 11 | public LogFileEventListener(string logFilePath, EventLevel maxVerbosity, Keywords keywordFilter, IEventListenerEventSink eventSink) 12 | : base(maxVerbosity, keywordFilter, eventSink) 13 | { 14 | this.SetLogFilePath(logFilePath); 15 | } 16 | 17 | public override void Dispose() 18 | { 19 | if (this.writer != null) 20 | { 21 | this.writer.Dispose(); 22 | this.writer = null; 23 | } 24 | 25 | if (this.logFile != null) 26 | { 27 | this.logFile.Dispose(); 28 | this.logFile = null; 29 | } 30 | } 31 | 32 | protected override void RecordMessageInternal(TraceEventMessage message) 33 | { 34 | this.writer.WriteLine(this.GetLogString(message.EventName, message.Opcode, message.Payload)); 35 | this.writer.Flush(); 36 | } 37 | 38 | protected void SetLogFilePath(string newfilePath) 39 | { 40 | Directory.CreateDirectory(Path.GetDirectoryName(newfilePath)); 41 | this.logFile = File.Open(newfilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read); 42 | this.logFile.Seek(0, SeekOrigin.End); 43 | this.writer = StreamWriter.Synchronized(new StreamWriter(this.logFile)); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/TraceEventMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Common.Tracing 4 | { 5 | public class TraceEventMessage 6 | { 7 | public string EventName { get; set; } 8 | public Guid ActivityId { get; set; } 9 | public Guid ParentActivityId { get; set; } 10 | public EventLevel Level { get; set; } 11 | public Keywords Keywords { get; set; } 12 | public EventOpcode Opcode { get; set; } 13 | public string Payload { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/Tracing/TracingConstants.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Common.Tracing 2 | { 3 | public static class TracingConstants 4 | { 5 | public static class MessageKey 6 | { 7 | public const string LogAlwaysMessage = ErrorMessage; 8 | public const string CriticalMessage = ErrorMessage; 9 | public const string ErrorMessage = "ErrorMessage"; 10 | public const string WarningMessage = "WarningMessage"; 11 | public const string InfoMessage = "Message"; 12 | public const string VerboseMessage = InfoMessage; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/VersionResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace GVFS.Common 4 | { 5 | public class VersionResponse 6 | { 7 | public string Version { get; set; } 8 | 9 | public static VersionResponse FromJsonString(string jsonString) 10 | { 11 | return JsonConvert.DeserializeObject<VersionResponse>(jsonString); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/X509Certificates/CertificateVerifier.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography.X509Certificates; 2 | 3 | namespace GVFS.Common.X509Certificates 4 | { 5 | public class CertificateVerifier 6 | { 7 | public virtual bool Verify(X509Certificate2 certificate) 8 | { 9 | return certificate.Verify(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Common/X509Certificates/SystemCertificateStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography.X509Certificates; 3 | 4 | namespace GVFS.Common.X509Certificates 5 | { 6 | public class SystemCertificateStore : IDisposable 7 | { 8 | private readonly X509Store store; 9 | 10 | private bool isOpen = false; 11 | 12 | public SystemCertificateStore() 13 | { 14 | this.store = new X509Store(); 15 | } 16 | 17 | public void Dispose() 18 | { 19 | this.store.Dispose(); 20 | } 21 | 22 | public virtual X509Certificate2Collection Find(X509FindType findType, string searchString, bool validOnly) 23 | { 24 | if (!this.isOpen) 25 | { 26 | this.store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly); 27 | this.isOpen = true; 28 | } 29 | 30 | return this.store.Certificates.Find(X509FindType.FindBySubjectName, searchString, validOnly); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests.LockHolder/GVFS.FunctionalTests.LockHolder.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net461</TargetFramework> 5 | <OutputType>Exe</OutputType> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <PackageReference Include="CommandLineParser" Version="2.6.0" /> 10 | </ItemGroup> 11 | 12 | <ItemGroup> 13 | <ProjectReference Include="..\GVFS.Common\GVFS.Common.csproj" /> 14 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 15 | <ProjectReference Include="..\GVFS.Tests\GVFS.Tests.csproj" /> 16 | </ItemGroup> 17 | 18 | </Project> 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests.LockHolder/Program.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | 3 | namespace GVFS.FunctionalTests.LockHolder 4 | { 5 | public class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | Parser.Default.ParseArguments<AcquireGVFSLockVerb>(args) 10 | .WithParsed(acquireGVFSLock => acquireGVFSLock.Execute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | [assembly: Parallelizable(ParallelScope.Fixtures)] 4 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Categories.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.FunctionalTests 2 | { 3 | public static class Categories 4 | { 5 | public const string ExtraCoverage = "ExtraCoverage"; 6 | public const string FastFetch = "FastFetch"; 7 | public const string GitCommands = "GitCommands"; 8 | public const string NeedsReactionInCI = "NeedsReactionInCI"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/FileSystemRunners/ShellRunner.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Tools; 2 | using System.Diagnostics; 3 | 4 | namespace GVFS.FunctionalTests.FileSystemRunners 5 | { 6 | public abstract class ShellRunner : FileSystemRunner 7 | { 8 | protected const string SuccessOutput = "True"; 9 | protected const string FailureOutput = "False"; 10 | 11 | protected abstract string FileName { get; } 12 | 13 | protected virtual string RunProcess(string arguments, string workingDirectory = "", string errorMsgDelimeter = "") 14 | { 15 | ProcessStartInfo startInfo = new ProcessStartInfo(); 16 | startInfo.UseShellExecute = false; 17 | startInfo.RedirectStandardOutput = true; 18 | startInfo.RedirectStandardError = true; 19 | startInfo.CreateNoWindow = true; 20 | startInfo.FileName = this.FileName; 21 | startInfo.Arguments = arguments; 22 | startInfo.WorkingDirectory = workingDirectory; 23 | 24 | ProcessResult result = ProcessHelper.Run(startInfo, errorMsgDelimeter: errorMsgDelimeter); 25 | return !string.IsNullOrEmpty(result.Output) ? result.Output : result.Errors; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/GVFSTestConfig.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace GVFS.FunctionalTests 4 | { 5 | public static class GVFSTestConfig 6 | { 7 | public static string RepoToClone { get; set; } 8 | 9 | public static bool NoSharedCache { get; set; } 10 | 11 | public static string LocalCacheRoot { get; set; } 12 | 13 | public static object[] FileSystemRunners { get; set; } 14 | 15 | public static object[] GitRepoTestsValidateWorkTree { get; set; } 16 | 17 | public static bool ReplaceInboxProjFS { get; set; } 18 | 19 | public static string PathToGVFS 20 | { 21 | get 22 | { 23 | return Properties.Settings.Default.PathToGVFS; 24 | } 25 | } 26 | 27 | public static string DotGVFSRoot { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/GlobalSetup.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Tests; 2 | using GVFS.FunctionalTests.Tools; 3 | using NUnit.Framework; 4 | using System; 5 | using System.IO; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace GVFS.FunctionalTests 9 | { 10 | [SetUpFixture] 11 | public class GlobalSetup 12 | { 13 | [OneTimeSetUp] 14 | public void RunBeforeAnyTests() 15 | { 16 | } 17 | 18 | [OneTimeTearDown] 19 | public void RunAfterAllTests() 20 | { 21 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 22 | { 23 | string serviceLogFolder = Path.Combine( 24 | Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), 25 | "GVFS", 26 | GVFSServiceProcess.TestServiceName, 27 | "Logs"); 28 | 29 | Console.WriteLine("GVFS.Service logs at '{0}' attached below.\n\n", serviceLogFolder); 30 | foreach (string filename in TestResultsHelper.GetAllFilesInDirectory(serviceLogFolder)) 31 | { 32 | TestResultsHelper.OutputFileContents(filename); 33 | } 34 | 35 | GVFSServiceProcess.UninstallService(); 36 | } 37 | 38 | PrintTestCaseStats.PrintRunTimeStats(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/CacheServerTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Tools; 2 | using GVFS.Tests.Should; 3 | using NUnit.Framework; 4 | 5 | namespace GVFS.FunctionalTests.Tests.EnlistmentPerFixture 6 | { 7 | [TestFixture] 8 | [Category(Categories.ExtraCoverage)] 9 | public class CacheServerTests : TestsWithEnlistmentPerFixture 10 | { 11 | private const string CustomUrl = "https://myCache"; 12 | 13 | [TestCase] 14 | public void SettingGitConfigChangesCacheServer() 15 | { 16 | ProcessResult result = GitProcess.InvokeProcess(this.Enlistment.RepoRoot, "config gvfs.cache-server " + CustomUrl); 17 | result.ExitCode.ShouldEqual(0, result.Errors); 18 | 19 | this.Enlistment.GetCacheServer().ShouldContain("Using cache server: User Defined (" + CustomUrl + ")"); 20 | } 21 | 22 | [TestCase] 23 | public void SetAndGetTests() 24 | { 25 | this.Enlistment.SetCacheServer("\"\"").ShouldContain("You must specify a value for the cache server"); 26 | 27 | string noneMessage = "Using cache server: None (" + this.Enlistment.RepoUrl + ")"; 28 | 29 | this.Enlistment.SetCacheServer("None").ShouldContain(noneMessage); 30 | this.Enlistment.GetCacheServer().ShouldContain(noneMessage); 31 | 32 | this.Enlistment.SetCacheServer(this.Enlistment.RepoUrl).ShouldContain(noneMessage); 33 | this.Enlistment.GetCacheServer().ShouldContain(noneMessage); 34 | 35 | this.Enlistment.SetCacheServer(CustomUrl).ShouldContain("Using cache server: User Defined (" + CustomUrl + ")"); 36 | this.Enlistment.GetCacheServer().ShouldContain("Using cache server: User Defined (" + CustomUrl + ")"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/DiagnoseTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.FileSystemRunners; 2 | using GVFS.Tests.Should; 3 | using NUnit.Framework; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace GVFS.FunctionalTests.Tests.EnlistmentPerFixture 9 | { 10 | [TestFixture] 11 | [NonParallelizable] 12 | [Category(Categories.ExtraCoverage)] 13 | public class DiagnoseTests : TestsWithEnlistmentPerFixture 14 | { 15 | private FileSystemRunner fileSystem; 16 | 17 | public DiagnoseTests() 18 | { 19 | this.fileSystem = new SystemIORunner(); 20 | } 21 | 22 | [TestCase] 23 | public void DiagnoseProducesZipFile() 24 | { 25 | Directory.Exists(this.Enlistment.DiagnosticsRoot).ShouldEqual(false); 26 | string output = this.Enlistment.Diagnose(); 27 | output.ShouldNotContain(ignoreCase: true, unexpectedSubstrings: "Failed"); 28 | 29 | IEnumerable<string> files = Directory.EnumerateFiles(this.Enlistment.DiagnosticsRoot); 30 | files.ShouldBeNonEmpty(); 31 | string zipFilePath = files.First(); 32 | 33 | zipFilePath.EndsWith(".zip").ShouldEqual(true); 34 | output.Contains(zipFilePath).ShouldEqual(true); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/StatusVerbTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.FileSystemRunners; 2 | using GVFS.Tests.Should; 3 | using NUnit.Framework; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | namespace GVFS.FunctionalTests.Tests.EnlistmentPerFixture 8 | { 9 | [TestFixture] 10 | public class StatusVerbTests : TestsWithEnlistmentPerFixture 11 | { 12 | [TestCase] 13 | public void GitTrace() 14 | { 15 | Dictionary<string, string> environmentVariables = new Dictionary<string, string>(); 16 | 17 | this.Enlistment.Status(trace: "1"); 18 | this.Enlistment.Status(trace: "2"); 19 | 20 | string logPath = Path.Combine(this.Enlistment.RepoRoot, "log-file.txt"); 21 | this.Enlistment.Status(trace: logPath); 22 | 23 | FileSystemRunner fileSystem = new SystemIORunner(); 24 | fileSystem.FileExists(logPath).ShouldBeTrue(); 25 | string.IsNullOrWhiteSpace(fileSystem.ReadAllText(logPath)).ShouldBeFalse(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/TestsWithEnlistmentPerFixture.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Tools; 2 | using NUnit.Framework; 3 | 4 | namespace GVFS.FunctionalTests.Tests.EnlistmentPerFixture 5 | { 6 | [TestFixture] 7 | public abstract class TestsWithEnlistmentPerFixture 8 | { 9 | private readonly bool forcePerRepoObjectCache; 10 | private readonly bool skipPrefetchDuringClone; 11 | 12 | public TestsWithEnlistmentPerFixture(bool forcePerRepoObjectCache = false, bool skipPrefetchDuringClone = false) 13 | { 14 | this.forcePerRepoObjectCache = forcePerRepoObjectCache; 15 | this.skipPrefetchDuringClone = skipPrefetchDuringClone; 16 | } 17 | 18 | public GVFSFunctionalTestEnlistment Enlistment 19 | { 20 | get; private set; 21 | } 22 | 23 | [OneTimeSetUp] 24 | public virtual void CreateEnlistment() 25 | { 26 | if (this.forcePerRepoObjectCache) 27 | { 28 | this.Enlistment = GVFSFunctionalTestEnlistment.CloneAndMountWithPerRepoCache(GVFSTestConfig.PathToGVFS, this.skipPrefetchDuringClone); 29 | } 30 | else 31 | { 32 | this.Enlistment = GVFSFunctionalTestEnlistment.CloneAndMount(GVFSTestConfig.PathToGVFS); 33 | } 34 | } 35 | 36 | [OneTimeTearDown] 37 | public virtual void DeleteEnlistment() 38 | { 39 | if (this.Enlistment != null) 40 | { 41 | this.Enlistment.UnmountAndDeleteAll(); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerTestCase/TestsWithEnlistmentPerTestCase.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Tools; 2 | using NUnit.Framework; 3 | 4 | namespace GVFS.FunctionalTests.Tests.EnlistmentPerTestCase 5 | { 6 | [TestFixture] 7 | public abstract class TestsWithEnlistmentPerTestCase 8 | { 9 | private readonly bool forcePerRepoObjectCache; 10 | 11 | public TestsWithEnlistmentPerTestCase(bool forcePerRepoObjectCache = false) 12 | { 13 | this.forcePerRepoObjectCache = forcePerRepoObjectCache; 14 | } 15 | 16 | public GVFSFunctionalTestEnlistment Enlistment 17 | { 18 | get; private set; 19 | } 20 | 21 | [SetUp] 22 | public virtual void CreateEnlistment() 23 | { 24 | if (this.forcePerRepoObjectCache) 25 | { 26 | this.Enlistment = GVFSFunctionalTestEnlistment.CloneAndMountWithPerRepoCache(GVFSTestConfig.PathToGVFS, skipPrefetch: false); 27 | } 28 | else 29 | { 30 | this.Enlistment = GVFSFunctionalTestEnlistment.CloneAndMount(GVFSTestConfig.PathToGVFS); 31 | } 32 | } 33 | 34 | [TearDown] 35 | public virtual void DeleteEnlistment() 36 | { 37 | if (this.Enlistment != null) 38 | { 39 | this.Enlistment.UnmountAndDeleteAll(); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/GitCommands/EnumerationMergeTest.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Properties; 2 | using NUnit.Framework; 3 | 4 | namespace GVFS.FunctionalTests.Tests.GitCommands 5 | { 6 | [TestFixtureSource(typeof(GitRepoTests), nameof(GitRepoTests.ValidateWorkingTree))] 7 | [Category(Categories.GitCommands)] 8 | public class EnumerationMergeTest : GitRepoTests 9 | { 10 | // Commit that found GvFlt Bug 12258777: Entries are sometimes skipped during 11 | // enumeration when they don't fit in a user's buffer 12 | private const string EnumerationReproCommitish = "FunctionalTests/20201014_EnumerationRepro"; 13 | 14 | public EnumerationMergeTest(Settings.ValidateWorkingTreeMode validateWorkingTree) 15 | : base(enlistmentPerTest: true, validateWorkingTree: validateWorkingTree) 16 | { 17 | } 18 | 19 | [TestCase] 20 | public void ConfirmEnumerationMatches() 21 | { 22 | this.ControlGitRepo.Fetch(GitRepoTests.ConflictSourceBranch); 23 | this.ValidateGitCommand("checkout " + GitRepoTests.ConflictSourceBranch); 24 | 25 | // Failure for ProjFS Bug 12258777 occurs during teardown, the calls above are to set up 26 | // the conditions to reproduce the bug 27 | } 28 | 29 | protected override void CreateEnlistment() 30 | { 31 | this.CreateEnlistment(EnumerationReproCommitish); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/GitCommands/HashObjectTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Properties; 2 | using GVFS.FunctionalTests.Should; 3 | using GVFS.FunctionalTests.Tools; 4 | using NUnit.Framework; 5 | using System.IO; 6 | 7 | namespace GVFS.FunctionalTests.Tests.GitCommands 8 | { 9 | [TestFixture] 10 | [Category(Categories.GitCommands)] 11 | public class HashObjectTests : GitRepoTests 12 | { 13 | public HashObjectTests() 14 | : base(enlistmentPerTest: false, validateWorkingTree: Settings.ValidateWorkingTreeMode.None) 15 | { 16 | } 17 | 18 | [TestCase] 19 | public void CanReadFileAfterHashObject() 20 | { 21 | this.ValidateGitCommand("status"); 22 | 23 | // Validate that Scripts\RunUnitTests.bad is not on disk at all 24 | string filePath = Path.Combine("Scripts", "RunUnitTests.bat"); 25 | 26 | this.Enlistment.UnmountGVFS(); 27 | this.Enlistment.GetVirtualPathTo(filePath).ShouldNotExistOnDisk(this.FileSystem); 28 | this.Enlistment.MountGVFS(); 29 | 30 | // TODO 1087312: Fix 'git hash-oject' so that it works for files that aren't on disk yet 31 | GitHelpers.InvokeGitAgainstGVFSRepo( 32 | this.Enlistment.RepoRoot, 33 | "hash-object " + GitHelpers.ConvertPathToGitFormat(filePath)); 34 | 35 | this.FileContentsShouldMatch(filePath); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/GitCommands/RmTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Properties; 2 | using GVFS.FunctionalTests.Should; 3 | using GVFS.FunctionalTests.Tools; 4 | using NUnit.Framework; 5 | using System.IO; 6 | 7 | namespace GVFS.FunctionalTests.Tests.GitCommands 8 | { 9 | [TestFixture] 10 | public class RmTests : GitRepoTests 11 | { 12 | public RmTests() 13 | : base(enlistmentPerTest: false, validateWorkingTree: Settings.ValidateWorkingTreeMode.None) 14 | { 15 | } 16 | 17 | [TestCase] 18 | public void CanReadFileAfterGitRmDryRun() 19 | { 20 | this.ValidateGitCommand("status"); 21 | 22 | // Validate that Scripts\RunUnitTests.bad is not on disk at all 23 | string filePath = Path.Combine("Scripts", "RunUnitTests.bat"); 24 | 25 | this.Enlistment.UnmountGVFS(); 26 | this.Enlistment.GetVirtualPathTo(filePath).ShouldNotExistOnDisk(this.FileSystem); 27 | this.Enlistment.MountGVFS(); 28 | 29 | this.ValidateGitCommand("rm --dry-run " + GitHelpers.ConvertPathToGitFormat(filePath)); 30 | this.FileContentsShouldMatch(filePath); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/TestsWithMultiEnlistment.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.Tools; 2 | using NUnit.Framework; 3 | using System.Collections.Generic; 4 | 5 | namespace GVFS.FunctionalTests.Tests.MultiEnlistmentTests 6 | { 7 | public class TestsWithMultiEnlistment 8 | { 9 | private List<GVFSFunctionalTestEnlistment> enlistmentsToDelete = new List<GVFSFunctionalTestEnlistment>(); 10 | 11 | [TearDown] 12 | public void DeleteEnlistments() 13 | { 14 | foreach (GVFSFunctionalTestEnlistment enlistment in this.enlistmentsToDelete) 15 | { 16 | enlistment.UnmountAndDeleteAll(); 17 | } 18 | 19 | this.OnTearDownEnlistmentsDeleted(); 20 | 21 | this.enlistmentsToDelete.Clear(); 22 | } 23 | 24 | /// <summary> 25 | /// Can be overridden for custom [TearDown] steps that occur after the test enlistements have been unmounted and deleted 26 | /// </summary> 27 | protected virtual void OnTearDownEnlistmentsDeleted() 28 | { 29 | } 30 | 31 | protected GVFSFunctionalTestEnlistment CreateNewEnlistment( 32 | string localCacheRoot = null, 33 | string branch = null, 34 | bool skipPrefetch = false) 35 | { 36 | GVFSFunctionalTestEnlistment output = GVFSFunctionalTestEnlistment.CloneAndMount( 37 | GVFSTestConfig.PathToGVFS, 38 | branch, 39 | localCacheRoot, 40 | skipPrefetch); 41 | this.enlistmentsToDelete.Add(output); 42 | return output; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tools/FileSystemHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace GVFS.FunctionalTests.Tools 5 | { 6 | public static class FileSystemHelpers 7 | { 8 | public static StringComparison PathComparison 9 | { 10 | get 11 | { 12 | return CaseSensitiveFileSystem ? 13 | StringComparison.Ordinal : 14 | StringComparison.OrdinalIgnoreCase; 15 | } 16 | } 17 | 18 | public static StringComparer PathComparer 19 | { 20 | get 21 | { 22 | return CaseSensitiveFileSystem ? 23 | StringComparer.Ordinal : 24 | StringComparer.OrdinalIgnoreCase; 25 | } 26 | } 27 | 28 | public static bool CaseSensitiveFileSystem 29 | { 30 | get 31 | { 32 | return RuntimeInformation.IsOSPlatform(OSPlatform.Linux); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tools/GitProcess.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | using System.IO; 4 | 5 | namespace GVFS.FunctionalTests.Tools 6 | { 7 | public static class GitProcess 8 | { 9 | public static string Invoke(string executionWorkingDirectory, string command) 10 | { 11 | return InvokeProcess(executionWorkingDirectory, command).Output; 12 | } 13 | 14 | public static ProcessResult InvokeProcess(string executionWorkingDirectory, string command, Dictionary<string, string> environmentVariables = null, Stream inputStream = null) 15 | { 16 | ProcessStartInfo processInfo = new ProcessStartInfo(Properties.Settings.Default.PathToGit); 17 | processInfo.WorkingDirectory = executionWorkingDirectory; 18 | processInfo.UseShellExecute = false; 19 | processInfo.RedirectStandardOutput = true; 20 | processInfo.RedirectStandardError = true; 21 | processInfo.Arguments = command; 22 | 23 | if (inputStream != null) 24 | { 25 | processInfo.RedirectStandardInput = true; 26 | } 27 | 28 | processInfo.EnvironmentVariables["GIT_TERMINAL_PROMPT"] = "0"; 29 | 30 | if (environmentVariables != null) 31 | { 32 | foreach (string key in environmentVariables.Keys) 33 | { 34 | processInfo.EnvironmentVariables[key] = environmentVariables[key]; 35 | } 36 | } 37 | 38 | return ProcessHelper.Run(processInfo, inputStream: inputStream); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tools/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32.SafeHandles; 2 | using System; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace GVFS.FunctionalTests.Tools 7 | { 8 | public class NativeMethods 9 | { 10 | [DllImport("kernel32.dll", SetLastError = true)] 11 | public static extern bool MoveFile(string lpExistingFileName, string lpNewFileName); 12 | 13 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 14 | public static extern SafeFileHandle CreateFile( 15 | [In] string lpFileName, 16 | uint dwDesiredAccess, 17 | FileShare dwShareMode, 18 | [In] IntPtr lpSecurityAttributes, 19 | [MarshalAs(UnmanagedType.U4)]FileMode dwCreationDisposition, 20 | uint dwFlagsAndAttributes, 21 | [In] IntPtr hTemplateFile); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tools/ProcessResult.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.FunctionalTests.Tools 2 | { 3 | public class ProcessResult 4 | { 5 | public ProcessResult(string output, string errors, int exitCode) 6 | { 7 | this.Output = output; 8 | this.Errors = errors; 9 | this.ExitCode = exitCode; 10 | } 11 | 12 | public string Output { get; } 13 | public string Errors { get; } 14 | public int ExitCode { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Tools/RepositoryHelpers.cs: -------------------------------------------------------------------------------- 1 | using GVFS.FunctionalTests.FileSystemRunners; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace GVFS.FunctionalTests.Tools 5 | { 6 | public static class RepositoryHelpers 7 | { 8 | public static void DeleteTestDirectory(string repoPath) 9 | { 10 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 11 | { 12 | // Use cmd.exe to delete the enlistment as it properly handles tombstones and reparse points 13 | CmdRunner.DeleteDirectoryWithUnlimitedRetries(repoPath); 14 | } 15 | else 16 | { 17 | BashRunner.DeleteDirectoryWithUnlimitedRetries(repoPath); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Windows/TestData/BackgroundGitUpdates/PersistentDictionary.edb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.FunctionalTests/Windows/TestData/BackgroundGitUpdates/PersistentDictionary.edb -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Windows/TestData/BackgroundGitUpdates/PersistentDictionary.jfm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.FunctionalTests/Windows/TestData/BackgroundGitUpdates/PersistentDictionary.jfm -------------------------------------------------------------------------------- /GVFS/GVFS.FunctionalTests/Windows/TestData/BackgroundGitUpdates/epc.chk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.FunctionalTests/Windows/TestData/BackgroundGitUpdates/epc.chk -------------------------------------------------------------------------------- /GVFS/GVFS.GVFlt/GVFS.GVFlt.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net461</TargetFramework> 5 | </PropertyGroup> 6 | 7 | <ItemGroup> 8 | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> 9 | </ItemGroup> 10 | 11 | </Project> 12 | -------------------------------------------------------------------------------- /GVFS/GVFS.GVFlt/GVFltCallbacks.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace GVFS.GVFlt 5 | { 6 | public class GVFltCallbacks 7 | { 8 | /// <summary> 9 | /// This struct must remain here for DiskLayout9to10Upgrade_BackgroundAndPlaceholderListToFileBased 10 | /// </summary> 11 | /// <remarks> 12 | /// This struct should only be used by the upgrader, it has been replaced by GVFS.Virtualization.Background.FileSystemTask 13 | /// </remarks> 14 | [Serializable] 15 | public struct BackgroundGitUpdate 16 | { 17 | // This enum must be present or the BinarySerializer will always deserialze Operation as 0 18 | public enum OperationType 19 | { 20 | Invalid = 0, 21 | } 22 | 23 | public OperationType Operation { get; set; } 24 | public string VirtualPath { get; set; } 25 | public string OldVirtualPath { get; set; } 26 | 27 | // Used by the logging in the upgrader 28 | public override string ToString() 29 | { 30 | return JsonConvert.SerializeObject(this); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /GVFS/GVFS.Installers/GVFS.Installers.template.nuspec: -------------------------------------------------------------------------------- 1 | <?xml version="1.0"?> 2 | <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> 3 | <metadata> 4 | <id>GVFS.Installers</id> 5 | <version>$versionlt;/version> 6 | <authors>Microsoft</authors> 7 | <requireLicenseAcceptance>false</requireLicenseAcceptance> 8 | <description>GVFS and G4W installers</description> 9 | </metadata> 10 | <files> 11 | <file src="SetupGVFS*.exe" target="GVFS" /> 12 | <file src="Git*.exe" target="G4W" /> 13 | <file src="PortableGit*.exe" target="G4W" /> 14 | </files> 15 | </package> 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Installers/install.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | SETLOCAL 3 | 4 | REM Lookup full paths to Git and VFS for Git installers 5 | FOR /F "tokens=* USEBACKQ" %%F IN ( `where /R %~dp0 Git*.exe` ) DO SET GIT_INSTALLER=%%F 6 | FOR /F "tokens=* USEBACKQ" %%F IN ( `where /R %~dp0 SetupGVFS*.exe` ) DO SET GVFS_INSTALLER=%%F 7 | 8 | REM Create new empty directory for logs 9 | SET LOGDIR=%~dp0\logs 10 | IF EXIST %LOGDIR% ( 11 | rmdir /S /Q %LOGDIR% 12 | ) 13 | mkdir %LOGDIR% 14 | 15 | ECHO Installing Git for Windows... 16 | %GIT_INSTALLER% /LOG="%LOGDIR%\git.log" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /ALLOWDOWNGRADE=1 17 | 18 | ECHO Installing VFS for Git... 19 | %GVFS_INSTALLER% /LOG="%LOGDIR%\gvfs.log" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /DIR="C:\Program Files\VFS for Git" 20 | -------------------------------------------------------------------------------- /GVFS/GVFS.MSBuild/GVFS.MSBuild.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>netstandard2.0</TargetFramework> 5 | <IncludeBuildOutput>false</IncludeBuildOutput> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <PackageReference Include="Microsoft.Build.Framework" Version="16.0.461" PrivateAssets="all" /> 10 | <PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.0.461" PrivateAssets="all" /> 11 | </ItemGroup> 12 | 13 | </Project> 14 | -------------------------------------------------------------------------------- /GVFS/GVFS.MSBuild/GVFS.targets: -------------------------------------------------------------------------------- 1 | <Project> 2 | <!-- Load custom build tasks --> 3 | <Import Project="GVFS.tasks" /> 4 | 5 | <!-- Windows application manifest generation --> 6 | <PropertyGroup Condition="'$(GenerateWindowsAppManifest)' == 'true'"> 7 | <ApplicationManifest>$(IntermediateOutputPath)app.manifest</ApplicationManifest> 8 | </PropertyGroup> 9 | 10 | <!-- Generate version header file before compiler native code --> 11 | <Target Name="GenerateVersionHeader" 12 | BeforeTargets="ClCompile;ResourceCompile" 13 | Inputs="$(GVFSVersion)" 14 | Outputs="$(GeneratedIncludePath)CommonVersionHeader.h"> 15 | <GenerateGVFSVersionHeader Version="$(GVFSVersion)" OutputFile="$(GeneratedIncludePath)CommonVersionHeader.h" /> 16 | <ItemGroup> 17 | <FileWrites Include="$(GeneratedIncludePath)CommonVersionHeader.h" /> 18 | </ItemGroup> 19 | </Target> 20 | 21 | <!-- Generate the manifest file before we set the win32 manifest properties --> 22 | <Target Name="GenerateWindowsAppManifest" 23 | BeforeTargets="SetWin32ManifestProperties" 24 | Condition="'$(GenerateWindowsAppManifest)' == 'true'" 25 | Inputs="$(Version);$(AssemblyName)" 26 | Outputs="$(IntermediateOutputPath)app.manifest"> 27 | <GenerateWindowsAppManifest Version="$(Version)" 28 | ApplicationName="$(AssemblyName)" 29 | OutputFile="$(IntermediateOutputPath)app.manifest"/> 30 | <ItemGroup> 31 | <FileWrites Include="$(IntermediateOutputPath)app.manifest" /> 32 | </ItemGroup> 33 | </Target> 34 | </Project> 35 | -------------------------------------------------------------------------------- /GVFS/GVFS.MSBuild/GVFS.tasks: -------------------------------------------------------------------------------- 1 | <Project> 2 | <PropertyGroup Condition="'$(MSBuildRuntimeType)' == 'Mono'"> 3 | <_TaskAssembly>$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll</_TaskAssembly> 4 | <_TaskFactory>CodeTaskFactory</_TaskFactory> 5 | </PropertyGroup> 6 | <PropertyGroup Condition="'$(MSBuildRuntimeType)' != 'Mono'"> 7 | <_TaskAssembly>$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</_TaskAssembly> 8 | <_TaskFactory>RoslynCodeTaskFactory</_TaskFactory> 9 | </PropertyGroup> 10 | 11 | <UsingTask TaskName="GenerateWindowsAppManifest" TaskFactory="$(_TaskFactory)" AssemblyFile="$(_TaskAssembly)"> 12 | <Task> 13 | <Code Type="Class" Source="$(MSBuildThisFileDirectory)GenerateWindowsAppManifest.cs" /> 14 | </Task> 15 | </UsingTask> 16 | <UsingTask TaskName="GenerateGVFSConstants" TaskFactory="$(_TaskFactory)" AssemblyFile="$(_TaskAssembly)"> 17 | <Task> 18 | <Code Type="Class" Source="$(MSBuildThisFileDirectory)GenerateGVFSConstants.cs" /> 19 | </Task> 20 | </UsingTask> 21 | <UsingTask TaskName="GenerateGVFSVersionHeader" TaskFactory="$(_TaskFactory)" AssemblyFile="$(_TaskAssembly)"> 22 | <Task> 23 | <Code Type="Class" Source="$(MSBuildThisFileDirectory)GenerateGVFSVersionHeader.cs" /> 24 | </Task> 25 | </UsingTask> 26 | <UsingTask TaskName="CompileTemplatedFile" TaskFactory="$(_TaskFactory)" AssemblyFile="$(_TaskAssembly)"> 27 | <Task> 28 | <Code Type="Class" Source="$(MSBuildThisFileDirectory)CompileTemplatedFile.cs" /> 29 | </Task> 30 | </UsingTask> 31 | </Project> 32 | -------------------------------------------------------------------------------- /GVFS/GVFS.MSBuild/GenerateGVFSVersionHeader.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Build.Framework; 2 | using Microsoft.Build.Utilities; 3 | using System.IO; 4 | 5 | namespace GVFS.MSBuild 6 | { 7 | public class GenerateGVFSVersionHeader : Task 8 | { 9 | [Required] 10 | public string Version { get; set; } 11 | 12 | [Required] 13 | public string OutputFile { get; set; } 14 | 15 | public override bool Execute() 16 | { 17 | this.Log.LogMessage(MessageImportance.Normal, 18 | "Creating GVFS version header file with version '{0}' at '{1}'...", 19 | this.Version, this.OutputFile); 20 | 21 | string outputDirectory = Path.GetDirectoryName(this.OutputFile); 22 | if (!Directory.Exists(outputDirectory)) 23 | { 24 | Directory.CreateDirectory(outputDirectory); 25 | } 26 | 27 | string template = 28 | @"/* 29 | * This file is auto-generated by GVFS.MSBuild.GenerateGVFSVersionHeader. 30 | * Any changes made directly in this file will be lost. 31 | */ 32 | #define GVFS_FILE_VERSION {1} 33 | #define GVFS_FILE_VERSION_STRING ""{0}"" 34 | #define GVFS_PRODUCT_VERSION {1} 35 | #define GVFS_PRODUCT_VERSION_STRING ""{0}"" 36 | "; 37 | 38 | File.WriteAllText( 39 | this.OutputFile, 40 | string.Format( 41 | template, 42 | this.Version, 43 | this.Version?.Replace('.',','))); 44 | 45 | return true; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Mount/GVFS.Mount.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net461</TargetFramework> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <ProjectReference Include="..\GVFS.Hooks\GVFS.Hooks.csproj"> 10 | <ReferenceOutputAssembly>false</ReferenceOutputAssembly> 11 | <OutputItemType>Content</OutputItemType> 12 | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 13 | <Targets>Build;DebugSymbolsProjectOutputGroup</Targets> 14 | </ProjectReference> 15 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 16 | </ItemGroup> 17 | 18 | <ItemGroup> 19 | <PackageReference Include="CommandLineParser" Version="2.6.0" /> 20 | </ItemGroup> 21 | 22 | </Project> 23 | -------------------------------------------------------------------------------- /GVFS/GVFS.Mount/MountAbortedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Mount 4 | { 5 | public class MountAbortedException : Exception 6 | { 7 | public MountAbortedException(InProcessMountVerb verb) 8 | { 9 | this.Verb = verb; 10 | } 11 | 12 | public InProcessMountVerb Verb { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Mount/Program.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | using GVFS.PlatformLoader; 3 | using System; 4 | 5 | namespace GVFS.Mount 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | GVFSPlatformLoader.Initialize(); 12 | try 13 | { 14 | Parser.Default.ParseArguments<InProcessMountVerb>(args) 15 | .WithParsed(mount => mount.Execute()); 16 | } 17 | catch (MountAbortedException e) 18 | { 19 | // Calling Environment.Exit() is required, to force all background threads to exit as well 20 | Environment.Exit((int)e.Verb.ReturnCode); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeHooks.Common/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <cstring> 4 | #include <string> 5 | 6 | #ifdef __APPLE__ 7 | typedef std::string PATH_STRING; 8 | typedef int PIPE_HANDLE; 9 | #define PRINTF_FMT(X, Y) __attribute__((__format__ (printf, X, Y))) 10 | #elif _WIN32 11 | typedef std::wstring PATH_STRING; 12 | typedef HANDLE PIPE_HANDLE; 13 | #define PRINTF_FMT(X, Y) 14 | #else 15 | #error Unsupported platform 16 | #endif 17 | 18 | #if __cplusplus < 201103L 19 | #error The hooks require at least C++11 support 20 | #endif 21 | 22 | enum ReturnCode 23 | { 24 | Success = 0, 25 | InvalidArgCount = 1, 26 | GetCurrentDirectoryFailure = 2, 27 | NotInGVFSEnlistment = 3, 28 | PipeConnectError = 4, 29 | PipeConnectTimeout = 5, 30 | InvalidSHA = 6, 31 | PipeWriteFailed = 7, 32 | PipeReadFailed = 8, 33 | FailureToDownload = 9, 34 | PathNameError = 10, 35 | 36 | LastError = PathNameError, 37 | }; 38 | 39 | void die(int err, const char *fmt, ...) PRINTF_FMT(2,3); 40 | inline void die(int err, const char *fmt, ...) 41 | { 42 | va_list params; 43 | va_start(params, fmt); 44 | vfprintf(stderr, fmt, params); 45 | va_end(params); 46 | exit(err); 47 | } 48 | 49 | PATH_STRING GetFinalPathName(const PATH_STRING& path); 50 | PATH_STRING GetGVFSPipeName(const char *appName); 51 | PIPE_HANDLE CreatePipeToGVFS(const PATH_STRING& pipeName); 52 | void DisableCRLFTranslationOnStdPipes(); 53 | 54 | bool WriteToPipe( 55 | PIPE_HANDLE pipe, 56 | const char* message, 57 | unsigned long messageLength, 58 | /* out */ unsigned long* bytesWritten, 59 | /* out */ int* error); 60 | 61 | bool ReadFromPipe( 62 | PIPE_HANDLE pipe, 63 | char* buffer, 64 | unsigned long bufferLength, 65 | /* out */ unsigned long* bytesRead, 66 | /* out */ int* error); 67 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/FileUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool SupersedeFile(const wchar_t* path, const char* newContent); 6 | } -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | GVFS.NativeTests 3 | ======================================================================== 4 | 5 | Summary: 6 | 7 | GVFS.NativeTests is a library used by GVFS.FunctionalTests to run GVFS 8 | functional tests using the native WinAPI. 9 | 10 | The GVFS.NativeTests dll is output into the appropriate GVFS.FunctionalTests 11 | directory so that the dll can be found when it is DllImported by GVFS.NativeTests. 12 | 13 | 14 | Folder Structure: 15 | 16 | interface -> Header files that are consumable by projects outside of GVFS.NativeTests 17 | include -> Header files that are internal to GVFS.NativeTests 18 | source -> GVFS.NativeTests source code 19 | 20 | 21 | Debugging: 22 | 23 | To step through tests in GVFS.NativeTests and to set breakpoints, ensure that the 24 | "Enable native code debugging" setting is checked in the GVFS.FunctionalTests 25 | project properites (Debug tab) -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/include/SafeHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Wrapper for HANDLE that calls CloseHandle when destroyed 4 | class SafeHandle 5 | { 6 | public: 7 | SafeHandle(HANDLE handle); 8 | ~SafeHandle(); 9 | 10 | HANDLE GetHandle(); 11 | void CloseHandle(); 12 | 13 | private: 14 | HANDLE handle; 15 | }; 16 | 17 | inline SafeHandle::SafeHandle(HANDLE handle) 18 | { 19 | this->handle = handle; 20 | } 21 | 22 | inline SafeHandle::~SafeHandle() 23 | { 24 | if (this->handle != NULL) 25 | { 26 | this->CloseHandle(); 27 | } 28 | } 29 | 30 | inline HANDLE SafeHandle::GetHandle() 31 | { 32 | return this->handle; 33 | } 34 | 35 | inline void SafeHandle::CloseHandle() 36 | { 37 | if (this->handle != NULL && this->handle != INVALID_HANDLE_VALUE) 38 | { 39 | ::CloseHandle(this->handle); 40 | this->handle = NULL; 41 | } 42 | } -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/include/SafeOverlapped.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Wrapper for OVERLAPPED that calls CloseHandle on the OVERLAPPED's hEvent when destroyed 4 | struct SafeOverlapped 5 | { 6 | SafeOverlapped(); 7 | ~SafeOverlapped(); 8 | 9 | OVERLAPPED overlapped; 10 | }; 11 | 12 | inline SafeOverlapped::SafeOverlapped() 13 | { 14 | memset(&this->overlapped, 0, sizeof(OVERLAPPED)); 15 | } 16 | 17 | inline SafeOverlapped::~SafeOverlapped() 18 | { 19 | if (this->overlapped.hEvent != NULL) 20 | { 21 | CloseHandle(this->overlapped.hEvent); 22 | } 23 | } -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/include/TestException.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class TestException : public std::exception 4 | { 5 | 6 | public: 7 | TestException(const std::string& message); 8 | virtual ~TestException(); 9 | virtual const char* what() const override; 10 | 11 | private: 12 | std::string message; 13 | }; 14 | 15 | inline TestException::TestException(const std::string& message) 16 | : message(message) 17 | { 18 | } 19 | 20 | inline TestException::~TestException() 21 | { 22 | } 23 | 24 | inline const char* TestException::what() const 25 | { 26 | return this->message.c_str(); 27 | } 28 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/include/TestVerifiers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Should.h" 4 | #include "TestHelpers.h" 5 | 6 | namespace TestVerifiers 7 | { 8 | 9 | inline void ExpectDirEntries(const std::string& path, std::vector<std::string>& entries) 10 | { 11 | std::vector<FileInfo> result = TestHelpers::EnumDirectory(path); 12 | entries.push_back("."); 13 | entries.push_back(".."); 14 | 15 | VERIFY_ARE_EQUAL(entries.size(), result.size()); 16 | 17 | for (const std::string& entry : entries) 18 | { 19 | bool found = false; 20 | for (std::vector<FileInfo>::iterator resultIt = result.begin(); resultIt != result.end(); resultIt++) 21 | { 22 | if (resultIt->Name == entry) 23 | { 24 | result.erase(resultIt); 25 | found = true; 26 | break; 27 | } 28 | } 29 | 30 | if (!found) 31 | { 32 | VERIFY_FAIL((" [" + entry + "] not found").c_str()); 33 | return; 34 | } 35 | } 36 | 37 | if (!result.empty()) 38 | { 39 | VERIFY_FAIL("Some expected results not found"); 40 | } 41 | } 42 | 43 | inline void AreEqual(const std::string& str1, const std::string& str2) 44 | { 45 | VERIFY_ARE_EQUAL(str1, str2); 46 | } 47 | 48 | } // namespace TestVerifiers -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/include/prjlib_internal.h: -------------------------------------------------------------------------------- 1 | // prjlib_internal.h 2 | // 3 | // Function declarations for internal functions in prjlib (used in the ProjFS tests) 4 | // that are not intended to be used by user applications (e.g. GVFS) built on GVFlt 5 | 6 | #pragma once 7 | 8 | #include "prjlibp.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | // 15 | // Functions operating on GVFS reparse points 16 | // 17 | HRESULT 18 | PrjpReadPrjReparsePointData( 19 | _In_ LPCWSTR FilePath, 20 | _Out_writes_bytes_(*DataSize) PGV_REPARSE_INFO ReparsePointData, 21 | _Out_opt_ PULONG ReparseTag, 22 | _Inout_ PUSHORT DataSize 23 | ); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/include/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include <SDKDDKVer.h> 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/NtQueryDirectoryFileTests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool QueryDirectoryFileRestartScanResetsFilter(const char* folderPath); 6 | } 7 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/PlaceholderUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool PlaceHolderHasVersionInfo(const char* virtualPath, int version, const WCHAR* sha); 6 | } -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_BugRegressionTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_ModifyFileInScratchAndDir(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_RMDIRTest1(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_RMDIRTest2(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_RMDIRTest3(const char* virtualRootPath); 9 | NATIVE_TESTS_EXPORT bool ProjFS_RMDIRTest4(const char* virtualRootPath); 10 | NATIVE_TESTS_EXPORT bool ProjFS_RMDIRTest5(const char* virtualRootPath); 11 | NATIVE_TESTS_EXPORT bool ProjFS_DeepNonExistFileUnderPartial(const char* virtualRootPath); 12 | NATIVE_TESTS_EXPORT bool ProjFS_SupersededReparsePoint(const char* virtualRootPath); 13 | 14 | // Note the following tests were not ported from ProjFS: 15 | // 16 | // StartInstanceAndFreeCallbacks 17 | // QickAttachDetach 18 | // - These timing scenarios don't need to be tested with GVFS 19 | // 20 | // UnableToReadPartialFile 21 | // - This test requires control over the ProjFS callback implementation 22 | // 23 | // DeepNonExistFileUnderFull 24 | // - Currently GVFS does not covert folders to full 25 | 26 | // The following were ported to the managed tests: 27 | // 28 | // CMDHangNoneActiveInstance 29 | } 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_DeleteFileTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteVirtualFile_SetDisposition(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteVirtualFile_DeleteOnClose(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_DeletePlaceholder_SetDisposition(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_DeletePlaceholder_DeleteOnClose(const char* virtualRootPath); 9 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteFullFile_SetDisposition(const char* virtualRootPath); 10 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteFullFile_DeleteOnClose(const char* virtualRootPath); 11 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteLocalFile_SetDisposition(const char* virtualRootPath); 12 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteLocalFile_DeleteOnClose(const char* virtualRootPath); 13 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteNotExistFile_SetDisposition(const char* virtualRootPath); 14 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteNotExistFile_DeleteOnClose(const char* virtualRootPath); 15 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteNonRootVirtualFile_SetDisposition(const char* virtualRootPath); 16 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteNonRootVirtualFile_DeleteOnClose(const char* virtualRootPath); 17 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteFileOutsideVRoot_SetDisposition(const char* pathOutsideRepo); 18 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteFileOutsideVRoot_DeleteOnClose(const char* pathOutsideRepo); 19 | 20 | // Note the following tests were not ported from ProjFS: 21 | // 22 | // DeleteFullFileWithoutFileContext_SetDisposition 23 | // DeleteFullFileWithoutFileContext_DeleteOnClose 24 | // - GVFS will always project new files when its back layer changes 25 | } 26 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_DeleteFolderTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteVirtualNonEmptyFolder_SetDisposition(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteVirtualNonEmptyFolder_DeleteOnClose(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_DeletePlaceholderNonEmptyFolder_SetDisposition(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_DeletePlaceholderNonEmptyFolder_DeleteOnClose(const char* virtualRootPath); 9 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteLocalEmptyFolder_SetDisposition(const char* virtualRootPath); 10 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteLocalEmptyFolder_DeleteOnClose(const char* virtualRootPath); 11 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteNonRootVirtualFolder_SetDisposition(const char* virtualRootPath); 12 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteNonRootVirtualFolder_DeleteOnClose(const char* virtualRootPath); 13 | 14 | // Note the following tests were not ported from ProjFS: 15 | // 16 | // DeleteVirtualEmptyFolder_SetDisposition 17 | // DeleteVirtualEmptyFolder_DeleteOnClose 18 | // - Git does not support empty folders 19 | // 20 | // DeleteFullNonEmptyFolder_SetDisposition 21 | // DeleteFullNonEmptyFolder_DeleteOnClose 22 | // - GVFS does not allow full folders 23 | } 24 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_DirEnumTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_EnumEmptyFolder(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_EnumFolderWithOneFileInPackage(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_EnumFolderWithOneFileInBoth(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_EnumFolderWithOneFileInBoth1(const char* virtualRootPath); 9 | NATIVE_TESTS_EXPORT bool ProjFS_EnumFolderDeleteExistingFile(const char* virtualRootPath); 10 | NATIVE_TESTS_EXPORT bool ProjFS_EnumFolderSmallBuffer(const char* virtualRootPath); 11 | NATIVE_TESTS_EXPORT bool ProjFS_EnumTestNoMoreNoSuchReturnCodes(const char* virtualRootPath); 12 | NATIVE_TESTS_EXPORT bool ProjFS_EnumTestQueryDirectoryFileRestartScanProjectedFile(const char* virtualRootPath); 13 | } 14 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_FileAttributeTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_ModifyFileInScratchAndCheckLastWriteTime(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_FileSize(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_ModifyFileInScratchAndCheckFileSize(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_FileAttributes(const char* virtualRootPath); 9 | 10 | // Note the following tests were not ported from ProjFS: 11 | // 12 | // LastWriteTime 13 | // - There is no last write time in the GVFS layer to compare with 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_FileEATest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_OneEAAttributeWillPass(const char* virtualRootPath); 6 | } 7 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_FileOperationTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_OpenRootFolder(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_WriteAndVerify(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_DeleteExistingFile(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_OpenNonExistingFile(const char* virtualRootPath); 9 | 10 | // Note the following tests were not ported from ProjFS: 11 | // 12 | // OpenFileForRead 13 | // - Covered in GVFS.FunctionalTests.Tests.EnlistmentPerFixture.WorkingDirectoryTests.ProjectedFileHasExpectedContents 14 | // OpenFileForWrite 15 | // - Covered in GVFS.FunctionalTests.Tests.LongRunningEnlistment.WorkingDirectoryTests.ShrinkFileContents (and other tests) 16 | // ReadFileAndVerifyContent 17 | // - Covered in GVFS.FunctionalTests.Tests.EnlistmentPerFixture.WorkingDirectoryTests.ProjectedFileHasExpectedContents 18 | // WriteFileAndVerifyFileInScratch 19 | // OverwriteAndVerify 20 | // - Does not apply: Tests that writing scratch layer does not impact backing layer contents 21 | // CreateNewFileInScratch 22 | // CreateNewFileAndWriteInScratch 23 | // - Covered in GVFS.FunctionalTests.Tests.LongRunningEnlistment.WorkingDirectoryTests.ShrinkFileContents (and other tests) 24 | } 25 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_MoveFolderTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_NoneToNone(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_VirtualToNone(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_PartialToNone(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_VirtualToVirtual(const char* virtualRootPath); 9 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_VirtualToPartial(const char* virtualRootPath); 10 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_OutsideToNone(const char* pathOutsideRepo, const char* virtualRootPath); 11 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_OutsideToVirtual(const char* pathOutsideRepo, const char* virtualRootPath); 12 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_NoneToOutside(const char* pathOutsideRepo, const char* virtualRootPath); 13 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_VirtualToOutside(const char* pathOutsideRepo, const char* virtualRootPath); 14 | NATIVE_TESTS_EXPORT bool ProjFS_MoveFolder_OutsideToOutside(const char* pathOutsideRepo, const char* virtualRootPath); 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_MultiThreadsTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_OpenForReadsSameTime(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_OpenForWritesSameTime(const char* virtualRootPath); 7 | 8 | // Note the following tests were not ported from ProjFS: 9 | // 10 | // GetPlaceholderInfoAndStopInstance 11 | // GetStreamAndStopInstance 12 | // EnumAndStopInstance 13 | // - These tests require precise control of when the virtualization instance is stopped 14 | 15 | // Note: ProjFS_OpenMultipleFilesForReadsSameTime was not ported from ProjFS code, it just follows 16 | // the same pattern as those tests 17 | NATIVE_TESTS_EXPORT bool ProjFS_OpenMultipleFilesForReadsSameTime(const char* virtualRootPath); 18 | } 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ProjFS_SetLinkTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_ToVirtualFile(const char* virtualRootPath); 6 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_ToPlaceHolder(const char* virtualRootPath); 7 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_ToFullFile(const char* virtualRootPath); 8 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_ToNonExistFileWillFail(const char* virtualRootPath); 9 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_NameAlreadyExistWillFail(const char* virtualRootPath); 10 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_FromOutside(const char* pathOutsideRepo, const char* virtualRootPath); 11 | NATIVE_TESTS_EXPORT bool ProjFS_SetLink_ToOutside(const char* pathOutsideRepo, const char* virtualRootPath); 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/ReadAndWriteTests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" 4 | { 5 | 6 | NATIVE_TESTS_EXPORT bool ReadAndWriteSeparateHandles(const char* fileVirtualPath); 7 | 8 | NATIVE_TESTS_EXPORT bool ReadAndWriteSameHandle(const char* fileVirtualPath, bool synchronousIO); 9 | 10 | NATIVE_TESTS_EXPORT bool ReadAndWriteRepeatedly(const char* fileVirtualPath, bool synchronousIO); 11 | 12 | NATIVE_TESTS_EXPORT bool RemoveReadOnlyAttribute(const char* fileVirtualPath); 13 | 14 | NATIVE_TESTS_EXPORT bool CannotWriteToReadOnlyFile(const char* fileVirtualPath); 15 | 16 | NATIVE_TESTS_EXPORT bool EnumerateAndReadDoesNotChangeEnumerationOrder(const char* folderVirtualPath); 17 | 18 | NATIVE_TESTS_EXPORT bool EnumerationErrorsMatchNTFSForNonExistentFolder(const char* nonExistentVirtualPath, const char* nonExistentPhysicalPath); 19 | 20 | NATIVE_TESTS_EXPORT bool EnumerationErrorsMatchNTFSForEmptyFolder(const char* emptyFolderVirtualPath, const char* emptyFolderPhysicalPath); 21 | 22 | NATIVE_TESTS_EXPORT bool CanDeleteEmptyFolderWithFileDispositionOnClose(const char* emptyFolderPath); 23 | 24 | NATIVE_TESTS_EXPORT bool ErrorWhenPathTreatsFileAsFolderMatchesNTFS(const char* fileVirtualPath, const char* fileNTFSPath, int creationDisposition); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/interface/TrailingSlashTests.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | extern "C" 5 | { 6 | NATIVE_TESTS_EXPORT bool EnumerateWithTrailingSlashMatchesWithoutSlashAfterDelete(const char* virtualRootPath); 7 | } -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/packages.config: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <packages> 3 | <package id="GVFS.ProjFS" version="2019.411.1" targetFramework="native" developmentDependency="true" /> 4 | </packages> -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/source/PlaceholderUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "PlaceholderUtils.h" 3 | #include "SafeHandle.h" 4 | #include "TestException.h" 5 | #include "TestHelpers.h" 6 | #include "TestVerifiers.h" 7 | #include "Should.h" 8 | 9 | using namespace TestHelpers; 10 | 11 | bool PlaceHolderHasVersionInfo(const char* virtualPath, int version, const WCHAR* sha) 12 | { 13 | try 14 | { 15 | std::string path(virtualPath); 16 | std::shared_ptr<GV_REPARSE_INFO> reparseInfo = GetReparseInfo(path); 17 | 18 | SHOULD_EQUAL(reparseInfo->versionInfo.ProviderID[0], static_cast<UCHAR>(version)); 19 | 20 | SHOULD_EQUAL(_wcsnicmp(sha, static_cast<WCHAR*>(static_cast<void*>(reparseInfo->versionInfo.ContentID)), PRJ_PLACEHOLDER_ID_LENGTH), 0); 21 | } 22 | catch (TestException&) 23 | { 24 | return false; 25 | } 26 | 27 | return true; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/source/ProjFS_FileEATest.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ProjFS_FileEATest.h" 3 | #include "SafeHandle.h" 4 | #include "TestException.h" 5 | #include "TestHelpers.h" 6 | #include "Should.h" 7 | 8 | using namespace TestHelpers; 9 | 10 | static const std::string TEST_ROOT_FOLDER("\\GVFlt_FileEATest"); 11 | 12 | bool ProjFS_OneEAAttributeWillPass(const char* virtualRootPath) 13 | { 14 | try 15 | { 16 | std::string fileName = virtualRootPath + TEST_ROOT_FOLDER + std::string("\\OneEAAttributeWillPass.txt"); 17 | 18 | ULONG size = 2 * 65535; 19 | PFILE_FULL_EA_INFORMATION buffer = (PFILE_FULL_EA_INFORMATION)calloc(1, size); 20 | auto status = SetEAInfo(fileName, buffer, size); 21 | VERIFY_ARE_EQUAL(STATUS_SUCCESS, status); 22 | 23 | OpenForRead(fileName); 24 | status = ReadEAInfo(fileName, buffer, &size); 25 | VERIFY_ARE_EQUAL(STATUS_SUCCESS, status); 26 | VERIFY_ARE_NOT_EQUAL((ULONG)0, size); 27 | 28 | } 29 | catch (TestException&) 30 | { 31 | return false; 32 | } 33 | 34 | return true; 35 | } -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/source/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | 4 | BOOL APIENTRY DllMain( HMODULE hModule, 5 | DWORD ul_reason_for_call, 6 | LPVOID lpReserved 7 | ) 8 | { 9 | UNREFERENCED_PARAMETER(hModule); 10 | UNREFERENCED_PARAMETER(lpReserved); 11 | 12 | switch (ul_reason_for_call) 13 | { 14 | case DLL_PROCESS_ATTACH: 15 | case DLL_THREAD_ATTACH: 16 | case DLL_THREAD_DETACH: 17 | case DLL_PROCESS_DETACH: 18 | break; 19 | } 20 | return TRUE; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /GVFS/GVFS.NativeTests/source/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GVFS.NativeTests.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // Add any additional headers you need in STDAFX.H and not in this file 8 | -------------------------------------------------------------------------------- /GVFS/GVFS.PerfProfiling/GVFS.PerfProfiling.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net461</TargetFramework> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <ProjectReference Include="..\GVFS.Common\GVFS.Common.csproj" /> 10 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 11 | <ProjectReference Include="..\GVFS.Virtualization\GVFS.Virtualization.csproj" /> 12 | </ItemGroup> 13 | 14 | </Project> 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/DiskLayoutUpgrades/DiskLayout10to11Upgrade_NewOperationType.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using GVFS.DiskLayoutUpgrades; 3 | 4 | namespace GVFS.Platform.Windows.DiskLayoutUpgrades 5 | { 6 | public class DiskLayout10to11Upgrade_NewOperationType : DiskLayoutUpgrade.MajorUpgrade 7 | { 8 | protected override int SourceMajorVersion 9 | { 10 | get { return 10; } 11 | } 12 | 13 | /// <summary> 14 | /// Version 10 to 11 only added a new value to BackgroundGitUpdate.OperationType, 15 | /// so we only need to bump the disk layout version version here. 16 | /// </summary> 17 | public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) 18 | { 19 | if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot)) 20 | { 21 | return false; 22 | } 23 | 24 | return true; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/DiskLayoutUpgrades/DiskLayout12_0To12_1Upgrade_StatusAheadBehind.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using GVFS.DiskLayoutUpgrades; 3 | using System.Collections.Generic; 4 | 5 | namespace GVFS.Platform.Windows.DiskLayoutUpgrades 6 | { 7 | public class DiskLayout12_0To12_1Upgrade_StatusAheadBehind : DiskLayoutUpgrade.MinorUpgrade 8 | { 9 | protected override int SourceMajorVersion 10 | { 11 | get { return 12; } 12 | } 13 | 14 | protected override int SourceMinorVersion 15 | { 16 | get { return 0; } 17 | } 18 | 19 | public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) 20 | { 21 | if (!this.TrySetGitConfig( 22 | tracer, 23 | enlistmentRoot, 24 | new Dictionary<string, string> 25 | { 26 | { "status.aheadbehind", "false" }, 27 | })) 28 | { 29 | return false; 30 | } 31 | 32 | return this.TryIncrementMinorVersion(tracer, enlistmentRoot); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/DiskLayoutUpgrades/DiskLayout15to16Upgrade_GitStatusCache.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using GVFS.DiskLayoutUpgrades; 3 | 4 | namespace GVFS.Platform.Windows.DiskLayoutUpgrades 5 | { 6 | /// <summary> 7 | /// This is a no-op upgrade step. It is here to prevent users from downgrading to a previous 8 | /// version of GVFS that is not GitStatusCache aware. 9 | /// 10 | /// This is because GVFS will set git config entries for the location of the git status cache when mounting, 11 | /// but does not unset them when unmounting (even if it did, it might not reliably unset these values). 12 | /// If a user downgrades, and they have a status cache file on disk, and git is configured to use the cache, 13 | /// then they might get stale / incorrect results after a downgrade. To avoid this possibility, we update 14 | /// the on-disk version during upgrade. 15 | /// </summary> 16 | public class DiskLayout15to16Upgrade_GitStatusCache : DiskLayoutUpgrade.MajorUpgrade 17 | { 18 | protected override int SourceMajorVersion => 15; 19 | 20 | public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) 21 | { 22 | if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot)) 23 | { 24 | return false; 25 | } 26 | 27 | return true; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/DiskLayoutUpgrades/DiskLayout17to18Upgrade_TombstoneFolderPlaceholders.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using GVFS.DiskLayoutUpgrades; 3 | 4 | namespace GVFS.Platform.Windows.DiskLayoutUpgrades 5 | { 6 | public class DiskLayout17to18Upgrade_TombstoneFolderPlaceholders : DiskLayoutUpgrade.MajorUpgrade 7 | { 8 | protected override int SourceMajorVersion => 17; 9 | 10 | public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) 11 | { 12 | // Don't need to upgrade since the tombstone folders are only needed when a git command deletes folders 13 | // And the git command would have needed to be cancelled or crashed to leave tombstones that would need 14 | // to be tracked and persisted to the placeholder database. 15 | if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot)) 16 | { 17 | return false; 18 | } 19 | 20 | return true; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/DiskLayoutUpgrades/DiskLayout18to19Upgrade_SqlitePlacholders.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.DiskLayoutUpgrades; 2 | 3 | namespace GVFS.Platform.Windows.DiskLayoutUpgrades 4 | { 5 | public class DiskLayout18to19Upgrade_SqlitePlacholders : DiskLayoutUpgrade_SqlitePlaceholders 6 | { 7 | protected override int SourceMajorVersion => 18; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/GVFS.Platform.Windows.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net461</TargetFramework> 5 | </PropertyGroup> 6 | 7 | <ItemGroup> 8 | <ProjectReference Include="..\GVFS.GVFlt\GVFS.GVFlt.csproj" /> 9 | <ProjectReference Include="..\GVFS.Virtualization\GVFS.Virtualization.csproj" /> 10 | </ItemGroup> 11 | 12 | <ItemGroup> 13 | <PackageReference Include="ManagedEsent" Version="1.9.4" /> 14 | <PackageReference Include="Microsoft.Database.Collections.Generic" Version="1.9.4" /> 15 | <PackageReference Include="Microsoft.Database.Isam" Version="1.9.4" /> 16 | <PackageReference Include="Microsoft.Windows.ProjFS" Version="1.1.19156.1" /> 17 | </ItemGroup> 18 | 19 | <ItemGroup> 20 | <Reference Include="System.Management" /> 21 | <Reference Include="System.ServiceProcess" /> 22 | </ItemGroup> 23 | 24 | </Project> 25 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/HResultExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Windows.ProjFS; 2 | 3 | namespace GVFS.Platform.Windows 4 | { 5 | public class HResultExtensions 6 | { 7 | public const int GenericProjFSError = -2147024579; // returned by ProjFS::DeleteFile() on Win server 2016 while deleting a partial file 8 | 9 | private const int FacilityNtBit = 0x10000000; // FACILITY_NT_BIT 10 | private const int FacilityWin32 = 7; // FACILITY_WIN32 11 | 12 | // #define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT)) 13 | public enum HResultFromNtStatus : int 14 | { 15 | FileNotAvailable = unchecked((int)0xC0000467) | FacilityNtBit, // STATUS_FILE_NOT_AVAILABLE 16 | FileClosed = unchecked((int)0xC0000128) | FacilityNtBit, // STATUS_FILE_CLOSED 17 | IoReparseTagNotHandled = unchecked((int)0xC0000279) | FacilityNtBit, // STATUS_IO_REPARSE_TAG_NOT_HANDLED 18 | DeviceNotReady = unchecked((int)0xC00000A3L) | FacilityNtBit, // STATUS_DEVICE_NOT_READY 19 | } 20 | 21 | // HRESULT_FROM_WIN32(unsigned long x) { return (HRESULT)(x) <= 0 ? (HRESULT)(x) : (HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000);} 22 | public static HResult HResultFromWin32(int win32error) 23 | { 24 | return win32error <= 0 ? (HResult)win32error : (HResult)unchecked((win32error & 0x0000FFFF) | (FacilityWin32 << 16) | 0x80000000); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/PlatformLoader.Windows.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.Git; 3 | using GVFS.Platform.Windows; 4 | using GVFS.Virtualization.FileSystem; 5 | 6 | namespace GVFS.PlatformLoader 7 | { 8 | public static class GVFSPlatformLoader 9 | { 10 | public static FileSystemVirtualizer CreateFileSystemVirtualizer(GVFSContext context, GVFSGitObjects gitObjects) 11 | { 12 | return new WindowsFileSystemVirtualizer(context, gitObjects); 13 | } 14 | 15 | public static void Initialize() 16 | { 17 | GVFSPlatform.Register(new WindowsPlatform()); 18 | return; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Platform.Windows/WindowsGitInstallation.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.Git; 3 | using Microsoft.Win32; 4 | using System.IO; 5 | 6 | namespace GVFS.Platform.Windows 7 | { 8 | public class WindowsGitInstallation : IGitInstallation 9 | { 10 | private const string GitProcessName = "git.exe"; 11 | private const string GitBinRelativePath = "cmd\\git.exe"; 12 | private const string GitInstallationRegistryKey = "SOFTWARE\\GitForWindows"; 13 | private const string GitInstallationRegistryInstallPathValue = "InstallPath"; 14 | 15 | public bool GitExists(string gitBinPath) 16 | { 17 | if (!string.IsNullOrWhiteSpace(gitBinPath)) 18 | { 19 | return File.Exists(gitBinPath); 20 | } 21 | 22 | return !string.IsNullOrEmpty(GetInstalledGitBinPath()); 23 | } 24 | 25 | public string GetInstalledGitBinPath() 26 | { 27 | string gitBinPath = WindowsPlatform.GetStringFromRegistry(GitInstallationRegistryKey, GitInstallationRegistryInstallPathValue); 28 | if (!string.IsNullOrWhiteSpace(gitBinPath)) 29 | { 30 | gitBinPath = Path.Combine(gitBinPath, GitBinRelativePath); 31 | if (File.Exists(gitBinPath)) 32 | { 33 | return gitBinPath; 34 | } 35 | } 36 | 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /GVFS/GVFS.PostIndexChangedHook/Version.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.PostIndexChangedHook/Version.rc -------------------------------------------------------------------------------- /GVFS/GVFS.PostIndexChangedHook/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Version.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.PostIndexChangedHook/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GVFS.PostIndexChangedHook.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.PostIndexChangedHook/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #ifdef _WIN32 9 | #include "targetver.h" 10 | #include <Windows.h> 11 | #endif 12 | 13 | #include <string> 14 | #include <stdarg.h> 15 | 16 | 17 | 18 | // TODO: reference additional headers your program requires here 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.PostIndexChangedHook/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include <SDKDDKVer.h> 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.ReadObjectHook/Version.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.ReadObjectHook/Version.rc -------------------------------------------------------------------------------- /GVFS/GVFS.ReadObjectHook/packet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include <stdio.h> 3 | 4 | size_t packet_txt_read(char *buf, size_t count, FILE *stream = stdin); 5 | void packet_txt_write(const char *buf, FILE *stream = stdout); 6 | void packet_flush(FILE *stream = stdout); 7 | -------------------------------------------------------------------------------- /GVFS/GVFS.ReadObjectHook/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Version.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.ReadObjectHook/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GVFS.ReadObjectHook.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.ReadObjectHook/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #ifdef _WIN32 9 | #include "targetver.h" 10 | #include <Windows.h> 11 | #endif 12 | 13 | #include <string> 14 | #include <stdarg.h> 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.ReadObjectHook/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include <SDKDDKVer.h> 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/Data/ActionItem.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace GVFS.Service.UI.Data 4 | { 5 | [XmlRoot("action")] 6 | public class ActionItem 7 | { 8 | [XmlAttribute("content")] 9 | public string Content { get; set; } 10 | 11 | [XmlAttribute("arguments")] 12 | public string Arguments { get; set; } 13 | 14 | [XmlAttribute("activationtype")] 15 | public string ActivationType { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/Data/ActionsData.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace GVFS.Service.UI.Data 4 | { 5 | public class ActionsData 6 | { 7 | [XmlAnyElement("actions")] 8 | public XmlList<ActionItem> Actions { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/Data/BindingData.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace GVFS.Service.UI.Data 4 | { 5 | public class BindingData 6 | { 7 | [XmlAttribute("template")] 8 | public string Template { get; set; } 9 | 10 | [XmlAnyElement] 11 | public XmlList<BindingItem> Items { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/Data/BindingItem.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace GVFS.Service.UI.Data 4 | { 5 | public abstract class BindingItem 6 | { 7 | [XmlRoot("text")] 8 | public class TextData : BindingItem 9 | { 10 | public TextData() 11 | { 12 | // Required for serialization 13 | } 14 | 15 | public TextData(string value) 16 | { 17 | this.Value = value; 18 | } 19 | 20 | [XmlText] 21 | public string Value { get; set; } 22 | } 23 | 24 | [XmlRoot("image")] 25 | public class ImageData : BindingItem 26 | { 27 | [XmlAttribute("placement")] 28 | public string Placement { get; set; } 29 | 30 | [XmlAttribute("src")] 31 | public string Source { get; set; } 32 | 33 | [XmlAttribute("hint-crop")] 34 | public string HintCrop { get; set; } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/Data/ToastData.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace GVFS.Service.UI.Data 4 | { 5 | [XmlRoot("toast")] 6 | public class ToastData 7 | { 8 | [XmlAttribute("launch")] 9 | public string Launch { get; set; } 10 | 11 | [XmlElement("visual")] 12 | public VisualData Visual { get; set; } 13 | 14 | [XmlElement("actions")] 15 | public ActionsData Actions { get; set; } 16 | 17 | [XmlElement("scenario")] 18 | public string Scenario { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/Data/VisualData.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace GVFS.Service.UI.Data 4 | { 5 | public class VisualData 6 | { 7 | [XmlElement("binding")] 8 | public BindingData Binding { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net461</TargetFramework> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.17134.1000-preview" /> 10 | </ItemGroup> 11 | 12 | <ItemGroup> 13 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 14 | </ItemGroup> 15 | 16 | <ItemGroup> 17 | <Content Include="..\GVFS\GitVirtualFileSystem.ico"> 18 | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 19 | </Content> 20 | </ItemGroup> 21 | 22 | </Project> 23 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/IToastNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Service.UI 4 | { 5 | public interface IToastNotifier 6 | { 7 | Action<string> UserResponseCallback { get; set; } 8 | void Notify(string title, string message, string actionButtonTitle, string callbackArgs); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service.UI/XmlList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml; 4 | using System.Xml.Schema; 5 | using System.Xml.Serialization; 6 | 7 | namespace GVFS.Service.UI 8 | { 9 | public class XmlList<T> : List<T>, IXmlSerializable where T : class 10 | { 11 | public XmlSchema GetSchema() 12 | { 13 | throw new NotImplementedException(); 14 | } 15 | 16 | public void ReadXml(XmlReader reader) 17 | { 18 | throw new NotImplementedException(); 19 | } 20 | 21 | public void WriteXml(XmlWriter writer) 22 | { 23 | XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 24 | ns.Add(string.Empty, string.Empty); 25 | foreach (T item in this) 26 | { 27 | XmlSerializer xml = new XmlSerializer(item.GetType()); 28 | xml.Serialize(writer, item, ns); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/Configuration.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using System.IO; 3 | 4 | namespace GVFS.Service 5 | { 6 | public class Configuration 7 | { 8 | private static Configuration instance = new Configuration(); 9 | private static string assemblyPath = null; 10 | 11 | private Configuration() 12 | { 13 | this.GVFSLocation = Path.Combine(AssemblyPath, GVFSPlatform.Instance.Constants.GVFSExecutableName); 14 | this.GVFSServiceUILocation = Path.Combine(AssemblyPath, GVFSConstants.Service.UIName + GVFSPlatform.Instance.Constants.ExecutableExtension); 15 | } 16 | 17 | public static Configuration Instance 18 | { 19 | get 20 | { 21 | return instance; 22 | } 23 | } 24 | 25 | public static string AssemblyPath 26 | { 27 | get 28 | { 29 | if (assemblyPath == null) 30 | { 31 | assemblyPath = ProcessHelper.GetCurrentProcessLocation(); 32 | } 33 | 34 | return assemblyPath; 35 | } 36 | } 37 | 38 | public string GVFSLocation { get; private set; } 39 | public string GVFSServiceUILocation { get; private set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/GVFS.Service.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net461</TargetFramework> 6 | <GenerateWindowsAppManifest>true</GenerateWindowsAppManifest> 7 | </PropertyGroup> 8 | 9 | <ItemGroup> 10 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 11 | <ProjectReference Include="..\GVFS.Service.UI\GVFS.Service.UI.csproj" /> 12 | </ItemGroup> 13 | 14 | <ItemGroup> 15 | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> 16 | <PackageReference Include="SharpZipLib" Version="1.3.3" /> 17 | </ItemGroup> 18 | 19 | <ItemGroup> 20 | <Reference Include="System.ServiceProcess" /> 21 | </ItemGroup> 22 | 23 | </Project> 24 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/Handlers/INotificationHandler.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.NamedPipes; 2 | 3 | namespace GVFS.Service.Handlers 4 | { 5 | public interface INotificationHandler 6 | { 7 | void SendNotification(NamedPipeMessages.Notification.Request request); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/Handlers/MessageHandler.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.NamedPipes; 2 | using GVFS.Common.Tracing; 3 | 4 | namespace GVFS.Service.Handlers 5 | { 6 | public abstract class MessageHandler 7 | { 8 | protected void WriteToClient(NamedPipeMessages.Message message, NamedPipeServer.Connection connection, ITracer tracer) 9 | { 10 | if (!connection.TrySendResponse(message)) 11 | { 12 | tracer.RelatedError("Failed to send line to client: {0}", message); 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/Handlers/RequestHandler.Windows.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.NamedPipes; 2 | using GVFS.Common.Tracing; 3 | using GVFS.Service.Handlers; 4 | using System.Runtime.Serialization; 5 | 6 | namespace GVFS.Service.Handlers 7 | { 8 | public class WindowsRequestHandler : RequestHandler 9 | { 10 | public WindowsRequestHandler( 11 | ITracer tracer, 12 | string etwArea, 13 | RepoRegistry repoRegistry) : base(tracer, etwArea, repoRegistry) 14 | { 15 | } 16 | 17 | protected override void HandleMessage( 18 | ITracer tracer, 19 | NamedPipeMessages.Message message, 20 | NamedPipeServer.Connection connection) 21 | { 22 | if (message.Header == NamedPipeMessages.EnableAndAttachProjFSRequest.Header) 23 | { 24 | this.requestDescription = EnableProjFSRequestDescription; 25 | NamedPipeMessages.EnableAndAttachProjFSRequest attachRequest = NamedPipeMessages.EnableAndAttachProjFSRequest.FromMessage(message); 26 | EnableAndAttachProjFSHandler attachHandler = new EnableAndAttachProjFSHandler(tracer, connection, attachRequest); 27 | attachHandler.Run(); 28 | } 29 | else 30 | { 31 | base.HandleMessage(tracer, message, connection); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/IRepoMounter.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Service 2 | { 3 | public interface IRepoMounter 4 | { 5 | bool MountRepository(string repoRoot, int sessionId); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/IRepoRegistry.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GVFS.Service 4 | { 5 | public interface IRepoRegistry 6 | { 7 | bool TryRegisterRepo(string repoRoot, string ownerSID, out string errorMessage); 8 | bool TryDeactivateRepo(string repoRoot, out string errorMessage); 9 | bool TryGetActiveRepos(out List<RepoRegistration> repoList, out string errorMessage); 10 | bool TryRemoveRepo(string repoRoot, out string errorMessage); 11 | void AutoMountRepos(string userId, int sessionId, bool checkDirectoryExists = true); 12 | void TraceStatus(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Service/Program.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.Tracing; 3 | using GVFS.PlatformLoader; 4 | using System; 5 | using System.Diagnostics; 6 | using System.ServiceProcess; 7 | 8 | namespace GVFS.Service 9 | { 10 | public static class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | GVFSPlatformLoader.Initialize(); 15 | 16 | AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler; 17 | 18 | using (JsonTracer tracer = new JsonTracer(GVFSConstants.Service.ServiceName, GVFSConstants.Service.ServiceName)) 19 | { 20 | using (GVFSService service = new GVFSService(tracer)) 21 | { 22 | // This will fail with a popup from a command prompt. To install as a service, run: 23 | // %windir%\Microsoft.NET\Framework64\v4.0.30319\installutil GVFS.Service.exe 24 | ServiceBase.Run(service); 25 | } 26 | } 27 | } 28 | 29 | private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e) 30 | { 31 | using (EventLog eventLog = new EventLog("Application")) 32 | { 33 | eventLog.Source = "Application"; 34 | eventLog.WriteEntry( 35 | "Unhandled exception in GVFS.Service: " + e.ExceptionObject.ToString(), 36 | EventLogEntryType.Error); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Service/RepoRegistration.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace GVFS.Service 4 | { 5 | public class RepoRegistration 6 | { 7 | public RepoRegistration() 8 | { 9 | } 10 | 11 | public RepoRegistration(string enlistmentRoot, string ownerSID) 12 | { 13 | this.EnlistmentRoot = enlistmentRoot; 14 | this.OwnerSID = ownerSID; 15 | this.IsActive = true; 16 | } 17 | 18 | public string EnlistmentRoot { get; set; } 19 | public string OwnerSID { get; set; } 20 | public bool IsActive { get; set; } 21 | 22 | public static RepoRegistration FromJson(string json) 23 | { 24 | return JsonConvert.DeserializeObject<RepoRegistration>( 25 | json, 26 | new JsonSerializerSettings 27 | { 28 | MissingMemberHandling = MissingMemberHandling.Ignore 29 | }); 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return 35 | string.Format( 36 | "({0} - {1}) {2}", 37 | this.IsActive ? "Active" : "Inactive", 38 | this.OwnerSID, 39 | this.EnlistmentRoot); 40 | } 41 | 42 | public string ToJson() 43 | { 44 | return JsonConvert.SerializeObject(this); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /GVFS/GVFS.Tests/DataSources.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Tests 2 | { 3 | public class DataSources 4 | { 5 | public static object[] AllBools 6 | { 7 | get 8 | { 9 | return new object[] 10 | { 11 | new object[] { true }, 12 | new object[] { false }, 13 | }; 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /GVFS/GVFS.Tests/GVFS.Tests.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net461</TargetFramework> 5 | </PropertyGroup> 6 | 7 | <ItemGroup> 8 | <PackageReference Include="NUnitLite" Version="3.12.0" /> 9 | <PackageReference Include="NUnit3TestAdapter" Version="3.13.0" /> 10 | </ItemGroup> 11 | 12 | </Project> 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Tests/Should/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace GVFS.Tests.Should 8 | { 9 | public static class StringExtensions 10 | { 11 | public static string Repeat(this string self, int count) 12 | { 13 | return string.Join(string.Empty, Enumerable.Range(0, count).Select(x => self).ToArray()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Category/CategoryConstants.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.UnitTests.Category 2 | { 3 | public static class CategoryConstants 4 | { 5 | public const string ExceptionExpected = "ExceptionExpected"; 6 | public const string CaseInsensitiveFileSystemOnly = "CaseInsensitiveFileSystemOnly"; 7 | public const string CaseSensitiveFileSystemOnly = "CaseSensitiveFileSystemOnly"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Common/AzDevOpsOrgFromNuGetFeedTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Tests.Should; 3 | using NUnit.Framework; 4 | 5 | namespace GVFS.UnitTests.Common 6 | { 7 | [TestFixture] 8 | public class NuGetUpgraderTests 9 | { 10 | [TestCase("https://pkgs.dev.azure.com/test-pat/_packaging/Test-GVFS-Installers-Custom/nuget/v3/index.json", "https://test-pat.visualstudio.com")] 11 | [TestCase("https://PKGS.DEV.azure.com/test-pat/_packaging/Test-GVFS-Installers-Custom/nuget/v3/index.json", "https://test-pat.visualstudio.com")] 12 | [TestCase("https://dev.azure.com/test-pat/_packaging/Test-GVFS-Installers-Custom/nuget/v3/index.json", null)] 13 | [TestCase("http://pkgs.dev.azure.com/test-pat/_packaging/Test-GVFS-Installers-Custom/nuget/v3/index.json", null)] 14 | public void CanConstructAzureDevOpsUrlFromPackageFeedUrl(string packageFeedUrl, string expectedAzureDevOpsUrl) 15 | { 16 | bool success = AzDevOpsOrgFromNuGetFeed.TryCreateCredentialQueryUrl( 17 | packageFeedUrl, 18 | out string azureDevOpsUrl, 19 | out string error); 20 | 21 | if (expectedAzureDevOpsUrl != null) 22 | { 23 | success.ShouldBeTrue(); 24 | azureDevOpsUrl.ShouldEqual(expectedAzureDevOpsUrl); 25 | error.ShouldBeNull(); 26 | } 27 | else 28 | { 29 | success.ShouldBeFalse(); 30 | azureDevOpsUrl.ShouldBeNull(); 31 | error.ShouldNotBeNull(); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Common/GitObjectsTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Git; 2 | using GVFS.Tests.Should; 3 | using NUnit.Framework; 4 | 5 | namespace GVFS.UnitTests.Common 6 | { 7 | [TestFixture] 8 | public class GitObjectsTests 9 | { 10 | [TestCase] 11 | public void IsLooseObjectsDirectory_ValidDirectories() 12 | { 13 | GitObjects.IsLooseObjectsDirectory("BB").ShouldBeTrue(); 14 | GitObjects.IsLooseObjectsDirectory("bb").ShouldBeTrue(); 15 | GitObjects.IsLooseObjectsDirectory("A7").ShouldBeTrue(); 16 | GitObjects.IsLooseObjectsDirectory("55").ShouldBeTrue(); 17 | } 18 | 19 | [TestCase] 20 | public void IsLooseObjectsDirectory_InvalidDirectories() 21 | { 22 | GitObjects.IsLooseObjectsDirectory("K7").ShouldBeFalse(); 23 | GitObjects.IsLooseObjectsDirectory("A-").ShouldBeFalse(); 24 | GitObjects.IsLooseObjectsDirectory("?B").ShouldBeFalse(); 25 | GitObjects.IsLooseObjectsDirectory("BBB").ShouldBeFalse(); 26 | GitObjects.IsLooseObjectsDirectory("B-B").ShouldBeFalse(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Common/PathsTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Tests.Should; 3 | using NUnit.Framework; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace GVFS.UnitTests.Common 7 | { 8 | [TestFixture] 9 | public class PathsTests 10 | { 11 | [TestCase] 12 | public void CanConvertOSPathToGitFormat() 13 | { 14 | string systemPath; 15 | string expectedGitPath; 16 | 17 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 18 | { 19 | systemPath = @"C:\This\is\a\path"; 20 | expectedGitPath = @"C:/This/is/a/path"; 21 | } 22 | else 23 | { 24 | systemPath = @"/This/is/a/path"; 25 | expectedGitPath = systemPath; 26 | } 27 | 28 | string actualTransformedPath = Paths.ConvertPathToGitFormat(systemPath); 29 | actualTransformedPath.ShouldEqual(expectedGitPath); 30 | 31 | string doubleTransformedPath = Paths.ConvertPathToGitFormat(actualTransformedPath); 32 | doubleTransformedPath.ShouldEqual(expectedGitPath); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Data/caseChange.txt: -------------------------------------------------------------------------------- 1 | :040000 000000 d813c8227132c3bf73c013f8913f207b4876b2bf 0000000000000000000000000000000000000000 D GVFLT_MultiThreadTest 2 | :040000 000000 1260ecb71f2be8eb92ea904c6dffa3e40eaaf1bf 0000000000000000000000000000000000000000 D GVFLT_MultiThreadTest/OpenForReadsSameTime 3 | :100644 000000 eabe8d5ec569cc7e199e77411ad935f101414032 0000000000000000000000000000000000000000 D GVFLT_MultiThreadTest/OpenForReadsSameTime/test 4 | :040000 000000 1260ecb71f2be8eb92ea904c6dffa3e40eaaf1bf 0000000000000000000000000000000000000000 D GVFLT_MultiThreadTest/OpenForWritesSameTime 5 | :100644 000000 eabe8d5ec569cc7e199e77411ad935f101414032 0000000000000000000000000000000000000000 D GVFLT_MultiThreadTest/OpenForWritesSameTime/test 6 | :000000 040000 0000000000000000000000000000000000000000 d813c8227132c3bf73c013f8913f207b4876b2bf A GVFlt_MultiThreadTest 7 | :000000 040000 0000000000000000000000000000000000000000 1260ecb71f2be8eb92ea904c6dffa3e40eaaf1bf A GVFlt_MultiThreadTest/OpenForReadsSameTime 8 | :000000 100644 0000000000000000000000000000000000000000 eabe8d5ec569cc7e199e77411ad935f101414032 A GVFlt_MultiThreadTest/OpenForReadsSameTime/test 9 | :000000 040000 0000000000000000000000000000000000000000 1260ecb71f2be8eb92ea904c6dffa3e40eaaf1bf A GVFlt_MultiThreadTest/OpenForWritesSameTime 10 | :000000 100644 0000000000000000000000000000000000000000 eabe8d5ec569cc7e199e77411ad935f101414032 A GVFlt_MultiThreadTest/OpenForWritesSameTime/test 11 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Data/index_v4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.UnitTests/Data/index_v4 -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Common/MockFileBasedLock.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.FileSystem; 3 | using GVFS.Common.Tracing; 4 | 5 | namespace GVFS.UnitTests.Mock.Common 6 | { 7 | public class MockFileBasedLock : FileBasedLock 8 | { 9 | public MockFileBasedLock( 10 | PhysicalFileSystem fileSystem, 11 | ITracer tracer, 12 | string lockPath) 13 | : base(fileSystem, tracer, lockPath) 14 | { 15 | } 16 | 17 | public override bool TryAcquireLock() 18 | { 19 | return true; 20 | } 21 | 22 | public override void Dispose() 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Common/MockGVFSEnlistment.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.Git; 3 | using GVFS.UnitTests.Mock.Git; 4 | using System.IO; 5 | 6 | namespace GVFS.UnitTests.Mock.Common 7 | { 8 | public class MockGVFSEnlistment : GVFSEnlistment 9 | { 10 | private MockGitProcess gitProcess; 11 | 12 | public MockGVFSEnlistment() 13 | : base(Path.Combine("mock:", "path"), "mock://repoUrl", Path.Combine("mock:", "git"), authentication: null) 14 | { 15 | this.GitObjectsRoot = Path.Combine("mock:", "path", ".git", "objects"); 16 | this.LocalObjectsRoot = this.GitObjectsRoot; 17 | this.GitPackRoot = Path.Combine("mock:", "path", ".git", "objects", "pack"); 18 | } 19 | 20 | public MockGVFSEnlistment(string enlistmentRoot, string repoUrl, string gitBinPath, MockGitProcess gitProcess) 21 | : base(enlistmentRoot, repoUrl, gitBinPath, authentication: null) 22 | { 23 | this.gitProcess = gitProcess; 24 | } 25 | 26 | public MockGVFSEnlistment(MockGitProcess gitProcess) 27 | : this() 28 | { 29 | this.gitProcess = gitProcess; 30 | } 31 | 32 | public override string GitObjectsRoot { get; protected set; } 33 | 34 | public override string LocalObjectsRoot { get; protected set; } 35 | 36 | public override string GitPackRoot { get; protected set; } 37 | 38 | public override GitProcess CreateGitProcess() 39 | { 40 | return this.gitProcess ?? new MockGitProcess(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Common/MockGitStatusCache.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.NamedPipes; 3 | using GVFS.Common.Tracing; 4 | using System; 5 | 6 | namespace GVFS.UnitTests.Mock.Common 7 | { 8 | public class MockGitStatusCache : GitStatusCache 9 | { 10 | public MockGitStatusCache(GVFSContext context, TimeSpan backoff) 11 | : base(context, backoff) 12 | { 13 | } 14 | 15 | public int InvalidateCallCount { get; private set; } 16 | 17 | public void ResetCalls() 18 | { 19 | this.InvalidateCallCount = 0; 20 | } 21 | 22 | public override void Dispose() 23 | { 24 | } 25 | 26 | public override void Initialize() 27 | { 28 | } 29 | 30 | public override void Invalidate() 31 | { 32 | this.InvalidateCallCount++; 33 | } 34 | 35 | public override bool IsReadyForExternalAcquireLockRequests(NamedPipeMessages.LockData requester, out string infoMessage) 36 | { 37 | infoMessage = string.Empty; 38 | return true; 39 | } 40 | 41 | public override bool IsCacheReadyAndUpToDate() 42 | { 43 | return false; 44 | } 45 | 46 | public override void RefreshAsynchronously() 47 | { 48 | } 49 | 50 | public override void Shutdown() 51 | { 52 | } 53 | 54 | public override bool WriteTelemetryandReset(EventMetadata metadata) 55 | { 56 | return false; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Common/MockLocalGVFSConfig.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace GVFS.UnitTests.Mock.Common 5 | { 6 | public class MockLocalGVFSConfig : LocalGVFSConfig 7 | { 8 | public MockLocalGVFSConfig() 9 | { 10 | this.Settings = new Dictionary<string, string>(); 11 | } 12 | 13 | private Dictionary<string, string> Settings { get; set; } 14 | 15 | public override bool TryGetAllConfig(out Dictionary<string, string> allConfig, out string error) 16 | { 17 | allConfig = new Dictionary<string, string>(this.Settings); 18 | error = null; 19 | 20 | return true; 21 | } 22 | 23 | public override bool TryGetConfig( 24 | string name, 25 | out string value, 26 | out string error) 27 | { 28 | error = null; 29 | 30 | this.Settings.TryGetValue(name, out value); 31 | return true; 32 | } 33 | 34 | public override bool TrySetConfig( 35 | string name, 36 | string value, 37 | out string error) 38 | { 39 | error = null; 40 | this.Settings[name] = value; 41 | 42 | return true; 43 | } 44 | 45 | public override bool TryRemoveConfig(string name, out string error) 46 | { 47 | error = null; 48 | this.Settings.Remove(name); 49 | 50 | return true; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Common/Tracing/MockListener.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using System.Collections.Generic; 3 | 4 | namespace GVFS.UnitTests.Mock.Common.Tracing 5 | { 6 | public class MockListener : EventListener 7 | { 8 | public MockListener(EventLevel maxVerbosity, Keywords keywordFilter) 9 | : base(maxVerbosity, keywordFilter, null) 10 | { 11 | } 12 | 13 | public List<string> EventNamesRead { get; set; } = new List<string>(); 14 | 15 | protected override void RecordMessageInternal(TraceEventMessage message) 16 | { 17 | this.EventNamesRead.Add(message.EventName); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Git/MockGitInstallation.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Git; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace GVFS.UnitTests.Mock.Git 9 | { 10 | public class MockGitInstallation : IGitInstallation 11 | { 12 | public bool GitExists(string gitBinPath) 13 | { 14 | return false; 15 | } 16 | 17 | public string GetInstalledGitBinPath() 18 | { 19 | return null; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Git/MockLibGit2Repo.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Git; 2 | using GVFS.Common.Tracing; 3 | using System; 4 | using System.IO; 5 | 6 | namespace GVFS.UnitTests.Mock.Git 7 | { 8 | public class MockLibGit2Repo : LibGit2Repo 9 | { 10 | public MockLibGit2Repo(ITracer tracer) 11 | : base() 12 | { 13 | } 14 | 15 | public override bool CommitAndRootTreeExists(string commitish) 16 | { 17 | return false; 18 | } 19 | 20 | public override bool ObjectExists(string sha) 21 | { 22 | return false; 23 | } 24 | 25 | public override bool TryCopyBlob(string sha, Action<Stream, long> writeAction) 26 | { 27 | throw new NotSupportedException(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/MockCacheServerInfo.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Http; 2 | 3 | namespace GVFS.UnitTests.Mock 4 | { 5 | public class MockCacheServerInfo : CacheServerInfo 6 | { 7 | public MockCacheServerInfo() : base("https://mock", "mock") 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/MockTextWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace GVFS.UnitTests.Mock.Upgrader 7 | { 8 | public class MockTextWriter : TextWriter 9 | { 10 | private StringBuilder stringBuilder; 11 | 12 | public MockTextWriter() : base() 13 | { 14 | this.AllLines = new List<string>(); 15 | this.stringBuilder = new StringBuilder(); 16 | } 17 | 18 | public List<string> AllLines { get; private set; } 19 | 20 | public override Encoding Encoding 21 | { 22 | get { return Encoding.Default; } 23 | } 24 | 25 | public override void Write(char value) 26 | { 27 | if (value.Equals('\r')) 28 | { 29 | return; 30 | } 31 | 32 | if (value.Equals('\n')) 33 | { 34 | this.AllLines.Add(this.stringBuilder.ToString()); 35 | this.stringBuilder.Clear(); 36 | return; 37 | } 38 | 39 | this.stringBuilder.Append(value); 40 | } 41 | 42 | public bool ContainsLine(string line) 43 | { 44 | return this.AllLines.Exists(x => x.Equals(line, StringComparison.Ordinal)); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Mock/Virtualization/BlobSize/MockBlobSizesDatabase.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Git; 2 | using GVFS.UnitTests.Mock.Common; 3 | using GVFS.Virtualization.BlobSize; 4 | using System; 5 | 6 | namespace GVFS.UnitTests.Mock.Virtualization.BlobSize 7 | { 8 | public class MockBlobSizes : BlobSizes 9 | { 10 | public MockBlobSizes() 11 | : base("mock:\\blobSizeDatabase", fileSystem: null, tracer: new MockTracer()) 12 | { 13 | } 14 | 15 | public override void Initialize() 16 | { 17 | } 18 | 19 | public override void Shutdown() 20 | { 21 | } 22 | 23 | public override BlobSizesConnection CreateConnection() 24 | { 25 | return new MockBlobSizesConnection(this); 26 | } 27 | 28 | public override void AddSize(Sha1Id sha, long length) 29 | { 30 | throw new NotSupportedException("SaveValue has not been implemented yet."); 31 | } 32 | 33 | public override void Flush() 34 | { 35 | throw new NotSupportedException("Flush has not been implemented yet."); 36 | } 37 | 38 | public class MockBlobSizesConnection : BlobSizesConnection 39 | { 40 | public MockBlobSizesConnection(MockBlobSizes mockBlobSizesDatabase) 41 | : base(mockBlobSizesDatabase) 42 | { 43 | } 44 | 45 | public override bool TryGetSize(Sha1Id sha, out long length) 46 | { 47 | throw new NotSupportedException("TryGetSize has not been implemented yet."); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Prefetch/BlobPrefetcherTests.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Prefetch; 2 | using GVFS.Tests.Should; 3 | using GVFS.UnitTests.Mock.FileSystem; 4 | using NUnit.Framework; 5 | using System.IO; 6 | 7 | namespace GVFS.UnitTests.Prefetch 8 | { 9 | [TestFixture] 10 | public class BlobPrefetcherTests 11 | { 12 | [TestCase] 13 | public void AppendToNewlineSeparatedFileTests() 14 | { 15 | MockFileSystem fileSystem = new MockFileSystem(new MockDirectory(Path.Combine("mock:", "GVFS", "UnitTests", "Repo"), null, null)); 16 | 17 | // Validate can write to a file that doesn't exist. 18 | string testFileName = Path.Combine("mock:", "GVFS", "UnitTests", "Repo", "appendTests"); 19 | BlobPrefetcher.AppendToNewlineSeparatedFile(fileSystem, testFileName, "expected content line 1"); 20 | fileSystem.ReadAllText(testFileName).ShouldEqual("expected content line 1\n"); 21 | 22 | // Validate that if the file doesn't end in a newline it gets a newline added. 23 | fileSystem.WriteAllText(testFileName, "existing content"); 24 | BlobPrefetcher.AppendToNewlineSeparatedFile(fileSystem, testFileName, "expected line 2"); 25 | fileSystem.ReadAllText(testFileName).ShouldEqual("existing content\nexpected line 2\n"); 26 | 27 | // Validate that if the file ends in a newline, we don't end up with two newlines 28 | fileSystem.WriteAllText(testFileName, "existing content\n"); 29 | BlobPrefetcher.AppendToNewlineSeparatedFile(fileSystem, testFileName, "expected line 2"); 30 | fileSystem.ReadAllText(testFileName).ShouldEqual("existing content\nexpected line 2\n"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Program.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Tests; 2 | using GVFS.UnitTests.Category; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace GVFS.UnitTests 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | NUnitRunner runner = new NUnitRunner(args); 15 | runner.AddGlobalSetupIfNeeded("GVFS.UnitTests.Setup"); 16 | 17 | List<string> excludeCategories = new List<string>(); 18 | 19 | if (Debugger.IsAttached) 20 | { 21 | excludeCategories.Add(CategoryConstants.ExceptionExpected); 22 | } 23 | 24 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 25 | { 26 | excludeCategories.Add(CategoryConstants.CaseInsensitiveFileSystemOnly); 27 | } 28 | else 29 | { 30 | excludeCategories.Add(CategoryConstants.CaseSensitiveFileSystemOnly); 31 | } 32 | 33 | Environment.ExitCode = runner.RunTests(includeCategories: null, excludeCategories: excludeCategories); 34 | 35 | if (Debugger.IsAttached) 36 | { 37 | Console.WriteLine("Tests completed. Press Enter to exit."); 38 | Console.ReadLine(); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Readme.md: -------------------------------------------------------------------------------- 1 | # GVFS Unit Tests 2 | 3 | ## Unit Test Projects 4 | 5 | ### GVFS.UnitTests 6 | 7 | * Targets .NET Core 8 | * Contains all unit tests that are .NET Standard compliant 9 | 10 | ### GVFS.UnitTests.Windows 11 | 12 | * Targets .NET Framework 13 | * Contains all unit tests that depend on .NET Framework assemblies 14 | * Has links (in the `NetCore` folder) to all of the unit tests in GVFS.UnitTests 15 | 16 | GVFS.UnitTests.Windows links in all of the tests from GVFS.UnitTests to ensure that they pass on both the .NET Core and .Net Framework platforms. 17 | 18 | ## Running Unit Tests 19 | 20 | **Option 1: `Scripts\RunUnitTests.bat`** 21 | 22 | `RunUnitTests.bat` will run both GVFS.UnitTests and GVFS.UnitTests.Windows 23 | 24 | **Option 2: Run individual projects from Visual Studio** 25 | 26 | GVFS.UnitTests and GVFS.UnitTests.Windows can both be run from Visual Studio. Simply set either as the StartUp project and run them from the IDE. 27 | 28 | ## Adding New Tests 29 | 30 | ### GVFS.UnitTests or GVFS.UnitTests.Windows? 31 | 32 | Whenever possible new unit tests should be added to GVFS.UnitTests. If the new tests are for a .NET Framework assembly (e.g. `GVFS.Platform.Windows`) 33 | then they will need to be added to GVFS.UnitTests.Windows. 34 | 35 | ### Adding New Test Files 36 | 37 | When adding new test files, keep the following in mind: 38 | 39 | * New test files that are added to GVFS.UnitTests will not appear in the `NetCore` folder of GVFS.UnitTests.Windows until the GVFS solution is reloaded. 40 | * New test files that are meant to be run on both .NET platforms should be added to the **GVFS.UnitTests** project. 41 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Setup.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.UnitTests.Mock.Common; 3 | using NUnit.Framework; 4 | 5 | namespace GVFS.UnitTests 6 | { 7 | [SetUpFixture] 8 | public class Setup 9 | { 10 | [OneTimeSetUp] 11 | public void SetUp() 12 | { 13 | GVFSPlatform.Register(new MockPlatform()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /GVFS/GVFS.UnitTests/Virtual/TestsWithCommonRepo.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.UnitTests.Mock.Common; 3 | using NUnit.Framework; 4 | 5 | namespace GVFS.UnitTests.Virtual 6 | { 7 | [TestFixture] 8 | public abstract class TestsWithCommonRepo 9 | { 10 | protected CommonRepoSetup Repo { get; private set; } 11 | 12 | [SetUp] 13 | public virtual void TestSetup() 14 | { 15 | this.Repo = new CommonRepoSetup(); 16 | 17 | string error; 18 | RepoMetadata.TryInitialize( 19 | new MockTracer(), 20 | this.Repo.Context.FileSystem, 21 | this.Repo.Context.Enlistment.DotGVFSRoot, 22 | out error); 23 | } 24 | 25 | [TearDown] 26 | public virtual void TestTearDown() 27 | { 28 | if (this.Repo != null) 29 | { 30 | this.Repo.Dispose(); 31 | } 32 | 33 | RepoMetadata.Shutdown(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /GVFS/GVFS.VirtualFileSystemHook/Version.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS.VirtualFileSystemHook/Version.rc -------------------------------------------------------------------------------- /GVFS/GVFS.VirtualFileSystemHook/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Version.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.VirtualFileSystemHook/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GVFS.VirtualFileSystemHook.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.VirtualFileSystemHook/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #ifdef _WIN32 9 | #include "targetver.h" 10 | #include <Windows.h> 11 | #endif 12 | 13 | #include <string> 14 | #include <stdarg.h> 15 | 16 | 17 | 18 | // TODO: reference additional headers your program requires here 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.VirtualFileSystemHook/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include <SDKDDKVer.h> 9 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Background/FileSystemTaskResult.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Virtualization.Background 2 | { 3 | public enum FileSystemTaskResult 4 | { 5 | Invalid = 0, 6 | 7 | Success, 8 | RetryableError, 9 | FatalError 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/BlobSize/BlobSizesException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Virtualization.BlobSize 4 | { 5 | public class BlobSizesException : Exception 6 | { 7 | public BlobSizesException(Exception innerException) 8 | : base(innerException.Message, innerException) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/FileSystem/FSResult.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Virtualization.FileSystem 2 | { 3 | public enum FSResult 4 | { 5 | Invalid = 0, 6 | Ok, 7 | IOError, 8 | DirectoryNotEmpty, 9 | FileOrPathNotFound, 10 | IoReparseTagNotHandled, 11 | VirtualizationInvalidOperation, 12 | GenericProjFSError, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/FileSystem/FileSystemResult.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Virtualization.FileSystem 2 | { 3 | public struct FileSystemResult 4 | { 5 | public FileSystemResult(FSResult result, int rawResult) 6 | { 7 | this.Result = result; 8 | this.RawResult = rawResult; 9 | } 10 | 11 | public FSResult Result { get; } 12 | 13 | /// <summary> 14 | /// Underlying result. The value of RawResult varies based on the operating system. 15 | /// </summary> 16 | public int RawResult { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/FileSystem/UpdateFailureReason.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Virtualization.FileSystem 4 | { 5 | [Flags] 6 | public enum UpdateFailureReason : uint 7 | { 8 | // These values are identical to ProjFS.UpdateFailureCause to allow for easier casting 9 | NoFailure = 0, 10 | DirtyMetadata = 1, 11 | DirtyData = 2, 12 | Tombstone = 4, 13 | ReadOnly = 8 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/FileSystem/UpdatePlaceholderType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Virtualization.FileSystem 4 | { 5 | [Flags] 6 | public enum UpdatePlaceholderType : uint 7 | { 8 | // These values are identical to ProjFS.UpdateType to allow for easier casting 9 | AllowDirtyMetadata = 1, 10 | AllowDirtyData = 2, 11 | AllowTombstone = 4, 12 | AllowReadOnly = 32 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/GVFS.Virtualization.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net461</TargetFramework> 5 | <AllowUnsafeBlocks>true</AllowUnsafeBlocks> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <ProjectReference Include="..\GVFS.Common\GVFS.Common.csproj" /> 10 | </ItemGroup> 11 | 12 | <ItemGroup> 13 | <PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.4" /> 14 | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> 15 | </ItemGroup> 16 | 17 | </Project> 18 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GVFS.UnitTests")] 4 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Projection/GitIndexProjection.FolderEntryData.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | using System; 3 | 4 | namespace GVFS.Virtualization.Projection 5 | { 6 | public partial class GitIndexProjection 7 | { 8 | internal abstract class FolderEntryData 9 | { 10 | public LazyUTF8String Name { get; protected set; } 11 | public abstract bool IsFolder { get; } 12 | 13 | protected static EventMetadata CreateEventMetadata(Exception e = null) 14 | { 15 | EventMetadata metadata = new EventMetadata(); 16 | metadata.Add("Area", nameof(FolderEntryData)); 17 | if (e != null) 18 | { 19 | metadata.Add("Exception", e.ToString()); 20 | } 21 | 22 | return metadata; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Projection/GitIndexProjection.PoolAllocationMultipliers.cs: -------------------------------------------------------------------------------- 1 | namespace GVFS.Virtualization.Projection 2 | { 3 | public partial class GitIndexProjection 4 | { 5 | /// <summary> 6 | /// Multipliers for allocating the various pools while parsing the index. 7 | /// These numbers come from looking at the allocations needed for various repos 8 | /// </summary> 9 | private static class PoolAllocationMultipliers 10 | { 11 | public const double FolderDataPool = 0.17; 12 | public const double FileDataPool = 1.1; 13 | public const double StringPool = 2.4; 14 | public const double BytePool = 30; 15 | public const double ExpandPoolNewObjects = 0.15; 16 | 17 | // Keep 10% extra objects so we don't have to expand on the very next GetNew() call 18 | public const double ShrinkExtraObjects = 1.1; 19 | 20 | // Make sure that the shrink will reclaim at least 10% of the objects 21 | public const double ShrinkMinPoolSize = 0.9; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Projection/GitIndexProjection.SparseFolder.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace GVFS.Virtualization.Projection 6 | { 7 | public partial class GitIndexProjection 8 | { 9 | /// <summary> 10 | /// This class is used to represent what has been added to sparse set of folders 11 | /// It is build in the RefreshSparseFolders method in the GitIndexProjection 12 | /// The last folder in the sparse entry will be marked with IsRecursive = true 13 | /// This is ONLY what is in the sparse folder set and NOT what is on disk or in 14 | /// the index for a folder 15 | /// </summary> 16 | /// <example> 17 | /// For sparse folder entries of: 18 | /// foo/example 19 | /// other 20 | /// 21 | /// The SparseFolderData would be: 22 | /// root 23 | /// Children: 24 | /// |- foo (IsRecursive = false, Depth = 0) 25 | /// | Children: 26 | /// | |- example (IsRecursive = true, Depth = 1) 27 | /// | 28 | /// |- other (IsRecursive = true, Depth = 0) 29 | /// </example> 30 | internal class SparseFolderData 31 | { 32 | public SparseFolderData() 33 | { 34 | this.Children = new Dictionary<string, SparseFolderData>(GVFSPlatform.Instance.Constants.PathComparer); 35 | } 36 | 37 | public bool IsRecursive { get; set; } 38 | public int Depth { get; set; } 39 | public Dictionary<string, SparseFolderData> Children { get; } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Projection/IProfilerOnlyIndexProjection.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Tracing; 2 | 3 | namespace GVFS.Virtualization.Projection 4 | { 5 | /// <summary> 6 | /// Interface used for performace profiling GitIndexProjection. This interface 7 | /// allows performance tests to force GitIndexProjection to parse the index on demand so 8 | /// that index parsing can be measured and profiled. 9 | /// </summary> 10 | public interface IProfilerOnlyIndexProjection 11 | { 12 | void ForceRebuildProjection(); 13 | void ForceAddMissingModifiedPaths(ITracer tracer); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Projection/ProjectedFileInfo.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common.Git; 2 | 3 | namespace GVFS.Virtualization.Projection 4 | { 5 | public class ProjectedFileInfo 6 | { 7 | public ProjectedFileInfo(string name, long size, bool isFolder, Sha1Id sha) 8 | { 9 | this.Name = name; 10 | this.Size = size; 11 | this.IsFolder = isFolder; 12 | this.Sha = sha; 13 | } 14 | 15 | public string Name { get; } 16 | public long Size { get; } 17 | public bool IsFolder { get; } 18 | 19 | public Sha1Id Sha { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /GVFS/GVFS.Virtualization/Projection/SizesUnavailableException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GVFS.Virtualization.Projection 4 | { 5 | public class SizesUnavailableException : Exception 6 | { 7 | public SizesUnavailableException(string message) 8 | : base(message) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GVFS/GVFS/CommandLine/UpgradeVerb.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | using System; 3 | 4 | namespace GVFS.CommandLine 5 | { 6 | [Verb(UpgradeVerbName, HelpText = "Checks for new GVFS release, downloads and installs it when available.")] 7 | public class UpgradeVerb : GVFSVerb.ForNoEnlistment 8 | { 9 | private const string UpgradeVerbName = "upgrade"; 10 | 11 | public UpgradeVerb() 12 | { 13 | this.Output = Console.Out; 14 | } 15 | 16 | [Option( 17 | "confirm", 18 | Default = false, 19 | Required = false, 20 | HelpText = "Pass in this flag to actually install the newest release")] 21 | public bool Confirmed { get; set; } 22 | 23 | [Option( 24 | "dry-run", 25 | Default = false, 26 | Required = false, 27 | HelpText = "Display progress and errors, but don't install GVFS")] 28 | public bool DryRun { get; set; } 29 | 30 | [Option( 31 | "no-verify", 32 | Default = false, 33 | Required = false, 34 | HelpText = "Do not verify NuGet packages after downloading them. Some platforms do not support NuGet verification.")] 35 | public bool NoVerify { get; set; } 36 | 37 | protected override string VerbName 38 | { 39 | get { return UpgradeVerbName; } 40 | } 41 | 42 | public override void Execute() 43 | { 44 | Console.Error.WriteLine("'gvfs upgrade' is no longer supported. Visit https://github.com/microsoft/vfsforgit for the latest install/upgrade instructions."); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /GVFS/GVFS/GVFS.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net461</TargetFramework> 6 | </PropertyGroup> 7 | 8 | <ItemGroup> 9 | <ProjectReference Include="..\GVFS.Hooks\GVFS.Hooks.csproj"> 10 | <ReferenceOutputAssembly>false</ReferenceOutputAssembly> 11 | <OutputItemType>Content</OutputItemType> 12 | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 13 | <Targets>Build;DebugSymbolsProjectOutputGroup</Targets> 14 | </ProjectReference> 15 | <ProjectReference Include="..\GVFS.Platform.Windows\GVFS.Platform.Windows.csproj" /> 16 | </ItemGroup> 17 | 18 | <ItemGroup> 19 | <PackageReference Include="CommandLineParser" Version="2.6.0" /> 20 | </ItemGroup> 21 | 22 | <ItemGroup> 23 | <Content Include="GitVirtualFileSystem.ico"> 24 | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 25 | </Content> 26 | </ItemGroup> 27 | 28 | </Project> 29 | -------------------------------------------------------------------------------- /GVFS/GVFS/GitVirtualFileSystem.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GVFS/GitVirtualFileSystem.ico -------------------------------------------------------------------------------- /GVFS/GVFS/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GVFS.UnitTests")] 4 | -------------------------------------------------------------------------------- /GVFS/GVFS/RepairJobs/BackgroundOperationDatabaseRepairJob.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.FileSystem; 3 | using GVFS.Common.Tracing; 4 | using GVFS.Virtualization.Background; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace GVFS.RepairJobs 9 | { 10 | public class BackgroundOperationDatabaseRepairJob : RepairJob 11 | { 12 | private readonly string dataPath; 13 | 14 | public BackgroundOperationDatabaseRepairJob(ITracer tracer, TextWriter output, GVFSEnlistment enlistment) 15 | : base(tracer, output, enlistment) 16 | { 17 | this.dataPath = Path.Combine(this.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks); 18 | } 19 | 20 | public override string Name 21 | { 22 | get { return "Background Operation Database"; } 23 | } 24 | 25 | public override IssueType HasIssue(List<string> messages) 26 | { 27 | string error; 28 | FileSystemTaskQueue instance; 29 | if (!FileSystemTaskQueue.TryCreate( 30 | this.Tracer, 31 | this.dataPath, 32 | new PhysicalFileSystem(), 33 | out instance, 34 | out error)) 35 | { 36 | messages.Add("Failed to read background operations: " + error); 37 | return IssueType.CantFix; 38 | } 39 | 40 | return IssueType.None; 41 | } 42 | 43 | public override FixResult TryFixIssues(List<string> messages) 44 | { 45 | return FixResult.Failure; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /GVFS/GVFS/RepairJobs/RepoMetadataDatabaseRepairJob.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.Tracing; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | 6 | namespace GVFS.RepairJobs 7 | { 8 | public class RepoMetadataDatabaseRepairJob : RepairJob 9 | { 10 | public RepoMetadataDatabaseRepairJob(ITracer tracer, TextWriter output, GVFSEnlistment enlistment) 11 | : base(tracer, output, enlistment) 12 | { 13 | } 14 | 15 | public override string Name 16 | { 17 | get { return "Repo Metadata Database"; } 18 | } 19 | 20 | public override IssueType HasIssue(List<string> messages) 21 | { 22 | string error; 23 | try 24 | { 25 | if (!RepoMetadata.TryInitialize(this.Tracer, this.Enlistment.DotGVFSRoot, out error)) 26 | { 27 | messages.Add("Could not open repo metadata: " + error); 28 | return IssueType.CantFix; 29 | } 30 | } 31 | finally 32 | { 33 | RepoMetadata.Shutdown(); 34 | } 35 | 36 | return IssueType.None; 37 | } 38 | 39 | public override FixResult TryFixIssues(List<string> messages) 40 | { 41 | return FixResult.Failure; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /GVFS/GVFS/RepairJobs/VFSForGitDatabaseRepairJob.cs: -------------------------------------------------------------------------------- 1 | using GVFS.Common; 2 | using GVFS.Common.Database; 3 | using GVFS.Common.FileSystem; 4 | using GVFS.Common.Tracing; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace GVFS.RepairJobs 9 | { 10 | public class VFSForGitDatabaseRepairJob : RepairJob 11 | { 12 | public VFSForGitDatabaseRepairJob(ITracer tracer, TextWriter output, GVFSEnlistment enlistment) 13 | : base(tracer, output, enlistment) 14 | { 15 | } 16 | 17 | public override string Name 18 | { 19 | get { return "Placeholder Database"; } 20 | } 21 | 22 | public override IssueType HasIssue(List<string> messages) 23 | { 24 | string error; 25 | string databasePath = Path.Combine(this.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.VFSForGit); 26 | if (SqliteDatabase.HasIssue(databasePath, new PhysicalFileSystem(), out error)) 27 | { 28 | messages.Add(quot;Could not load {this.Name}: {error}"); 29 | return IssueType.CantFix; 30 | } 31 | 32 | return IssueType.None; 33 | } 34 | 35 | public override FixResult TryFixIssues(List<string> messages) 36 | { 37 | return FixResult.Failure; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /GVFS/GitHooksLoader/GitHooksLoader.vcxproj.filters: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 | <ItemGroup> 4 | <Filter Include="Source Files"> 5 | <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> 6 | <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> 7 | </Filter> 8 | <Filter Include="Header Files"> 9 | <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> 10 | <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> 11 | </Filter> 12 | <Filter Include="Resource Files"> 13 | <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> 14 | <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> 15 | </Filter> 16 | </ItemGroup> 17 | <ItemGroup> 18 | <ClInclude Include="stdafx.h"> 19 | <Filter>Header Files</Filter> 20 | </ClInclude> 21 | <ClInclude Include="targetver.h"> 22 | <Filter>Header Files</Filter> 23 | </ClInclude> 24 | <ClInclude Include="resource.h"> 25 | <Filter>Header Files</Filter> 26 | </ClInclude> 27 | </ItemGroup> 28 | <ItemGroup> 29 | <ClCompile Include="stdafx.cpp"> 30 | <Filter>Source Files</Filter> 31 | </ClCompile> 32 | <ClCompile Include="GitHooksLoader.cpp"> 33 | <Filter>Source Files</Filter> 34 | </ClCompile> 35 | </ItemGroup> 36 | <ItemGroup> 37 | <ResourceCompile Include="Version.rc"> 38 | <Filter>Resource Files</Filter> 39 | </ResourceCompile> 40 | </ItemGroup> 41 | </Project> -------------------------------------------------------------------------------- /GVFS/GitHooksLoader/Version.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GitHooksLoader/Version.rc -------------------------------------------------------------------------------- /GVFS/GitHooksLoader/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/VFSForGit/2ad18e8ed9b070fed9f018eb1011e3ecfdddf8dc/GVFS/GitHooksLoader/resource.h -------------------------------------------------------------------------------- /GVFS/GitHooksLoader/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GitHooksLoader.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /GVFS/GitHooksLoader/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | #include <Windows.h> 10 | #include <stdio.h> 11 | 12 | -------------------------------------------------------------------------------- /GVFS/GitHooksLoader/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include <SDKDDKVer.h> 9 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /Version.props: -------------------------------------------------------------------------------- 1 | <Project> 2 | 3 | <PropertyGroup> 4 | <!-- Default GVFS version number if not specified at build time --> 5 | <GVFSVersion Condition="'$(GVFSVersion)' == ''" >0.2.173.2</GVFSVersion> 6 | 7 | <!-- 8 | Update the GitPackageVersion for the version that is shipped and tested with Scalar. 9 | The MinimumGitVersion is intentionally lower to allow side-by-side installs of 10 | VFS for Git (which is less flexible). Only update that version if we rely upon a 11 | new command-line interface in Git or if there is a truly broken interaction. 12 | 13 | Note that we require that the revision (Z) of the Git version string (2.X.Y.vfs.Z.W) 14 | is an exact match. We will use this to signal that a microsoft/git version introduces 15 | a breaking change that requires a VFS for Git upgrade. 16 | 17 | Using the revision part allows us to modify the other version items arbitrarily, 18 | including taking version numbers 2.X.Y from upstream and updating .W if we have any 19 | hotfixes to microsoft/git. 20 | --> 21 | <GitPackageVersion>2.20220414.4</GitPackageVersion> 22 | <MinimumGitVersion>v2.31.0.vfs.0.1</MinimumGitVersion> 23 | </PropertyGroup> 24 | 25 | </Project> 26 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | VFS for Git: Virtualized File System for Git 2 | ============================================ 3 | 4 | VFS stands for Virtual File System. VFS for Git virtualizes the file system 5 | beneath your Git repository so that Git and all tools see what appears to be a 6 | regular working directory, but VFS for Git only downloads objects as they 7 | are needed. VFS for Git also manages the files that Git will consider, to 8 | ensure that Git operations such as `status`, `checkout`, etc., can be as quick 9 | as possible because they will only consider the files that the user has 10 | accessed, not all files in the repository. 11 | 12 | Installing 13 | ---------- 14 | 15 | * VFS for Git requires Windows 10 Anniversary Update (Windows 10 version 1607) or later 16 | * Run the latest VFS for Git and Git for Windows installers from https://github.com/Microsoft/VFSForGit/releases 17 | 18 | Documentation 19 | ------------- 20 | 21 | * [Getting Started](getting-started.md): Get started with VFS for Git. 22 | Includes `gvfs clone`. 23 | 24 | * [Troubleshooting](troubleshooting.md): 25 | Collect diagnostic information or update custom settings. Includes 26 | `gvfs diagnose`, `gvfs config`, `gvfs upgrade`, and `gvfs cache-server`. 27 | 28 | * [Frequently Asked Questions](faq.md) 29 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "msbuild-sdks": { 3 | "Microsoft.Build.Traversal": "2.0.19", 4 | "Microsoft.Build.NoTargets": "1.0.85" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <configuration> 3 | <config> 4 | <add key="repositoryPath" value="..\packages" /> 5 | </config> 6 | <packageSources> 7 | <clear /> 8 | <add key="Dependencies" value="https://pkgs.dev.azure.com/gvfs/ci/_packaging/Dependencies/nuget/v3/index.json" /> 9 | </packageSources> 10 | <packageRestore> 11 | <add key="enabled" value="true" /> 12 | <add key="automatic" value="true" /> 13 | </packageRestore> 14 | </configuration> 15 | -------------------------------------------------------------------------------- /scripts/InitializeEnvironment.bat: -------------------------------------------------------------------------------- 1 | @IF "%_echo%"=="" (ECHO OFF) ELSE (ECHO ON) 2 | 3 | REM Set environment variables for interesting paths that scripts might need access to. 4 | PUSHD %~dp0 5 | SET VFS_SCRIPTSDIR=%CD% 6 | POPD 7 | 8 | CALL :RESOLVEPATH "%VFS_SCRIPTSDIR%\.." 9 | SET VFS_SRCDIR=%_PARSED_PATH_% 10 | 11 | CALL :RESOLVEPATH "%VFS_SRCDIR%\.." 12 | SET VFS_ENLISTMENTDIR=%_PARSED_PATH_% 13 | 14 | SET VFS_OUTDIR=%VFS_ENLISTMENTDIR%\out 15 | SET VFS_PACKAGESDIR=%VFS_ENLISTMENTDIR%\packages 16 | SET VFS_PUBLISHDIR=%VFS_ENLISTMENTDIR%\publish 17 | 18 | REM Clean up 19 | SET _PARSED_PATH_= 20 | 21 | GOTO :EOF 22 | 23 | :RESOLVEPATH 24 | SET "_PARSED_PATH_=%~f1" 25 | GOTO :EOF 26 | -------------------------------------------------------------------------------- /scripts/RunFunctionalTests.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | CALL %~dp0\InitializeEnvironment.bat || EXIT /b 10 3 | 4 | IF "%1"=="" (SET "CONFIGURATION=Debug") ELSE (SET "CONFIGURATION=%1") 5 | 6 | REM Ensure GVFS installation is on the PATH for the Functional Tests to find 7 | SETLOCAL 8 | SET PATH=C:\Program Files\VFS for Git\;C:\Program Files\GVFS;C:\Program Files\Git\cmd;%PATH% 9 | 10 | ECHO PATH = %PATH% 11 | 12 | ECHO gvfs location: 13 | where gvfs 14 | IF NOT %ERRORLEVEL% == 0 ( 15 | ECHO error: unable to locate GVFS on the PATH (has it been installed?) 16 | ) 17 | 18 | ECHO GVFS.Service location: 19 | where GVFS.Service 20 | IF NOT %ERRORLEVEL% == 0 ( 21 | ECHO error: unable to locate GVFS.Service on the PATH (has it been installed?) 22 | ) 23 | 24 | ECHO git location: 25 | where git 26 | IF NOT %ERRORLEVEL% == 0 ( 27 | ECHO error: unable to locate Git on the PATH (has it been installed?) 28 | ) 29 | 30 | %VFS_OUTDIR%\GVFS.FunctionalTests\bin\%CONFIGURATION%\net461\win-x64\GVFS.FunctionalTests.exe /result:TestResult.xml %2 %3 %4 %5 31 | 32 | SET error=%ERRORLEVEL% 33 | CALL %VFS_SCRIPTSDIR%\StopAllServices.bat 34 | EXIT /b %error% 35 | -------------------------------------------------------------------------------- /scripts/RunUnitTests.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | CALL %~dp0\InitializeEnvironment.bat || EXIT /b 10 3 | 4 | IF "%1"=="" (SET "CONFIGURATION=Debug") ELSE (SET "CONFIGURATION=%1") 5 | 6 | SET RESULT=0 7 | 8 | %VFS_OUTDIR%\GVFS.UnitTests\bin\%CONFIGURATION%\net461\win-x64\GVFS.UnitTests.exe || SET RESULT=1 9 | 10 | EXIT /b %RESULT% 11 | -------------------------------------------------------------------------------- /scripts/StopAllServices.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | CALL %~dp0\InitializeEnvironment.bat || EXIT /b 10 3 | 4 | CALL %VFS_SCRIPTSDIR%\StopService.bat GVFS.Service 5 | CALL %VFS_SCRIPTSDIR%\StopService.bat Test.GVFS.Service 6 | -------------------------------------------------------------------------------- /scripts/StopService.bat: -------------------------------------------------------------------------------- 1 | sc stop %1 2 | verify >nul 3 | --------------------------------------------------------------------------------