private bool SetConfigSettings(GitProcess git, CacheServerInfo cacheServer) { string error; return(CacheServerInfo.TrySaveToConfig(git, cacheServer, out error) && GVFSVerb.TrySetGitConfigSettings(git)); }
private ReturnCode ExecuteGVFSVerb <TVerb>(ITracer tracer) where TVerb : GVFSVerb, new() { try { ReturnCode returnCode; StringBuilder commandOutput = new StringBuilder(); using (StringWriter writer = new StringWriter(commandOutput)) { returnCode = GVFSVerb.Execute <TVerb>(this.EnlistmentRootPath, verb => verb.Output = writer); } tracer.RelatedEvent( EventLevel.Informational, typeof(TVerb).Name, new EventMetadata { { "Output", commandOutput.ToString() }, { "ReturnCode", returnCode } }); return(returnCode); } catch (Exception e) { tracer.RelatedError( new EventMetadata { { "Verb", typeof(TVerb).Name }, { "Exception", e.Message } }); return(ReturnCode.GenericError); } }
private void SetGitConfigSettings(GitProcess git) { if (!GVFSVerb.TrySetGitConfigSettings(git)) { this.ReportErrorAndExit("Unable to configure git repo"); } }
private bool TryMount(GVFSEnlistment enlistment, string mountExecutableLocation, out string errorMessage) { if (!GVFSVerb.TrySetRequiredGitConfigSettings(enlistment)) { errorMessage = "Unable to configure git repo"; return(false); } const string ParamPrefix = "--"; if (GVFSPlatform.Instance.IsUnderConstruction) { mountExecutableLocation = Path.Combine(ProcessHelper.GetCurrentProcessLocation(), "gvfs.mount"); } GVFSPlatform.Instance.StartBackgroundProcess( mountExecutableLocation, new[] { enlistment.EnlistmentRoot, ParamPrefix + GVFSConstants.VerbParameters.Mount.Verbosity, this.Verbosity, ParamPrefix + GVFSConstants.VerbParameters.Mount.Keywords, this.KeywordsCsv }); if (GVFSPlatform.Instance.IsUnderConstruction) { // TODO(Mac): figure out the timing issue here on connecting to the pipe System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1)); } return(GVFSEnlistment.WaitUntilMounted(enlistment.EnlistmentRoot, this.Unattended, out errorMessage)); }
private bool TryMount(ITracer tracer, GVFSEnlistment enlistment, string mountExecutableLocation, out string errorMessage) { if (!GVFSVerb.TrySetRequiredGitConfigSettings(enlistment)) { errorMessage = "Unable to configure git repo"; return(false); } const string ParamPrefix = "--"; GVFSPlatform.Instance.StartBackgroundProcess( tracer, mountExecutableLocation, new[] { enlistment.EnlistmentRoot, ParamPrefix + GVFSConstants.VerbParameters.Mount.Verbosity, this.Verbosity, ParamPrefix + GVFSConstants.VerbParameters.Mount.Keywords, this.KeywordsCsv, ParamPrefix + GVFSConstants.VerbParameters.Mount.StartedByService, this.StartedByService.ToString() }); return(GVFSEnlistment.WaitUntilMounted(enlistment.EnlistmentRoot, this.Unattended, out errorMessage)); }
private bool TryMount(ITracer tracer, GVFSEnlistment enlistment, string mountExecutableLocation, out string errorMessage) { if (!GVFSVerb.TrySetRequiredGitConfigSettings(enlistment)) { errorMessage = "Unable to configure git repo"; return(false); } const string ParamPrefix = "--"; tracer.RelatedInfo($"{nameof(this.TryMount)}: Launching background process('{mountExecutableLocation}') for {enlistment.EnlistmentRoot}"); GVFSPlatform.Instance.StartBackgroundVFS4GProcess( tracer, mountExecutableLocation, new[] { enlistment.EnlistmentRoot, ParamPrefix + GVFSConstants.VerbParameters.Mount.Verbosity, this.Verbosity, ParamPrefix + GVFSConstants.VerbParameters.Mount.Keywords, this.KeywordsCsv, ParamPrefix + GVFSConstants.VerbParameters.Mount.StartedByService, this.StartedByService.ToString(), ParamPrefix + GVFSConstants.VerbParameters.Mount.StartedByVerb, true.ToString() }); tracer.RelatedInfo($"{nameof(this.TryMount)}: Waiting for repo to be mounted"); return(GVFSEnlistment.WaitUntilMounted(tracer, enlistment.EnlistmentRoot, this.Unattended, out errorMessage)); }
private ReturnCode RunAndRecordGVFSVerb <TVerb>(string archiveFolderPath, string outputFileName) where TVerb : GVFSVerb, new() { try { using (FileStream file = new FileStream(Path.Combine(archiveFolderPath, outputFileName), FileMode.CreateNew)) using (StreamWriter writer = new StreamWriter(file)) { return(GVFSVerb.Execute <TVerb>( this.EnlistmentRootPath, verb => { verb.Output = writer; verb.ServiceName = this.ServiceName; })); } } catch (Exception e) { this.WriteMessage(string.Format( "Verb {0} failed with exception {1}", typeof(TVerb), e)); return(ReturnCode.GenericError); } }
private ReturnCode RunAndRecordGVFSVerb <TVerb>(string archiveFolderPath, string outputFileName, Action <TVerb> customConfigureVerb = null) where TVerb : GVFSVerb, new() { try { using (FileStream file = new FileStream(Path.Combine(archiveFolderPath, outputFileName), FileMode.CreateNew)) using (StreamWriter writer = new StreamWriter(file)) { customConfigureVerb = customConfigureVerb ?? new Action <TVerb>(verb => { }); Action <TVerb> composedVerbConfiguration; composedVerbConfiguration = verb => { customConfigureVerb(verb); verb.Output = writer; verb.ServiceName = this.ServiceName; }; return(GVFSVerb.Execute <TVerb>(this.EnlistmentRootPath, composedVerbConfiguration)); } } catch (Exception e) { this.WriteMessage(string.Format( "Verb {0} failed with exception {1}", typeof(TVerb), e)); return(ReturnCode.GenericError); } }
private bool TryMount(GVFSEnlistment enlistment, string mountExeLocation, out string errorMessage) { if (!GVFSVerb.TrySetGitConfigSettings(enlistment)) { errorMessage = "Unable to configure git repo"; return(false); } const string ParamPrefix = "--"; ProcessHelper.StartBackgroundProcess( mountExeLocation, string.Join( " ", enlistment.EnlistmentRoot, ParamPrefix + GVFSConstants.VerbParameters.Mount.Verbosity, this.Verbosity, ParamPrefix + GVFSConstants.VerbParameters.Mount.Keywords, this.KeywordsCsv, this.ShowDebugWindow ? ParamPrefix + GVFSConstants.VerbParameters.Mount.DebugWindow : string.Empty), createWindow: this.ShowDebugWindow); return(GVFSEnlistment.WaitUntilMounted(enlistment.EnlistmentRoot, this.Unattended, out errorMessage)); }
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 VerbAbortedException(GVFSVerb verb) { this.Verb = verb; }
private Result CreateClone( ITracer tracer, GVFSEnlistment enlistment, GitObjectsHttpRequestor objectRequestor, GitRefs refs, string branch) { Result initRepoResult = this.TryInitRepo(tracer, refs, enlistment); if (!initRepoResult.Success) { return(initRepoResult); } PhysicalFileSystem fileSystem = new PhysicalFileSystem(); string errorMessage; if (!this.TryCreateAlternatesFile(fileSystem, enlistment, out errorMessage)) { return(new Result("Error configuring alternate: " + errorMessage)); } GitRepo gitRepo = new GitRepo(tracer, enlistment, fileSystem); GVFSContext context = new GVFSContext(tracer, fileSystem, gitRepo, enlistment); GVFSGitObjects gitObjects = new GVFSGitObjects(context, objectRequestor); if (!this.TryDownloadCommit( refs.GetTipCommitId(branch), enlistment, objectRequestor, gitObjects, gitRepo, out errorMessage)) { return(new Result(errorMessage)); } if (!GVFSVerb.TrySetRequiredGitConfigSettings(enlistment) || !GVFSVerb.TrySetOptionalGitConfigSettings(enlistment)) { return(new Result("Unable to configure git repo")); } CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment); if (!cacheServerResolver.TrySaveUrlToLocalConfig(objectRequestor.CacheServer, out errorMessage)) { return(new Result("Unable to configure cache server: " + errorMessage)); } GitProcess git = new GitProcess(enlistment); string originBranchName = "origin/" + branch; GitProcess.Result createBranchResult = git.CreateBranchWithUpstream(branch, originBranchName); if (createBranchResult.ExitCodeIsFailure) { return(new Result("Unable to create branch '" + originBranchName + "': " + createBranchResult.Errors + "\r\n" + createBranchResult.Output)); } File.WriteAllText( Path.Combine(enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Head), "ref: refs/heads/" + branch); if (!this.TryDownloadRootGitAttributes(enlistment, gitObjects, gitRepo, out errorMessage)) { return(new Result(errorMessage)); } this.CreateGitScript(enlistment); string installHooksError; if (!HooksInstaller.InstallHooks(context, out installHooksError)) { tracer.RelatedError(installHooksError); return(new Result(installHooksError)); } GitProcess.Result forceCheckoutResult = git.ForceCheckout(branch); if (forceCheckoutResult.ExitCodeIsFailure && forceCheckoutResult.Errors.IndexOf("unable to read tree") > 0) { // It is possible to have the above TryDownloadCommit() fail because we // already have the commit and root tree we intend to check out, but // don't have a tree further down the working directory. If we fail // checkout here, its' because we don't have these trees and the // read-object hook is not available yet. Force downloading the commit // again and retry the checkout. if (!this.TryDownloadCommit( refs.GetTipCommitId(branch), enlistment, objectRequestor, gitObjects, gitRepo, out errorMessage, checkLocalObjectCache: false)) { return(new Result(errorMessage)); } forceCheckoutResult = git.ForceCheckout(branch); } if (forceCheckoutResult.ExitCodeIsFailure) { string[] errorLines = forceCheckoutResult.Errors.Split('\n'); StringBuilder checkoutErrors = new StringBuilder(); foreach (string gitError in errorLines) { if (IsForceCheckoutErrorCloneFailure(gitError)) { checkoutErrors.AppendLine(gitError); } } if (checkoutErrors.Length > 0) { string error = "Could not complete checkout of branch: " + branch + ", " + checkoutErrors.ToString(); tracer.RelatedError(error); return(new Result(error)); } } if (!RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out errorMessage)) { tracer.RelatedError(errorMessage); return(new Result(errorMessage)); } try { RepoMetadata.Instance.SaveCloneMetadata(tracer, enlistment); this.LogEnlistmentInfoAndSetConfigValues(tracer, git, enlistment); } catch (Exception e) { tracer.RelatedError(e.ToString()); return(new Result(e.Message)); } finally { RepoMetadata.Shutdown(); } // Prepare the working directory folder for GVFS last to ensure that gvfs mount will fail if gvfs clone has failed Exception exception; string prepFileSystemError; if (!GVFSPlatform.Instance.KernelDriver.TryPrepareFolderForCallbacks(enlistment.WorkingDirectoryRoot, out prepFileSystemError, out exception)) { EventMetadata metadata = new EventMetadata(); metadata.Add(nameof(prepFileSystemError), prepFileSystemError); if (exception != null) { metadata.Add("Exception", exception.ToString()); } tracer.RelatedError(metadata, $"{nameof(this.CreateClone)}: TryPrepareFolderForCallbacks failed"); return(new Result(prepFileSystemError)); } return(new Result(true)); }
private Result CreateClone( ITracer tracer, GVFSEnlistment enlistment, GitObjectsHttpRequestor objectRequestor, GitRefs refs, string branch) { Result initRepoResult = this.TryInitRepo(tracer, refs, enlistment); if (!initRepoResult.Success) { return(initRepoResult); } PhysicalFileSystem fileSystem = new PhysicalFileSystem(); string errorMessage; if (!this.TryCreateAlternatesFile(fileSystem, enlistment, out errorMessage)) { return(new Result("Error configuring alternate: " + errorMessage)); } GitRepo gitRepo = new GitRepo(tracer, enlistment, fileSystem); GVFSContext context = new GVFSContext(tracer, fileSystem, gitRepo, enlistment); GVFSGitObjects gitObjects = new GVFSGitObjects(context, objectRequestor); if (!this.TryDownloadCommit( refs.GetTipCommitId(branch), enlistment, objectRequestor, gitObjects, gitRepo, out errorMessage)) { return(new Result(errorMessage)); } if (!GVFSVerb.TrySetRequiredGitConfigSettings(enlistment) || !GVFSVerb.TrySetOptionalGitConfigSettings(enlistment)) { return(new Result("Unable to configure git repo")); } CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment); if (!cacheServerResolver.TrySaveUrlToLocalConfig(objectRequestor.CacheServer, out errorMessage)) { return(new Result("Unable to configure cache server: " + errorMessage)); } GitProcess git = new GitProcess(enlistment); string originBranchName = "origin/" + branch; GitProcess.Result createBranchResult = git.CreateBranchWithUpstream(branch, originBranchName); if (createBranchResult.HasErrors) { return(new Result("Unable to create branch '" + originBranchName + "': " + createBranchResult.Errors + "\r\n" + createBranchResult.Output)); } File.WriteAllText( Path.Combine(enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Head), "ref: refs/heads/" + branch); File.AppendAllText( Path.Combine(enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Info.SparseCheckoutPath), GVFSConstants.GitPathSeparatorString + GVFSConstants.SpecialGitFiles.GitAttributes + "\n"); if (!this.TryDownloadRootGitAttributes(enlistment, gitObjects, gitRepo, out errorMessage)) { return(new Result(errorMessage)); } this.CreateGitScript(enlistment); string installHooksError; if (!HooksInstaller.InstallHooks(context, out installHooksError)) { tracer.RelatedError(installHooksError); return(new Result(installHooksError)); } GitProcess.Result forceCheckoutResult = git.ForceCheckout(branch); if (forceCheckoutResult.HasErrors) { string[] errorLines = forceCheckoutResult.Errors.Split('\n'); StringBuilder checkoutErrors = new StringBuilder(); foreach (string gitError in errorLines) { if (IsForceCheckoutErrorCloneFailure(gitError)) { checkoutErrors.AppendLine(gitError); } } if (checkoutErrors.Length > 0) { string error = "Could not complete checkout of branch: " + branch + ", " + checkoutErrors.ToString(); tracer.RelatedError(error); return(new Result(error)); } } if (!RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out errorMessage)) { tracer.RelatedError(errorMessage); return(new Result(errorMessage)); } try { RepoMetadata.Instance.SaveCloneMetadata(tracer, enlistment); this.LogEnlistmentInfoAndSetConfigValues(tracer, git, enlistment); } catch (Exception e) { tracer.RelatedError(e.ToString()); return(new Result(e.Message)); } finally { RepoMetadata.Shutdown(); } // Prepare the working directory folder for GVFS last to ensure that gvfs mount will fail if gvfs clone has failed string prepFileSystemError; if (!GVFSPlatform.Instance.KernelDriver.TryPrepareFolderForCallbacks(enlistment.WorkingDirectoryRoot, out prepFileSystemError)) { tracer.RelatedError(prepFileSystemError); return(new Result(prepFileSystemError)); } return(new Result(true)); }
private bool SetConfigSettings(GitProcess git) { return(this.enlistment.TrySetCacheServerUrlConfig() && GVFSVerb.TrySetGitConfigSettings(git)); }
public CloneVerb.Result CreateClone(GitRefs refs, string branch) { CloneVerb.Result initRepoResult = this.TryInitRepo(refs, this.enlistment); if (!initRepoResult.Success) { return(initRepoResult); } string errorMessage; if (!this.enlistment.TryConfigureAlternate(out errorMessage)) { return(new CloneVerb.Result("Error configuring alternate: " + errorMessage)); } PhysicalFileSystem fileSystem = new PhysicalFileSystem(); GitRepo gitRepo = new GitRepo(this.tracer, this.enlistment, fileSystem); GVFSGitObjects gitObjects = new GVFSGitObjects(new GVFSContext(this.tracer, fileSystem, gitRepo, this.enlistment), this.objectRequestor); if (!gitObjects.TryEnsureCommitIsLocal(refs.GetTipCommitId(branch), commitDepth: 2)) { return(new CloneVerb.Result("Could not download tip commits from: " + Uri.EscapeUriString(this.objectRequestor.CacheServer.ObjectsEndpointUrl))); } if (!GVFSVerb.TrySetGitConfigSettings(this.enlistment)) { return(new CloneVerb.Result("Unable to configure git repo")); } CacheServerResolver cacheServerResolver = new CacheServerResolver(this.tracer, this.enlistment); if (!cacheServerResolver.TrySaveUrlToLocalConfig(this.objectRequestor.CacheServer, out errorMessage)) { return(new CloneVerb.Result("Unable to configure cache server: " + errorMessage)); } GitProcess git = new GitProcess(this.enlistment); string originBranchName = "origin/" + branch; GitProcess.Result createBranchResult = git.CreateBranchWithUpstream(branch, originBranchName); if (createBranchResult.HasErrors) { return(new CloneVerb.Result("Unable to create branch '" + originBranchName + "': " + createBranchResult.Errors + "\r\n" + createBranchResult.Output)); } File.WriteAllText( Path.Combine(this.enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Head), "ref: refs/heads/" + branch); File.AppendAllText( Path.Combine(this.enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Info.SparseCheckoutPath), GVFSConstants.GitPathSeparatorString + GVFSConstants.SpecialGitFiles.GitAttributes + "\n"); CloneVerb.Result hydrateResult = this.HydrateRootGitAttributes(gitObjects, gitRepo, branch); if (!hydrateResult.Success) { return(hydrateResult); } this.CreateGitScript(); GitProcess.Result forceCheckoutResult = git.ForceCheckout(branch); if (forceCheckoutResult.HasErrors) { string[] errorLines = forceCheckoutResult.Errors.Split('\n'); StringBuilder checkoutErrors = new StringBuilder(); foreach (string gitError in errorLines) { if (IsForceCheckoutErrorCloneFailure(gitError)) { checkoutErrors.AppendLine(gitError); } } if (checkoutErrors.Length > 0) { string error = "Could not complete checkout of branch: " + branch + ", " + checkoutErrors.ToString(); this.tracer.RelatedError(error); return(new CloneVerb.Result(error)); } } GitProcess.Result updateIndexresult = git.UpdateIndexVersion4(); if (updateIndexresult.HasErrors) { string error = "Could not update index, error: " + updateIndexresult.Errors; this.tracer.RelatedError(error); return(new CloneVerb.Result(error)); } string installHooksError; if (!HooksInstaller.InstallHooks(this.enlistment, out installHooksError)) { this.tracer.RelatedError(installHooksError); return(new CloneVerb.Result(installHooksError)); } if (!RepoMetadata.TryInitialize(this.tracer, this.enlistment.DotGVFSRoot, out errorMessage)) { this.tracer.RelatedError(errorMessage); return(new CloneVerb.Result(errorMessage)); } try { RepoMetadata.Instance.SaveCurrentDiskLayoutVersion(); } catch (Exception e) { this.tracer.RelatedError(e.ToString()); return(new CloneVerb.Result(e.Message)); } finally { RepoMetadata.Shutdown(); } // Prepare the working directory folder for GVFS last to ensure that gvfs mount will fail if gvfs clone has failed string prepGVFltError; if (!GVFltCallbacks.TryPrepareFolderForGVFltCallbacks(this.enlistment.WorkingDirectoryRoot, out prepGVFltError)) { this.tracer.RelatedError(prepGVFltError); return(new CloneVerb.Result(prepGVFltError)); } return(new CloneVerb.Result(true)); }