in GVFS/GVFS/CommandLine/DehydrateVerb.cs [62:226]
protected override void Execute(GVFSEnlistment enlistment)
{
using (JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, "Dehydrate"))
{
tracer.AddLogFileEventListener(
GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Dehydrate),
EventLevel.Informational,
Keywords.Any);
tracer.WriteStartEvent(
enlistment.EnlistmentRoot,
enlistment.RepoUrl,
CacheServerResolver.GetUrlFromConfig(enlistment),
new EventMetadata
{
{ "Confirmed", this.Confirmed },
{ "NoStatus", this.NoStatus },
{ "NamedPipeName", enlistment.NamedPipeName },
{ "Folders", this.Folders },
{ nameof(this.EnlistmentRootPathParameter), this.EnlistmentRootPathParameter },
});
// This is only intended to be run by functional tests
if (this.MaintenanceJob != null)
{
this.InitializeLocalCacheAndObjectsPaths(tracer, enlistment, retryConfig: null, serverGVFSConfig: null, cacheServer: null);
PhysicalFileSystem fileSystem = new PhysicalFileSystem();
using (GitRepo gitRepo = new GitRepo(tracer, enlistment, fileSystem))
using (GVFSContext context = new GVFSContext(tracer, fileSystem, gitRepo, enlistment))
{
switch (this.MaintenanceJob)
{
case "LooseObjects":
(new LooseObjectsStep(context, forceRun: true)).Execute();
return;
case "PackfileMaintenance":
(new PackfileMaintenanceStep(
context,
forceRun: true,
batchSize: this.PackfileMaintenanceBatchSize ?? PackfileMaintenanceStep.DefaultBatchSize)).Execute();
return;
case "PostFetch":
(new PostFetchStep(context, new System.Collections.Generic.List<string>(), requireObjectCacheLock: false)).Execute();
return;
default:
this.ReportErrorAndExit($"Unknown maintenance job requested: {this.MaintenanceJob}");
break;
}
}
}
bool fullDehydrate = string.IsNullOrEmpty(this.Folders);
if (!this.Confirmed && fullDehydrate)
{
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' from the parent
of your enlistment's src folder.
");
return;
}
else if (!this.Confirmed)
{
this.Output.WriteLine(
@"WARNING: THIS IS AN EXPERIMENTAL FEATURE
All of your downloaded objects, branches, and siblings of the src folder
will be preserved. This will remove the folders specified and any working directory
files and folders even if ignored by git similar to 'git clean -xdf <path>'.
Before you dehydrate, you will have to commit any working directory changes
you want to keep and have a clean 'git status'.
To actually execute the dehydrate, run 'gvfs dehydrate --confirm --folders <folder list>'
from a parent of the folders list.
");
return;
}
if (this.NoStatus && !fullDehydrate)
{
this.ReportErrorAndExit(tracer, "Dehydrate --no-status not valid with --folders");
return;
}
bool cleanStatus = this.StatusChecked || this.CheckGitStatus(tracer, enlistment, fullDehydrate);
string backupRoot = Path.GetFullPath(Path.Combine(enlistment.EnlistmentRoot, "dehydrate_backup", DateTime.Now.ToString("yyyyMMdd_HHmmss")));
this.Output.WriteLine();
if (fullDehydrate)
{
this.WriteMessage(tracer, $"Starting {this.RunningVerbName}. All of your existing files will be backed up in " + backupRoot);
}
this.WriteMessage(tracer, $"WARNING: If you abort the {this.RunningVerbName} after this point, the repo may become corrupt");
this.Output.WriteLine();
this.Unmount(tracer);
string error;
if (!DiskLayoutUpgrade.TryCheckDiskLayoutVersion(tracer, enlistment.EnlistmentRoot, out error))
{
this.ReportErrorAndExit(tracer, error);
}
if (fullDehydrate)
{
RetryConfig retryConfig;
if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error))
{
this.ReportErrorAndExit(tracer, "Failed to determine GVFS timeout and max retries: " + error);
}
string errorMessage;
if (!this.TryAuthenticate(tracer, enlistment, out errorMessage))
{
this.ReportErrorAndExit(tracer, errorMessage);
}
// Local cache and objects paths are required for TryDownloadGitObjects
this.InitializeLocalCacheAndObjectsPaths(tracer, enlistment, retryConfig, serverGVFSConfig: null, cacheServer: null);
this.RunFullDehydrate(tracer, enlistment, backupRoot, retryConfig);
}
else
{
string[] folders = this.Folders.Split(new[] { FolderListSeparator }, StringSplitOptions.RemoveEmptyEntries);
if (folders.Length > 0)
{
if (cleanStatus)
{
this.DehydrateFolders(tracer, enlistment, folders);
}
else
{
this.ReportErrorAndExit($"Cannot {this.ActionName}: must have a clean git status.");
}
}
else
{
this.ReportErrorAndExit($"No folders to {this.ActionName}.");
}
}
}
}