private static bool TryFindUpgrade(JsonTracer tracer, string enlistmentRoot, out DiskLayoutUpgrade upgrade) { int majorVersion; int minorVersion; string error; if (!TryGetDiskLayoutVersion(tracer, enlistmentRoot, out majorVersion, out minorVersion, out error)) { StartLogFile(enlistmentRoot, tracer); tracer.RelatedError(error); upgrade = null; return(false); } Dictionary <int, MinorUpgrade> minorVersionUpgradesForCurrentMajorVersion; if (minorVersionUpgrades.TryGetValue(majorVersion, out minorVersionUpgradesForCurrentMajorVersion)) { MinorUpgrade minorUpgrade; if (minorVersionUpgradesForCurrentMajorVersion.TryGetValue(minorVersion, out minorUpgrade)) { StartLogFile(enlistmentRoot, tracer); tracer.RelatedInfo( "Upgrading from disk layout {0}.{1} to {0}.{2}", majorVersion, minorVersion, minorVersion + 1); upgrade = minorUpgrade; return(true); } } MajorUpgrade majorUpgrade; if (majorVersionUpgrades.TryGetValue(majorVersion, out majorUpgrade)) { StartLogFile(enlistmentRoot, tracer); tracer.RelatedInfo("Upgrading from disk layout {0} to {1}", majorVersion, majorVersion + 1); upgrade = majorUpgrade; return(true); } // return true to indicate that we succeeded, and no upgrader was found upgrade = null; return(true); }
protected override void Execute(GVFSEnlistment enlistment) { using (JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, SparseVerbName)) { tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Sparse), EventLevel.Informational, Keywords.Any); bool needToChangeProjection = false; using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.EnlistmentRoot, new SqliteDatabase())) { SparseTable sparseTable = new SparseTable(database); HashSet <string> directories = sparseTable.GetAll(); string[] foldersToRemove = this.ParseFolderList(this.Remove); string[] foldersToAdd = this.ParseFolderList(this.Add); if (this.List || (foldersToAdd.Length == 0 && foldersToRemove.Length == 0)) { if (directories.Count == 0) { this.Output.WriteLine("No folders in sparse list. When the sparse list is empty, all folders are projected."); } else { foreach (string directory in directories) { this.Output.WriteLine(directory); } } return; } foreach (string folder in foldersToRemove) { if (directories.Contains(folder)) { needToChangeProjection = true; break; } } if (!needToChangeProjection) { foreach (string folder in foldersToAdd) { if (!directories.Contains(folder)) { needToChangeProjection = true; break; } } } if (needToChangeProjection) { // Make sure there is a clean git status before allowing sparse set to change this.CheckGitStatus(tracer, enlistment); if (!this.ShowStatusWhileRunning( () => { foreach (string directoryPath in foldersToRemove) { tracer.RelatedInfo($"Removing '{directoryPath}' from sparse folders."); sparseTable.Remove(directoryPath); } foreach (string directoryPath in foldersToAdd) { tracer.RelatedInfo($"Adding '{directoryPath}' to sparse folders."); sparseTable.Add(directoryPath); } return(true); }, "Updating sparse folder set", suppressGvfsLogMessage: true)) { this.ReportErrorAndExit(tracer, "Failed to update sparse folder set."); } } } if (needToChangeProjection) { // Force a projection update to get the current inclusion set this.ForceProjectionChange(tracer, enlistment); tracer.RelatedInfo("Projection updated after adding or removing folders."); } else { this.WriteMessage(tracer, "No folders to update in sparse set."); } } }
protected override void Execute(GVFSEnlistment enlistment) { string errorMessage = null; string mountExecutableLocation = null; using (JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, "ExecuteMount")) { PhysicalFileSystem fileSystem = new PhysicalFileSystem(); GitRepo gitRepo = new GitRepo(tracer, enlistment, fileSystem); GVFSContext context = new GVFSContext(tracer, fileSystem, gitRepo, enlistment); if (!HooksInstaller.InstallHooks(context, out errorMessage)) { this.ReportErrorAndExit("Error installing hooks: " + errorMessage); } CacheServerInfo cacheServer = this.ResolvedCacheServer ?? CacheServerResolver.GetCacheServerFromConfig(enlistment); tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.MountVerb), EventLevel.Verbose, Keywords.Any); tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, cacheServer.Url, new EventMetadata { { "Unattended", this.Unattended }, { "IsElevated", GVFSPlatform.Instance.IsElevated() }, { "NamedPipeName", enlistment.NamedPipeName }, { nameof(this.EnlistmentRootPathParameter), this.EnlistmentRootPathParameter }, }); if (!GVFSPlatform.Instance.KernelDriver.IsReady(tracer, enlistment.EnlistmentRoot, this.Output, out errorMessage)) { tracer.RelatedEvent( EventLevel.Informational, $"{nameof(MountVerb)}_{nameof(this.Execute)}_EnablingKernelDriverViaService", new EventMetadata { { "KernelDriver.IsReady_Error", errorMessage }, { TracingConstants.MessageKey.InfoMessage, "Service will retry" } }); if (!this.ShowStatusWhileRunning( () => { return(this.TryEnableAndAttachPrjFltThroughService(enlistment.EnlistmentRoot, out errorMessage)); }, $"Attaching ProjFS to volume")) { this.ReportErrorAndExit(tracer, ReturnCode.FilterError, errorMessage); } } RetryConfig retryConfig = null; ServerGVFSConfig serverGVFSConfig = this.DownloadedGVFSConfig; if (!this.SkipVersionCheck) { string authErrorMessage; if (!this.TryAuthenticate(tracer, enlistment, out authErrorMessage)) { this.Output.WriteLine(" WARNING: " + authErrorMessage); this.Output.WriteLine(" Mount will proceed, but new files cannot be accessed until GVFS can authenticate."); } if (serverGVFSConfig == null) { if (retryConfig == null) { retryConfig = this.GetRetryConfig(tracer, enlistment); } serverGVFSConfig = this.QueryGVFSConfig(tracer, enlistment, retryConfig); } this.ValidateClientVersions(tracer, enlistment, serverGVFSConfig, showWarnings: true); CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment); cacheServer = cacheServerResolver.ResolveNameFromRemote(cacheServer.Url, serverGVFSConfig); this.Output.WriteLine("Configured cache server: " + cacheServer); } this.InitializeLocalCacheAndObjectsPaths(tracer, enlistment, retryConfig, serverGVFSConfig, cacheServer); if (!this.ShowStatusWhileRunning( () => { return(this.PerformPreMountValidation(tracer, enlistment, out mountExecutableLocation, out errorMessage)); }, "Validating repo")) { this.ReportErrorAndExit(tracer, errorMessage); } if (!this.SkipVersionCheck) { string error; if (!RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out error)) { this.ReportErrorAndExit(tracer, error); } try { GitProcess git = new GitProcess(enlistment); this.LogEnlistmentInfoAndSetConfigValues(tracer, git, enlistment); } finally { RepoMetadata.Shutdown(); } } if (!this.ShowStatusWhileRunning( () => { return(this.TryMount(tracer, enlistment, mountExecutableLocation, out errorMessage)); }, "Mounting")) { this.ReportErrorAndExit(tracer, errorMessage); } if (!this.Unattended) { tracer.RelatedInfo($"{nameof(this.Execute)}: Registering for automount"); if (this.ShowStatusWhileRunning( () => { return(this.RegisterMount(enlistment, out errorMessage)); }, "Registering for automount")) { tracer.RelatedInfo($"{nameof(this.Execute)}: Registered for automount"); } else { this.Output.WriteLine(" WARNING: " + errorMessage); tracer.RelatedInfo($"{nameof(this.Execute)}: Failed to register for automount"); } } } }
protected override void Execute(GVFSEnlistment enlistment) { if (this.List || ( !this.Prune && !this.Disable && string.IsNullOrEmpty(this.Add) && string.IsNullOrEmpty(this.Remove) && string.IsNullOrEmpty(this.Set) && string.IsNullOrEmpty(this.File))) { this.ListSparseFolders(enlistment.EnlistmentRoot); return; } this.CheckOptions(); using (JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, SparseVerbName)) { tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Sparse), EventLevel.Informational, Keywords.Any); EventMetadata metadata = new EventMetadata(); metadata.Add(nameof(this.Set), this.Set); metadata.Add(nameof(this.File), this.File); metadata.Add(nameof(this.Add), this.Add); metadata.Add(nameof(this.Remove), this.Remove); metadata.Add(nameof(this.Prune), this.Prune); metadata.Add(nameof(this.Disable), this.Disable); tracer.RelatedInfo(metadata, $"Running sparse"); HashSet <string> directories; bool needToChangeProjection = false; using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.EnlistmentRoot, new SqliteDatabase())) { SparseTable sparseTable = new SparseTable(database); directories = sparseTable.GetAll(); List <string> foldersToRemove = new List <string>(); List <string> foldersToAdd = new List <string>(); if (this.Disable) { if (directories.Count > 0) { this.WriteMessage(tracer, "Removing all folders from sparse list. When the sparse list is empty, all folders are projected."); needToChangeProjection = true; foldersToRemove.AddRange(directories); directories.Clear(); } else { return; } } else if (!string.IsNullOrEmpty(this.Set) || !string.IsNullOrEmpty(this.File)) { IEnumerable <string> folders = null; if (!string.IsNullOrEmpty(this.Set)) { folders = this.ParseFolderList(this.Set); } else if (!string.IsNullOrEmpty(this.File)) { PhysicalFileSystem fileSystem = new PhysicalFileSystem(); folders = this.ParseFolderList(fileSystem.ReadAllText(this.File), folderSeparator: Environment.NewLine); } else { this.WriteMessage(tracer, "Invalid options specified."); throw new InvalidOperationException(); } foreach (string folder in folders) { if (!directories.Contains(folder)) { needToChangeProjection = true; foldersToAdd.Add(folder); } else { // Remove from directories so that the only directories left in the directories collection // will be the ones that will need to be removed from sparse set directories.Remove(folder); } } if (directories.Count > 0) { needToChangeProjection = true; foldersToRemove.AddRange(directories); directories.Clear(); } // Need to add folders that will be in the projection back into directories for the status check foreach (string folder in folders) { directories.Add(folder); } } else { // Process adds and removes foreach (string folder in this.ParseFolderList(this.Remove)) { if (directories.Contains(folder)) { needToChangeProjection = true; directories.Remove(folder); foldersToRemove.Add(folder); } } foreach (string folder in this.ParseFolderList(this.Add)) { if (!directories.Contains(folder)) { needToChangeProjection = true; directories.Add(folder); foldersToAdd.Add(folder); } } } if (needToChangeProjection || this.Prune) { if (directories.Count > 0) { // Make sure there is a clean git status before allowing sparse set to change this.CheckGitStatus(tracer, enlistment, directories); } this.UpdateSparseFolders(tracer, sparseTable, foldersToRemove, foldersToAdd); } if (needToChangeProjection) { // Force a projection update to get the current inclusion set this.ForceProjectionChange(tracer, enlistment); tracer.RelatedInfo("Projection updated after adding or removing folders."); } else { this.WriteMessage(tracer, "No folders to update in sparse set."); } if (this.Prune && directories.Count > 0) { this.PruneFoldersOutsideSparse(tracer, enlistment, sparseTable); } } } }