public void ParsesUserSuppliedFriendlyName() { string error; CacheServerInfo output; CacheServerInfo.TryDetermineCacheServer( UserSuppliedCacheName, gitProcess: null, enlistment: this.enlistment, knownCaches: KnownCaches, output: out output, error: out error).ShouldBeTrue(error); output.Url.ShouldEqual(UserSuppliedUrl); }
public void FailsToParseInvalidUserSuppliedFriendlyName() { string error; CacheServerInfo output; CacheServerInfo.TryDetermineCacheServer( "invalidCacheName", gitProcess: null, enlistment: this.enlistment, knownCaches: KnownCaches, output: out output, error: out error).ShouldBeFalse(); output.ShouldBeNull(); }
public void ParsesConfiguredCacheName() { MockGitProcess git = new MockGitProcess(); git.SetExpectedCommandResult("config gvfs.cache-server", () => new GitProcess.Result(UserSuppliedCacheName, string.Empty, GitProcess.Result.SuccessCode)); string error; CacheServerInfo output; CacheServerInfo.TryDetermineCacheServer( userUrlish: null, gitProcess: git, enlistment: this.enlistment, knownCaches: KnownCaches, output: out output, error: out error).ShouldBeTrue(error); output.Url.ShouldEqual(UserSuppliedUrl); }
public void ResolvesUrlIntoFriendlyName() { MockGitProcess git = new MockGitProcess(); string error; CacheServerInfo output; CacheServerInfo.TryDetermineCacheServer( userUrlish: UserSuppliedUrl, gitProcess: git, enlistment: this.enlistment, knownCaches: KnownCaches, output: out output, error: out error).ShouldBeTrue(error); output.Name.ShouldEqual(UserSuppliedCacheName); output.Url.ShouldEqual(UserSuppliedUrl); }
public void Execute() { GVFSEnlistment enlistment = this.CreateEnlistment(this.EnlistmentRootPath); EventLevel verbosity; Keywords keywords; this.ParseEnumArgs(out verbosity, out keywords); JsonEtwTracer tracer = this.CreateTracer(enlistment, verbosity, keywords); RetryConfig retryConfig; string error; if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error)) { this.ReportErrorAndExit("Failed to determine GVFS timeout and max retries: " + error); } CacheServerInfo cacheServer; if (!CacheServerInfo.TryDetermineCacheServer(null, tracer, enlistment, retryConfig, out cacheServer, out error)) { this.ReportErrorAndExit(error); } tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, cacheServer.Url); InProcessMount mountHelper = new InProcessMount(tracer, enlistment, cacheServer, retryConfig, this.ShowDebugWindow); try { mountHelper.Mount(verbosity, keywords); } catch (Exception ex) { tracer.RelatedError("Failed to mount: {0}", ex.ToString()); this.ReportErrorAndExit("Failed to mount: {0}", ex.Message); } }
public void FallsBackToDefaultCache() { MockGitProcess git = new MockGitProcess(); git.SetExpectedCommandResult(@"config gvfs.mock:\repourl.cache-server-url", () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.GenericFailureCode)); string error; CacheServerInfo output; CacheServerInfo.TryDetermineCacheServer( userUrlish: null, gitProcess: git, enlistment: this.enlistment, knownCaches: KnownCaches, output: out output, error: out error).ShouldBeTrue(error); output.Name.ShouldEqual(DefaultCacheName); }
public void FallsBackToDeprecatedConfigSetting() { MockGitProcess git = new MockGitProcess(); git.SetExpectedCommandResult(@"config gvfs.mock:\repourl.cache-server-url", () => new GitProcess.Result(UserSuppliedUrl, string.Empty, GitProcess.Result.SuccessCode)); git.SetExpectedCommandResult(@"config --local gvfs.cache-server " + UserSuppliedUrl, () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.SuccessCode)); string error; CacheServerInfo output; CacheServerInfo.TryDetermineCacheServer( userUrlish: null, gitProcess: git, enlistment: this.enlistment, knownCaches: null, output: out output, error: out error).ShouldBeTrue(error); output.Url.ShouldEqual(UserSuppliedUrl); }
protected override void Execute(GVFSEnlistment enlistment) { using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Prefetch")) { if (this.Verbose) { tracer.AddDiagnosticConsoleEventListener(EventLevel.Informational, Keywords.Any); } else { tracer.AddPrettyConsoleEventListener(EventLevel.Error, Keywords.Any); } tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Prefetch), EventLevel.Informational, Keywords.Any); RetryConfig retryConfig; string error; if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error)) { tracer.RelatedError("Failed to determine GVFS timeout and max retries: " + error); Environment.Exit((int)ReturnCode.GenericError); } retryConfig.Timeout = TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes); CacheServerInfo cache; if (!CacheServerInfo.TryDetermineCacheServer(null, tracer, enlistment, retryConfig, out cache, out error)) { tracer.RelatedError(error); Environment.ExitCode = (int)ReturnCode.GenericError; return; } tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, cache.Url); try { EventMetadata metadata = new EventMetadata(); metadata.Add("Commits", this.Commits); metadata.Add("PathWhitelist", this.PathWhitelist); metadata.Add("PathWhitelistFile", this.PathWhitelistFile); tracer.RelatedEvent(EventLevel.Informational, "PerformPrefetch", metadata); GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, cache, retryConfig); if (this.Commits) { this.PrefetchCommits(tracer, enlistment, objectRequestor); } else { this.PrefetchBlobs(tracer, enlistment, objectRequestor); } } catch (VerbAbortedException) { throw; } catch (AggregateException aggregateException) { this.Output.WriteLine( "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot), enlistment.EnlistmentRoot); foreach (Exception innerException in aggregateException.Flatten().InnerExceptions) { tracer.RelatedError( new EventMetadata { { "Verb", typeof(PrefetchVerb).Name }, { "ErrorMessage", $"Unhandled {innerException.GetType().Name}: {innerException.Message}" }, { "Exception", innerException.ToString() } }); } Environment.ExitCode = (int)ReturnCode.GenericError; } catch (Exception e) { this.Output.WriteLine( "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot), enlistment.EnlistmentRoot); tracer.RelatedError( new EventMetadata { { "Verb", typeof(PrefetchVerb).Name }, { "ErrorMessage", $"Unhandled {e.GetType().Name}: {e.Message}" }, { "Exception", e.ToString() } }); } } }
protected override void Execute(GVFSEnlistment enlistment) { string errorMessage = null; if (!HooksInstaller.InstallHooks(enlistment, out errorMessage)) { this.ReportErrorAndExit("Error installing hooks: " + errorMessage); } if (!enlistment.TryConfigureAlternate(out errorMessage)) { this.ReportErrorAndExit("Error configuring alternate: " + errorMessage); } using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "PreMount")) { tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Mount), EventLevel.Verbose, Keywords.Any); if (!this.SkipVersionCheck) { string authErrorMessage = null; if (!this.ShowStatusWhileRunning( () => enlistment.Authentication.TryRefreshCredentials(tracer, out authErrorMessage), "Authenticating")) { this.Output.WriteLine(" WARNING: " + authErrorMessage); this.Output.WriteLine(" Mount will proceed, but new files cannot be accessed until GVFS can authenticate."); } } RetryConfig retryConfig = null; string error; if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error)) { this.ReportErrorAndExit("Failed to determine GVFS timeout and max retries: " + error); } GVFSConfig gvfsConfig; CacheServerInfo cacheServer; using (ConfigHttpRequestor configRequestor = new ConfigHttpRequestor(tracer, enlistment, retryConfig)) { gvfsConfig = configRequestor.QueryGVFSConfig(); } if (!CacheServerInfo.TryDetermineCacheServer(null, enlistment, gvfsConfig.CacheServers, out cacheServer, out error)) { this.ReportErrorAndExit(error); } tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, cacheServer.Url); if (!GvFltFilter.TryAttach(tracer, enlistment.EnlistmentRoot, out errorMessage)) { if (!this.ShowStatusWhileRunning( () => { return(this.AttachGvFltThroughService(enlistment, out errorMessage)); }, "Attaching GvFlt to volume")) { this.ReportErrorAndExit(errorMessage); } } this.ValidateClientVersions(tracer, enlistment, gvfsConfig); } if (!this.ShowStatusWhileRunning( () => { return(this.TryMount(enlistment, out errorMessage)); }, "Mounting")) { this.ReportErrorAndExit(errorMessage); } if (!this.ShowStatusWhileRunning( () => { return(this.RegisterMount(enlistment, out errorMessage)); }, "Registering for automount")) { this.Output.WriteLine(" WARNING: " + errorMessage); } }
public override void Execute() { int exitCode = 0; this.EnlistmentRootPath = this.GetCloneRoot(); this.CheckGVFltHealthy(); this.CheckNotInsideExistingRepo(); try { GVFSEnlistment enlistment; Result cloneResult = new Result(false); using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "GVFSClone")) { cloneResult = this.TryCreateEnlistment(out enlistment); if (cloneResult.Success) { tracer.AddLogFileEventListener( GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Clone), EventLevel.Informational, Keywords.Any); string authErrorMessage = null; if (!this.ShowStatusWhileRunning( () => enlistment.Authentication.TryRefreshCredentials(tracer, out authErrorMessage), "Authenticating")) { this.ReportErrorAndExit("Unable to clone because authentication failed"); } RetryConfig retryConfig; string error; if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error)) { this.ReportErrorAndExit("Failed to determine GVFS timeout and max retries: " + error); } retryConfig.Timeout = TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes); GVFSConfig gvfsConfig; CacheServerInfo cacheServer; using (ConfigHttpRequestor configRequestor = new ConfigHttpRequestor(tracer, enlistment, retryConfig)) { gvfsConfig = configRequestor.QueryGVFSConfig(); } if (!CacheServerInfo.TryDetermineCacheServer(this.CacheServerUrl, enlistment, gvfsConfig.CacheServers, out cacheServer, out error)) { this.ReportErrorAndExit(error); } tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, cacheServer.Url, new EventMetadata { { "Branch", this.Branch }, { "SingleBranch", this.SingleBranch }, { "NoMount", this.NoMount }, { "NoPrefetch", this.NoPrefetch } }); this.Output.WriteLine("Clone parameters:"); this.Output.WriteLine(" Repo URL: " + enlistment.RepoUrl); this.Output.WriteLine(" Cache Server: " + cacheServer); this.Output.WriteLine(" Destination: " + enlistment.EnlistmentRoot); this.ValidateClientVersions(tracer, enlistment, gvfsConfig); this.ShowStatusWhileRunning( () => { cloneResult = this.TryClone(tracer, enlistment, cacheServer, retryConfig); return(cloneResult.Success); }, "Cloning"); } if (!cloneResult.Success) { tracer.RelatedError(cloneResult.ErrorMessage); } } if (cloneResult.Success) { if (!this.NoPrefetch) { PrefetchVerb prefetch = new PrefetchVerb(); prefetch.EnlistmentRootPath = this.EnlistmentRootPath; prefetch.Commits = true; prefetch.Execute(); } if (this.NoMount) { this.Output.WriteLine("\r\nIn order to mount, first cd to within your enlistment, then call: "); this.Output.WriteLine("gvfs mount"); } else { MountVerb mount = new MountVerb(); mount.EnlistmentRootPath = this.EnlistmentRootPath; mount.SkipMountedCheck = true; mount.SkipVersionCheck = true; mount.ServiceName = this.ServiceName; mount.Execute(); } } else { this.Output.WriteLine("\r\nCannot clone @ {0}", this.EnlistmentRootPath); this.Output.WriteLine("Error: {0}", cloneResult.ErrorMessage); exitCode = (int)ReturnCode.GenericError; } } catch (AggregateException e) { this.Output.WriteLine("Cannot clone @ {0}:", this.EnlistmentRootPath); foreach (Exception ex in e.Flatten().InnerExceptions) { this.Output.WriteLine("Exception: {0}", ex.ToString()); } exitCode = (int)ReturnCode.GenericError; } catch (VerbAbortedException) { throw; } catch (Exception e) { this.ReportErrorAndExit("Cannot clone @ {0}: {1}", this.EnlistmentRootPath, e.ToString()); } Environment.Exit(exitCode); }
protected override void Execute(GVFSEnlistment enlistment) { using (ITracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "CacheVerb")) { RetryConfig retryConfig; string error; if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error)) { this.ReportErrorAndExit("Failed to determine GVFS timeout and max retries: " + error); } GVFSConfig config; using (ConfigHttpRequestor configRequestor = new ConfigHttpRequestor(tracer, enlistment, retryConfig)) { config = configRequestor.QueryGVFSConfig(); if (config == null) { this.ReportErrorAndExit("Could not query for available cache servers."); } } CacheServerInfo cache; if (!string.IsNullOrWhiteSpace(this.CacheToSet)) { if (CacheServerInfo.TryParse(this.CacheToSet, enlistment, config.CacheServers, out cache)) { if (!CacheServerInfo.TrySaveToConfig(new GitProcess(enlistment), cache, out error)) { this.ReportErrorAndExit("Failed to save cache to config: " + error); } } else { this.ReportErrorAndExit("Unrecognized or invalid cache name or url: " + this.CacheToSet); } this.OutputCacheInfo(cache); this.Output.WriteLine("You must remount GVFS for this to take effect."); } else if (this.ListCacheServers) { if (config.CacheServers.Any()) { this.Output.WriteLine("Available cache servers for: " + enlistment.RepoUrl); foreach (CacheServerInfo cacheServer in config.CacheServers) { this.Output.WriteLine("{0, -25} ({1})", cacheServer.Name, cacheServer.Url); } } else { this.Output.WriteLine("There are no available cache servers for: " + enlistment.RepoUrl); } } else { if (!CacheServerInfo.TryDetermineCacheServer(null, enlistment, config.CacheServers, out cache, out error)) { this.ReportErrorAndExit(error); } this.OutputCacheInfo(cache); } } }
protected override void Execute(GVFSEnlistment enlistment) { string diagnosticsRoot = Path.Combine(enlistment.DotGVFSRoot, "diagnostics"); if (!Directory.Exists(diagnosticsRoot)) { Directory.CreateDirectory(diagnosticsRoot); } string archiveFolderPath = Path.Combine(diagnosticsRoot, "gvfs_" + DateTime.Now.ToString("yyyyMMdd_HHmmss")); Directory.CreateDirectory(archiveFolderPath); using (FileStream diagnosticLogFile = new FileStream(Path.Combine(archiveFolderPath, "diagnostics.log"), FileMode.CreateNew)) using (this.diagnosticLogFileWriter = new StreamWriter(diagnosticLogFile)) { this.WriteMessage("Collecting diagnostic info into temp folder " + archiveFolderPath); this.WriteMessage(string.Empty); this.WriteMessage("gvfs version " + ProcessHelper.GetCurrentProcessVersion()); this.WriteMessage(GitProcess.Version(enlistment).Output); this.WriteMessage(GitProcess.GetInstalledGitBinPath()); this.WriteMessage(string.Empty); this.WriteMessage("Enlistment root: " + enlistment.EnlistmentRoot); this.WriteMessage("Repo URL: " + enlistment.RepoUrl); string error; CacheServerInfo cacheServer; if (CacheServerInfo.TryDetermineCacheServer(null, enlistment, null, out cacheServer, out error)) { this.WriteMessage("Cache Server: " + cacheServer); } else { this.WriteMessage(error); } this.WriteMessage(string.Empty); this.WriteMessage("Copying .gvfs folder..."); this.CopyAllFiles(enlistment.EnlistmentRoot, archiveFolderPath, GVFSConstants.DotGVFS.Root, copySubFolders: false); this.WriteMessage("Copying GVFlt logs..."); this.FlushGvFltLogBuffers(); string system32LogFilesPath = Environment.ExpandEnvironmentVariables(System32LogFilesRoot); this.CopyAllFiles(system32LogFilesPath, archiveFolderPath, GVFltLogFolderName, copySubFolders: false); this.LogGvFltTimeout(); this.WriteMessage("Checking on GVFS..."); this.RunAndRecordGVFSVerb <LogVerb>(archiveFolderPath, "gvfs_log.txt"); ReturnCode statusResult = this.RunAndRecordGVFSVerb <StatusVerb>(archiveFolderPath, "gvfs_status.txt"); if (statusResult == ReturnCode.Success) { this.WriteMessage("GVFS is mounted. Unmounting so we can read files that GVFS has locked..."); this.RunAndRecordGVFSVerb <UnmountVerb>(archiveFolderPath, "gvfs_unmount.txt", verb => verb.SkipLock = this.SkipLock); } else { this.WriteMessage("GVFS was not mounted."); } this.WriteMessage("Checking Defender exclusion..."); this.WriteAntiVirusExclusions(enlistment.EnlistmentRoot, archiveFolderPath, "DefenderExclusionInfo.txt"); this.WriteMessage("Copying .git folder..."); this.CopyAllFiles(enlistment.WorkingDirectoryRoot, archiveFolderPath, GVFSConstants.DotGit.Root, copySubFolders: false); this.CopyAllFiles(enlistment.WorkingDirectoryRoot, archiveFolderPath, GVFSConstants.DotGit.Hooks.Root, copySubFolders: false); this.CopyAllFiles(enlistment.WorkingDirectoryRoot, archiveFolderPath, GVFSConstants.DotGit.Info.Root, copySubFolders: false); this.CopyAllFiles(enlistment.WorkingDirectoryRoot, archiveFolderPath, GVFSConstants.DotGit.Logs.Root, copySubFolders: true); this.CopyAllFiles(enlistment.WorkingDirectoryRoot, archiveFolderPath, GVFSConstants.DotGit.Refs.Root, copySubFolders: true); this.CopyAllFiles(enlistment.WorkingDirectoryRoot, archiveFolderPath, GVFSConstants.DotGit.Objects.Info.Root, copySubFolders: false); this.CopyEsentDatabase <long, GVFltCallbacks.BackgroundGitUpdate>( enlistment.DotGVFSRoot, Path.Combine(archiveFolderPath, GVFSConstants.DotGVFS.Root), GVFSConstants.DatabaseNames.BackgroundGitUpdates); this.CopyEsentDatabase <string, string>( enlistment.DotGVFSRoot, Path.Combine(archiveFolderPath, GVFSConstants.DotGVFS.Root), GVFSConstants.DatabaseNames.PlaceholderList); this.CopyEsentDatabase <string, long>( enlistment.DotGVFSRoot, Path.Combine(archiveFolderPath, GVFSConstants.DotGVFS.Root), GVFSConstants.DatabaseNames.BlobSizes); this.CopyEsentDatabase <string, string>( enlistment.DotGVFSRoot, Path.Combine(archiveFolderPath, GVFSConstants.DotGVFS.Root), GVFSConstants.DatabaseNames.RepoMetadata); this.CopyAllFiles(enlistment.DotGVFSRoot, Path.Combine(archiveFolderPath, GVFSConstants.DotGVFS.Root), GVFSConstants.DotGVFS.CorruptObjectsName, copySubFolders: false); this.WriteMessage("Copying GVFS.Service logs and data..."); this.CopyAllFiles( Paths.GetServiceDataRoot(string.Empty), archiveFolderPath, this.ServiceName, copySubFolders: true); this.WriteMessage(string.Empty); this.WriteMessage("Remounting GVFS..."); ReturnCode mountResult = this.RunAndRecordGVFSVerb <MountVerb>(archiveFolderPath, "gvfs_mount.txt"); if (mountResult == ReturnCode.Success) { this.WriteMessage("Mount succeeded"); } else { this.WriteMessage("Failed to remount. The reason for failure was captured."); } this.CopyAllFiles(enlistment.DotGVFSRoot, Path.Combine(archiveFolderPath, GVFSConstants.DotGVFS.Root), "logs", copySubFolders: false); } string zipFilePath = archiveFolderPath + ".zip"; ZipFile.CreateFromDirectory(archiveFolderPath, zipFilePath); PhysicalFileSystem.RecursiveDelete(archiveFolderPath); this.Output.WriteLine(); this.Output.WriteLine("Diagnostics complete. All of the gathered info, as well as all of the output above, is captured in"); this.Output.WriteLine(zipFilePath); this.Output.WriteLine(); this.Output.WriteLine("If you are experiencing an issue, please email the GVFS team with your repro steps and include this zip file."); }
private int ExecuteWithExitCode() { // CmdParser doesn't strip quotes, and Path.Combine will throw this.GitBinPath = this.GitBinPath.Replace("\"", string.Empty); if (!GitProcess.GitExists(this.GitBinPath)) { Console.WriteLine( "Could not find git.exe {0}", !string.IsNullOrWhiteSpace(this.GitBinPath) ? "at " + this.GitBinPath : "on %PATH%"); return(ExitFailure); } if (this.Commit != null && this.Branch != null) { Console.WriteLine("Cannot specify both a commit sha and a branch name."); return(ExitFailure); } this.SearchThreadCount = this.SearchThreadCount > 0 ? this.SearchThreadCount : Environment.ProcessorCount; this.DownloadThreadCount = this.DownloadThreadCount > 0 ? this.DownloadThreadCount : Math.Min(Environment.ProcessorCount, MaxDefaultDownloadThreads); this.IndexThreadCount = this.IndexThreadCount > 0 ? this.IndexThreadCount : Environment.ProcessorCount; this.CheckoutThreadCount = this.CheckoutThreadCount > 0 ? this.CheckoutThreadCount : Environment.ProcessorCount; this.GitBinPath = !string.IsNullOrWhiteSpace(this.GitBinPath) ? this.GitBinPath : GitProcess.GetInstalledGitBinPath(); GitEnlistment enlistment = GitEnlistment.CreateFromCurrentDirectory(this.GitBinPath); if (enlistment == null) { Console.WriteLine("Must be run within a git repo"); return(ExitFailure); } string commitish = this.Commit ?? this.Branch; if (string.IsNullOrWhiteSpace(commitish)) { GitProcess.Result result = new GitProcess(enlistment).GetCurrentBranchName(); if (result.HasErrors || string.IsNullOrWhiteSpace(result.Output)) { Console.WriteLine("Could not retrieve current branch name: " + result.Errors); return(ExitFailure); } commitish = result.Output.Trim(); } Guid parentActivityId = Guid.Empty; if (!string.IsNullOrWhiteSpace(this.ParentActivityId) && !Guid.TryParse(this.ParentActivityId, out parentActivityId)) { Console.WriteLine("The ParentActivityId provided (" + this.ParentActivityId + ") is not a valid GUID."); } using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft.Git.FastFetch", parentActivityId, "FastFetch")) { if (this.Verbose) { tracer.AddDiagnosticConsoleEventListener(EventLevel.Informational, Keywords.Any); } else { tracer.AddPrettyConsoleEventListener(EventLevel.Error, Keywords.Any); } string fastfetchLogFile = Enlistment.GetNewLogFileName(enlistment.FastFetchLogRoot, "fastfetch"); tracer.AddLogFileEventListener(fastfetchLogFile, EventLevel.Informational, Keywords.Any); RetryConfig retryConfig = new RetryConfig(this.MaxAttempts, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes)); string error; CacheServerInfo cacheServer; if (!CacheServerInfo.TryDetermineCacheServer(this.CacheServerUrl, tracer, enlistment, retryConfig, out cacheServer, out error)) { tracer.RelatedError(error); return(ExitFailure); } tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, cacheServer.Url, new EventMetadata { { "TargetCommitish", commitish }, { "Checkout", this.Checkout }, }); FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment, cacheServer, retryConfig); if (!FetchHelper.TryLoadPathWhitelist(tracer, this.PathWhitelist, this.PathWhitelistFile, enlistment, fetchHelper.PathWhitelist)) { return(ExitFailure); } bool isSuccess; try { Func <bool> doPrefetch = () => { try { bool isBranch = this.Commit == null; fetchHelper.FastFetch(commitish, isBranch); return(!fetchHelper.HasFailures); } catch (FetchHelper.FetchException e) { tracer.RelatedError(e.Message); return(false); } }; if (this.Verbose) { isSuccess = doPrefetch(); } else { isSuccess = ConsoleHelper.ShowStatusWhileRunning( doPrefetch, "Fetching", output: Console.Out, showSpinner: !Console.IsOutputRedirected, gvfsLogEnlistmentRoot: null); Console.WriteLine(); Console.WriteLine("See the full log at " + fastfetchLogFile); } isSuccess &= !fetchHelper.HasFailures; } catch (AggregateException e) { isSuccess = false; foreach (Exception ex in e.Flatten().InnerExceptions) { tracer.RelatedError(ex.ToString()); } } catch (Exception e) { isSuccess = false; tracer.RelatedError(e.ToString()); } EventMetadata stopMetadata = new EventMetadata(); stopMetadata.Add("Success", isSuccess); tracer.Stop(stopMetadata); return(isSuccess ? ExitSuccess : ExitFailure); } }