private GVFSEnlistment CreateEnlistment(string enlistmentRootPath, GitAuthentication authentication) { string gitBinPath = GVFSPlatform.Instance.GitInstallation.GetInstalledGitBinPath(); if (string.IsNullOrWhiteSpace(gitBinPath)) { this.ReportErrorAndExit("Error: " + GVFSConstants.GitIsNotInstalledError); } string hooksPath = null; if (GVFSPlatform.Instance.UnderConstruction.RequiresDeprecatedGitHooksLoader) { // On Windows, the soon-to-be deprecated GitHooksLoader tries to call out to the hooks process without // its full path, so we have to pass the path along to our background git processes via the PATH // environment variable. On Mac this is not needed because we just copy our own hook directly into // the .git/hooks folder, and once Windows does the same, this hooksPath can be removed (from here // and all the classes that handle it on the way to GitProcess) hooksPath = ProcessHelper.WhereDirectory(GVFSPlatform.Instance.Constants.GVFSHooksExecutableName); if (hooksPath == null) { this.ReportErrorAndExit("Could not find " + GVFSPlatform.Instance.Constants.GVFSHooksExecutableName); } } GVFSEnlistment enlistment = null; try { if (this.validateOriginURL) { enlistment = GVFSEnlistment.CreateFromDirectory(enlistmentRootPath, gitBinPath, hooksPath, authentication); } else { enlistment = GVFSEnlistment.CreateWithoutRepoUrlFromDirectory(enlistmentRootPath, gitBinPath, hooksPath, authentication); } if (enlistment == null) { this.ReportErrorAndExit( "Error: '{0}' is not a valid GVFS enlistment", enlistmentRootPath); } } catch (InvalidRepoException e) { this.ReportErrorAndExit( "Error: '{0}' is not a valid GVFS enlistment. {1}", enlistmentRootPath, e.Message); } return(enlistment); }
private GVFSEnlistment CreateEnlistment(string enlistmentRootPath) { string gitBinPath = GVFSPlatform.Instance.GitInstallation.GetInstalledGitBinPath(); if (string.IsNullOrWhiteSpace(gitBinPath)) { this.ReportErrorAndExit("Error: " + GVFSConstants.GitIsNotInstalledError); } string hooksPath; if (GVFSPlatform.Instance.IsUnderConstruction) { hooksPath = "hooksUnderConstruction"; } else { hooksPath = ProcessHelper.WhereDirectory(GVFSPlatform.Instance.Constants.GVFSHooksExecutableName); if (hooksPath == null) { this.ReportErrorAndExit("Could not find " + GVFSPlatform.Instance.Constants.GVFSHooksExecutableName); } } GVFSEnlistment enlistment = null; try { if (this.validateOriginURL) { enlistment = GVFSEnlistment.CreateFromDirectory(enlistmentRootPath, gitBinPath, hooksPath); } else { enlistment = GVFSEnlistment.CreateWithoutRepoUrlFromDirectory(enlistmentRootPath, gitBinPath, hooksPath); } if (enlistment == null) { this.ReportErrorAndExit( "Error: '{0}' is not a valid GVFS enlistment", enlistmentRootPath); } } catch (InvalidRepoException e) { this.ReportErrorAndExit( "Error: '{0}' is not a valid GVFS enlistment. {1}", enlistmentRootPath, e.Message); } return(enlistment); }
public override void Execute() { if (string.IsNullOrWhiteSpace(this.EnlistmentRootPath)) { this.EnlistmentRootPath = Environment.CurrentDirectory; } GVFSEnlistment enlistment = GVFSEnlistment.CreateWithoutRepoUrlFromDirectory( this.EnlistmentRootPath, GitProcess.GetInstalledGitBinPath()); if (enlistment == null) { this.ReportErrorAndExit("'gvfs repair' must be run within a GVFS enlistment"); } if (!this.Confirmed) { this.Output.WriteLine( @"WARNING: THIS IS AN EXPERIMENTAL FEATURE This command detects and repairs issues that prevent a GVFS repo from mounting. A few such checks are currently implemented, and some of them can be repaired. More repairs and more checks are coming soon. Without --confirm, it will non-invasively check if repairs are necessary. To actually execute any necessary repair(s), run 'gvfs repair --confirm' "); } if (!ConsoleHelper.ShowStatusWhileRunning( () => { return(GVFSVerb.Execute <StatusVerb>(enlistment.EnlistmentRoot, verb => verb.Output = new StringWriter()) != ReturnCode.Success); }, "Checking 'gvfs status'", this.Output, showSpinner: true, suppressGvfsLogMessage: true)) { this.ReportErrorAndExit("You can only run 'gvfs repair' if GVFS is not mounted. Run 'gvfs unmount' and try again."); } this.Output.WriteLine(); using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "RepairVerb")) { tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Repair), EventLevel.Verbose, Keywords.Any); tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, enlistment.CacheServerUrl, new EventMetadata { { "Confirmed", this.Confirmed } }); List <RepairJob> jobs = new List <RepairJob>(); // Repair ESENT Databases jobs.Add(new BackgroundOperationDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new BlobSizeDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new PlaceholderDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new RepoMetadataDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new GitHeadRepairJob(tracer, this.Output, enlistment)); Dictionary <RepairJob, List <string> > healthy = new Dictionary <RepairJob, List <string> >(); Dictionary <RepairJob, List <string> > cantFix = new Dictionary <RepairJob, List <string> >(); Dictionary <RepairJob, List <string> > fixable = new Dictionary <RepairJob, List <string> >(); foreach (RepairJob job in jobs) { List <string> messages = new List <string>(); switch (job.HasIssue(messages)) { case RepairJob.IssueType.None: healthy[job] = messages; break; case RepairJob.IssueType.CantFix: cantFix[job] = messages; break; case RepairJob.IssueType.Fixable: fixable[job] = messages; break; } } foreach (RepairJob job in healthy.Keys) { this.WriteMessage(tracer, string.Format("{0, -30}: Healthy", job.Name)); this.WriteMessages(tracer, healthy[job]); } if (healthy.Count > 0) { this.Output.WriteLine(); } foreach (RepairJob job in cantFix.Keys) { this.WriteMessage(tracer, job.Name); this.WriteMessages(tracer, cantFix[job]); this.Indent(); this.WriteMessage(tracer, "'gvfs repair' does not currently support fixing this problem"); this.Output.WriteLine(); } foreach (RepairJob job in fixable.Keys) { this.WriteMessage(tracer, job.Name); this.WriteMessages(tracer, fixable[job]); this.Indent(); if (this.Confirmed) { List <string> repairMessages = new List <string>(); if (job.TryFixIssues(repairMessages)) { this.WriteMessage(tracer, "Repair succeeded"); } else { this.WriteMessage(tracer, "Repair failed. Run 'gvfs log' for more info."); } this.WriteMessages(tracer, repairMessages); } else { this.WriteMessage(tracer, "Run 'gvfs repair --confirm' to attempt a repair"); } this.Output.WriteLine(); } } }
public override void Execute() { this.ValidatePathParameter(this.EnlistmentRootPath); string hooksPath = this.GetGVFSHooksPathAndCheckVersion(tracer: null); GVFSEnlistment enlistment = GVFSEnlistment.CreateWithoutRepoUrlFromDirectory( this.EnlistmentRootPath, GitProcess.GetInstalledGitBinPath(), hooksPath); if (enlistment == null) { this.ReportErrorAndExit("'gvfs repair' must be run within a GVFS enlistment"); } if (!this.Confirmed) { this.Output.WriteLine( @"WARNING: THIS IS AN EXPERIMENTAL FEATURE This command detects and repairs issues that prevent a GVFS repo from mounting. A few such checks are currently implemented, and some of them can be repaired. More repairs and more checks are coming soon. Without --confirm, it will non-invasively check if repairs are necessary. To actually execute any necessary repair(s), run 'gvfs repair --confirm' "); } string error; if (!DiskLayoutUpgrade.TryCheckDiskLayoutVersion(tracer: null, enlistmentRoot: enlistment.EnlistmentRoot, error: out error)) { this.ReportErrorAndExit(error); } if (!ConsoleHelper.ShowStatusWhileRunning( () => { // Don't use 'gvfs status' here. The repo may be corrupt such that 'gvfs status' cannot run normally, // causing repair to continue when it shouldn't. using (NamedPipeClient pipeClient = new NamedPipeClient(enlistment.NamedPipeName)) { if (!pipeClient.Connect()) { return(true); } } return(false); }, "Checking that GVFS is not mounted", this.Output, showSpinner: true, gvfsLogEnlistmentRoot: null)) { this.ReportErrorAndExit("You can only run 'gvfs repair' if GVFS is not mounted. Run 'gvfs unmount' and try again."); } this.Output.WriteLine(); using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "RepairVerb")) { tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Repair), EventLevel.Verbose, Keywords.Any); tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, "N/A", new EventMetadata { { "Confirmed", this.Confirmed }, { "IsElevated", ProcessHelper.IsAdminElevated() }, }); List <RepairJob> jobs = new List <RepairJob>(); // Repair databases jobs.Add(new BackgroundOperationDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new RepoMetadataDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new PlaceholderDatabaseRepairJob(tracer, this.Output, enlistment)); jobs.Add(new BlobSizeDatabaseRepairJob(tracer, this.Output, enlistment)); // Repair .git folder files jobs.Add(new GitHeadRepairJob(tracer, this.Output, enlistment)); jobs.Add(new GitIndexRepairJob(tracer, this.Output, enlistment)); jobs.Add(new GitConfigRepairJob(tracer, this.Output, enlistment)); Dictionary <RepairJob, List <string> > healthy = new Dictionary <RepairJob, List <string> >(); Dictionary <RepairJob, List <string> > cantFix = new Dictionary <RepairJob, List <string> >(); Dictionary <RepairJob, List <string> > fixable = new Dictionary <RepairJob, List <string> >(); foreach (RepairJob job in jobs) { List <string> messages = new List <string>(); switch (job.HasIssue(messages)) { case RepairJob.IssueType.None: healthy[job] = messages; break; case RepairJob.IssueType.CantFix: cantFix[job] = messages; break; case RepairJob.IssueType.Fixable: fixable[job] = messages; break; } } foreach (RepairJob job in healthy.Keys) { this.WriteMessage(tracer, string.Format("{0, -30}: Healthy", job.Name)); this.WriteMessages(tracer, healthy[job]); } if (healthy.Count > 0) { this.Output.WriteLine(); } foreach (RepairJob job in cantFix.Keys) { this.WriteMessage(tracer, job.Name); this.WriteMessages(tracer, cantFix[job]); this.Indent(); this.WriteMessage(tracer, "'gvfs repair' does not currently support fixing this problem"); this.Output.WriteLine(); } foreach (RepairJob job in fixable.Keys) { this.WriteMessage(tracer, job.Name); this.WriteMessages(tracer, fixable[job]); this.Indent(); if (this.Confirmed) { List <string> repairMessages = new List <string>(); switch (job.TryFixIssues(repairMessages)) { case RepairJob.FixResult.Success: this.WriteMessage(tracer, "Repair succeeded"); break; case RepairJob.FixResult.ManualStepsRequired: this.WriteMessage(tracer, "Repair succeeded, but requires some manual steps before remounting."); break; case RepairJob.FixResult.Failure: this.WriteMessage(tracer, "Repair failed. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot)); break; } this.WriteMessages(tracer, repairMessages); } else { this.WriteMessage(tracer, "Run 'gvfs repair --confirm' to attempt a repair"); } this.Output.WriteLine(); } } }