in GVFS/GVFS/CommandLine/SparseVerb.cs [138:303]
protected override void Execute(GVFSEnlistment enlistment)
{
if (this.List || (
!this.Prune &&
!this.Disable &&
string.IsNullOrEmpty(this.Add) &&
string.IsNullOrEmpty(this.Remove) &&
string.IsNullOrEmpty(this.Set) &&
string.IsNullOrEmpty(this.File)))
{
this.ListSparseFolders(enlistment.EnlistmentRoot);
return;
}
this.CheckOptions();
using (JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, SparseVerbName))
{
tracer.AddLogFileEventListener(
GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Sparse),
EventLevel.Informational,
Keywords.Any);
EventMetadata metadata = new EventMetadata();
metadata.Add(nameof(this.Set), this.Set);
metadata.Add(nameof(this.File), this.File);
metadata.Add(nameof(this.Add), this.Add);
metadata.Add(nameof(this.Remove), this.Remove);
metadata.Add(nameof(this.Prune), this.Prune);
metadata.Add(nameof(this.Disable), this.Disable);
tracer.RelatedInfo(metadata, $"Running sparse");
HashSet<string> directories;
bool needToChangeProjection = false;
using (GVFSDatabase database = new GVFSDatabase(new PhysicalFileSystem(), enlistment.EnlistmentRoot, new SqliteDatabase()))
{
SparseTable sparseTable = new SparseTable(database);
directories = sparseTable.GetAll();
List<string> foldersToRemove = new List<string>();
List<string> foldersToAdd = new List<string>();
if (this.Disable)
{
if (directories.Count > 0)
{
this.WriteMessage(tracer, "Removing all folders from sparse list. When the sparse list is empty, all folders are projected.");
needToChangeProjection = true;
foldersToRemove.AddRange(directories);
directories.Clear();
}
else
{
return;
}
}
else if (!string.IsNullOrEmpty(this.Set) || !string.IsNullOrEmpty(this.File))
{
IEnumerable<string> folders = null;
if (!string.IsNullOrEmpty(this.Set))
{
folders = this.ParseFolderList(this.Set);
}
else if (!string.IsNullOrEmpty(this.File))
{
PhysicalFileSystem fileSystem = new PhysicalFileSystem();
folders = this.ParseFolderList(fileSystem.ReadAllText(this.File), folderSeparator: Environment.NewLine);
}
else
{
this.WriteMessage(tracer, "Invalid options specified.");
throw new InvalidOperationException();
}
foreach (string folder in folders)
{
if (!directories.Contains(folder))
{
needToChangeProjection = true;
foldersToAdd.Add(folder);
}
else
{
// Remove from directories so that the only directories left in the directories collection
// will be the ones that will need to be removed from sparse set
directories.Remove(folder);
}
}
if (directories.Count > 0)
{
needToChangeProjection = true;
foldersToRemove.AddRange(directories);
directories.Clear();
}
// Need to add folders that will be in the projection back into directories for the status check
foreach (string folder in folders)
{
directories.Add(folder);
}
}
else
{ // Process adds and removes
foreach (string folder in this.ParseFolderList(this.Remove))
{
if (directories.Contains(folder))
{
needToChangeProjection = true;
directories.Remove(folder);
foldersToRemove.Add(folder);
}
}
foreach (string folder in this.ParseFolderList(this.Add))
{
if (!directories.Contains(folder))
{
needToChangeProjection = true;
directories.Add(folder);
foldersToAdd.Add(folder);
}
}
}
if (needToChangeProjection || this.Prune)
{
if (directories.Count > 0)
{
// Make sure there is a clean git status before allowing sparse set to change
this.CheckGitStatus(tracer, enlistment, directories);
}
this.UpdateSparseFolders(tracer, sparseTable, foldersToRemove, foldersToAdd);
}
if (needToChangeProjection)
{
// Force a projection update to get the current inclusion set
this.ForceProjectionChange(tracer, enlistment);
tracer.RelatedInfo("Projection updated after adding or removing folders.");
}
else
{
this.WriteMessage(tracer, "No folders to update in sparse set.");
}
List<string> foldersPruned;
if (this.Prune && directories.Count > 0)
{
foldersPruned = this.PruneFoldersOutsideSparse(tracer, enlistment, sparseTable);
}
else
{
foldersPruned = new List<string>();
}
if (needToChangeProjection || this.Prune)
{
// Update the last write times of the parents of folders being added/removed
// so that File Explorer will refresh them
UpdateParentFolderLastWriteTimes(tracer, enlistment.WorkingDirectoryBackingRoot, foldersToRemove, foldersToAdd, foldersPruned);
}
}
}
}