public void GetAllEntriesAndPrepToWriteAllEntriesSplitsFilesAndFoldersCorrectly() { ConfigurableFileSystem fs = new ConfigurableFileSystem(); using (PlaceholderListDatabase dut1 = CreatePlaceholderListDatabase(fs, string.Empty)) { dut1.AddAndFlushFile(InputGitIgnorePath, InputGitIgnoreSHA); dut1.AddAndFlushFolder("partialFolder", isExpanded: false); dut1.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA); dut1.AddAndFlushFolder("expandedFolder", isExpanded: true); dut1.AddAndFlushFile(InputThirdFilePath, InputThirdFileSHA); dut1.AddAndFlushPossibleTombstoneFolder("tombstone"); dut1.RemoveAndFlush(InputThirdFilePath); } string error; PlaceholderListDatabase dut2; PlaceholderListDatabase.TryCreate(null, MockEntryFileName, fs, out dut2, out error).ShouldEqual(true, error); List <PlaceholderListDatabase.PlaceholderData> fileData; List <PlaceholderListDatabase.PlaceholderData> folderData; dut2.GetAllEntriesAndPrepToWriteAllEntries(out fileData, out folderData); fileData.Count.ShouldEqual(2); folderData.Count.ShouldEqual(3); folderData.ShouldContain( new[] { new PlaceholderListDatabase.PlaceholderData("partialFolder", PlaceholderListDatabase.PartialFolderValue), new PlaceholderListDatabase.PlaceholderData("expandedFolder", PlaceholderListDatabase.ExpandedFolderValue), new PlaceholderListDatabase.PlaceholderData("tombstone", PlaceholderListDatabase.PossibleTombstoneFolderValue), }, (data1, data2) => data1.Path == data2.Path && data1.Sha == data2.Sha); }
public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) { string dotGVFSRoot = Path.Combine(enlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot); try { string error; PlaceholderListDatabase placeholders; if (!PlaceholderListDatabase.TryCreate( tracer, Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList), new PhysicalFileSystem(), out placeholders, out error)) { tracer.RelatedError("Failed to open placeholder database: " + error); return(false); } using (placeholders) { List <IPlaceholderData> oldPlaceholderEntries = placeholders.GetAllEntries(); List <IPlaceholderData> newPlaceholderEntries = new List <IPlaceholderData>(); foreach (IPlaceholderData entry in oldPlaceholderEntries) { if (entry.Sha == GVFSConstants.AllZeroSha) { newPlaceholderEntries.Add(new PlaceholderListDatabase.PlaceholderData(entry.Path, PlaceholderListDatabase.PartialFolderValue)); } else { newPlaceholderEntries.Add(entry); } } placeholders.WriteAllEntriesAndFlush(newPlaceholderEntries); } } catch (IOException ex) { tracer.RelatedError("Could not write to placeholder database: " + ex.ToString()); return(false); } catch (Exception ex) { tracer.RelatedError("Error updating placeholder database folder entries: " + ex.ToString()); return(false); } if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot)) { return(false); } return(true); }
private static PlaceholderListDatabase CreatePlaceholderListDatabase(ConfigurableFileSystem fs, string initialContents) { fs.ExpectedFiles.Add(MockEntryFileName, new ReusableMemoryStream(initialContents)); string error; PlaceholderListDatabase dut; PlaceholderListDatabase.TryCreate(null, MockEntryFileName, fs, out dut, out error).ShouldEqual(true, error); dut.ShouldNotBeNull(); return(dut); }
/// <summary> /// Adds the folder placeholders to the placeholders list /// </summary> public override bool TryUpgrade(ITracer tracer, string enlistmentRoot) { string dotGVFSRoot = Path.Combine(enlistmentRoot, GVFSConstants.DotGVFS.Root); try { string error; PlaceholderListDatabase placeholders; if (!PlaceholderListDatabase.TryCreate( tracer, Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList), new PhysicalFileSystem(), out placeholders, out error)) { tracer.RelatedError("Failed to open placeholder database: " + error); return(false); } using (placeholders) { string workingDirectoryRoot = Path.Combine(enlistmentRoot, GVFSConstants.WorkingDirectoryRootName); // Run through the folder placeholders adding to the placeholder list IEnumerable <PlaceholderListDatabase.PlaceholderData> folderPlaceholderPaths = GetFolderPlaceholdersFromDisk(tracer, new PhysicalFileSystem(), workingDirectoryRoot) .Select(x => x.Substring(workingDirectoryRoot.Length + 1)) .Select(x => new PlaceholderListDatabase.PlaceholderData(x, GVFSConstants.AllZeroSha)); List <PlaceholderListDatabase.PlaceholderData> placeholderEntries = placeholders.GetAllEntriesAndPrepToWriteAllEntries(); placeholderEntries.AddRange(folderPlaceholderPaths); placeholders.WriteAllEntriesAndFlush(placeholderEntries); } } catch (IOException ex) { tracer.RelatedError("Could not write to placeholder database: " + ex.ToString()); return(false); } catch (Exception ex) { tracer.RelatedError("Error updating placeholder database with folders: " + ex.ToString()); return(false); } if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot)) { return(false); } return(true); }
public void WritesPlaceholderAddToFile() { ConfigurableFileSystem fs = new ConfigurableFileSystem(); PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, string.Empty); dut.AddAndFlushFile(InputGitIgnorePath, InputGitIgnoreSHA); fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedGitIgnoreEntry); dut.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA); fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries); }
public void HandlesRaceBetweenAddAndWriteAllEntries() { ConfigurableFileSystem fs = new ConfigurableFileSystem(); fs.ExpectedFiles.Add(MockEntryFileName + ".tmp", new ReusableMemoryStream(string.Empty)); PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, ExpectedGitIgnoreEntry); List <PlaceholderListDatabase.PlaceholderData> existingEntries = dut.GetAllEntriesAndPrepToWriteAllEntries(); dut.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA); dut.WriteAllEntriesAndFlush(existingEntries); fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries); }
public void HandlesRaceBetweenRemoveAndWriteAllEntries() { const string DeleteGitAttributesEntry = "D .gitattributes" + PlaceholderDatabaseNewLine; ConfigurableFileSystem fs = new ConfigurableFileSystem(); fs.ExpectedFiles.Add(MockEntryFileName + ".tmp", new ReusableMemoryStream(string.Empty)); PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, ExpectedTwoEntries); List <PlaceholderListDatabase.PlaceholderData> existingEntries = dut.GetAllEntriesAndPrepToWriteAllEntries(); dut.RemoveAndFlush(InputGitAttributesPath); dut.WriteAllEntriesAndFlush(existingEntries); fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries + DeleteGitAttributesEntry); }
public void WriteAllEntriesCorrectlyWritesFile() { ConfigurableFileSystem fs = new ConfigurableFileSystem(); fs.ExpectedFiles.Add(MockEntryFileName + ".tmp", new ReusableMemoryStream(string.Empty)); PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, string.Empty); List <PlaceholderListDatabase.PlaceholderData> allData = new List <PlaceholderListDatabase.PlaceholderData>() { new PlaceholderListDatabase.PlaceholderData(InputGitIgnorePath, InputGitIgnoreSHA), new PlaceholderListDatabase.PlaceholderData(InputGitAttributesPath, InputGitAttributesSHA) }; dut.WriteAllEntriesAndFlush(allData); fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries); }
public void ParsesExistingDataCorrectly() { ConfigurableFileSystem fs = new ConfigurableFileSystem(); PlaceholderListDatabase dut = CreatePlaceholderListDatabase( fs, "A .gitignore\0AE930E4CF715315FC90D4AEC98E16A7398F8BF64\r\n" + "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test.txt\0B6948308A8633CC1ED94285A1F6BF33E35B7C321\r\n" + "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test.txt\0C7048308A8633CC1ED94285A1F6BF33E35B7C321\r\n" + "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test2.txt\0D19198D6EA60F0D66F0432FEC6638D0A73B16E81\r\n" + "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test3.txt\0E45EA0D328E581696CAF1F823686F3665A5F05C1\r\n" + "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test4.txt\0FCB3E2C561649F102DD8110A87DA82F27CC05833\r\n" + "A Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\0E51B377C95076E4C6A9E22A658C5690F324FD0AD\r\n" + "D Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\r\n" + "D Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\r\n" + "D Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\r\n"); dut.EstimatedCount.ShouldEqual(5); }
public override IssueType HasIssue(List <string> messages) { string error; PlaceholderListDatabase placeholders; if (!PlaceholderListDatabase.TryCreate( this.Tracer, this.databasePath, new PhysicalFileSystem(), out placeholders, out error)) { messages.Add(error); return(IssueType.CantFix); } return(IssueType.None); }
public void GetAllEntriesAndPrepToWriteAllEntriesReturnsCorrectEntries() { ConfigurableFileSystem fs = new ConfigurableFileSystem(); using (PlaceholderListDatabase dut1 = CreatePlaceholderListDatabase(fs, string.Empty)) { dut1.AddAndFlushFile(InputGitIgnorePath, InputGitIgnoreSHA); dut1.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA); dut1.AddAndFlushFile(InputThirdFilePath, InputThirdFileSHA); dut1.RemoveAndFlush(InputThirdFilePath); } string error; PlaceholderListDatabase dut2; PlaceholderListDatabase.TryCreate(null, MockEntryFileName, fs, out dut2, out error).ShouldEqual(true, error); List <PlaceholderListDatabase.PlaceholderData> allData = dut2.GetAllEntriesAndPrepToWriteAllEntries(); allData.Count.ShouldEqual(2); }
public FileSystemCallbacks( GVFSContext context, GVFSGitObjects gitObjects, RepoMetadata repoMetadata, BlobSizes blobSizes, GitIndexProjection gitIndexProjection, BackgroundFileSystemTaskRunner backgroundFileSystemTaskRunner, FileSystemVirtualizer fileSystemVirtualizer, GitStatusCache gitStatusCache = null) { this.logsHeadFileProperties = null; this.postFetchJobLock = new object(); this.context = context; this.gitObjects = gitObjects; this.fileSystemVirtualizer = fileSystemVirtualizer; this.placeHolderCreationCount = new ConcurrentDictionary <string, PlaceHolderCreateCounter>(StringComparer.OrdinalIgnoreCase); this.newlyCreatedFileAndFolderPaths = new ConcurrentHashSet <string>(StringComparer.OrdinalIgnoreCase); string error; if (!ModifiedPathsDatabase.TryLoadOrCreate( this.context.Tracer, Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.ModifiedPaths), this.context.FileSystem, out this.modifiedPaths, out error)) { throw new InvalidRepoException(error); } this.BlobSizes = blobSizes; this.BlobSizes.Initialize(); PlaceholderListDatabase placeholders; if (!PlaceholderListDatabase.TryCreate( this.context.Tracer, Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList), this.context.FileSystem, out placeholders, out error)) { throw new InvalidRepoException(error); } this.GitIndexProjection = gitIndexProjection ?? new GitIndexProjection( context, gitObjects, this.BlobSizes, repoMetadata, fileSystemVirtualizer, placeholders, this.modifiedPaths); if (backgroundFileSystemTaskRunner != null) { this.backgroundFileSystemTaskRunner = backgroundFileSystemTaskRunner; this.backgroundFileSystemTaskRunner.SetCallbacks( this.PreBackgroundOperation, this.ExecuteBackgroundOperation, this.PostBackgroundOperation); } else { this.backgroundFileSystemTaskRunner = new BackgroundFileSystemTaskRunner( this.context, this.PreBackgroundOperation, this.ExecuteBackgroundOperation, this.PostBackgroundOperation, Path.Combine(context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks)); } this.enableGitStatusCache = gitStatusCache != null; // If the status cache is not enabled, create a dummy GitStatusCache that will never be initialized // This lets us from having to add null checks to callsites into GitStatusCache. this.gitStatusCache = gitStatusCache ?? new GitStatusCache(context, TimeSpan.Zero); this.logsHeadPath = Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Logs.Head); EventMetadata metadata = new EventMetadata(); metadata.Add("placeholders.Count", placeholders.EstimatedCount); metadata.Add("background.Count", this.backgroundFileSystemTaskRunner.Count); metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(FileSystemCallbacks)} created"); this.context.Tracer.RelatedEvent(EventLevel.Informational, $"{nameof(FileSystemCallbacks)}_Constructor", metadata); }
public FileSystemCallbacks( GVFSContext context, GVFSGitObjects gitObjects, RepoMetadata repoMetadata, BlobSizes blobSizes, GitIndexProjection gitIndexProjection, BackgroundFileSystemTaskRunner backgroundFileSystemTaskRunner, FileSystemVirtualizer fileSystemVirtualizer) { this.logsHeadFileProperties = null; this.postFetchJobLock = new object(); this.context = context; this.gitObjects = gitObjects; this.fileSystemVirtualizer = fileSystemVirtualizer; this.placeHolderCreationCount = new ConcurrentDictionary <string, PlaceHolderCreateCounter>(StringComparer.OrdinalIgnoreCase); string error; if (!ModifiedPathsDatabase.TryLoadOrCreate( this.context.Tracer, Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.ModifiedPaths), this.context.FileSystem, out this.modifiedPaths, out error)) { throw new InvalidRepoException(error); } this.BlobSizes = blobSizes; this.BlobSizes.Initialize(); PlaceholderListDatabase placeholders; if (!PlaceholderListDatabase.TryCreate( this.context.Tracer, Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList), this.context.FileSystem, out placeholders, out error)) { throw new InvalidRepoException(error); } this.GitIndexProjection = gitIndexProjection ?? new GitIndexProjection( context, gitObjects, this.BlobSizes, repoMetadata, fileSystemVirtualizer, placeholders, this.modifiedPaths); this.backgroundFileSystemTaskRunner = backgroundFileSystemTaskRunner ?? new BackgroundFileSystemTaskRunner( this.context, this.PreBackgroundOperation, this.ExecuteBackgroundOperation, this.PostBackgroundOperation, Path.Combine(context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks)); this.logsHeadPath = Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Logs.Head); EventMetadata metadata = new EventMetadata(); metadata.Add("placeholders.Count", placeholders.EstimatedCount); metadata.Add("background.Count", this.backgroundFileSystemTaskRunner.Count); metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(FileSystemCallbacks)} created"); this.context.Tracer.RelatedEvent(EventLevel.Informational, $"{nameof(FileSystemCallbacks)}_Constructor", metadata); }
private bool UpdatePlaceholderList(ITracer tracer, string dotGVFSRoot) { string esentPlaceholderFolder = Path.Combine(dotGVFSRoot, EsentPlaceholderListFolder); if (Directory.Exists(esentPlaceholderFolder)) { string newPlaceholderFolder = Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList); try { using (PersistentDictionary <string, string> oldPlaceholders = new PersistentDictionary <string, string>(esentPlaceholderFolder)) { string error; PlaceholderListDatabase newPlaceholders; if (!PlaceholderListDatabase.TryCreate( tracer, newPlaceholderFolder, new PhysicalFileSystem(), out newPlaceholders, out error)) { tracer.RelatedError("Failed to create new placeholder database: " + error); return(false); } using (newPlaceholders) { List <PlaceholderListDatabase.PlaceholderData> data = new List <PlaceholderListDatabase.PlaceholderData>(); foreach (KeyValuePair <string, string> kvp in oldPlaceholders) { tracer.RelatedInfo("Copying ESENT entry: {0} = {1}", kvp.Key, kvp.Value); data.Add(new PlaceholderListDatabase.PlaceholderData(path: kvp.Key, fileShaOrFolderValue: kvp.Value)); } newPlaceholders.WriteAllEntriesAndFlush(data); } } } catch (IOException ex) { tracer.RelatedError("Could not write to new placeholder database: " + ex.Message); return(false); } catch (EsentException ex) { tracer.RelatedError("Placeholder database appears to be from an older version of GVFS and corrupted: " + ex.Message); return(false); } string backupName; if (this.TryRenameFolderForDelete(tracer, esentPlaceholderFolder, out backupName)) { // If this fails, we leave behind cruft, but there's no harm because we renamed. this.TryDeleteFolder(tracer, backupName); return(true); } else { // To avoid double upgrading, we should rollback if we can't rename the old data this.TryDeleteFile(tracer, RepoMetadata.Instance.DataFilePath); return(false); } } return(true); }