コード例 #1
0
ファイル: DiagnoseVerb.cs プロジェクト: yyqyu/GVFS
        private void GetLocalCachePaths(GVFSEnlistment enlistment, out string localCacheRoot, out string gitObjectsRoot)
        {
            localCacheRoot = null;
            gitObjectsRoot = null;

            try
            {
                using (ITracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "DiagnoseVerb"))
                {
                    string error;
                    if (RepoMetadata.TryInitialize(tracer, Path.Combine(enlistment.EnlistmentRoot, GVFSConstants.DotGVFS.Root), out error))
                    {
                        RepoMetadata.Instance.TryGetLocalCacheRoot(out localCacheRoot, out error);
                        RepoMetadata.Instance.TryGetGitObjectsRoot(out gitObjectsRoot, out error);
                    }
                    else
                    {
                        this.WriteMessage("Failed to determine local cache path and git objects root, RepoMetadata error: " + error);
                    }
                }
            }
            catch (Exception e)
            {
                this.WriteMessage(string.Format("Failed to determine local cache path and git objects root, Exception: {0}", e));
            }
            finally
            {
                RepoMetadata.Shutdown();
            }
        }
コード例 #2
0
        public void SuccessForBatchObjectDownloadJob()
        {
            using (JsonEtwTracer tracer = CreateTracer())
            {
                MockEnlistment     enlistment     = new MockEnlistment();
                MockHttpGitObjects httpGitObjects = new MockHttpGitObjects(tracer, enlistment);
                httpGitObjects.AddBlobContent(FakeSha, FakeShaContents);
                MockPhysicalGitObjects gitObjects = new MockPhysicalGitObjects(tracer, enlistment, httpGitObjects);

                BlockingCollection <string> input = new BlockingCollection <string>();
                input.Add(FakeSha);
                input.CompleteAdding();

                BatchObjectDownloadJob dut = new BatchObjectDownloadJob(1, 1, input, new BlockingCollection <string>(), tracer, enlistment, httpGitObjects, gitObjects);
                dut.Start();
                dut.WaitForCompletion();

                string sha;
                input.TryTake(out sha).ShouldEqual(false);
                dut.AvailablePacks.Count.ShouldEqual(0);

                dut.AvailableObjects.Count.ShouldEqual(1);
                string output = dut.AvailableObjects.Take();
                output.ShouldEqual(FakeSha);
            }
        }
コード例 #3
0
ファイル: PrefetchVerb.cs プロジェクト: wsideteam1/gvfs
        protected override void Execute(GVFSEnlistment enlistment, ITracer tracer = null)
        {
            EventLevel verbosity;

            if (!Enum.TryParse(this.Verbosity, out verbosity))
            {
                this.ReportErrorAndExit("Error: Invalid verbosity: " + this.Verbosity);
            }

            if (tracer != null)
            {
                this.PerformPrefetch(enlistment, tracer);
            }
            else
            {
                using (JsonEtwTracer prefetchTracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Prefetch"))
                {
                    prefetchTracer.AddLogFileEventListener(
                        GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, this.VerbName),
                        EventLevel.Informational,
                        Keywords.Any);

                    prefetchTracer.AddConsoleEventListener(verbosity, ~Keywords.Network);

                    prefetchTracer.WriteStartEvent(
                        enlistment.EnlistmentRoot,
                        enlistment.RepoUrl,
                        enlistment.CacheServerUrl);

                    this.PerformPrefetch(enlistment, prefetchTracer);
                }
            }
        }
コード例 #4
0
ファイル: JsonEtwTracerTests.cs プロジェクト: wjmjimmie/GVFS
        public void EventsAreFilteredByVerbosity()
        {
            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft-GVFS-Test", "EventsAreFilteredByVerbosity1"))
                using (MockListener listener = new MockListener(EventLevel.Informational, Keywords.Any))
                {
                    tracer.AddInProcEventListener(listener);

                    tracer.RelatedEvent(EventLevel.Informational, "ShouldReceive", metadata: null);
                    listener.EventNamesRead.ShouldContain(name => name.Equals("ShouldReceive"));

                    tracer.RelatedEvent(EventLevel.Verbose, "ShouldNotReceive", metadata: null);
                    listener.EventNamesRead.ShouldNotContain(name => name.Equals("ShouldNotReceive"));
                }

            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft-GVFS-Test", "EventsAreFilteredByVerbosity2"))
                using (MockListener listener = new MockListener(EventLevel.Verbose, Keywords.Any))
                {
                    tracer.AddInProcEventListener(listener);

                    tracer.RelatedEvent(EventLevel.Informational, "ShouldReceive", metadata: null);
                    listener.EventNamesRead.ShouldContain(name => name.Equals("ShouldReceive"));

                    tracer.RelatedEvent(EventLevel.Verbose, "ShouldAlsoReceive", metadata: null);
                    listener.EventNamesRead.ShouldContain(name => name.Equals("ShouldAlsoReceive"));
                }
        }
