Skip to content

Commit

Permalink
Update projection to use the included folders
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Willford committed Aug 5, 2019
1 parent 0800b48 commit 73a5772
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using GVFS.FunctionalTests.FileSystemRunners;
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Tools;
using GVFS.Tests.Should;
using NUnit.Framework;
using System.IO;

namespace GVFS.FunctionalTests.Tests.EnlistmentPerFixture
{
[TestFixture]
public class IncludedFolderTests : TestsWithEnlistmentPerFixture
{
private FileSystemRunner fileSystem = new SystemIORunner();

[TestCase]
public void BasicTestsAddingAndRemoving()
{
// directories before limiting them
string[] allRootDirectories = Directory.GetDirectories(this.Enlistment.RepoRoot);
string[] directoriesForParentAdd = Directory.GetDirectories(Path.Combine(this.Enlistment.RepoRoot, "GVFS", "GVFS"));

GVFSProcess gvfsProcess = new GVFSProcess(this.Enlistment);
gvfsProcess.AddIncludedFolders(Path.Combine("GVFS", "GVFS"));

string[] directories = Directory.GetDirectories(this.Enlistment.RepoRoot);
directories.Length.ShouldEqual(2);
directories[0].ShouldEqual(Path.Combine(this.Enlistment.RepoRoot, ".git"));
directories[1].ShouldEqual(Path.Combine(this.Enlistment.RepoRoot, "GVFS"));

string folder = this.Enlistment.GetVirtualPathTo("GVFS", "GVFS");
folder.ShouldBeADirectory(this.fileSystem);
folder = this.Enlistment.GetVirtualPathTo("GVFS", "GVFS", "CommandLine");
folder.ShouldBeADirectory(this.fileSystem);

folder = this.Enlistment.GetVirtualPathTo("Scripts");
folder.ShouldNotExistOnDisk(this.fileSystem);

// Remove the last directory should make all folders appear again
gvfsProcess.RemoveIncludedFolders(Path.Combine("GVFS", "GVFS"));
directories = Directory.GetDirectories(this.Enlistment.RepoRoot);
directories.ShouldMatchInOrder(allRootDirectories);

// Add parent directory should make the parent recursive
gvfsProcess.AddIncludedFolders(Path.Combine("GVFS", "GVFS", "CommandLine"));
directories = Directory.GetDirectories(Path.Combine(this.Enlistment.RepoRoot, "GVFS", "GVFS"));
directories.Length.ShouldEqual(1);
directories[0].ShouldEqual(Path.Combine(this.Enlistment.RepoRoot, "GVFS", "GVFS", "CommandLine"));

gvfsProcess.AddIncludedFolders(Path.Combine("GVFS", "GVFS"));
directories = Directory.GetDirectories(Path.Combine(this.Enlistment.RepoRoot, "GVFS", "GVFS"));
directories.ShouldMatchInOrder(directoriesForParentAdd);

// Add and remove folder
gvfsProcess.AddIncludedFolders("Scripts");
folder.ShouldBeADirectory(this.fileSystem);

gvfsProcess.RemoveIncludedFolders("Scripts");
folder.ShouldNotExistOnDisk(this.fileSystem);

// Add and remove sibling folder to GVFS/GVFS
gvfsProcess.AddIncludedFolders(Path.Combine("GVFS", "FastFetch"));
folder = this.Enlistment.GetVirtualPathTo("GVFS", "FastFetch");
folder.ShouldBeADirectory(this.fileSystem);

gvfsProcess.RemoveIncludedFolders(Path.Combine("GVFS", "FastFetch"));
folder.ShouldNotExistOnDisk(this.fileSystem);
folder = this.Enlistment.GetVirtualPathTo("GVFS", "GVFS");
folder.ShouldBeADirectory(this.fileSystem);

// Add subfolder of GVFS/GVFS and make sure it stays recursive
gvfsProcess.AddIncludedFolders(Path.Combine("GVFS", "GVFS", "Properties"));
folder = this.Enlistment.GetVirtualPathTo("GVFS", "GVFS", "Properties");
folder.ShouldBeADirectory(this.fileSystem);

folder = this.Enlistment.GetVirtualPathTo("GVFS", "GVFS", "CommandLine");
folder.ShouldBeADirectory(this.fileSystem);
}
}
}
16 changes: 16 additions & 0 deletions GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GVFS.Tests.Should;
using System.Diagnostics;
using System.IO;

