Example #1
0
        private static void ExitWithError(params string[] messages)
        {
            foreach (string message in messages)
            {
                Console.Error.WriteLine(message);
            }

            tracer.RelatedError(string.Join("\r\n", messages));
            Environment.Exit(1);
        }
Example #2
0
        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);
        }
Example #3
0
        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));
            }
        }
Example #4
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));
                }
            }
        }
Example #5
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);
            }
        }
Example #6
0
        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);
        }
Example #7
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);
            }
        }
Example #8
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();
                }
            }
        }
Example #9
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);
        }
Example #10
0
        public override void Execute()
        {
            int exitCode = 0;

            this.CheckGVFltRunning();
            this.CheckNotInsideExistingRepo();

            string fullPath = GVFSEnlistment.ToFullPath(this.EnlistmentRootPath, this.GetDefaultEnlistmentRoot());

            if (fullPath == null)
            {
                this.ReportErrorAndExit("Unable to write to directory " + this.EnlistmentRootPath);
            }

            this.EnlistmentRootPath = fullPath;
            this.CacheServerUrl     = Enlistment.StripObjectsEndpointSuffix(this.CacheServerUrl);

            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);

                        tracer.WriteStartEvent(
                            enlistment.EnlistmentRoot,
                            enlistment.RepoUrl,
                            enlistment.CacheServerUrl,
                            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: " + (enlistment.CacheServerUrl == enlistment.RepoUrl ? "None" : enlistment.CacheServerUrl));
                        this.Output.WriteLine("  Destination:  " + enlistment.EnlistmentRoot);

                        this.ShowStatusWhileRunning(
                            () =>
                        {
                            cloneResult = this.TryClone(tracer, enlistment);
                            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);
        }
Example #11
0
        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);
        }
Example #12
0
        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;
                }
            }
        }
Example #13
0
        public override void Execute()
        {
            int exitCode = 0;

            this.EnlistmentRootPath = this.GetCloneRoot();

            this.CheckGVFltHealthy();
            this.CheckNotInsideExistingRepo();
            this.BlockEmptyCacheServerUrl(this.CacheServerUrl);

            try
            {
                GVFSEnlistment enlistment;
                Result         cloneResult = new Result(false);

                CacheServerInfo cacheServer = null;

                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);
                        tracer.WriteStartEvent(
                            enlistment.EnlistmentRoot,
                            enlistment.RepoUrl,
                            this.CacheServerUrl,
                            enlistment.GitObjectsRoot,
                            new EventMetadata
                        {
                            { "Branch", this.Branch },
                            { "SingleBranch", this.SingleBranch },
                            { "NoMount", this.NoMount },
                            { "NoPrefetch", this.NoPrefetch },
                            { "Unattended", this.Unattended },
                            { "IsElevated", ProcessHelper.IsAdminElevated() },
                        });

                        CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment);
                        cacheServer = cacheServerResolver.ParseUrlOrFriendlyName(this.CacheServerUrl);

                        this.Output.WriteLine("Clone parameters:");
                        this.Output.WriteLine("  Repo URL:     " + enlistment.RepoUrl);
                        this.Output.WriteLine("  Cache Server: " + cacheServer);
                        this.Output.WriteLine("  Destination:  " + enlistment.EnlistmentRoot);

                        string authErrorMessage = null;
                        if (!this.ShowStatusWhileRunning(
                                () => enlistment.Authentication.TryRefreshCredentials(tracer, out authErrorMessage),
                                "Authenticating"))
                        {
                            this.ReportErrorAndExit(tracer, "Unable to clone because authentication failed");
                        }

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

                        cacheServer = this.ResolveCacheServerUrlIfNeeded(tracer, cacheServer, cacheServerResolver, gvfsConfig);
                        this.ValidateClientVersions(tracer, enlistment, gvfsConfig, showWarnings: true);

                        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)
                    {
                        this.Execute <PrefetchVerb>(
                            this.EnlistmentRootPath,
                            verb =>
                        {
                            verb.Commits             = true;
                            verb.SkipVersionCheck    = true;
                            verb.ResolvedCacheServer = cacheServer;
                        });
                    }

                    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
                    {
                        this.Execute <MountVerb>(
                            this.EnlistmentRootPath,
                            verb =>
                        {
                            verb.SkipMountedCheck = true;
                            verb.SkipVersionCheck = true;
                        });
                    }
                }
                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);
        }