コード例 #5
0
ファイル: DiskLayoutUpgrade.cs プロジェクト: yyqyu/GVFS
        private static bool CheckLayoutVersionWasIncremented(JsonEtwTracer tracer, string enlistmentRoot, DiskLayoutUpgrade upgrade)
        {
            string error;
            int    actualMajorVersion;
            int    actualMinorVersion;

            if (!TryGetDiskLayoutVersion(tracer, enlistmentRoot, out actualMajorVersion, out actualMinorVersion, out error))
            {
                tracer.RelatedError(error);
                return(false);
            }

            int expectedMajorVersion =
                upgrade.IsMajorUpgrade
                ? upgrade.SourceMajorVersion + 1
                : upgrade.SourceMajorVersion;
            int expectedMinorVersion =
                upgrade.IsMajorUpgrade
                ? 0
                : upgrade.SourceMinorVersion + 1;

            if (actualMajorVersion != expectedMajorVersion ||
                actualMinorVersion != expectedMinorVersion)
            {
                throw new InvalidDataException(string.Format(
                                                   "Disk layout upgrade did not increment layout version. Expected: {0}.{1}, Actual: {2}.{3}",
                                                   expectedMajorVersion,
                                                   expectedMinorVersion,
                                                   actualMajorVersion,
                                                   actualMinorVersion));
            }

            return(true);
        }
コード例 #6
0
ファイル: CloneVerb.cs プロジェクト: BrianMcBrayer/GVFS
        private Result TryClone(JsonEtwTracer tracer, GVFSEnlistment enlistment)
        {
            this.CheckGitVersion(enlistment);

            Result pipeResult;

            using (NamedPipeServer pipeServer = this.StartNamedPipe(enlistment, out pipeResult))
            {
                if (!pipeResult.Success)
                {
                    return(pipeResult);
                }

                HttpGitObjects httpGitObjects = new HttpGitObjects(tracer, enlistment, Environment.ProcessorCount);
                this.ValidateGVFSVersion(enlistment, httpGitObjects, tracer);

                GitRefs refs = httpGitObjects.QueryInfoRefs(this.SingleBranch ? this.Branch : null);

                if (refs == null)
                {
                    return(new Result("Could not query info/refs from: " + Uri.EscapeUriString(enlistment.RepoUrl)));
                }

                if (this.Branch == null)
                {
                    this.Branch = refs.GetDefaultBranch();

                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("Branch", this.Branch);
                    tracer.RelatedEvent(EventLevel.Informational, "CloneDefaultRemoteBranch", metadata);
                }
                else
                {
                    if (!refs.HasBranch(this.Branch))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Branch", this.Branch);
                        tracer.RelatedEvent(EventLevel.Warning, "CloneBranchDoesNotExist", metadata);

                        string errorMessage = string.Format("Remote branch {0} not found in upstream origin", this.Branch);
                        return(new Result(errorMessage));
                    }
                }

                if (!enlistment.TryCreateEnlistmentFolders())
                {
                    string error = "Could not create enlistment directory";
                    tracer.RelatedError(error);
                    return(new Result(error));
                }

                this.CheckAntiVirusExclusion(enlistment);

                CloneHelper cloneHelper = new CloneHelper(tracer, enlistment, httpGitObjects);
                return(cloneHelper.CreateClone(refs, this.Branch));
            }
        }