namespace GVFS.FunctionalTests.Tools
{
Expand All @@ -9,6 +10,11 @@ public class GVFSProcess
private readonly string enlistmentRoot;
private readonly string localCacheRoot;

public GVFSProcess(GVFSFunctionalTestEnlistment enlistment)
: this(GVFSTestConfig.PathToGVFS, enlistment.EnlistmentRoot, Path.Combine(enlistment.EnlistmentRoot, GVFSTestConfig.DotGVFSRoot))
{
}

public GVFSProcess(string pathToGVFS, string enlistmentRoot, string localCacheRoot)
{
this.pathToGVFS = pathToGVFS;
Expand Down Expand Up @@ -42,6 +48,16 @@ public bool TryMount(out string output)
return this.IsEnlistmentMounted();
}

public void AddIncludedFolders(params string[] folders)
{
this.CallGVFS($"include {this.enlistmentRoot} -a {string.Join(";", folders)}");
}

public void RemoveIncludedFolders(params string[] folders)
{
this.CallGVFS($" include {this.enlistmentRoot} -r {string.Join(";", folders)}");
}

public string Prefetch(string args, bool failOnError, string standardInput = null)
{
return this.CallGVFS("prefetch \"" + this.enlistmentRoot + "\" " + args, failOnError, standardInput: standardInput);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ public bool BuildingProjection_HasSameParentAsLastEntry
get; private set;
}

public bool BuildingProjection_ShouldInclude
{
get; set;
}

public bool BuildingProjection_ShouldIncludeRecursive
{
get; set;
}

public IncludedFolderData BuildingProjection_LastEntryIncludedFolder
{
get; set;
}

/// <summary>
/// Parses the path using LazyUTF8Strings. It should only be called when building a new projection.
/// </summary>
Expand Down Expand Up @@ -211,6 +226,9 @@ public void ClearLastParent()
{
this.buildingProjectionPreviousFinalSeparatorIndex = int.MaxValue;
this.BuildingProjection_HasSameParentAsLastEntry = false;
this.BuildingProjection_ShouldInclude = false;
this.BuildingProjection_ShouldIncludeRecursive = false;
this.BuildingProjection_LastEntryIncludedFolder = null;
this.BuildingProjection_LastParent = null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace GVFS.Virtualization.Projection
{
public partial class GitIndexProjection
{
internal class IncludedFolderData
{
public IncludedFolderData()
{
this.Children = new Dictionary<string, IncludedFolderData>();
}

public bool IsRecursive { get; set; }
public Dictionary<string, IncludedFolderData> Children { get; }
}
}
}
77 changes: 76 additions & 1 deletion GVFS/GVFS.Virtualization/Projection/GitIndexProjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -58,6 +59,7 @@ public partial class GitIndexProjection : IDisposable, IProfilerOnlyIndexProject
private BlobSizes blobSizes;
private IPlaceholderCollection placeholderDatabase;
private IIncludedFolderCollection includedFolderCollection;
private IncludedFolderData rootIncludedFolder;
private GVFSGitObjects gitObjects;
private BackgroundFileSystemTaskRunner backgroundFileSystemTaskRunner;
private ReaderWriterLockSlim projectionReadWriteLock;
Expand Down Expand Up @@ -111,6 +113,8 @@ public GitIndexProjection(
this.placeholderDatabase = placeholderDatabase;
this.includedFolderCollection = includedFolderCollection;
this.modifiedPaths = modifiedPaths;
this.rootIncludedFolder = new IncludedFolderData();
this.RefreshFoldersToInclude();
}

// For Unit Testing
Expand Down Expand Up @@ -661,7 +665,12 @@ private void AddItemFromIndexEntry(GitIndexEntry indexEntry)
{
if (indexEntry.BuildingProjection_HasSameParentAsLastEntry)
{
indexEntry.BuildingProjection_LastParent.AddChildFile(indexEntry.BuildingProjection_GetChildName(), indexEntry.Sha);
if (this.rootIncludedFolder.Children.Count == 0 ||
indexEntry.BuildingProjection_ShouldInclude ||
indexEntry.BuildingProjection_ShouldIncludeRecursive)
{
indexEntry.BuildingProjection_LastParent.AddChildFile(indexEntry.BuildingProjection_GetChildName(), indexEntry.Sha);
}
}
else
{
Expand Down Expand Up @@ -703,9 +712,45 @@ private void ClearProjectionCaches()
LazyUTF8String.FreePool();
this.projectionFolderCache.Clear();
this.nonDefaultFileTypesAndModes.Clear();
this.RefreshFoldersToInclude();
this.rootFolderData.ResetData(new LazyUTF8String("<root>"));
}

private void RefreshFoldersToInclude()
{
this.rootIncludedFolder.Children.Clear();
if (this.includedFolderCollection != null)
{
Dictionary<string, IncludedFolderData> parentFolder = this.rootIncludedFolder.Children;
foreach (string directoryPath in this.includedFolderCollection.GetAll())
{
string[] folders = directoryPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < folders.Length; i++)
{
IncludedFolderData folderData;
if (!parentFolder.ContainsKey(folders[i]))
{
folderData = new IncludedFolderData();
parentFolder.Add(folders[i], folderData);
}
else
{
folderData = parentFolder[folders[i]];
}

if (!folderData.IsRecursive)
{
folderData.IsRecursive = i == folders.Length - 1;
}

parentFolder = folderData.Children;
}

parentFolder = this.rootIncludedFolder.Children;
}
}
}

private bool TryGetSha(string childName, string parentKey, out string sha)
{
sha = string.Empty;
Expand Down Expand Up @@ -798,6 +843,36 @@ private FolderData AddFileToTree(GitIndexEntry indexEntry)
throw new InvalidDataException("Found a file (" + parentFolderName + ") where a folder was expected: " + gitPath);
}

if (this.rootIncludedFolder.Children.Count > 0)
{
if (indexEntry.BuildingProjection_LastEntryIncludedFolder == null)
{
indexEntry.BuildingProjection_LastEntryIncludedFolder = this.rootIncludedFolder;
}

if (!indexEntry.BuildingProjection_ShouldIncludeRecursive)
{
string folderName = indexEntry.BuildingProjection_PathParts[pathIndex].GetString();
if (indexEntry.BuildingProjection_LastEntryIncludedFolder.Children.ContainsKey(folderName))
{
indexEntry.BuildingProjection_ShouldInclude = true;
indexEntry.BuildingProjection_ShouldIncludeRecursive = indexEntry.BuildingProjection_LastEntryIncludedFolder.Children[folderName].IsRecursive;
indexEntry.BuildingProjection_LastEntryIncludedFolder = indexEntry.BuildingProjection_LastEntryIncludedFolder.Children[folderName];
}
else
{
indexEntry.BuildingProjection_ShouldInclude = false;
indexEntry.BuildingProjection_ShouldIncludeRecursive = false;
indexEntry.BuildingProjection_LastEntryIncludedFolder = null;
}

if (!indexEntry.BuildingProjection_ShouldInclude)
{
return parentFolder;
}
}
}

parentFolder = parentFolder.ChildEntries.GetOrAddFolder(indexEntry.BuildingProjection_PathParts[pathIndex]);
}

Expand Down

0 comments on commit 73a5772

Please sign in to comment.