Example #14
0
        public void Execute()
        {
            // 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;
            }

            if (this.Commit != null && this.Branch != null)
            {
                Console.WriteLine("Cannot specify both a commit sha and a branch name to checkout.");
                return;
            }

            this.CacheServerUrl = Enlistment.StripObjectsEndpointSuffix(this.CacheServerUrl);

            this.SearchThreadCount   = this.SearchThreadCount > 0 ? this.SearchThreadCount : Environment.ProcessorCount;
            this.DownloadThreadCount = this.DownloadThreadCount > 0 ? this.DownloadThreadCount : Environment.ProcessorCount;
            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();

            Enlistment enlistment = (Enlistment)GVFSEnlistment.CreateFromCurrentDirectory(this.CacheServerUrl, this.GitBinPath)
                                    ?? GitEnlistment.CreateFromCurrentDirectory(this.CacheServerUrl, this.GitBinPath);

            if (enlistment == null)
            {
                Console.WriteLine("Must be run within a .git repo or GVFS enlistment");
                return;
            }

            string commitish = this.Commit ?? this.Branch ?? DefaultBranch;

            EventLevel maxVerbosity = this.Silent ? EventLevel.LogAlways : EventLevel.Informational;

            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft.Git.FastFetch", "FastFetch"))
            {
                tracer.AddConsoleEventListener(maxVerbosity, Keywords.Any);
                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    enlistment.CacheServerUrl,
                    new EventMetadata
                {
                    { "TargetCommitish", commitish },
                });

                FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment);

                fetchHelper.MaxRetries = this.MaxRetries;

                if (!FetchHelper.TryLoadPathWhitelist(this.PathWhitelist, this.PathWhitelistFile, tracer, fetchHelper.PathWhitelist))
                {
                    Environment.ExitCode = 1;
                    return;
                }

                try
                {
                    bool isBranch = this.Commit == null;
                    fetchHelper.FastFetch(commitish, isBranch);
                    if (fetchHelper.HasFailures)
                    {
                        Environment.ExitCode = 1;
                    }
                }
                catch (AggregateException e)
                {
                    Environment.ExitCode = 1;
                    foreach (Exception ex in e.Flatten().InnerExceptions)
                    {
                        tracer.RelatedError(ex.ToString());
                    }
                }
                catch (Exception e)
                {
                    Environment.ExitCode = 1;
                    tracer.RelatedError(e.ToString());
                }

                EventMetadata stopMetadata = new EventMetadata();
                stopMetadata.Add("Success", Environment.ExitCode == 0);
                tracer.Stop(stopMetadata);
            }

            if (Debugger.IsAttached)
            {
                Console.ReadKey();
            }
        }
Example #15
0
        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() }
                    });
                }
            }
        }
Example #16
0
        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() }
                    });
                }
            }
        }
Example #17
0
        private Result TryClone(JsonEtwTracer tracer, GVFSEnlistment enlistment)
        {
            this.CheckVolumeSupportsDeleteNotifications(tracer, enlistment);
            this.CheckGitVersion(enlistment);

            Result pipeResult;

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

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

                using (GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, Environment.ProcessorCount))
                {
                    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));
                    }

                    // Only check Defender exclusions if not mounting, otherwise let mount take care of it.
                    if (this.NoMount)
                    {
                        this.CheckAntiVirusExclusion(enlistment);
                    }

                    CloneHelper cloneHelper = new CloneHelper(tracer, enlistment, objectRequestor);
                    return(cloneHelper.CreateClone(refs, this.Branch));
                }
            }
        }
Example #18
0
        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);
            }
        }
