private void ReExpandFolder()

in GVFS/GVFS.Virtualization/Projection/GitIndexProjection.cs [1540:1634]


        private void ReExpandFolder(
            string relativeFolderPath,
            HashSet<string> existingPlaceholders)
        {
            bool foundFolder = this.TryGetOrAddFolderDataFromCache(relativeFolderPath, out FolderData folderData);
            if (!foundFolder)
            {
                // Folder is no longer in the projection
                existingPlaceholders.Remove(relativeFolderPath);
                this.placeholderDatabase.Remove(relativeFolderPath);
                return;
            }

            if (GVFSPlatform.Instance.KernelDriver.EmptyPlaceholdersRequireFileSize)
            {
                using (BlobSizes.BlobSizesConnection blobSizesConnection = this.blobSizes.CreateConnection())
                {
                    folderData.PopulateSizes(
                    this.context.Tracer,
                    this.gitObjects,
                    blobSizesConnection,
                    availableSizes: null,
                    cancellationToken: CancellationToken.None);
                }
            }

            for (int i = 0; i < folderData.ChildEntries.Count; i++)
            {
                FolderEntryData childEntry = folderData.ChildEntries[i];
                if (!childEntry.IsFolder || ((FolderData)childEntry).IsIncluded)
                {
                    string childRelativePath;
                    if (relativeFolderPath.Length == 0)
                    {
                        childRelativePath = childEntry.Name.GetString();
                    }
                    else
                    {
                        childRelativePath = relativeFolderPath + Path.DirectorySeparatorChar + childEntry.Name.GetString();
                    }

                    if (!existingPlaceholders.Contains(childRelativePath))
                    {
                        FileSystemResult result;
                        if (childEntry.IsFolder)
                        {
                            result = this.fileSystemVirtualizer.WritePlaceholderDirectory(childRelativePath);
                            if (result.Result == FSResult.Ok)
                            {
                                this.placeholderDatabase.AddPartialFolder(childRelativePath, sha: null);
                            }
                            else if (result.Result == FSResult.IOError)
                            {
                                // When running in sparse mode there could be directories that were left on disk but are not in the
                                // modified paths or in the placeholder list because they were not part of the projection
                                // At this point they need to be re-expanded because they are on disk and part of the projection
                                if (this.context.FileSystem.DirectoryExists(Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, childRelativePath)))
                                {
                                    this.ReExpandFolder(childRelativePath, existingPlaceholders);
                                    this.placeholderDatabase.AddExpandedFolder(childRelativePath);
                                }
                            }
                        }
                        else
                        {
                            FileData childFileData = childEntry as FileData;
                            string fileSha = childFileData.Sha.ToString();
                            result = this.fileSystemVirtualizer.WritePlaceholderFile(childRelativePath, childFileData.Size, fileSha);
                            if (result.Result == FSResult.Ok)
                            {
                                this.placeholderDatabase.AddFile(childRelativePath, fileSha);
                            }
                        }

                        switch (result.Result)
                        {
                            case FSResult.Ok:
                                break;

                            case FSResult.FileOrPathNotFound:
                                // Git command must have removed the folder being re-expanded (relativeFolderPath)
                                // Remove the folder from existingFolderPlaceholders so that its parent will create
                                // it again (when it's re-expanded)
                                existingPlaceholders.Remove(relativeFolderPath);
                                this.placeholderDatabase.Remove(relativeFolderPath);
                                return;

                            default:
                                // TODO(#245): Handle failures of WritePlaceholderDirectory and WritePlaceholderFile
                                break;
                        }
                    }
                }
            }
        }