in GVFS/GVFS/CommandLine/CloneVerb.cs [82:280]
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 (!GVFSPlatform.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, GVFSConstants.WorkingDirectoryRootName),
GVFSPlatform.Instance.Constants.PathComparison))
{
this.ReportErrorAndExit("'--local-cache-path' cannot be inside the src folder");
}
}
this.CheckKernelDriverSupported(normalizedEnlistmentRootPath);
this.CheckNotInsideExistingRepo(normalizedEnlistmentRootPath);
this.BlockEmptyCacheServerUrl(this.CacheServerUrl);
try
{
GVFSEnlistment enlistment;
Result cloneResult = new Result(false);
CacheServerInfo cacheServer = null;
ServerGVFSConfig serverGVFSConfig = null;
using (JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, "GVFSClone"))
{
cloneResult = this.TryCreateEnlistment(fullEnlistmentRootPathParameter, normalizedEnlistmentRootPath, out enlistment);
if (cloneResult.Success)
{
// Create the enlistment root explicitly with CreateDirectoryAccessibleByAuthUsers before calling
// AddLogFileEventListener to ensure that elevated and non-elevated users have access to the root.
string createDirectoryError;
if (!GVFSPlatform.Instance.FileSystem.TryCreateDirectoryAccessibleByAuthUsers(enlistment.EnlistmentRoot, out createDirectoryError))
{
this.ReportErrorAndExit($"Failed to create '{enlistment.EnlistmentRoot}': {createDirectoryError}");
}
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", GVFSPlatform.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 GVFS 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));
serverGVFSConfig = this.QueryGVFSConfig(tracer, enlistment, retryConfig);
cacheServer = this.ResolveCacheServer(tracer, cacheServer, cacheServerResolver, serverGVFSConfig);
this.ValidateClientVersions(tracer, enlistment, serverGVFSConfig, showWarnings: true);
this.ShowStatusWhileRunning(
() =>
{
cloneResult = this.TryClone(tracer, enlistment, cacheServer, retryConfig, serverGVFSConfig, 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.ServerGVFSConfig = serverGVFSConfig;
});
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.DownloadedGVFSConfig = serverGVFSConfig;
});
}
}
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);
}