Example #19
0
        public override void Execute()
        {
            int exitCode = 0;

            this.ValidatePathParameter(this.EnlistmentRootPath);
            this.ValidatePathParameter(this.LocalCacheRoot);

            this.EnlistmentRootPath = this.GetCloneRoot();

            if (!string.IsNullOrWhiteSpace(this.LocalCacheRoot))
            {
                if (Path.GetFullPath(this.LocalCacheRoot).StartsWith(
                        Path.Combine(this.EnlistmentRootPath, GVFSConstants.WorkingDirectoryRootName),
                        StringComparison.OrdinalIgnoreCase))
                {
                    this.ReportErrorAndExit("'--local-cache-path' cannot be inside the src folder");
                }
            }

            this.CheckNTFSVolume();
            this.CheckNotInsideExistingRepo();
            this.BlockEmptyCacheServerUrl(this.CacheServerUrl);

            try
            {
                GVFSEnlistment enlistment;
                Result         cloneResult = new Result(false);

                CacheServerInfo cacheServer = null;
                GVFSConfig      gvfsConfig  = null;

                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);
                        tracer.WriteStartEvent(
                            enlistment.EnlistmentRoot,
                            enlistment.RepoUrl,
                            this.CacheServerUrl,
                            new EventMetadata
                        {
                            { "Branch", this.Branch },
                            { "LocalCacheRoot", this.LocalCacheRoot },
                            { "SingleBranch", this.SingleBranch },
                            { "NoMount", this.NoMount },
                            { "NoPrefetch", this.NoPrefetch },
                            { "Unattended", this.Unattended },
                            { "IsElevated", ProcessHelper.IsAdminElevated() },
                        });

                        CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment);
                        cacheServer = cacheServerResolver.ParseUrlOrFriendlyName(this.CacheServerUrl);

                        string error;
                        string resolvedLocalCacheRoot;
                        if (string.IsNullOrWhiteSpace(this.LocalCacheRoot))
                        {
                            if (!LocalCacheResolver.TryGetDefaultLocalCacheRoot(enlistment, out resolvedLocalCacheRoot, out error))
                            {
                                this.ReportErrorAndExit(tracer, "Cannot clone, error determining local cache path: " + error);
                            }
                        }
                        else
                        {
                            resolvedLocalCacheRoot = Path.GetFullPath(this.LocalCacheRoot);
                        }

                        this.Output.WriteLine("Clone parameters:");
                        this.Output.WriteLine("  Repo URL:     " + enlistment.RepoUrl);
                        this.Output.WriteLine("  Branch:       " + (string.IsNullOrWhiteSpace(this.Branch) ? "Default" : this.Branch));
                        this.Output.WriteLine("  Cache Server: " + cacheServer);
                        this.Output.WriteLine("  Local Cache:  " + resolvedLocalCacheRoot);
                        this.Output.WriteLine("  Destination:  " + enlistment.EnlistmentRoot);

                        string authErrorMessage = null;
                        if (!this.ShowStatusWhileRunning(
                                () => enlistment.Authentication.TryRefreshCredentials(tracer, out authErrorMessage),
                                "Authenticating"))
                        {
                            this.ReportErrorAndExit(tracer, "Cannot clone because authentication failed");
                        }

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

                        cacheServer = this.ResolveCacheServer(tracer, cacheServer, cacheServerResolver, gvfsConfig);

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

                        this.ShowStatusWhileRunning(
                            () =>
                        {
                            cloneResult = this.TryClone(tracer, enlistment, cacheServer, retryConfig, gvfsConfig, resolvedLocalCacheRoot);
                            return(cloneResult.Success);
                        },
                            "Cloning");
                    }

                    if (!cloneResult.Success)
                    {
                        tracer.RelatedError(cloneResult.ErrorMessage);
                    }
                }

                if (cloneResult.Success)
                {
                    if (!this.NoPrefetch)
                    {
                        ReturnCode result = this.Execute <PrefetchVerb>(
                            this.EnlistmentRootPath,
                            verb =>
                        {
                            verb.Commits             = true;
                            verb.SkipVersionCheck    = true;
                            verb.ResolvedCacheServer = cacheServer;
                            verb.GVFSConfig          = gvfsConfig;
                        });

                        if (result != ReturnCode.Success)
                        {
                            this.Output.WriteLine("\r\nError during prefetch @ {0}", this.EnlistmentRootPath);
                            exitCode = (int)result;
                        }
                    }

                    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
                    {
                        this.Execute <MountVerb>(
                            this.EnlistmentRootPath,
                            verb =>
                        {
                            verb.SkipMountedCheck     = true;
                            verb.SkipVersionCheck     = true;
                            verb.ResolvedCacheServer  = cacheServer;
                            verb.DownloadedGVFSConfig = gvfsConfig;
                        });
                    }
                }
                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);
        }