コード例 #7
0
        private bool RequestMount(GVFSEnlistment enlistment, out string errorMessage)
        {
            this.CheckGitVersion(enlistment);
            this.CheckGVFSHooksVersion(enlistment, null);
            this.CheckAntiVirusExclusion(enlistment);

            string mountExeLocation = Path.Combine(ProcessHelper.GetCurrentProcessLocation(), MountExeName);

            if (!File.Exists(mountExeLocation))
            {
                errorMessage = "Could not find GVFS.Mount.exe. You may need to reinstall GVFS.";
                return(false);
            }

            if (!this.SkipVersionCheck)
            {
                using (ITracer mountTracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Mount"))
                {
                    HttpGitObjects gitObjects = new HttpGitObjects(mountTracer, enlistment, maxConnections: 1);
                    this.ValidateGVFSVersion(enlistment, gitObjects, mountTracer);
                }
            }

            // We have to parse these parameters here to make sure they are valid before
            // handing them to the background process which cannot tell the user when they are bad
            EventLevel verbosity;
            Keywords   keywords;

            this.ParseEnumArgs(out verbosity, out keywords);

            GitProcess git = new GitProcess(enlistment);

            if (!git.IsValidRepo())
            {
                errorMessage = "The physical git repo is missing or invalid";
                return(false);
            }

            this.SetGitConfigSettings(git);

            const string ParamPrefix = "--";

            ProcessHelper.StartBackgroundProcess(
                mountExeLocation,
                string.Join(
                    " ",
                    enlistment.EnlistmentRoot,
                    ParamPrefix + MountParameters.Verbosity,
                    this.Verbosity,
                    ParamPrefix + MountParameters.Keywords,
                    this.KeywordsCsv,
                    this.ShowDebugWindow ? ParamPrefix + MountParameters.DebugWindow : string.Empty),
                createWindow: this.ShowDebugWindow);

            return(this.WaitForMountToComplete(enlistment, out errorMessage));
        }
コード例 #8
0
        private Result TryClone(JsonEtwTracer tracer, GVFSEnlistment enlistment, CacheServerInfo cacheServer, RetryConfig retryConfig)
        {
            Result pipeResult;

            using (NamedPipeServer pipeServer = this.StartNamedPipe(tracer, enlistment, out pipeResult))
            {
                if (!pipeResult.Success)
                {
                    return(pipeResult);
                }

                using (GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, cacheServer, retryConfig))
                {
                    GitRefs refs = objectRequestor.QueryInfoRefs(this.SingleBranch ? this.Branch : null);

                    if (refs == null)
                    {
                        return(new Result("Could not query info/refs from: " + Uri.EscapeUriString(enlistment.RepoUrl)));
                    }

                    if (this.Branch == null)
                    {
                        this.Branch = refs.GetDefaultBranch();

                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Branch", this.Branch);
                        tracer.RelatedEvent(EventLevel.Informational, "CloneDefaultRemoteBranch", metadata);
                    }
                    else
                    {
                        if (!refs.HasBranch(this.Branch))
                        {
                            EventMetadata metadata = new EventMetadata();
                            metadata.Add("Branch", this.Branch);
                            tracer.RelatedEvent(EventLevel.Warning, "CloneBranchDoesNotExist", metadata);

                            string errorMessage = string.Format("Remote branch {0} not found in upstream origin", this.Branch);
                            return(new Result(errorMessage));
                        }
                    }

                    if (!enlistment.TryCreateEnlistmentFolders())
                    {
                        string error = "Could not create enlistment directory";
                        tracer.RelatedError(error);
                        return(new Result(error));
                    }

                    CloneHelper cloneHelper = new CloneHelper(tracer, enlistment, objectRequestor);
                    return(cloneHelper.CreateClone(refs, this.Branch));
                }
            }
        }
コード例 #9
0
        protected override void Dispose(bool disposing)
        {
            this.StopRunning();

            if (this.tracer != null)
            {
                this.tracer.Dispose();
                this.tracer = null;
            }

            base.Dispose(disposing);
        }
コード例 #10
0
ファイル: ProfilingEnvironment.cs プロジェクト: yyqyu/GVFS
        private GVFSContext CreateContext()
        {
            ITracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "GVFS.PerfProfiling", useCriticalTelemetryFlag: false);

            PhysicalFileSystem fileSystem = new PhysicalFileSystem();
            GitRepo            gitRepo    = new GitRepo(
                tracer,
                this.Enlistment,
                fileSystem);

            return(new GVFSContext(tracer, fileSystem, gitRepo, this.Enlistment));
        }
