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); tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, enlistment.CacheServerUrl); 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); if (this.Commits) { if (!string.IsNullOrEmpty(this.PathWhitelistFile) || !string.IsNullOrWhiteSpace(this.PathWhitelist)) { this.ReportErrorAndExit("Cannot supply both --commits (-c) and --folders (-f)"); } PrefetchHelper prefetchHelper = new PrefetchHelper( tracer, enlistment, DownloadThreadCount); if (this.Verbose) { prefetchHelper.TryPrefetchCommitsAndTrees(); } else { this.ShowStatusWhileRunning( () => { return(prefetchHelper.TryPrefetchCommitsAndTrees()); }, "Fetching commits and trees"); } return; } FetchHelper fetchHelper = new FetchHelper( tracer, enlistment, ChunkSize, SearchThreadCount, DownloadThreadCount, IndexThreadCount); if (!FetchHelper.TryLoadPathWhitelist(tracer, this.PathWhitelist, this.PathWhitelistFile, enlistment, fetchHelper.PathWhitelist)) { Environment.ExitCode = (int)ReturnCode.GenericError; return; } GitProcess gitProcess = new GitProcess(enlistment); GitProcess.Result result = gitProcess.RevParse(GVFSConstants.HeadCommitName); if (result.HasErrors) { tracer.RelatedError(result.Errors); this.Output.WriteLine(result.Errors); Environment.ExitCode = (int)ReturnCode.GenericError; return; } string headCommitId = result.Output; Func <bool> doPrefetch = () => { try { fetchHelper.FastFetch(headCommitId.Trim(), isBranch: false); return(!fetchHelper.HasFailures); } catch (FetchHelper.FetchException e) { tracer.RelatedError(e.Message); return(false); } }; if (this.Verbose) { doPrefetch(); } else { this.ShowStatusWhileRunning(doPrefetch, "Fetching blobs"); } if (fetchHelper.HasFailures) { Environment.ExitCode = 1; } } catch (AggregateException aggregateException) { this.Output.WriteLine("Cannot prefetch @ {0}:", 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 (VerbAbortedException) { throw; } catch (Exception e) { this.Output.WriteLine("Cannot prefetch @ {0}:", enlistment.EnlistmentRoot); tracer.RelatedError( new EventMetadata { { "Verb", typeof(PrefetchVerb).Name }, { "ErrorMessage", $"Unhandled {e.GetType().Name}: {e.Message}" }, { "Exception", e.ToString() } }); } } }
private void PrefetchBlobs(ITracer tracer, GVFSEnlistment enlistment, GitObjectsHttpRequestor blobRequestor, CacheServerInfo cacheServer) { PrefetchHelper fetchHelper = new PrefetchHelper( tracer, enlistment, blobRequestor, ChunkSize, SearchThreadCount, DownloadThreadCount, IndexThreadCount); string error; if (!PrefetchHelper.TryLoadFolderList(enlistment, this.Folders, this.FoldersListFile, fetchHelper.FolderList, out error)) { this.ReportErrorAndExit(tracer, error); } if (!PrefetchHelper.TryLoadFileList(enlistment, this.Files, fetchHelper.FileList, out error)) { this.ReportErrorAndExit(tracer, error); } if (fetchHelper.FolderList.Count == 0 && fetchHelper.FileList.Count == 0) { this.ReportErrorAndExit(tracer, "Did you mean to fetch all blobs? If so, specify `--files *` to confirm."); } if (this.HydrateFiles) { if (!this.CheckIsMounted(verbose: true)) { this.ReportErrorAndExit("You can only specify --hydrate if the repo is mounted. Run 'gvfs mount' and try again."); } } GitProcess gitProcess = new GitProcess(enlistment); GitProcess.Result result = gitProcess.RevParse(GVFSConstants.DotGit.HeadName); if (result.HasErrors) { tracer.RelatedError(result.Errors); this.Output.WriteLine(result.Errors); Environment.ExitCode = (int)ReturnCode.GenericError; return; } int matchedBlobCount = 0; int downloadedBlobCount = 0; int readFileCount = 0; string headCommitId = result.Output; Func <bool> doPrefetch = () => { try { fetchHelper.PrefetchWithStats( headCommitId.Trim(), isBranch: false, readFilesAfterDownload: this.HydrateFiles, matchedBlobCount: out matchedBlobCount, downloadedBlobCount: out downloadedBlobCount, readFileCount: out readFileCount); return(!fetchHelper.HasFailures); } catch (PrefetchHelper.FetchException e) { tracer.RelatedError(e.Message); return(false); } }; if (this.Verbose) { doPrefetch(); } else { string message = this.HydrateFiles ? "Fetching blobs and hydrating files " : "Fetching blobs "; this.ShowStatusWhileRunning(doPrefetch, message + this.GetCacheServerDisplay(cacheServer)); } if (fetchHelper.HasFailures) { Environment.ExitCode = 1; } else { Console.WriteLine(); Console.WriteLine("Stats:"); Console.WriteLine(" Matched blobs: " + matchedBlobCount); Console.WriteLine(" Already cached: " + (matchedBlobCount - downloadedBlobCount)); Console.WriteLine(" Downloaded: " + downloadedBlobCount); if (this.HydrateFiles) { Console.WriteLine(" Hydrated files: " + readFileCount); } } }
private void PerformPrefetch(GVFSEnlistment enlistment, ITracer tracer) { 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); if (this.Commits) { if (!string.IsNullOrEmpty(this.PathWhitelistFile) || !string.IsNullOrWhiteSpace(this.PathWhitelist)) { this.ReportErrorAndExit("Cannot supply both --commits (-c) and --folders (-f)"); } PrefetchHelper prefetchHelper = new PrefetchHelper( tracer, enlistment, DownloadThreadCount); prefetchHelper.PrefetchCommitsAndTrees(); return; } FetchHelper fetchHelper = new FetchHelper( tracer, enlistment, ChunkSize, SearchThreadCount, DownloadThreadCount, IndexThreadCount); if (!FetchHelper.TryLoadPathWhitelist(this.PathWhitelist, this.PathWhitelistFile, tracer, fetchHelper.PathWhitelist)) { Environment.ExitCode = (int)ReturnCode.GenericError; return; } bool gvfsHeadFileExists; string error; string projectedCommitId; if (!enlistment.TryParseGVFSHeadFile(out gvfsHeadFileExists, out error, out projectedCommitId)) { tracer.RelatedError(error); this.Output.WriteLine(error); Environment.ExitCode = (int)ReturnCode.GenericError; return; } fetchHelper.FastFetch(projectedCommitId.Trim(), isBranch: false); if (fetchHelper.HasFailures) { Environment.ExitCode = 1; } } catch (AggregateException e) { this.Output.WriteLine("Cannot prefetch @ {0}:", enlistment.EnlistmentRoot); foreach (Exception ex in e.Flatten().InnerExceptions) { this.Output.WriteLine("Exception: {0}", ex.ToString()); } Environment.ExitCode = (int)ReturnCode.GenericError; } catch (VerbAbortedException) { throw; } catch (Exception e) { this.ReportErrorAndExit("Cannot prefetch @ {0}: {1}", enlistment.EnlistmentRoot, e.ToString()); } }