public override void Execute() { int exitCode = 0; this.ValidatePathParameter(this.EnlistmentRootPathParameter); this.ValidatePathParameter(this.LocalCacheRoot); string fullEnlistmentRootPathParameter; string normalizedEnlistmentRootPath = this.GetCloneRoot(out fullEnlistmentRootPathParameter); if (!string.IsNullOrWhiteSpace(this.LocalCacheRoot)) { string fullLocalCacheRootPath = Path.GetFullPath(this.LocalCacheRoot); string errorMessage; string normalizedLocalCacheRootPath; if (!GSDPlatform.Instance.FileSystem.TryGetNormalizedPath(fullLocalCacheRootPath, out normalizedLocalCacheRootPath, out errorMessage)) { this.ReportErrorAndExit($"Failed to determine normalized path for '--local-cache-path' path {fullLocalCacheRootPath}: {errorMessage}"); } if (normalizedLocalCacheRootPath.StartsWith( Path.Combine(normalizedEnlistmentRootPath, GSDConstants.WorkingDirectoryRootName), StringComparison.OrdinalIgnoreCase)) { this.ReportErrorAndExit("'--local-cache-path' cannot be inside the src folder"); } } this.CheckNotInsideExistingRepo(normalizedEnlistmentRootPath); this.BlockEmptyCacheServerUrl(this.CacheServerUrl); try { GSDEnlistment enlistment; Result cloneResult = new Result(false); CacheServerInfo cacheServer = null; ServerGSDConfig serverGSDConfig = null; using (JsonTracer tracer = new JsonTracer(GSDConstants.GSDEtwProviderName, "GSDClone")) { cloneResult = this.TryCreateEnlistment(fullEnlistmentRootPathParameter, normalizedEnlistmentRootPath, out enlistment); if (cloneResult.Success) { tracer.AddLogFileEventListener( GSDEnlistment.GetNewGSDLogFileName(enlistment.GSDLogsRoot, GSDConstants.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", GSDPlatform.Instance.IsElevated() }, { "NamedPipeName", enlistment.NamedPipeName }, { "ProcessID", Process.GetCurrentProcess().Id }, { nameof(this.EnlistmentRootPathParameter), this.EnlistmentRootPathParameter }, { nameof(fullEnlistmentRootPathParameter), fullEnlistmentRootPathParameter }, }); CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment); cacheServer = cacheServerResolver.ParseUrlOrFriendlyName(this.CacheServerUrl); string resolvedLocalCacheRoot; if (string.IsNullOrWhiteSpace(this.LocalCacheRoot)) { string localCacheRootError; if (!LocalCacheResolver.TryGetDefaultLocalCacheRoot(enlistment, out resolvedLocalCacheRoot, out localCacheRootError)) { this.ReportErrorAndExit( tracer, $"Failed to determine the default location for the local GSD cache: `{localCacheRootError}`"); } } 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; if (!this.TryAuthenticate(tracer, enlistment, out authErrorMessage)) { this.ReportErrorAndExit(tracer, "Cannot clone because authentication failed: " + authErrorMessage); } RetryConfig retryConfig = this.GetRetryConfig(tracer, enlistment, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes)); serverGSDConfig = this.QueryGSDConfig(tracer, enlistment, retryConfig); cacheServer = this.ResolveCacheServer(tracer, cacheServer, cacheServerResolver, serverGSDConfig); this.ValidateClientVersions(tracer, enlistment, serverGSDConfig, showWarnings: true); this.ShowStatusWhileRunning( () => { cloneResult = this.TryClone(tracer, enlistment, cacheServer, retryConfig, serverGSDConfig, resolvedLocalCacheRoot); return(cloneResult.Success); }, "Cloning", normalizedEnlistmentRootPath); } if (!cloneResult.Success) { tracer.RelatedError(cloneResult.ErrorMessage); } } if (cloneResult.Success) { if (!this.NoPrefetch) { ReturnCode result = this.Execute <PrefetchVerb>( enlistment, verb => { verb.Commits = true; verb.SkipVersionCheck = true; verb.ResolvedCacheServer = cacheServer; verb.ServerGSDConfig = serverGSDConfig; }); if (result != ReturnCode.Success) { this.Output.WriteLine("\r\nError during prefetch @ {0}", fullEnlistmentRootPathParameter); 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>( enlistment, verb => { verb.SkipMountedCheck = true; verb.SkipVersionCheck = true; verb.ResolvedCacheServer = cacheServer; verb.DownloadedGSDConfig = serverGSDConfig; }); GitProcess git = new GitProcess(enlistment); git.ForceCheckoutAllFiles(); } } else { this.Output.WriteLine("\r\nCannot clone @ {0}", fullEnlistmentRootPathParameter); this.Output.WriteLine("Error: {0}", cloneResult.ErrorMessage); exitCode = (int)ReturnCode.GenericError; } } catch (AggregateException e) { this.Output.WriteLine("Cannot clone @ {0}:", fullEnlistmentRootPathParameter); 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}", fullEnlistmentRootPathParameter, e.ToString()); } Environment.Exit(exitCode); }