コード例 #11
0
ファイル: CacheServerVerb.cs プロジェクト: smodin/GVFS
        protected override void Execute(GVFSEnlistment enlistment)
        {
            this.BlockEmptyCacheServerUrl(this.CacheToSet);

            RetryConfig retryConfig = new RetryConfig(RetryConfig.DefaultMaxRetries, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes));

            using (ITracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "CacheVerb"))
            {
                GVFSConfig gvfsConfig = this.QueryGVFSConfig(tracer, enlistment, retryConfig);

                CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment);
                string error = null;

                if (this.CacheToSet != null)
                {
                    CacheServerInfo cacheServer = cacheServerResolver.ParseUrlOrFriendlyName(this.CacheToSet);
                    cacheServer = this.ResolveCacheServerUrlIfNeeded(tracer, cacheServer, cacheServerResolver, gvfsConfig);

                    if (!cacheServerResolver.TrySaveUrlToLocalConfig(cacheServer, out error))
                    {
                        this.ReportErrorAndExit("Failed to save cache to config: " + error);
                    }

                    this.Output.WriteLine("You must remount GVFS for this to take effect.");
                }
                else if (this.ListCacheServers)
                {
                    List <CacheServerInfo> cacheServers = gvfsConfig.CacheServers.ToList();

                    if (cacheServers != null && cacheServers.Any())
                    {
                        this.Output.WriteLine();
                        this.Output.WriteLine("Available cache servers for: " + enlistment.RepoUrl);
                        foreach (CacheServerInfo cacheServer in cacheServers)
                        {
                            this.Output.WriteLine(cacheServer);
                        }
                    }
                    else
                    {
                        this.Output.WriteLine("There are no available cache servers for: " + enlistment.RepoUrl);
                    }
                }
                else
                {
                    string          cacheServerUrl = CacheServerResolver.GetUrlFromConfig(enlistment);
                    CacheServerInfo cacheServer    = cacheServerResolver.ResolveNameFromRemote(cacheServerUrl, gvfsConfig);

                    this.Output.WriteLine("Using cache server: " + cacheServer);
                }
            }
        }
コード例 #12
0
        private static void StartLogFile(string enlistmentRoot, JsonEtwTracer tracer)
        {
            if (!tracer.HasLogFileEventListener)
            {
                tracer.AddLogFileEventListener(
                    GVFSEnlistment.GetNewGVFSLogFileName(
                        Path.Combine(enlistmentRoot, GVFSConstants.DotGVFS.LogPath),
                        GVFSConstants.LogFileTypes.Upgrade),
                    EventLevel.Informational,
                    Keywords.Any);

                tracer.WriteStartEvent(enlistmentRoot, repoUrl: "N/A", cacheServerUrl: "N/A", gitObjectsRoot: "N/A");
            }
        }
コード例 #13
0
ファイル: Program.cs プロジェクト: yyqyu/GVFS
        public static void Main(string[] args)
        {
            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft.Git.GVFS.Service.UI", "Service.UI"))
            {
                string logLocation = Path.Combine(
                    Environment.GetEnvironmentVariable("LocalAppData"),
                    GVFSConstants.Service.UIName,
                    "serviceUI.log");

                tracer.AddLogFileEventListener(logLocation, EventLevel.Informational, Keywords.Any);
                GVFSServiceUI process = new GVFSServiceUI(tracer);
                process.Start(args);
            }
        }
コード例 #14
0
ファイル: Program.cs プロジェクト: yyqyu/GVFS
        public static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;

            using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.Service.ServiceName, GVFSConstants.Service.ServiceName))
            {
                using (GVFSService service = new GVFSService(tracer))
                {
                    // This will fail with a popup from a command prompt. To install as a service, run:
                    // %windir%\Microsoft.NET\Framework64\v4.0.30319\installutil GVFS.Service.exe
                    ServiceBase.Run(service);
                }
            }
        }
コード例 #15
0
        private JsonEtwTracer CreateTracer(GVFSEnlistment enlistment, EventLevel verbosity, Keywords keywords)
        {
            JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "GVFSMount");

            tracer.AddLogFileEventListener(
                GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.MountProcess),
                verbosity,
                keywords);
            if (this.ShowDebugWindow)
            {
                tracer.AddDiagnosticConsoleEventListener(verbosity, keywords);
            }

            return(tracer);
        }
コード例 #16
0
ファイル: DiskLayoutUpgrade.cs プロジェクト: yyqyu/GVFS
        private static bool TryFindUpgrade(JsonEtwTracer 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, DiskLayoutUpgrade.MinorUpgrade> minorVersionUpgradesForCurrentMajorVersion;

            if (MinorVersionUpgrades.TryGetValue(majorVersion, out minorVersionUpgradesForCurrentMajorVersion))
            {
                DiskLayoutUpgrade.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);
                }
            }

            DiskLayoutUpgrade.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);
        }
コード例 #17
0
        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);

            CacheServerInfo cacheServer = CacheServerResolver.GetCacheServerFromConfig(enlistment);

            tracer.WriteStartEvent(
                enlistment.EnlistmentRoot,
                enlistment.RepoUrl,
                cacheServer.Url,
                enlistment.GitObjectsRoot,
                new EventMetadata
            {
                { "IsElevated", ProcessHelper.IsAdminElevated() },
            });

            AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) =>
            {
                this.UnhandledGVFSExceptionHandler(tracer, sender, e);
            };

            RetryConfig retryConfig;
            string      error;

            if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error))
            {
                this.ReportErrorAndExit("Failed to determine GVFS timeout and max retries: " + error);
            }

            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);
            }
        }
コード例 #18
0
ファイル: MountVerb.cs プロジェクト: wsideteam1/gvfs
        private ITracer CreateTracer(GVFSEnlistment enlistment, EventLevel verbosity, Keywords keywords)
        {
            JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "GVFSMount");

            tracer.AddLogFileEventListener(GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot), verbosity, keywords);
            if (this.ShowDebugWindow)
            {
                tracer.AddConsoleEventListener(verbosity, keywords);
            }

            tracer.WriteStartEvent(
                enlistment.EnlistmentRoot,
                enlistment.RepoUrl,
                enlistment.CacheServerUrl);
            return(tracer);
        }
コード例 #19
0
        public static void Main(string[] args)
        {
            args = ReadAndRemoveSpecialArgValues(args);

            using (tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "GVFS.Hooks"))
            {
                tracer.WriteStartEvent(
                    null,
                    null,
                    null,
                    new EventMetadata
                {
                    { "Args", string.Join(" ", args) },
                });

                try
                {
                    if (args.Length < 2)
                    {
                        ExitWithError("Usage: gvfs.hooks <hook> <git verb> [<other arguments>]");
                    }

                    switch (GetHookType(args))
                    {
                    case PrecommandHook:
                        CheckForLegalCommands(args);
                        RunPreCommands(args);
                        AcquireGlobalLock(args);
                        break;

                    case PostcommandHook:
                        // no-op - keep this handling to support old clones that had the
                        // post-command hook installed.
                        break;

                    default:
                        ExitWithError("Unrecognized hook: " + string.Join(" ", args));
                        break;
                    }
                }
                catch (Exception ex)
                {
                    ExitWithError("Unexpected exception: " + ex.ToString());
                }
            }
        }
コード例 #20
0
        public void ErrorsForIndexPackFile()
        {
            using (JsonEtwTracer tracer = CreateTracer())
            {
                MockEnlistment         enlistment = new MockEnlistment();
                MockPhysicalGitObjects gitObjects = new MockPhysicalGitObjects(tracer, enlistment, null);

                BlockingCollection <IndexPackRequest> input = new BlockingCollection <IndexPackRequest>();
                BlobDownloadRequest downloadRequest         = new BlobDownloadRequest(new string[] { FakeSha });
                input.Add(new IndexPackRequest("mock:\\path\\packFileName", downloadRequest));
                input.CompleteAdding();

                IndexPackJob dut = new IndexPackJob(1, input, new BlockingCollection <string>(), tracer, gitObjects);
                dut.Start();
                dut.WaitForCompletion();
            }
        }
コード例 #21
0
        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);
            }
        }
コード例 #22
0
ファイル: JsonEtwTracerTests.cs プロジェクト: wjmjimmie/GVFS
        public void EventsAreFilteredByKeyword()
        {
            // Network filters all but network out
            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft-GVFS-Test", "EventsAreFilteredByKeyword1"))
                using (MockListener listener = new MockListener(EventLevel.Verbose, Keywords.Network))
                {
                    tracer.AddInProcEventListener(listener);

                    tracer.RelatedEvent(EventLevel.Informational, "ShouldReceive", metadata: null, keyword: Keywords.Network);
                    listener.EventNamesRead.ShouldContain(name => name.Equals("ShouldReceive"));

                    tracer.RelatedEvent(EventLevel.Verbose, "ShouldNotReceive", metadata: null);
                    listener.EventNamesRead.ShouldNotContain(name => name.Equals("ShouldNotReceive"));
                }

            // Any filters nothing out
            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft-GVFS-Test", "EventsAreFilteredByKeyword2"))
                using (MockListener listener = new MockListener(EventLevel.Verbose, Keywords.Any))
                {
                    tracer.AddInProcEventListener(listener);

                    tracer.RelatedEvent(EventLevel.Informational, "ShouldReceive", metadata: null, keyword: Keywords.Network);
                    listener.EventNamesRead.ShouldContain(name => name.Equals("ShouldReceive"));

                    tracer.RelatedEvent(EventLevel.Verbose, "ShouldAlsoReceive", metadata: null);
                    listener.EventNamesRead.ShouldContain(name => name.Equals("ShouldAlsoReceive"));
                }

            // None filters everything out (including events marked as none)
            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft-GVFS-Test", "EventsAreFilteredByKeyword3"))
                using (MockListener listener = new MockListener(EventLevel.Verbose, Keywords.None))
                {
                    tracer.AddInProcEventListener(listener);

                    tracer.RelatedEvent(EventLevel.Informational, "ShouldNotReceive", metadata: null, keyword: Keywords.Network);
                    listener.EventNamesRead.ShouldBeEmpty();

                    tracer.RelatedEvent(EventLevel.Verbose, "ShouldAlsoNotReceive", metadata: null);
                    listener.EventNamesRead.ShouldBeEmpty();
                }
        }
コード例 #23
0
        public static bool TryRunAllUpgrades(string enlistmentRoot)
        {
            using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "DiskLayoutUpgrade"))
            {
                try
                {
                    DiskLayoutUpgrade upgrade = null;
                    while (TryFindUpgrade(tracer, enlistmentRoot, out upgrade))
                    {
                        if (upgrade == null)
                        {
                            return(true);
                        }

                        if (!upgrade.TryUpgrade(tracer, enlistmentRoot))
                        {
                            return(false);
                        }

                        if (!CheckLayoutVersionWasIncremented(tracer, enlistmentRoot, upgrade))
                        {
                            return(false);
                        }
                    }

                    return(false);
                }
                catch (Exception e)
                {
                    StartLogFile(enlistmentRoot, tracer);
                    tracer.RelatedError(e.ToString());
                    return(false);
                }
                finally
                {
                    RepoMetadata.Shutdown();
                }
            }
        }
コード例 #24
0
        private static bool TryFindUpgrade(JsonEtwTracer tracer, string enlistmentRoot, out DiskLayoutUpgrade upgrade)
        {
            int    version;
            string error;

            if (!TryGetDiskLayoutVersion(tracer, enlistmentRoot, out version, out error))
            {
                StartLogFile(enlistmentRoot, tracer);
                tracer.RelatedError(error);
                upgrade = null;
                return(false);
            }

            if (AllUpgrades.TryGetValue(version, out upgrade))
            {
                StartLogFile(enlistmentRoot, tracer);
                tracer.RelatedInfo("Upgrading from disk layout {0} to {1}", version, version + 1);
                return(true);
            }

            return(true);
        }
コード例 #25
0
        public void ErrorsForBatchObjectDownloadJob()
        {
            using (JsonEtwTracer tracer = CreateTracer())
            {
                MockEnlistment         enlistment     = new MockEnlistment();
                MockHttpGitObjects     httpGitObjects = new MockHttpGitObjects(tracer, enlistment);
                MockPhysicalGitObjects gitObjects     = new MockPhysicalGitObjects(tracer, enlistment, httpGitObjects);

                BlockingCollection <string> input = new BlockingCollection <string>();
                input.Add(FakeSha);
                input.CompleteAdding();

                BatchObjectDownloadJob dut = new BatchObjectDownloadJob(1, 1, input, new BlockingCollection <string>(), tracer, enlistment, httpGitObjects, gitObjects);
                dut.Start();
                dut.WaitForCompletion();

                string sha;
                input.TryTake(out sha).ShouldEqual(false);

                IndexPackRequest request;
                dut.AvailablePacks.TryTake(out request).ShouldEqual(false);
            }
        }
コード例 #26
0
        private bool RequestMount(GVFSEnlistment enlistment, out string errorMessage)
        {
            this.CheckGitVersion(enlistment);
            this.CheckGVFSHooksVersion(enlistment, null);

            if (!this.SkipVersionCheck)
            {
                using (ITracer mountTracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Mount"))
                {
                    this.CheckVolumeSupportsDeleteNotifications(mountTracer, enlistment);

                    using (ConfigHttpRequestor configRequestor = new ConfigHttpRequestor(mountTracer, enlistment))
                    {
                        GVFSConfig config = configRequestor.QueryGVFSConfig();
                        this.ValidateGVFSVersion(enlistment, config, mountTracer);
                    }
                }
            }

            // We have to parse these parameters here to make sure they are valid before
            // handing them to the background process which cannot tell the user when they are bad
            EventLevel verbosity;
            Keywords   keywords;

            this.ParseEnumArgs(out verbosity, out keywords);

            GitProcess git = new GitProcess(enlistment);

            if (!git.IsValidRepo())
            {
                errorMessage = "The physical git repo is missing or invalid";
                return(false);
            }

            this.SetGitConfigSettings(git);
            return(this.SendMountRequest(enlistment, verbosity, keywords, out errorMessage));
        }
コード例 #27
0
ファイル: DehydrateVerb.cs プロジェクト: BrianMcBrayer/GVFS
        protected override void Execute(GVFSEnlistment enlistment)
        {
            using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Dehydrate"))
            {
                tracer.AddLogFileEventListener(
                    GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Dehydrate),
                    EventLevel.Informational,
                    Keywords.Any);
                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    enlistment.CacheServerUrl,
                    new EventMetadata
                {
                    { "Confirmed", this.Confirmed },
                    { "NoStatus", this.NoStatus },
                });

                if (!this.Confirmed)
                {
                    this.Output.WriteLine(
                        @"WARNING: THIS IS AN EXPERIMENTAL FEATURE

Dehydrate will back up your src folder, and then create a new, empty src folder 
with a fresh virtualization of the repo. All of your downloaded objects, branches, 
and siblings of the src folder will be preserved. Your modified working directory 
files will be moved to the backup, and your new working directory will not have 
any of your uncommitted changes.

Before you dehydrate, make sure you have committed any working directory changes 
you want to keep. If you choose not to, you can still find your uncommitted changes 
in the backup folder, but it will be harder to find them because 'git status' 
will not work in the backup.

To actually execute the dehydrate, run 'gvfs dehydrate --confirm'
");

                    return;
                }

                this.CheckGitStatus(tracer, enlistment);

                string backupRoot = Path.GetFullPath(Path.Combine(enlistment.EnlistmentRoot, "dehydrate_backup", DateTime.Now.ToString("yyyyMMdd_HHmmss")));
                this.Output.WriteLine();
                this.WriteMessage(tracer, "Starting dehydration. All of your existing files will be backed up in " + backupRoot);
                this.WriteMessage(tracer, "WARNING: If you abort the dehydrate after this point, the repo may become corrupt");
                this.Output.WriteLine();

                this.Unmount(tracer);

                if (this.TryBackupFiles(tracer, enlistment, backupRoot) &&
                    this.TryRecreateIndex(tracer, enlistment))
                {
                    // Converting the src folder to partial must be the final step before mount
                    this.PrepareSrcFolder(tracer, enlistment);
                    this.Mount(tracer);

                    this.Output.WriteLine();
                    this.WriteMessage(tracer, "The repo was successfully dehydrated and remounted");
                }
                else
                {
                    this.Output.WriteLine();
                    this.WriteMessage(tracer, "ERROR: Backup failed. We will attempt to mount, but you may need to reclone if that fails");

                    this.Mount(tracer);
                    this.WriteMessage(tracer, "Dehydrate failed, but remounting succeeded");
                }
            }
        }
コード例 #28
0
ファイル: FastFetchVerb.cs プロジェクト: yyqyu/GVFS
        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", useCriticalTelemetryFlag: false))
            {
                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);

                CacheServerInfo cacheServer = new CacheServerInfo(this.GetRemoteUrl(enlistment), null);

                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    cacheServer.Url,
                    new EventMetadata
                {
                    { "TargetCommitish", commitish },
                    { "Checkout", this.Checkout },
                });

                RetryConfig retryConfig = new RetryConfig(this.MaxAttempts, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes));
                FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment, cacheServer, retryConfig);
                string      error;
                if (!FetchHelper.TryLoadFolderList(enlistment, this.FolderList, this.FolderListFile, fetchHelper.FolderList, out error))
                {
                    tracer.RelatedError(error);
                    Console.WriteLine(error);
                    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);
            }
        }
コード例 #29
0
ファイル: RepairVerb.cs プロジェクト: wjmjimmie/GVFS
        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();
                }
            }
        }
コード例 #30
0
ファイル: PrefetchVerb.cs プロジェクト: yyqyu/GVFS
        protected override void Execute(GVFSEnlistment enlistment)
        {
            using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Prefetch"))
            {
                if (this.Verbose)
                {
                    tracer.AddDiagnosticConsoleEventListener(EventLevel.Informational, Keywords.Any);
                }

                string cacheServerUrl = CacheServerResolver.GetUrlFromConfig(enlistment);

                tracer.AddLogFileEventListener(
                    GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Prefetch),
                    EventLevel.Informational,
                    Keywords.Any);
                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    cacheServerUrl);

                RetryConfig retryConfig = this.GetRetryConfig(tracer, enlistment, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes));

                CacheServerInfo cacheServer = this.ResolvedCacheServer;
                GVFSConfig      gvfsConfig  = this.GVFSConfig;
                if (!this.SkipVersionCheck)
                {
                    string authErrorMessage;
                    if (!this.ShowStatusWhileRunning(
                            () => enlistment.Authentication.TryRefreshCredentials(tracer, out authErrorMessage),
                            "Authenticating"))
                    {
                        this.ReportErrorAndExit(tracer, "Unable to prefetch because authentication failed");
                    }

                    if (gvfsConfig == null)
                    {
                        gvfsConfig = this.QueryGVFSConfig(tracer, enlistment, retryConfig);
                    }

                    if (cacheServer == null)
                    {
                        CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment);
                        cacheServer = cacheServerResolver.ResolveNameFromRemote(cacheServerUrl, gvfsConfig);
                    }

                    this.ValidateClientVersions(tracer, enlistment, gvfsConfig, showWarnings: false);

                    this.Output.WriteLine("Configured cache server: " + cacheServer);
                }

                this.InitializeLocalCacheAndObjectsPaths(tracer, enlistment, retryConfig, gvfsConfig, cacheServer);

                try
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("Commits", this.Commits);
                    metadata.Add("Files", this.Files);
                    metadata.Add("Folders", this.Folders);
                    metadata.Add("FoldersListFile", this.FoldersListFile);
                    metadata.Add("HydrateFiles", this.HydrateFiles);
                    tracer.RelatedEvent(EventLevel.Informational, "PerformPrefetch", metadata);

                    GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, cacheServer, retryConfig);

                    if (this.Commits)
                    {
                        if (!string.IsNullOrWhiteSpace(this.Files) ||
                            !string.IsNullOrWhiteSpace(this.Folders) ||
                            !string.IsNullOrWhiteSpace(this.FoldersListFile))
                        {
                            this.ReportErrorAndExit(tracer, "You cannot prefetch commits and blobs at the same time.");
                        }

                        if (this.HydrateFiles)
                        {
                            this.ReportErrorAndExit(tracer, "You can only specify --hydrate with --files or --folders");
                        }

                        PhysicalFileSystem fileSystem = new PhysicalFileSystem();
                        using (FileBasedLock prefetchLock = new FileBasedLock(
                                   fileSystem,
                                   tracer,
                                   Path.Combine(enlistment.GitPackRoot, PrefetchCommitsAndTreesLock),
                                   enlistment.EnlistmentRoot,
                                   cleanupStaleLock: false,
                                   overwriteExistingLock: true))
                        {
                            this.WaitUntilLockIsAcquired(tracer, prefetchLock);
                            this.PrefetchCommits(tracer, enlistment, objectRequestor, cacheServer);
                        }
                    }
                    else
                    {
                        this.PrefetchBlobs(tracer, enlistment, objectRequestor, cacheServer);
                    }
                }
                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 },
                            { "Exception", innerException.ToString() }
                        },
                            $"Unhandled {innerException.GetType().Name}: {innerException.Message}");
                    }

                    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 },
                        { "Exception", e.ToString() }
                    },
                        $"Unhandled {e.GetType().Name}: {e.Message}");

                    Environment.ExitCode = (int)ReturnCode.GenericError;
                }
            }
        }